关于交叉编译01
在64位系统下交叉编译32位库
背景
有时候,会需要我们在原本的64位系统上,编译出32位系统上的库及可执行程序(如果我们不想去下载这个32位系统,或者说因为某些原因下载不到这个系统,就不能说直接简单的把自己的项目拷贝到32位系统上进行编译),那么这时候需要就是需要交叉编译来实现。
一般来说,交叉编译的核心,就是我们的项目依赖的gcc/g++的版本的不同,比如原本我们在64位系统上,系统默认的gcc/g++版本是4.9.0;但是现在我们希望移植到的平台,它的gcc/g++版本是5.3.0;那么我们首先要下载5.3.0版本的gcc/g++。
配置希望移植到的平台的gcc/g++版本
接下来就是用我们指定的gcc/g++版本对我们要移植的项目进行编译,编译程序时需要指定:
使用的gcc(可用户自定义路径名):
/usr/muhan/new/i686-gnu-gcc-5.3.0
使用的g++(可用户自定义路径名):
/usr/muhan/new/i686-linux-gnu-g++
同时需要指定编译时的sysroot为(可用户自定义路径名):
/usr/muhan/new/i686-linux-gnu/sysroot
可以通过以下命令设置
1 | export CC=/usr/muhan/new/i686-gnu-gcc-5.3.0 |
在编译第三方依赖库的过程中,一般有以下五种情况
一、第三方程序里有CMakeLists.txt时(如libcurl)
直接在CMakeLists.txt里增加以下3行
1 | set(CMAKE_CXX_FLAGS “-m32”) |
此时增加“-m32“选项是因为,我们要在64位系统下编译32位的库,所以要指定-m32选项
然后输入mkdir build && cd build & cmake .. & make & sudo make install 即可
二、如果没有CMakeLists.txt,但是有config文件(如openssl)
1 | 1. 输入setarch i386 ./config -m32 –prefix=/usr/muhan/ssl –openssldir=/usr/muhan/ssl -Wl,-rpath,/usr/local/ssl/lib shared |
三、如果没有CMakeLists.txt,也没有config文件,但是有configure文件(如libuuid)
先执行./configure,会生成Makefile文件
然后修改Makefile, 增加m32选项 (参考链接https://blog.csdn.net/u013819292/article/details/53375731讲的非常仔细了)
(1) 替换ld中的选项,/usr/bin/ld -m elf_x86_64修改为/usr/bin/ld -m elf_i386
sed -i ‘s/elf_x86_64/elf_i386/g’ find . -name “Makefile”
(2) 增加m32选项,使用32位gcc
sed -i ‘s/gcc/gcc -m32/g’ find . -name “Makefile”
(3) 修改错误的替换
sed -i ‘s/gcc -m323/gcc -m3/g’ find . -name “Makefile”
然后执行make && sudo make install 即可
四、如果没有CMakeLists.txt,也没有config文件,也没有configure文件,但是有Makefile文件
此时的处理方式和第三种情况一样,只是省了一个执行configure这个步骤来生成Makefile而已,剩下的步骤一样
五、如果没有CMakeLists.txt,也没有config文件,也没有configure文件,也没有Makefile文件,什么编译文件都没有给的情况下
一般来说,这种情况非常少见,第三方库一般都会给出编译文件,如果真的碰上了什么编译文件都不给的,有可能是这个编译方式太简单了,直接用gcc/g++指令即可编译了,不过此时需要注意,要用我们指定的gcc/g++版本去编译!
比如此时使用指令: /usr/muhan/new/i686-gnu-gcc-5.3.0 test.c
来代替原本的: gcc test.c
也可以在这种情况下,自行编写CMakeLists.txt文件等其他编译文件,来编译这个项目,这个可以根据实际情况来自行调整。
交叉编译遇到问题时,排查的方向
1.要注意当前编译的gcc、g++的版本,是不是我们指定的版本
很可能忘记设置了某个编译选项,导致用了系统自带的gcc/g++版本进行编译,而不是我们希望移植到的那个平台的gcc/g++版本进行编译;
2.当前编译的程序,它所依赖的第三方的库,是不是也是同一个交叉编译工具链编译出来的32位的版本
有可能忘记添加了-m32选项,从而导致在64位系统下默认编译出来64位的库,这一点我们可以用file指令或者objdump指令去检查一下我们生成的库文件的信息来进行确认;
也有可能是用的旧的工具链编译出来的32位库,而不是用的交叉编译工具链编译出来的;
3.指定的头文件和库的路径是否正确
如果我们发现,自己链接的库一句确认了是指定的gcc/g++版本编译出来的32位库,确认库的信息是正确的,但是项目中链接这个库的时候还是在报错,那么就需要去检查一下,项目里面设置的查找库的路径是否正确,也许项目现在还在链接系统原本的64位库,而不是我们新编译出来的32位库
总结
在交叉编译的过程中,有时候会遇上一些零零碎碎的小问题,还是要具体情况具体分析,百度or谷歌是一个好习惯,很多问题一些大佬已经给解决了,可以从网上搜到现成的解决方案