嵌入式linux开发-交叉编译的一些tips(Embedded Linux Development – some tips of cross compilation)

嵌入式linux开发-交叉编译的一些tips

时间:20201013,版本:V0.1

1.交叉编译工具链的组成

交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc三个部分组成。有时出于减小 libc 库大小的考虑,也可以用别的 c 库来代替 glibc,例如 uClibc和 newlib。

2.交叉编译工具的获取

(1)可以去下别人厂商提供的或者别人制作好的。

(2)交叉编译工具的制作可以参考这个文章:How to Build a GCC Cross-Compiler

https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/

以及《嵌入式linux系统开发教程 第二版》(图6-1),过程说的很清楚。制作过程比较繁琐,主要是因为为了生成完整版的gcc,需要先编译一个辅助版的不依赖glibc的编译器,再用辅助gcc编译libc,再生成完整的gcc。

(3)从头做一个太麻烦,可以使用工具。我们这里采用buildroot生成的。Buildroot使用见本站其文章。

3.交叉编译链工具的命名规则

交叉编译知识解析(二) —— 交叉编译器的名字的命名规则

https://blog.csdn.net/zqixiao_09/article/details/51823165

https://www.crifan.com/files/doc/docbook/cross_compile/release/html/cross_compile.html#crosscompiler_naming_rule

4.交叉编译器引用头文件的位置

交叉编译器默认引用的.h文件和lib文件的位置,可以使用如下的命令查看:

(这里的mipsel-linux-gcc是使用buildroot生成的。)

./mipsel-linux-gcc -print-search-dirs

打印出搜索路径。一堆挤在一起的路径,很难看。

网上大家貌似更喜欢另一个命令:

$  echo ‘main(){}’ | ./mipsel-linux-gcc -E -v -x c –

参数-E:

只进行预处理步骤,这个不生成文件, 需要把它重定向到一个输出文件里面。

参数-v:

使用 gcc -v 可以查看默认开启的选项。编译这个工具时所使用的configure 参数配置。

参数 – (只有一个短线):

这个参数需要特殊说明一下。短线的意思是 Specify input file as stdin, 在这里就是从管道接收输入了。-x c 的意思是以c语言来编译接收的文件。因为接收的是字符流,没有文件名,所指告知gcc是c语言。Gcc默认也是c。

命令输出的结果中会包含搜索路径,并说明这些配置是记录在编译器的 built-in specs。

我的电脑上,路径是:

#include <…> search starts here:

/home/jack/worktable/buildroot/output/host/lib/gcc/mipsel-buildroot-linux-uclibc/8.4.0/include

/home/jack/worktable/buildroot/output/host/lib/gcc/mipsel-buildroot-linux-uclibc/8.4.0/include-fixed

/home/jack/worktable/buildroot/output/host/mipsel-buildroot-linux-uclibc/sysroot/usr/include

End of search list.

可以看到,交叉编译工具的搜索目录一般就在安装目录了。

5.源码包交叉编译的一般过程(configure的常用参数的含义)

源码包和普通的linux程序的编译差不多,configure、make、make install。

这里需要注意的是参数和环境变量。

configure是autotools生成的配置脚本,用于生成makefile。

./configure –help 查看相关的参数。

重要的参数有:

–prefix

安装路径前缀,指使用make install 后,是指生成的可执行文件安装在哪个目录,这个目录需要根据实际情况作选择。如果该目录不存在,会自动创建。

例如:        

./configure  –prefix=$home/work/    

–build

执行代码编译的主机,正常的话就是你的主机系统。这个参数一般由config.guess来猜就可以。当然自己指定也可以。

–host

编译出来的二进制程序所运行于的主机,因为绝大多数是本机编译,本机执行,所以这个值就等于build。只有交叉编译的时候(也就是本机编译,其他系统机器执行)才会build和host不同。用host指定运行平台。

–target

被编译的程序生成的程序将运行于的平台。这个选项只有在建立交叉编译环境(制作交叉编译工具)的时候用到,正常编译和交叉编译都不会用到。他用build主机上的编译器,编译一个新的编译工具(binutils, gcc,gdb等),这个新的编译器运行于host,它(新的编译器)编译出来的其他程序将运行在target系统上。

在前文中生成的mips平台的工具,执行:

$ mipsel-linux-gcc -v

输出中就会显示生成此工具时的configure参数:

Configured with: ./configure  ..–target=mipsel-buildroot-linux-uclibc ..

举个栗子:

./configure –host=arm-unknown-linux-gnueabi –target=arm-unknown-linux-gnueabi –build=”i686-pc-linux” –prefix=$DIST/libnet

问题是,到哪里精确的获取这几个平台值呢?交叉编译的时候我一般用编译工具的名称去掉工具名称。例如工具是mips-robotech-linux-gcc,那么–host就设置成:

–host=mips-robotech-linux

这里其实最重要的是–host参数了,configure使用–host参数寻找交叉编译工具。前提是在path环境变量里设置了交叉编译工具的路径。编译器也可以用环境变量CC指定。

–with-sysroot

https://answerywj.com/2019/04/26/what-is-sysroot/

重要的环境变量:

CC

指定编译器,默认为gcc、cc或者HOST-gcc

例如:

./configure  CC=/home/path/mips-linux-gcc

或者使用export指定

$export CC=/home/path/mips-linux-gcc

两种写法有什么区别呢?使用export应该是正规的方式,有的configure脚本可能不支持第一种方式。

所以,指定编译器既可以通过–host去关联也可以通过CC指定,怎样更合适呢?一般./configure –help里会告诉你,环境变量优先级更高,能够覆盖掉./configure脚本自己的推断。

CFLAGS、 CPPFLAGS

C compiler flags,最常用是指定(非标准默认的)头文件的路径。以及其他的编译标志。

例如:

export CFLAGS=”-I$WDIR/arm-unknown-linux-gnueabi/include  -mhard-float  -mfpu=vfpv3-d16″

LDFLAGS

linker flags, 例如.指定库文件的路径 -L<lib dir>, if you have libraries in a nonstandard directory <lib dir>。

例如:

export LDFLAGS=”-L$WDIR/arm-unknown-linux-gnueabi/lib”

LIBS

libraries to pass to the linker, e.g. -l<library>。

-l后面紧接着库名,链接时在搜索目录中寻找库文件,搜索名为libxxx.a 或 libxxx.so

LDFLAGS告诉链接器从哪里寻找库文件,LIBS告诉链接器要链接哪些库文件。

参考:

https://blog.csdn.net/xhoufei2010/article/details/82768995

https://unix.stackexchange.com/questions/149359/what-is-the-correct-syntax-to-add-cflags-and-ldflags-to-configure

https://blog.csdn.net/zqixiao_09/article/details/51823165

https://www.crifan.com/files/doc/docbook/cross_compile/release/html/cross_compile.html#crosscompiler_naming_rule

————————

Embedded Linux Development – some tips of cross compilation

Time: 20201013, version: v0 one

1. Composition of cross compilation tool chain

Cross compilation tool chain is a comprehensive development environment composed of compiler, connector and interpreter. Cross compilation tool chain is mainly composed of binutils, GCC and glibc. Sometimes, in order to reduce the size of libc library, other C libraries can be used to replace glibc, such as uclibc and newlib.

2. Acquisition of cross compilation tools

(1) You can go to the products provided by other manufacturers or made by others.

(2) For the production of cross compiler tool, please refer to this article: how to build a GCC cross compiler

https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/

And the second edition of embedded Linux system development tutorial (Figure 6-1), the process is very clear. The production process is cumbersome, mainly because in order to generate a complete version of GCC, you need to compile an auxiliary version of the compiler that does not rely on glibc, then compile libc with auxiliary GCC, and then generate a complete GCC.

(3) It’s too troublesome to make one from scratch. You can use tools. Here we use buildroot to generate. See the article on this website for the use of builderoot.

3. Naming rules of cross compilation chain tools

Analysis of cross compiler knowledge (II) — naming rules of cross compiler names

https://blog.csdn.net/zqixiao_09/article/details/51823165

https://www.crifan.com/files/doc/docbook/cross_compile/release/html/cross_compile.html#crosscompiler_naming_rule

4. Location of cross compiler reference header file

The cross compiler references by default The location of H file and lib file can be viewed with the following command:

(mipsel Linux GCC here is generated using builderoot.)

./mipsel-linux-gcc -print-search-dirs

Print out the search path. A bunch of crowded paths are ugly.

People on the Internet seem to prefer another command:

$  echo ‘main(){}’ | ./mipsel-linux-gcc -E -v -x c –

Parameter – E:

Only the preprocessing steps are performed. This does not generate a file. You need to redirect it to an output file.

Parameter -v:

Use GCC – V to view the options that are turned on by default. The configuration parameter used when compiling this tool.

Parameter – (only one short line):

This parameter needs special description. The short line means specify input file as stdin, where the input is received from the pipeline- X C means to compile the received file in C language. Because the received character stream has no file name, it tells GCC that it is C language. GCC is also C by default.

The result of the command output will include the search path and indicate that these configurations are recorded in the build in specs of the compiler.

On my computer, the path is:

#include <…> search starts here:

/home/jack/worktable/buildroot/output/host/lib/gcc/mipsel-buildroot-linux-uclibc/8.4.0/include

/home/jack/worktable/buildroot/output/host/lib/gcc/mipsel-buildroot-linux-uclibc/8.4.0/include-fixed

/home/jack/worktable/buildroot/output/host/mipsel-buildroot-linux-uclibc/sysroot/usr/include

End of search list.

You can see that the search directory of the cross compilation tool is generally in the installation directory.

5. General process of cross compilation of source package (meaning of common parameters of configure)

The source package is similar to the compilation of ordinary Linux programs, such as configure, make and make install.

Here we need to pay attention to the parameters and environment variables.

Configure is a configuration script generated by Autotools to generate makefiles.

. / configure — help view relevant parameters.

< strong > important parameters are: < / strong >

–prefix

Installation path prefix refers to the directory where the generated executable files are installed after using make install. This directory needs to be selected according to the actual situation. If the directory does not exist, it will be created automatically.

For example:

./configure  –prefix=$home/work/    

–build

The host that executes code compilation is normally your host system. This parameter is generally defined by config Guess. Of course, you can specify it yourself.

–host

The compiled binary program runs on the host, because most of it is compiled and executed locally, so this value is equal to build. Build is different from host only when cross compiling (that is, native compilation and execution by other system machines). Specify the running platform with host.

–target

The program generated by the compiled program will run on the platform. This option is only used when establishing a cross compilation environment (making a cross compilation tool). Normal compilation and cross compilation will not be used. He compiles a new compiler tool (binutils, GCC, GDB, etc.) with the compiler on the build host. The new compiler runs on the host, and other programs compiled by it (the new compiler) will run on the target system.

The MIPs platform tool generated in the previous article executes:

$ mipsel-linux-gcc -v

The configure parameter when the tool was generated will be displayed in the output:

Configured with: ./configure  ..–target=mipsel-buildroot-linux-uclibc ..

Take chestnuts for example:

./configure –host=arm-unknown-linux-gnueabi –target=arm-unknown-linux-gnueabi –build=”i686-pc-linux” –prefix=$DIST/libnet

The question is, where can we accurately obtain these platform values? When cross compiling, I usually use the name of the compiling tool to remove the tool name. For example, if the tool is MIPS robot Linux GCC, then — host is set to:

–host=mips-robotech-linux

In fact, the most important thing here is the — host parameter. Configure uses the — host parameter to find a cross compilation tool. The premise is that the path of the cross compilation tool is set in the path environment variable. The compiler can also be specified with the environment variable CC.

–with-sysroot

https://answerywj.com/2019/04/26/what-is-sysroot/

< strong > important environmental variables: < / strong >

CC

Specifies the compiler, which defaults to GCC, CC, or host GCC

For example:

./configure  CC=/home/path/mips-linux-gcc

Or use export to specify

$export CC=/home/path/mips-linux-gcc

What is the difference between the two writing methods? Export should be used in a normal way. Some configure scripts may not support the first way.

Therefore, the specified compiler can be associated through — host or specified through CC. How is it more appropriate? Average/ Configure — help will tell you that < strong > environment variables have higher priority and can be overwritten/ The configure script its own inference

CFLAGS、 CPPFLAGS

C compiler flags, which is most commonly used to specify the path of the (non-standard default) header file. And other compilation flags.

< strong > for example: < / strong >

export CFLAGS=”-I$WDIR/arm-unknown-linux-gnueabi/include  -mhard-float  -mfpu=vfpv3-d16″

LDFLAGS

linker flags, 例如.指定库文件的路径 -L<lib dir>, if you have libraries in a nonstandard directory <lib dir>。

< strong > for example: < / strong >

export LDFLAGS=”-L$WDIR/arm-unknown-linux-gnueabi/lib”

LIBS

libraries to pass to the linker, e.g. -l<library>。

-L followed by the library name. When linking, look for the library file in the search directory, and the search name is libxxx A or libxxx so

Ldflags tells the linker where to find library files, and LIBS tells the linker which library files to link.

reference resources:

https://blog.csdn.net/xhoufei2010/article/details/82768995

https://unix.stackexchange.com/questions/149359/what-is-the-correct-syntax-to-add-cflags-and-ldflags-to-configure

https://blog.csdn.net/zqixiao_09/article/details/51823165

https://www.crifan.com/files/doc/docbook/cross_compile/release/html/cross_compile.html#crosscompiler_naming_rule