当来自我的 makefile 的 运行 时,GCC 忽略了一个库

GCC ignoring a library when run from my makefile

我制作了自己的库,称为 j(发明)。 我将库放在我的生成文件的目录中。 为了展示我的布局,这里是 ls -R 吐出的逐字记录:

a.exe  header  libj.a  makefile  src

./header:
jlib

./header/jlib:
dstring.h  eio.h

./src:
main.c  main.d  main.o  

当我运行gcc src/main.c -static -L. -lj -Iheader -std=c11它链接就好了!但是,当我 运行 我认为与我的 makefile 等效时,ld 抱怨缺少符号...
我正在使用 Mingw-w64 Windows。

这是我的生成文件:

target := librarytest.exe
lflags := -static -L. -lj
cflags := -std=c11 -g -Iheader -Wall
cc := C:\MinGW\bin\gcc

srcfiles := $(wildcard src/*.c)
hdrfiles := $(wildcard header/*)

objfiles := $(srcfiles:.c=.o)
dependencies := $(srcfiles:.c=.d)

build: $(target)

$(target): $(objfiles)
    $(cc) -o $(target) $(objfiles) $(lflags)

.c.o:
    $(cc) $(cflags) -MMD -MP -c $< -o $@


-include $(dependencies)

这是确切的错误:

C:\MinGW\bin\gcc -std=c11 -g -Iheader -Wall -MMD -MP -c src/main.c -o src/main.o
src/main.c: In function 'main':
src/main.c:8:14: warning: variable 'paramSeed' set but not used [-Wunused-but-set-variable]
  const char* paramSeed = NULL;
              ^
C:\MinGW\bin\gcc -o librarytest.exe src/main.o -static -L. -lj
src/main.o: In function `main':
F:\school\csci440\homework1/src/main.c:56: undefined reference to `String_wrap_d'
F:\school\csci440\homework1/src/main.c:57: undefined reference to `String_touint'
collect2.exe: error: ld returned 1 exit status
makefile:15: recipe for target 'librarytest.exe' failed
mingw32-make: *** [librarytest.exe] Error 1

这是 libj.a

的海里
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
                 U __imp___iob_func
                 U fprintf
                 U free
                 U malloc
                 U memcpy
                 U printf
                 U realloc
                 U sscanf
                 U strcpy
000000000000013f T String_append
0000000000000000 T String_construct_d
000000000000004f T String_construct_s
00000000000000ce T String_deconstruct_d
00000000000000fa T String_deconstruct_s
0000000000000286 T String_empty
00000000000002e6 T String_find_after
000000000000025c T String_print
00000000000002a6 T String_touint
0000000000000093 T String_wrap_d
                 U strlen

eio.o:
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
                 U __imp___iob_func
                 U fgets
0000000000000000 T readline
                 U String_append
                 U String_construct
                 U String_empty
                 U strlen

我显然不像我想的那样理解链接,而且我在 Google 上找不到任何内容,因为我一直在获得有关基本链接的结果,就像我的第一个工作示例一样。

正在将评论转化为答案。

在用确切的错误消息和库的内容详细说明问题之前:

What do you see as the linking command from make? You have a path to your compiler in the makefile; are you sure that's the same program you execute from the command line? You're also linking an object file in the makefile but compiling the source file to object and then linking on the command line — what is the error message again?

乔恩·韦尔登回复:

When I compile with the same exe as the path in the makefile I get other errors that I'll add to my question.

为了进一步说明,我问:

Does it work if you replace $(objfiles) by $(srcfiles) in the link command line? The paramSeed warning isn't affecting the linking (but would if you add -Werror to your compiler options). Is there any risk of a mix of 32-bit code in your program and 64-bit code in your library, or vice versa? You'd often get a warning if that was an issue, but it would also prevent linking.

Jon Weldon 回复:

@JonathanLeffler was right with the discrepancy in the paths. My path env variable finds gcc first in a Haskell installation, which is 32 bit. However, when I was using my makefile, the gcc in my specified directory was 64 bit. GCC either ignored the library, or couldn't resolve the symbols because of a naming convention I suppose.

如果您以前没有遇到过此类问题,则很难诊断。但是,链接器根本找不到任何包含正确类型目标文件中的符号的目标文件。关于错误类型的目标文件(或整个库)的警告本来很好,但最终它是正确的——它找不到正确的符号。