静态库中未定义对早期包含的静态库中包含的全局符号的引用?

Undefined reference in static library to global symbol included in an earlier included static library?

我正在尝试为没有标准包含且没有标准库的 RISC-V 静态构建应用程序,而是尝试 link 在静态构建的 musl-libc 中使用其 libc.a和 crt1.o 文件(注意,我将 crt1.o 构建到静态库 libcrt1.a 中)。

以下是我的程序:

#include <stdio.h>

int main()
{
    printf("Hello world!");
    return 0;
}

这是我的 Makefile:

CC=/home/john/deps/install/opt/riscv/bin/riscv64-unknown-elf-gcc
CFLAGS=-Wall -g --static -static-libgcc -nostdinc -nostdlib -I/home/john/musl-1.1.23/install/include
LDFLAGS=-L/home/john/deps/install/opt/riscv/lib/gcc/riscv64-unknown-elf/8.1.0 -L/home/john/musl-1.1.23/install/lib -lc -lgcc -lcrt1

hello.elf: hello.c
        ${CC} ${CFLAGS} -o $@ $^ ${LDFLAGS}

clean:
        rm -f hello.elf

当我尝试这样做时,出现以下错误:

/home/john/musl-1.1.23/install/lib/libcrt1_weak.a(crt1.o): In function `_start_c':
/home/john/musl-1.1.23/crt/crt1.c:18: undefined reference to `__libc_start_main'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'hello.elf' failed

但是,当我检查 libc 和 libcrt1 的符号时,我发现 __libc_start_main 是 libc:

中定义的全局符号
File: libc.a(__libc_start_main.o)
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS __libc_start_main.c
   323: 0000000000000000   112 FUNC    GLOBAL DEFAULT   14 __libc_start_main

(为清楚起见,这里是 libcrt1 中符号的打印输出):

    88: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_start_main

如果能帮助理解为什么这个全局符号没有被解析,我们将不胜感激。

库必须在命令行的末尾。 ld 只在库中搜索符号一次。

LDFLAGS=-L/home/john/deps/install/opt/riscv/lib/gcc/riscv64-unknown-elf/8.1.0 -L/home/john/musl-1.1.23/install/lib -lcrt1 -lgcc -lc 

--library=archive Add archive file archive to the list of files to link. This option may be used any number of times. ld will search its path-list for occurrences of libarchive.a for every archive specified. On systems which support shared libraries, ld may also search for libraries with extensions other than .a. Specifically, on ELF and SunOS systems, ld will search a directory for a library with an extension of .so before searching for one with an extension of .a. By convention, a .so extension indicates a shared library. 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.