关于makefile:gcc和ld拒绝静态链接库

gcc and ld is refusing to link library statically

只是为了好玩(以及为了一般地学习编译),我给自己一个任务是构建一个xorg服务器,其中所有库都静态链接,除了glibc。由于某些原因,gcc只会忽略我的某些静态库。

当我运行类似的东西时(最后两行是相关的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gcc -DHAVE_DIX_CONFIG_H -Wall -Wpointer-arith -Wmissing-declarations -Wformat=2 -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wbad-function-cast \\
-Wold-style-definition -Wdeclaration-after-statement -Wunused -Wuninitialized -Wshadow -Wmissing-noreturn -Wmissing-format-attribute -Wredundant-decls \\
-Wlogical-op -Werror=implicit -Werror=nonnull -Werror=init-self -Werror=main -Werror=missing-braces -Werror=sequence-point -Werror=return-type -Werror=trigraphs \\
-Werror=array-bounds -Werror=write-strings -Werror=address -Werror=int-to-pointer-cast -Werror=pointer-to-int-cast -fno-strict-aliasing -fno-strict-aliasing \\
-D_DEFAULT_SOURCE -D_BSD_SOURCE -DHAS_FCHOWN -DHAS_STICKY_DIR_BIT -I/usr/include/libdrm -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 \\
-I/usr/include/X11/dri -I../../include -I../../include -I../../Xext -I../../composite -I../../damageext -I../../xfixes -I../../Xi -I../../mi -I../../miext/sync \\
-I../../miext/shadow -I../../miext/damage -I../../render -I../../randr -I../../fb -I../../dbe -I../../present -fvisibility=hidden -DHAVE_XORG_CONFIG_H \\
-fvisibility=hidden -I/usr/include/libdrm -g -O2 -pthread -o Xorg sdksyms.o \\
   /lib/arm-linux-gnueabihf/libz.a ../../dix/.libs/libmain.a ../../dix/.libs/libdix.a loader/.libs/libloader.a common/.libs/libcommon.a  os-support/.libs/libxorgos.a \\
parser/.libs/libxf86config.a dixmods/.libs/libdixmods.a modes/.libs/libxf86modes.a ramdac/.libs/libramdac.a ddc/.libs/libddc.a i2c/.libs/libi2c.a \\
../../composite/.libs/libcomposite.a ../../xfixes/.libs/libxfixes.a ../../Xext/.libs/libXext.a ../../dbe/.libs/libdbe.a ../../record/.libs/librecord.a \\
../../randr/.libs/librandr.a ../../render/.libs/librender.a ../../damageext/.libs/libdamageext.a ../../present/.libs/libpresent.a \\
../../miext/damage/.libs/libdamage.a ../../Xi/.libs/libXi.a ../../xkb/.libs/libxkb.a xkb/.libs/libxorgxkb.a dri/.libs/libdri.a dri2/.libs/libdri2.a \\
../../dri3/.libs/libdri3.a ../../glx/.libs/libglxvnd.a ../../miext/sync/.libs/libsync.a ../../mi/.libs/libmi.a ../../os/.libs/libos.a -lcrypto \\
../../Xext/.libs/libXvidmode.a \\
-Wl,-Bstatic -lpciaccess -ldrm -lpixman-1 -lXau -lxshmfence -lm -lbz2 -lfontenc -ludev \\
-Wl,-Bdynamic -lXdmcp -lXfont2 -lrt -ldl -lpthread

它产生具有以下链接的二进制文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(sid)root@localhost:/opt/xorg-server-1.20.5/hw/xfree86# ldd Xorg
        libcrypto.so.1.1 => /lib/arm-linux-gnueabihf/libcrypto.so.1.1 (0xf6a8b000)
        libXdmcp.so.6 => /lib/arm-linux-gnueabihf/libXdmcp.so.6 (0xf6a77000)
        libXfont2.so.2 => /lib/arm-linux-gnueabihf/libXfont2.so.2 (0xf6a4b000)
        librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xf6a35000)
        libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0xf6a22000)
        libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xf69fd000)
        libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xf6902000)
        /lib/ld-linux-armhf.so.3 (0xf6ec7000)
        libbsd.so.0 => /lib/arm-linux-gnueabihf/libbsd.so.0 (0xf68df000)
        libz.so.1 => /lib/arm-linux-gnueabihf/libz.so.1 (0xf68bc000)
        libbz2.so.1.0 => /lib/arm-linux-gnueabihf/libbz2.so.1.0 (0xf68a0000)
        libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xf6837000)
        libfontenc.so.1 => /lib/arm-linux-gnueabihf/libfontenc.so.1 (0xf6822000)
        libfreetype.so.6 => /lib/arm-linux-gnueabihf/libfreetype.so.6 (0xf67a2000)
        libpng16.so.16 => /lib/arm-linux-gnueabihf/libpng16.so.16 (0xf6770000)

从输出中可以看到," libz "是动态链接的。所以我想我会尝试强制gcc / ld使用静态libz代替。但是什么都行不通。我尝试将"-lz "添加到-Bstatic列表中,并且还尝试了" -l:libz.a "以及文件" / lib / arm-linux的完整路径-gnueabihf / libz.a "。没有任何效果,最终的二进制文件仍然链接到动态.so库。 gcc不会给我任何错误,它似乎只是忽略了我静态链接某些库的请求。

我在做什么错?

此外,当我将两个库"-lXdmcp -lXfont2 "从动态列表移到静态列表时,gcc会失败,并出现一些错误,好像这些库正在引用未包含的内容?我该如何调试类似的链接问题?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXdmcp.a(Key.o): in function `XdmcpGenerateKey':
(.text+0x2): undefined reference to `arc4random_buf'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `sfnt_get_ushort':
(.text+0x1a): undefined reference to `FT_Load_Sfnt_Table'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FreeTypeFreeFace.part.3':
(.text+0x412): undefined reference to `FT_Done_Face'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FreeTypeFreeFont':
(.text+0x4aa): undefined reference to `FT_Done_Size'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FreeTypeActivateInstance':
(.text+0x686): undefined reference to `FT_Activate_Size'
/usr/bin/ld: (.text+0x6b4): undefined reference to `FT_Set_Transform'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FreeTypeLoadFont':
(.text+0x8f8): undefined reference to `FT_Get_Sfnt_Table'
/usr/bin/ld: (.text+0xb6e): undefined reference to `FT_Get_PS_Font_Info'
/usr/bin/ld: (.text+0xc7c): undefined reference to `FT_New_Size'
/usr/bin/ld: (.text+0xcb8): undefined reference to `FT_Set_Char_Size'
/usr/bin/ld: (.text+0xcc6): undefined reference to `FT_Done_Size'
/usr/bin/ld: (.text+0xe70): undefined reference to `FT_Set_Pixel_Sizes'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FT_Do_SBit_Metrics.isra.6':
(.text+0xf9c): undefined reference to `FT_Set_Pixel_Sizes'
/usr/bin/ld: (.text+0xfaa): undefined reference to `FT_Load_Glyph'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `ft_get_very_lazy_bbox':
(.text+0x10a4): undefined reference to `FT_Load_Sfnt_Table'
/usr/bin/ld: (.text+0x10d8): undefined reference to `FT_MulFix'
/usr/bin/ld: (.text+0x10e8): undefined reference to `FT_MulFix'
/usr/bin/ld: (.text+0x10f2): undefined reference to `FT_MulFix'
/usr/bin/ld: (.text+0x10fc): undefined reference to `FT_MulFix'
/usr/bin/ld: (.text+0x116a): undefined reference to `FT_Vector_Transform'
/usr/bin/ld: (.text+0x1172): undefined reference to `FT_Vector_Transform'
/usr/bin/ld: (.text+0x117a): undefined reference to `FT_Vector_Transform'
/usr/bin/ld: (.text+0x1182): undefined reference to `FT_Vector_Transform'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FreeTypeRasteriseGlyph':
(.text+0x1530): undefined reference to `FT_Outline_Get_BBox'
/usr/bin/ld: (.text+0x1704): undefined reference to `FT_Outline_Get_BBox'
/usr/bin/ld: (.text+0x17d0): undefined reference to `FT_Load_Glyph'
/usr/bin/ld: (.text+0x1810): undefined reference to `FT_Outline_Get_BBox'
/usr/bin/ld: (.text+0x1c56): undefined reference to `FT_Load_Glyph'
/usr/bin/ld: (.text+0x1d0e): undefined reference to `FT_Render_Glyph'
/usr/bin/ld: (.text+0x1dd0): undefined reference to `FT_Outline_Get_BBox'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftfuncs.o): in function `FreeTypeLoadXFont':
(.text+0x3042): undefined reference to `FT_New_Face'
/usr/bin/ld: (.text+0x3088): undefined reference to `FT_Init_FreeType'
/usr/bin/ld: (.text+0x33f6): undefined reference to `FT_Get_Sfnt_Table'
/usr/bin/ld: (.text+0x3af0): undefined reference to `FT_Get_Sfnt_Table'
/usr/bin/ld: (.text+0x3afc): undefined reference to `FT_Get_Sfnt_Table'
/usr/bin/ld: (.text+0x3b08): undefined reference to `FT_Get_PS_Font_Info'
/usr/bin/ld: (.text+0x3e8a): undefined reference to `FT_Get_Postscript_Name'
/usr/bin/ld: (.text+0x3f04): undefined reference to `FT_Get_X11_Font_Format'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(fttools.o): in function `FTGetName':
(.text+0x22): undefined reference to `FT_Get_Sfnt_Name_Count'
/usr/bin/ld: (.text+0x40): undefined reference to `FT_Get_Sfnt_Name'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(gunzip.o): in function `BufZipFileClose':
(.text+0x48): undefined reference to `inflateEnd'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(gunzip.o): in function `BufZipFileFill':
(.text+0xcc): undefined reference to `inflate'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(gunzip.o): in function `BufFilePushZIP':
(.text+0x1cc): undefined reference to `inflateInit2_'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(bunzip2.o): in function `BufBzip2FileClose':
(.text+0x48): undefined reference to `BZ2_bzDecompressEnd'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(bunzip2.o): in function `BufBzip2FileFill':
(.text+0xce): undefined reference to `BZ2_bzDecompress'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(bunzip2.o): in function `BufFilePushBZIP2':
(.text+0x1c2): undefined reference to `BZ2_bzDecompressInit'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftenc.o): in function `FTPickMapping':
(.text+0x20): undefined reference to `FontEncFromXLFD'
/usr/bin/ld: (.text+0x68): undefined reference to `FT_Get_BDF_Charset_ID'
/usr/bin/ld: (.text+0xd0): undefined reference to `FT_Get_BDF_Charset_ID'
/usr/bin/ld: (.text+0xe2): undefined reference to `FT_Select_Charmap'
/usr/bin/ld: (.text+0xf4): undefined reference to `FontEncFind'
/usr/bin/ld: (.text+0x10a): undefined reference to `FontEncFind'
/usr/bin/ld: (.text+0x118): undefined reference to `FT_Has_PS_Glyph_Names'
/usr/bin/ld: (.text+0x18c): undefined reference to `FT_Get_BDF_Charset_ID'
/usr/bin/ld: (.text+0x19c): undefined reference to `FontEncFind'
/usr/bin/ld: (.text+0x242): undefined reference to `FontEncFind'
/usr/bin/ld: (.text+0x282): undefined reference to `FT_Get_Sfnt_Table'
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/libXfont2.a(ftenc.o): in function `FTRemap':
(.text+0x2d6): undefined reference to `FontEncName'
/usr/bin/ld: (.text+0x2ea): undefined reference to `FontEncRecode'
/usr/bin/ld: (.text+0x2f6): undefined reference to `FT_Set_Charmap'
/usr/bin/ld: (.text+0x316): undefined reference to `FT_Set_Charmap'
/usr/bin/ld: (.text+0x2e6): undefined reference to `FT_Get_Name_Index'
/usr/bin/ld: (.text+0x304): undefined reference to `FT_Get_Char_Index'
/usr/bin/ld: (.text+0x326): undefined reference to `FT_Get_Char_Index'
collect2: error: ld returned 1 exit status

简短的回答:如果选择静态库(假设有"。a "可用),则库的顺序很重要-在命令行上很重要!

长答案:
如果您有两个与主代码(M)相关联的库(A,B),其中有调用M-> A和A-> B,则必须按该顺序指定库:M,A,B。回想一下,当引用静态库时,链接器将尝试在命名库中查找任何未解析的引用(函数,变量,方法等),并仅提取可解决这些问题的\\'。o \\'文件。从\\'。a \\'到可执行文件的引用。

如果将库指定为M,B,A,则链接器将查找库\\'B \\',并且不会标识要包含的任何\\'。o \\'(因为仅存在引用M-> A )。然后它将从A库中检索\\'。o \\',以满足调用M-> A,并报告新发现的调用A-> B的错误。

使用共享库时,整个\\ .so将被链接(通过引用),并且\\ .so \\中的所有全局定义的符号将对可执行文件中的任何模块可用,包括链接的模块从其他.so。因此,指定\\'。so \\'的顺序通常无关紧要


it simply seem to ignore my request of statically linking some
libraries.

本身不太可能。

What am I doing wrong?

您误解了动态链接的性质。至少这些因素在起作用:

  • 您要链接的共享对象可能对其他动态对象有自己的依赖性。

  • 根据平台和实现的细节,即使某些动态对象自身的依赖关系未由命令行上的任何名称解决,该链接也可能会成功。

  • 您链接的静态库很可能无法为任何动态库中的任何内容提供可行的分辨率。

  • 程序的总体动态依赖关系(如ldd所示)是所涉及的所有共享对象的依赖关系的可传递闭包。它们不一定全部由包含程序入口点的SO直接引用,并且如果交换出共享库实现,它们甚至可能随着时间而改变。

底线:很有可能,您的某些非预期动态依赖项至少来自您链接的共享对象,可能是libXdmcp和libXfont2。静态库是链接的,它们将用于解析主程序中以及命令行上位于它们之前的静态库中的符号,但是它们不能满足共享对象对动态符号的引用,无论该对象在何处出现。命令行。

Also, when I move the two libraries"-lXdmcp -lXfont2" from the
dynamic list to the static list, gcc fails with some errors that looks
like the libraries are referencing things that is not included? How
would I debug linking problems like that?

静态库需要在链接命令行上正确订购。每个库都必须在(静态)库之前包含它们所需的符号,因此这些特殊的库可能需要显示在最前面。如有必要,您可以在命令行上重复使用库,如果您具有循环依赖项,则很有用;否则,如果您在寻找可行的订单时遇到困难,可以用作快速破解。

您可以通过弄清楚库是否提供链接程序抱怨的符号以及哪个库都引用了它们来进行调试。这将告诉您必要的命令行顺序。