gcc ... -static ...
尝试静态连接所有已连接的库,但我没有一些库的静态版本(例如:libX11)。gcc ... -static ...
尝试静态连接所有已连接的库,但我没有一些库的静态版本(例如:libX11)。gcc -lsome_dynamic_lib code.c some_static_lib.a
code.c
文件之前列出静态库,则保证其中的符号将被忽略,除非其中一个库对象文件中恰好有一个main()
函数。 - Jonathan Leffler你还可以使用-Bdynamic
选项中的ld
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
,在使用 -Wl,-Bstatic
或在 -Wl,-Bdynamic
之后,连接器将选择 libs1.so
。在调用 -ls1
之前,请不要忘记传递 -L/libs1-library-location/
。
-Wl,-Bstatic
和 -Wl,-Bdynamic
的顺序很重要。 - Pavel Vlasov从ld
的man页面中(这不适用于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
文件始终会以动态方式链接。
libX11.a
和ldd a.out
的输出之间有什么关系? - khatchadldd
输出所需的共享库列表,但 libX11 并未出现在其中。 - khatchad#!/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
(减号 l 冒号)选项可以在 gcc 中用于链接静态库(感谢https://dev59.com/h2w15IYBdhLWcg3wfb3i#20728782)。它有文档吗?在 gcc 的官方文档中没有(即对于共享库而言也并非完全正确):https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
binutils ld文档对此进行了描述。选项-llibrary -l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.) ... The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories.
-lname
将搜索libname.so
,然后搜索libname.a
,添加lib前缀和.so
(如果此时启用),或者.a
后缀。但是-l:name
选项只会精确搜索指定的名称:
https://sourceware.org/binutils/docs/ld/Options.html
变量-l namespec --library=namespec
Add the archive or object file specified by
namespec
to the list of files to link. This option may be used any number of times. Ifnamespec
is of the form:filename
, ld will search the library path for a file calledfilename
, otherwise it will search the library path for a file calledlibnamespec.a
.On systems which support shared libraries, ld may also search for files other than
libnamespec.a
. Specifically, on ELF and SunOS systems, ld will search a directory for a library calledlibnamespec.so
before searching for one calledlibnamespec.a
. (By convention, a.so
extension indicates a shared library.) Note that this behavior does not apply to:filename
, which always specifies a file calledfilename
.The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
See the
-(
option for a way to force the linker to search archives multiple times.You may list the same archive multiple times on the command line.
This type of archive searching is standard for Unix linkers. However, if you are using ld on AIX, note that it is different from the behaviour of the AIX linker.
-l:namespec
自binutils 2.18版本(2007年)开始有文档记录:https://sourceware.org/binutils/docs-2.18/ld/Options.html。一些装载器(链接器)提供了开启和关闭动态加载的开关。如果GCC在这样的系统上运行(Solaris - 可能还有其他系统),那么您可以使用相关选项。
如果您知道要静态链接哪些库,可以在链接行中简单地指定静态库文件 - 通过完整路径。
要在一行中链接动态库和静态库,您必须将静态库放在动态库和目标文件之后,像这样:
gcc -lssl main.o -lFooLib -o main
否则,它将无法正常工作。我花了一些时间才明白这一点。