답변:
gcc -lsome_dynamic_lib code.c some_static_lib.a
code.c
파일 앞에 정적 라이브러리를 나열하면 해당 기호가 무시되지 않는 한 무시됩니다. main()
라이브러리 오브젝트 파일 중 하나에 기능.
ld
옵션 을 사용할 수도 있습니다.-Bdynamic
gcc <objectfiles> -static -lstatic1 -lstatic2 -Wl,-Bdynamic -ldynamic1 -ldynamic2
그 이후의 모든 라이브러리 (gcc에 의해 자동으로 연결된 시스템 라이브러리 포함)는 동적으로 연결됩니다.
gcc objectfiles -o program -Wl,-Bstatic -ls1 -ls2 -Wl,-Bdynamic -ld1 -ld2
다음을 사용할 수도 있습니다. -static-libgcc -static-libstdc++
gcc 라이브러리 용 플래그
경우에 것을 명심 libs1.so
하고 libs1.a
모두가 존재 링커가 선택할 것 libs1.so
이 전인지 -Wl,-Bstatic
또는 후 -Wl,-Bdynamic
. -L/libs1-library-location/
전화하기 전에 통과하는 것을 잊지 마십시오 -ls1
.
-static
명령의 어딘가 를 사용 하면 실패합니다 (원하는 라이브러리보다 더 많은 것을 정적으로 연결하려고한다고 가정합니다).
-Wl,-Bstatic
와는 -Wl,-Bdynamic
중요하다.
ld
(gcc에서는 작동하지 않음) 맨 페이지 에서 --static
옵션을 참조하십시오 .
이 옵션은 명령 줄에서 여러 번 사용할 수 있습니다.이 옵션은 뒤에 오는 -l 옵션을 검색하는 라이브러리에 영향을줍니다.
한 가지 해결책은 --static
명령 줄 의 옵션 앞에 동적 종속성을 배치하는 것 입니다.
또 다른 가능성은를 사용하지 --static
않고 대신 특정 라이브러리에서 정적으로 링크하기 위해 정적 개체 파일의 전체 파일 이름 / 경로 (즉, -l 옵션을 사용하지 않음)를 제공하는 것입니다. 예:
# echo "int main() {}" > test.cpp
# c++ test.cpp /usr/lib/libX11.a
# ldd a.out
linux-vdso.so.1 => (0x00007fff385cc000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f9a5b233000)
libm.so.6 => /lib/libm.so.6 (0x00007f9a5afb0000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f9a5ad99000)
libc.so.6 => /lib/libc.so.6 (0x00007f9a5aa46000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9a5b53f000)
예에서 볼 수 libX11
있듯이은 정적으로 링크 되었기 때문에 동적으로 링크 된 라이브러리 목록에 없습니다.
주의 : .so
파일은 전체 파일 이름 / 경로로 지정된 경우에도 항상 동적으로 연결됩니다.
ldd a.out
?
ldd
필요한 공유 라이브러리를 출력하고 libX11은 해당 목록에 나타나지 않습니다.
내가 이해하는 문제는 다음과 같습니다. 일부는 정적, 일부는 동적, 일부는 정적 및 동적의 여러 라이브러리가 있습니다. gcc 의 기본 동작은 "대부분 동적"을 연결하는 것입니다. 즉, gcc 는 가능한 경우 동적 라이브러리에 연결되지만 그렇지 않으면 정적 라이브러리로 대체됩니다. gcc에 -static 옵션을 사용하는 경우 적절한 동적 라이브러리가 있더라도 정적 라이브러리 만 연결하고 정적 라이브러리를 찾을 수없는 경우 오류와 함께 종료됩니다.
gcc 가 갖고 싶었던 또 다른 옵션 은 내가 -mostly-static 이라고 부르고 본질적으로 -dynamic (기본값) 의 반대입니다 . -대부분 정적 은 존재한다면 정적 라이브러리에 대한 링크를 선호하지만 동적 라이브러리로 됩니다.
이 옵션은 존재하지 않지만 다음 알고리즘으로 에뮬레이션 할 수 있습니다.
-static 을 포함하여 out으로 링크 명령 줄을 구성합니다 .
동적 링크 옵션을 반복합니다.
라이브러리 경로, 즉 변수 <lib_path> 에 -L <lib_dir> 형식의 옵션을 누적합니다.
각 동적 링크 옵션, 즉 -l <lib_name> 형식의 옵션에 대해 gcc <lib_path> -print-file-name = lib <lib_name> .a 명령을 실행 하고 출력을 캡처하십시오.
명령이 전달한 것 이외의 것을 인쇄하면 정적 라이브러리의 전체 경로가됩니다. 동적 라이브러리 옵션을 정적 라이브러리의 전체 경로로 바꿉니다.
전체 링크 명령 줄을 처리 할 때까지 헹구고 반복합니다. 선택적으로 스크립트는 정적 링크에서 제외 할 라이브러리 이름 목록을 가져올 수도 있습니다.
다음 bash 스크립트가 트릭을 수행하는 것 같습니다.
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Usage: $0 [--exclude <lib_name>]. . . <link_command>"
fi
exclude=()
lib_path=()
while [ $# -ne 0 ]; do
case "$1" in
-L*)
if [ "$1" == -L ]; then
shift
LPATH="-L$1"
else
LPATH="$1"
fi
lib_path+=("$LPATH")
echo -n "\"$LPATH\" "
;;
-l*)
NAME="$(echo $1 | sed 's/-l\(.*\)/\1/')"
if echo "${exclude[@]}" | grep " $NAME " >/dev/null; then
echo -n "$1 "
else
LIB="$(gcc $lib_path -print-file-name=lib"$NAME".a)"
if [ "$LIB" == lib"$NAME".a ]; then
echo -n "$1 "
else
echo -n "\"$LIB\" "
fi
fi
;;
--exclude)
shift
exclude+=(" $1 ")
;;
*) echo -n "$1 "
esac
shift
done
echo
예를 들면 :
mostlyStatic gcc -o test test.c -ldl -lpthread
내 시스템에서 다음을 반환합니다.
gcc -o test test.c "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libdl.a" "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
또는 제외 :
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
다음을 얻습니다.
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
-l:libstatic1.a
gcc에는 정적 라이브러리를 연결하는 데 사용할 수있는 -l 옵션의 (l 콜론 빼기) 변형 도 있습니다 ( https://stackoverflow.com/a/20728782 감사합니다 ). 문서화되어 있습니까? gcc의 공식 문서에는 없습니다 (공유 라이브러리에도 정확하지 않음) : https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
-llibrary -l library
연결할 때 library라는 라이브러리를 검색합니다. (별도의 인수로 라이브러리를 사용하는 두 번째 대안은 POSIX 준수만을위한 것이며 권장되지 않습니다.) ... -l 옵션을 사용하는 것과 파일 이름을 지정하는 것의 유일한 차이점은 -l이 라이브러리를 'lib'로 둘러싸고 '.a'는 여러 디렉토리를 검색합니다.
binutils ld doc에서 설명합니다. 이 -lname
옵션은 lib 접두사 및 (현재 활성화 된 경우) 또는 접미사 libname.so
를 libname.a
추가 하기 위해 검색합니다 . 그러나 옵션은 지정된 이름 만 정확하게 검색합니다 :
https://sourceware.org/binutils/docs/ld/Options.html.so
.a
-l:name
-l namespec --library=namespec
namespec
링크 할 파일 목록에에 지정된 아카이브 또는 개체 파일을 추가합니다 . 이 옵션은 여러 번 사용할 수 있습니다. 이namespec
형식:filename
이면 ld는 라이브러리 경로에서라는 파일filename
을 검색하고, 그렇지 않으면 라이브러리 경로에서라는 파일을 검색합니다libnamespec.a
.공유 라이브러리를 지원하는 시스템에서 ld는
libnamespec.a
. 특히 ELF 및 SunOS 시스템에서 ld는라는 라이브러리libnamespec.so
를 검색하기 전에 라는 라이브러리에 대한 디렉토리를 검색합니다libnamespec.a
. (관습 적으로.so
확장자는 공유 라이브러리를 나타냅니다.)이 동작은에 적용되지 않으며:filename
항상라는 파일을 지정합니다.filename
.링커는 명령 줄에 지정된 위치에서 아카이브를 한 번만 검색합니다. 아카이브가 명령 줄에서 아카이브 이전에 나타난 일부 개체에서 정의되지 않은 기호를 정의하는 경우 링커는 아카이브의 적절한 파일을 포함합니다. 그러나 나중에 명령 줄에 나타나는 개체의 정의되지 않은 기호로 인해 링커가 아카이브를 다시 검색하지 않습니다.
-(
링커가 아카이브를 여러 번 검색하도록하는 방법 은 옵션을 참조하십시오 .명령 줄에 동일한 아카이브를 여러 번 나열 할 수 있습니다.
이러한 유형의 아카이브 검색은 Unix 링커의 표준입니다. 그러나 AIX에서 ld를 사용하는 경우 AIX 링커의 동작과 다릅니다.
변종 -l:namespec
은 2.18 버전의 binutils (2007) 이후 문서화되었습니다. https://sourceware.org/binutils/docs-2.18/ld/Options.html
일부 로더 (링커)는 동적로드를 켜고 끄는 스위치를 제공합니다. GCC가 이러한 시스템 (Solaris 및 기타)에서 실행중인 경우 관련 옵션을 사용할 수 있습니다.
정적으로 링크하려는 라이브러리를 알고있는 경우 링크 라인에서 전체 경로로 정적 라이브러리 파일을 간단히 지정할 수 있습니다.