문제
컴파일러에 문제가있어 라이브러리에서 사용하고 싶은 함수에 대한 '정의되지 않은 참조'가 있다고 말합니다. 문제에 대한 정보를 공유하겠습니다.
- 나는 C에 대한 GCC로 크로스 컴파일하고 있습니다.
- 프로토 타입이 포함 된 다른 헤더가 포함 된 포함 된 헤더를 통해 액세스하는 라이브러리 기능을 호출하고 있습니다.
- -i를 사용하여 헤더 디렉토리를 포함 시켰으며 그것이 발견되고 있다고 확신합니다.
- 먼저 .O 파일을 작성한 다음 별도의 명령으로 연결합니다.
그래서 내 생각은 라이브러리 파일을 포함하는 순서 일지 모르지만 주문하는 올바른 방법이 무엇인지 잘 모르겠습니다. .o 파일 전후에 헤더 폴더를 포함 시켰습니다.
어떤 사람들은 링커가 어떻게하는지에 대한 설명이 좋을 것이라고 제안합니다.
감사!
답변에 대한 응답
- 라이브러리 파일이 없습니다.
- 라이브러리 파일에 대한 나의 이해는 단지 헤더 및 소스 파일 모음이지만 소스에서 만든 .O 파일 모음 일 것입니다!
- 라이브러리 개체 파일이 생성되지 않아야 할 것입니다. 예, 포함과 도서관의 차이점을 이해하지 못하는 것 같습니다.
모든 응답에 감사드립니다! 나는 도서관에 대해 많은 것을 배웠다. 모든 응답을 받아 들인 답변으로 넣고 싶습니다 :-)
해결책
.o 파일을 생성하기 위해 라이브러리에서 .c 파일을 컴파일하지 않는 것 같습니다. 링커는 라이브러리를 컴파일하여 생성 된 .o 파일에서 프로토 타입의 구현을 찾습니다.
빌드 프로세스가 라이브러리 .C 파일을 컴파일합니까?
실제로 소스 코드 인 경우 왜 "라이브러리"라고 부릅니까?
다른 팁
헤더는 기능 선언 및 기능 정의를 제공합니다. 링커를 허용하려면 함수의 구현 (정의되지 않은 참조를 제거)을 찾으려면 컴파일러 드라이버 (GCC)에 기능이 -L 플래그를 사용하는 특정 라이브러리를 연결하도록 요청해야합니다. 예를 들어 -lm은 수학 라이브러리를 연결합니다. 함수의 매뉴얼 페이지는 일반적으로 기능을 찾기 위해 지정 해야하는 라이브러리를 지정해야합니다.
링커에서 지정된 라이브러리를 찾을 수없는 경우 -L 스위치 (예 : -l/usr/local/lib)를 사용하여 라이브러리 검색 경로를 추가 할 수 있습니다. Library_Path 환경 변수를 통해 라이브러리 경로에 영구적으로 영향을 줄 수 있습니다.
다음은 문제를 디버깅하는 데 도움이되는 추가 세부 사항입니다. 컨벤션에 의해 라이브러리 파일의 이름은 lib로 접두사를 붙이고 (정적 형태로) .a 확장자가 있습니다. 따라서 시스템의 기본 수학 라이브러리 (-LM과 연결된 것)의 정적으로 연결된 버전은 일반적으로 /usr/lib/libm.a에 있습니다. 주어진 라이브러리가 정의하는 기호를 보려면 라이브러리 파일에서 NM- 정의 전용을 실행할 수 있습니다. 내 시스템에서 libm.a에서 명령을 실행하면 다음과 같은 출력이 제공됩니다.
e_atan2.o:
00000000 T atan2
e_asinf.o:
00000000 T asinf
e_asin.o:
00000000 T asin
컴파일러가 사용하는 라이브러리 경로와 기본적으로로드하는 라이브러리를 확인하려면 -V 옵션으로 GCC를 호출 할 수 있습니다. 다시 내 시스템에서 이것은 다음과 같은 출력을 제공합니다.
GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd)
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o
라이브러리와 헤더 개념을 혼합 한 것을 두려워합니다. 도서관이 있다고 가정 해 봅시다 libmylib.a
기능이 포함되어 있습니다 myfunc()
그리고 해당 헤더 mylib.h
그것은 프로토 타입을 정의합니다. 소스 파일에서 myapp.c
직접 또는 직접 또는 다른 헤더를 포함하는 헤더를 포함합니다. 예를 들어:
/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...
소스 파일은 다음과 같습니다.
/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");
이제 얻을 수 있도록 컴파일 할 수 있습니다 myapp.o
:
gcc -c -I../mylib/includes myapp.c
-나는 단지 GCC에 헤더 파일이 어디에 있는지 알려주고 라이브러리 자체와 관련이 없습니다!
이제 응용 프로그램을 실제 라이브러리와 연결할 수 있습니다.
gcc -o myapp -L../mylib/libs myapp.o -lmylib
주목하십시오 -L
스위치는 GCC에 라이브러리가 어디에 있는지, -l
코드를 라이브러리에 연결하도록 지시합니다.
이 마지막 단계를 수행하지 않으면 설명한 문제가 발생할 수 있습니다.
더 복잡한 다른 경우가있을 수 있지만 귀하의 질문에 따르면 이것이 문제를 해결하기에 충분하기를 바랍니다.
Makefile 및 귀하가 호출하려는 라이브러리 기능을 게시하십시오. 간단한 GCC MakeFiles조차도 일반적으로 다음과 같은 선이 있습니다.
LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared
이 경우 표준 C 라이브러리를 연결하는 것을 의미합니다.
링커가 라이브러리를 찾을 수있는 경로를 추가해야한다고 생각합니다. GCC/LD에서는 -l로 -L로이를 수행 할 수 있으며 -L로 라이브러리를 수행 할 수 있습니다.
-ldir,-library-path = dir
표준 검색 디렉토리 이전의 검색 디렉토리 DIR (이 옵션은 해당 디렉토리를 검색하는 -L 옵션보다 우선합니다).
-larch, -library = 아카이브
링크 할 파일 목록에 아카이브 파일 아치를 포함시킵니다.
답변에 대한 응답 - 라이브러리에는 .A 라이브러리 파일, 단지 .h 및 .c가 없으므로 -L은 Abtoriate가 아닙니다.
그러면 먼저 라이브러리를 만들어야 할 수도 있습니까?
gcc -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
새로운 버전의 GCC로 프로그램을 구축 할 때이 문제가 발생했습니다. -std = gnu89 옵션으로 GCC를 호출하여 문제가 해결되었습니다. 분명히 이것은 인라인 함수 선언 때문이었습니다. 이 솔루션을 찾았습니다 https://gcc.gnu.org/gcc-5/porting_to.html