使用Makefile编译不同平台目标文件方法
一、源码autoconf、automake生成软件包
1、基础概念
二、automake步骤流程
①autoscan命令生成autoscan.log和configure.scan
autoscan是用来扫描源代码目录生成configure.scan文件的。autoscan可以用目录名做为参数,但如果你不使用参数的话,那么autoscan将认为使用的是当前目录。autoscan将扫描你所指定目录中的源文件,并创建configure.scan文件。
②重命名configure.scan为configure.in,然后配置configure.in
configure.scan包含了系统配置的基本选项,里面都是一些宏定义。需要将它改名为configure.in
configure.in文件的内容是一些宏,这些宏经过autoconf 处理后会变成检查系统特性、环境变量、软件必须的参数的shell脚本。configure.in文件中的宏的顺序并没有规定,但是必须在所有宏的最前面和最后面分别加上AC_INIT宏和AC_OUTPUT宏。
③aclocal命令生成aclcal.m4
aclocal是一个perl 脚本程序。aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”。
④编写acconfig.h头文件
⑤autoheader命令生成config.h.in
⑥编写Makefile.am
Makefile.am是用来生成Makefile.in的,需要手工书写。Makefile.am中定义了一些内容: AUTOMAKE_OPTIONS 这个是automake的选项。在执行automake时,它会检查目录下是否存在标准GNU软件包中应具备的各种文件,例如AUTHORS、ChangeLog、NEWS等文件。将其设置成foreign时,automake会改用一般软件包的标准来检查。 bin_PROGRAMS 这个是指定所要产生的可执行文件的文件名。如果要产生多个可执行文件,那么在各个名字间用空格隔开。 helloworld_SOURCES 这个是指定产生“helloworld”时所需要的源代码。如果它用到了多个源文件,使用空格符号将它们隔开。比如需要helloworld.h,helloworld.c那么请写成helloworld_SOURCES= helloworld.h helloworld.c。 如果在bin_PROGRAMS定义了多个可执行文件,则对应每个可执行文件都要定义相对的filename_SOURCES。
⑦在源文件子目录中也编写相应的Makefile.am
⑧执行automake -a 或者automake –add-missing命令产生Makefile.in
选项--add-missing的定义是“add missing standard files to package”,它会让automake加入一个标准的软件包所必须的一些文件。 用automake产生出来的Makefile.in文件是符合GNU Makefile惯例的,接下来只要执行configure这个shell 脚本就可以产生合适的 Makefile 文件了。
⑨执行autoconf生成最终的configure
autoconf是用来产生configure文件的。configure是一个脚本,它能设置源程序来适应各种不同的操作系统平台,并且根据不同的系统来产生合适的Makefile,从而可以使源代码能在不同的操作系统平台上被编译出来。
⑩运行./configure
执行make ,根据Makefile编译源代码,连接,生成目标文件,可执行文件。
make clean
清除上次的make命令所产生的object文件(后缀为“.o”的文件)及可执行文件。
make install
将编译成功的可执行文件安装到系统目录中,一般为/usr/local/bin目录。
make dist
产生发布软件包文件(即distribution package)。这个命令将会将可执行文件及相关文件打包成一个tar.gz压缩的文件用来作为发布软件的软件包。
make distcheck
生成发布软件包并对其进行测试检查,以确定发布包的正确性。这个操作将自动把压缩包文件解开,然后执行configure命令,并且执行make,来确认编译不出现错误,最后提示你软件包已经准备好,可以发布了。
make distclean
类似make clean,但同时也将configure生成的文件全部删除掉,包括Makefile。
三、修改Makefile(参数传递)
编译的可执行文件有时候需要在PC机(x86)的平台上运行,有时候则需要在A嵌入式平台(arm端)i.mx6的平台上运行,而还有时候则需要在B嵌入式平台(arm端)mini2440的平台上运行,需要能随时进行切换,编译出对应平台所需要的可执行文件。
方法:
①最土的办法自然就是写三份makefile,需要编译某一个平台时,拷贝对应的makefile,然后再make。 效率很低。
②在makefile中,定义三套编译规则,通过输入make x86,以及make imx6,以及make mini2440这样的目标选择命令,来指示编译器选择某一套编译规则并运行 ,导致makefile的文件很冗余,存在多套几乎一模一样的编译规则。
③在makefile中预先使用一个未定义的变量, 这个变量可以在make执行时传递给它。向make命令传递参数,告诉它怎么去解释makefile这个文件。
同一个工程在不同平台上编译时需要修改的Makefile中选项为:
build_triplet = x86_64-unknown-linux-gnu
可通过命令uname -a 查看当前设备平台版本信息 ;--build=编译该软件所使用的平台。 //注:该参数在不指定的情况下将自动尝试猜测目前平台的名称
host_triplet = arm-unknown-linux-gnu
--host=该软件将运行的平台 ; --target=该软件所处理的目标平台
ACLOCAL = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/missing –run aclocal-1.11
AMTAR = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/missing –run tar
AUTOCONF = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/missing –run autoconf
AUTOHEADER = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/missing –run autoheader
AUTOMAKE = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/missing –run automake-1.11
指定一些自动生成的文件路径
CC = arm-hisiv510-linux-gcc
特定交叉编译工具指定 H90板端:arm-hisiv510-linux-gcc
H100板端:aarch64-linux-gnu-gcc
CPP = arm-hisiv510-linux-gcc -E
E参数将对源程序example.c进行预处理,生成example.i文件, 就是将#include,#define等进行文件插入及宏扩展等操作。
MAKEINFO = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/missing –run makeinfo
abs_builddir = /workteam/huangxiang6/data/work/strace-4.6
abs_srcdir = /workteam/huangxiang6/data/work/strace-4.6
abs_top_builddir = /workteam/huangxiang6/data/work/strace-4.6
abs_top_srcdir = /workteam/huangxiang6/data/work/strace-4.6
build = x86_64-unknown-linux-gnu
build_cpu = x86_64
build_os = linux-gnu
host = arm-unknown-linux-gnu
host_alias = arm-linux
host_cpu = arm
host_os = linux-gnu
includedir = /opt/toolchains-BE/hisi/arm-hisiv510-linux/bin/../target/usr/include
install_sh = ${SHELL} /workteam/huangxiang6/data/work/strace-4.6/install-sh
opsys = linux
OS = linux (说明:OS is one of linux , sunos4 , svr4 , or freebsd .)
ARCH = arm (ARCH is i386, m68k , sparc , etc.包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是i386。)
搞不明白的几个问题:
在编译服务器上./configure 后生成的Makefile中的配置 build是X86,host也是X86,将make后的可执行文件strace传到H90板上,出现的错误很好理解:
-sh: ./strace: cannot execute binary file: Exec format error
但是将Makefile修改为arm-hisiv510-linux的环境后运行make报错:
syscall.c:46:21: fatal error: sys/reg.h:没有那个文件或目录
#include
原因:项目中的makefile必须能够正确的定位源文件和依赖文件 ,特殊的预定义变量VPATH用于指示make如何查找文件 ,不同文件夹可作为VPATH的值同时出现,文件夹的名字之间需要使用分隔符进行区分 。
例如:VPATH:=inc src
VPATH:=inc;src
VPATH:=inc:src
VPATH使用场景:当前文件夹找不到需要的文件时 ;
make会在VPATH指定的文件夹中依次搜索文件;
当多个文件夹存在同名文件时,选择第一次搜索到的文件 ;
VPATH只能决定make的搜索路径,无法决定命令的搜索路径 ;
对于特定的编译命令(gcc),需要独立指定编译搜索路径
四、CMake
网上有一种方法CMake 可以编译源代码、制作程序库、产生适配器(wrapper)、还可以用任意的顺序建构执行档。CMake 支持 in-place 建构(二进档和源代码在同一个目录树中)和 out-of-place 建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake 也支持静态与动态程式库的建构。
“CMake”这个名字是“cross platform make”的缩写。虽然名字中含有“make”,但是CMake和Unix上常见的“make”系统是分开的,而且更为高阶。