使用 GCC 交叉编译器时对 printf 的未定义引用
Undefined reference to printf when using GCC cross compiler
我正在尝试使用针对 mips
:
的交叉编译器 (GCC 4.9.2) 编译以下简单的 'Hello World' 程序
#include <stdio.h>
int main()
{
int x = 5;
printf("x = %d\n", x);
}
x
变量用于阻止 GCC 将 printf
更改为 puts
,对于简单的以换行符结尾的字符串,它似乎会自动执行此操作。
我在 ${HOME}/xc
下构建了一个交叉编译器,并使用以下命令执行它:
${HOME}/xc/bin/mips-gcc -v hello.c
但是,我收到以下错误:
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status
我假设这是链接器的问题,因为如果在搜索路径上找不到例如 stdio.h
,我预计该过程会更早失败。我可以编译一个更简单的程序,它只是 returns 零,所以并不是整个工具链都坏了,大概只是标准库链接(我使用的是 newlib 2.2.0-1)。
无论我运行 Linux (Ubuntu 14.10) 还是 Cygwin (Windows 8).[=21] 下的交叉编译器,我都会得到同样的错误。 =]
GCC 的完整输出是:
Using built-in specs.
COLLECT_GCC=/home/paul/xc/bin/mips-gcc
COLLECT_LTO_WRAPPER=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper
Target: mips
Configured with: /home/paul/xc/mips/tmp/gcc-4.9.2/configure --prefix=/home/paul/xc --target=mips --enable-languages=c --with-newlib --without-isl --without-cloogs --disable-threads --disable-libssp --disable-libgomp --disable-libmudflap
Thread model: single
gcc version 4.9.2 (GCC)
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/libexec/gcc/mips/4.9.2/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -auxbase hello -version -o /tmp/ccCpAajQ.s
GNU C (GCC) version 4.9.2 (mips)
compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/sys-include"
#include "..." search starts here:
#include <...> search starts here:
/home/paul/xc/lib/gcc/mips/4.9.2/include
/home/paul/xc/lib/gcc/mips/4.9.2/include-fixed
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/include
End of search list.
GNU C (GCC) version 4.9.2 (mips)
compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: cffaaedf0b24662e67a5d97387fc5b17
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/as -EB -O1 -no-mdebug -mabi=32 -o /tmp/ccW5mHJu.o /tmp/ccCpAajQ.s
COMPILER_PATH=/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/
LIBRARY_PATH=/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib/
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/libexec/gcc/mips/4.9.2/collect2 -plugin /home/paul/xc/libexec/gcc/mips/4.9.2/liblto_plugin.so -plugin-opt=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper -plugin-opt=-fresolution=/tmp/cc8TAJb9.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc -EB /home/paul/xc/lib/gcc/mips/4.9.2/crti.o /home/paul/xc/lib/gcc/mips/4.9.2/crtbegin.o -L/home/paul/xc/lib/gcc/mips/4.9.2 -L/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib /tmp/ccW5mHJu.o -lgcc -lgcc /home/paul/xc/lib/gcc/mips/4.9.2/crtend.o /home/paul/xc/lib/gcc/mips/4.9.2/crtn.o
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400050
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status
我正在使用的构建脚本在这里(我是根据六个教程编写的,这些教程都建议略有不同):
https://github.com/UoMCS/mips-cross-compile
基本上它执行以下步骤:
- 构建 binutils。
- 构建 GCC(第 1 阶段)。
- 构建新库。
- 构建 GCC(第 2 阶段)。
我知道还有其他工具,例如 crosstool-ng 和 builtroot,但是我正在构建这个工具链的人想要在启动构建过程之前编辑 binutils 的部分,并且工具链也有在 Cygwin 下工作(crosstool-ng 不会因为各种原因,包括区分大小写的文件路径)。
我认为这可能是显而易见的事情,但我已经弄乱了一个星期,看不出它会是什么。任何帮助将不胜感激!
有必要构建库以配合您的交叉编译器。特别是,您需要具有 cross-compiled 版本的 glibc 或标准库的其他一些实现,才能获得 printf()
.
版本
查看 this link 中的示例,了解您需要考虑的事项类型,以获得您需要的所有内容 - cross-compiler、headers 和库.
自定义规范文件可以工作:
cd /home/paul/xc/lib/gcc/mips/4.9.2/
${HOME}/xc/bin/mips-gcc -dumpspecs > specs
添加到规格文件:
*lib:
-lc
注意*lib:
前和-lc
后必须有空行。也许您必须将库名称更改为您的 newlib-c-library 的名称。也许必须添加的不仅仅是 -lc
,例如我的 Linux 上的 *lib:
部分看起来更复杂。
更新:默认库的内置规范lib
在此处配置:
在文件 gcc-4.9.2/gcc/gcc.c
行 527-530:
/* config.h can define LIB_SPEC to override the default libraries. */
#ifndef LIB_SPEC
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#endif
在文件 gcc-4.9.2/gcc/config/mips/elf.h
第 40-42 行中:
/* Leave the linker script to choose the appropriate libraries. */
#undef LIB_SPEC
#define LIB_SPEC ""
也许 gcc.c
中的默认值 LIB_SPEC
通过注释掉 elf.h
中的第 40-42 行对你有用。
也许您需要编辑 elf.h
并将空的 LIB_SPEC
替换为 "-lc"
或类似的内容。
更新:当您配置 gcc
时,您给了 --target=mips
。在 gcc-4.9.2\gcc\config.gcc
中还有其他更具体的 mips-targets,例如 mips*-*-linux*
,也许选择合适的目标会给出正确的 LIB_SPEC
并且 linking 将会成功。
更新:大端Linux 目标:mips-unknown-linux-gnu
小端Linux 目标:mipsel-unknown-linux-gnu
source
更新:使用您的构建脚本,我能够link您的示例程序并进行以下修改:
在你的 config.sh
:
export ISL_VERSION="0.12.2"
在文件 gcc-4.9.2/gcc/config/mips/elf.h
第 40-42 行中:
/* Leave the linker script to choose the appropriate libraries. */
#undef LIB_SPEC
#define LIB_SPEC "-lc -lcfe -lc"
如果您不想在 elf.h
中进行修改,则必须在调用 mips-gcc
时提供库。
更新:
newlib doesn't work at all, GCC fails in the second stage with an error about not being able to find crti.o etc.
奇怪,使用您的构建脚本 crti.o
已创建:
[osboxes@osboxes 4.9.2]$ pwd
/home/osboxes/xc/lib/gcc/mips/4.9.2
[osboxes@osboxes 4.9.2]$ ll
total 6240
-rw-r--r--. 1 osboxes osboxes 3248 May 16 19:49 crtbegin.o
-rw-r--r--. 1 osboxes osboxes 1924 May 16 19:49 crtend.o
-rw-r--r--. 1 osboxes osboxes 1040 May 16 19:49 crti.o
-rw-r--r--. 1 osboxes osboxes 1056 May 16 19:49 crtn.o
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 include
drwxrwxr-x. 2 osboxes osboxes 4096 May 16 19:45 include-fixed
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 install-tools
-rw-r--r--. 1 osboxes osboxes 6289352 May 16 19:49 libgcc.a
-rw-r--r--. 1 osboxes osboxes 56844 May 16 19:49 libgcov.a
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 plugin
-rw-rw-r--. 1 osboxes osboxes 6215 May 18 18:45 specs
printf()
已在 libc
、
中实施
请检查你的c lib,比如glibc
,哦,你的是newlib
。
- 试试@4566976 的方法
- 使用
readelf -s
检查 printf
部分是否存在于 libc.so
libc.a
(我不确定newlib中的lib文件名,我的是glibc)
尝试在命令行上链接库:
${HOME}/xc/bin/mips-gcc -v hello.c -lib
包括标准库(lib 和 io)header 默认链接实现(libc.so 或 .a)。但是,您使用的是 'user-defined' 实现,可能未链接正确的实现。
我建议在命令行上进行显式链接。我不确定语法。
编辑:
或者更好 仍然,使用 makefile 通过以下行进行编译,并在 INCLUDES 占位符中指定其他包含目录:
CC = gcc
CXX = g++
INCLUDES =
CFLAGS = -g -Wall $(INCLUDES)
CXXFLAGS = -g -Wall $(INCLUDES)
LDFLAGS = -g
hello: hello.o newlib.o
hello.o: hello.c newlib.h
newlib.o: newlib.c newlib.h
newlib.h
是您将包含在 newlib.c
(implementation/definition) 源文件(声明函数)和 hello.c
中的 header 文件。它的命名可能与 stdio.h
不同。
看看这个,它可能有帮助:
Why do you have to link the math library in C?
还有这个:
最方便的方法是使用 putchar 代替 printf。可能您必须更改一些代码,或者您可能必须添加 macros/functions 可能 运行 像 printf.
我正在尝试使用针对 mips
:
#include <stdio.h>
int main()
{
int x = 5;
printf("x = %d\n", x);
}
x
变量用于阻止 GCC 将 printf
更改为 puts
,对于简单的以换行符结尾的字符串,它似乎会自动执行此操作。
我在 ${HOME}/xc
下构建了一个交叉编译器,并使用以下命令执行它:
${HOME}/xc/bin/mips-gcc -v hello.c
但是,我收到以下错误:
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status
我假设这是链接器的问题,因为如果在搜索路径上找不到例如 stdio.h
,我预计该过程会更早失败。我可以编译一个更简单的程序,它只是 returns 零,所以并不是整个工具链都坏了,大概只是标准库链接(我使用的是 newlib 2.2.0-1)。
无论我运行 Linux (Ubuntu 14.10) 还是 Cygwin (Windows 8).[=21] 下的交叉编译器,我都会得到同样的错误。 =]
GCC 的完整输出是:
Using built-in specs.
COLLECT_GCC=/home/paul/xc/bin/mips-gcc
COLLECT_LTO_WRAPPER=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper
Target: mips
Configured with: /home/paul/xc/mips/tmp/gcc-4.9.2/configure --prefix=/home/paul/xc --target=mips --enable-languages=c --with-newlib --without-isl --without-cloogs --disable-threads --disable-libssp --disable-libgomp --disable-libmudflap
Thread model: single
gcc version 4.9.2 (GCC)
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/libexec/gcc/mips/4.9.2/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -auxbase hello -version -o /tmp/ccCpAajQ.s
GNU C (GCC) version 4.9.2 (mips)
compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/sys-include"
#include "..." search starts here:
#include <...> search starts here:
/home/paul/xc/lib/gcc/mips/4.9.2/include
/home/paul/xc/lib/gcc/mips/4.9.2/include-fixed
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/include
End of search list.
GNU C (GCC) version 4.9.2 (mips)
compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: cffaaedf0b24662e67a5d97387fc5b17
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/as -EB -O1 -no-mdebug -mabi=32 -o /tmp/ccW5mHJu.o /tmp/ccCpAajQ.s
COMPILER_PATH=/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/
LIBRARY_PATH=/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib/
COLLECT_GCC_OPTIONS='-v'
/home/paul/xc/libexec/gcc/mips/4.9.2/collect2 -plugin /home/paul/xc/libexec/gcc/mips/4.9.2/liblto_plugin.so -plugin-opt=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper -plugin-opt=-fresolution=/tmp/cc8TAJb9.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc -EB /home/paul/xc/lib/gcc/mips/4.9.2/crti.o /home/paul/xc/lib/gcc/mips/4.9.2/crtbegin.o -L/home/paul/xc/lib/gcc/mips/4.9.2 -L/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib /tmp/ccW5mHJu.o -lgcc -lgcc /home/paul/xc/lib/gcc/mips/4.9.2/crtend.o /home/paul/xc/lib/gcc/mips/4.9.2/crtn.o
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400050
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status
我正在使用的构建脚本在这里(我是根据六个教程编写的,这些教程都建议略有不同):
https://github.com/UoMCS/mips-cross-compile
基本上它执行以下步骤:
- 构建 binutils。
- 构建 GCC(第 1 阶段)。
- 构建新库。
- 构建 GCC(第 2 阶段)。
我知道还有其他工具,例如 crosstool-ng 和 builtroot,但是我正在构建这个工具链的人想要在启动构建过程之前编辑 binutils 的部分,并且工具链也有在 Cygwin 下工作(crosstool-ng 不会因为各种原因,包括区分大小写的文件路径)。
我认为这可能是显而易见的事情,但我已经弄乱了一个星期,看不出它会是什么。任何帮助将不胜感激!
有必要构建库以配合您的交叉编译器。特别是,您需要具有 cross-compiled 版本的 glibc 或标准库的其他一些实现,才能获得 printf()
.
查看 this link 中的示例,了解您需要考虑的事项类型,以获得您需要的所有内容 - cross-compiler、headers 和库.
自定义规范文件可以工作:
cd /home/paul/xc/lib/gcc/mips/4.9.2/
${HOME}/xc/bin/mips-gcc -dumpspecs > specs
添加到规格文件:
*lib:
-lc
注意*lib:
前和-lc
后必须有空行。也许您必须将库名称更改为您的 newlib-c-library 的名称。也许必须添加的不仅仅是 -lc
,例如我的 Linux 上的 *lib:
部分看起来更复杂。
更新:默认库的内置规范
lib
在此处配置:
在文件 gcc-4.9.2/gcc/gcc.c
行 527-530:
/* config.h can define LIB_SPEC to override the default libraries. */
#ifndef LIB_SPEC
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#endif
在文件 gcc-4.9.2/gcc/config/mips/elf.h
第 40-42 行中:
/* Leave the linker script to choose the appropriate libraries. */
#undef LIB_SPEC
#define LIB_SPEC ""
也许 gcc.c
中的默认值 LIB_SPEC
通过注释掉 elf.h
中的第 40-42 行对你有用。
也许您需要编辑 elf.h
并将空的 LIB_SPEC
替换为 "-lc"
或类似的内容。
更新:当您配置
gcc
时,您给了 --target=mips
。在 gcc-4.9.2\gcc\config.gcc
中还有其他更具体的 mips-targets,例如 mips*-*-linux*
,也许选择合适的目标会给出正确的 LIB_SPEC
并且 linking 将会成功。
更新:大端Linux 目标:
mips-unknown-linux-gnu
小端Linux 目标:mipsel-unknown-linux-gnu
source
更新:使用您的构建脚本,我能够link您的示例程序并进行以下修改:
在你的 config.sh
:
export ISL_VERSION="0.12.2"
在文件 gcc-4.9.2/gcc/config/mips/elf.h
第 40-42 行中:
/* Leave the linker script to choose the appropriate libraries. */
#undef LIB_SPEC
#define LIB_SPEC "-lc -lcfe -lc"
如果您不想在 elf.h
中进行修改,则必须在调用 mips-gcc
时提供库。
更新:
newlib doesn't work at all, GCC fails in the second stage with an error about not being able to find crti.o etc.
奇怪,使用您的构建脚本 crti.o
已创建:
[osboxes@osboxes 4.9.2]$ pwd
/home/osboxes/xc/lib/gcc/mips/4.9.2
[osboxes@osboxes 4.9.2]$ ll
total 6240
-rw-r--r--. 1 osboxes osboxes 3248 May 16 19:49 crtbegin.o
-rw-r--r--. 1 osboxes osboxes 1924 May 16 19:49 crtend.o
-rw-r--r--. 1 osboxes osboxes 1040 May 16 19:49 crti.o
-rw-r--r--. 1 osboxes osboxes 1056 May 16 19:49 crtn.o
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 include
drwxrwxr-x. 2 osboxes osboxes 4096 May 16 19:45 include-fixed
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 install-tools
-rw-r--r--. 1 osboxes osboxes 6289352 May 16 19:49 libgcc.a
-rw-r--r--. 1 osboxes osboxes 56844 May 16 19:49 libgcov.a
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 plugin
-rw-rw-r--. 1 osboxes osboxes 6215 May 18 18:45 specs
printf()
已在 libc
、
请检查你的c lib,比如glibc
,哦,你的是newlib
。
- 试试@4566976 的方法
- 使用
readelf -s
检查printf
部分是否存在于libc.so
libc.a
(我不确定newlib中的lib文件名,我的是glibc)
尝试在命令行上链接库:
${HOME}/xc/bin/mips-gcc -v hello.c -lib
包括标准库(lib 和 io)header 默认链接实现(libc.so 或 .a)。但是,您使用的是 'user-defined' 实现,可能未链接正确的实现。
我建议在命令行上进行显式链接。我不确定语法。
编辑: 或者更好 仍然,使用 makefile 通过以下行进行编译,并在 INCLUDES 占位符中指定其他包含目录:
CC = gcc
CXX = g++
INCLUDES =
CFLAGS = -g -Wall $(INCLUDES)
CXXFLAGS = -g -Wall $(INCLUDES)
LDFLAGS = -g
hello: hello.o newlib.o
hello.o: hello.c newlib.h
newlib.o: newlib.c newlib.h
newlib.h
是您将包含在 newlib.c
(implementation/definition) 源文件(声明函数)和 hello.c
中的 header 文件。它的命名可能与 stdio.h
不同。
看看这个,它可能有帮助:
Why do you have to link the math library in C?
还有这个:
最方便的方法是使用 putchar 代替 printf。可能您必须更改一些代码,或者您可能必须添加 macros/functions 可能 运行 像 printf.