项目中使用python做算法处理。为了保护源代码,因此编译成so后执行。一开始代码只运行在x86平台,因此编译的时候,直接调用python3 setup.py build_ext --inplace就可以了。但是这两天需要将算法移植到arm平台,但是编译环节还是在x86的电脑上的话,直接调用上面这条语句就没有成功。解决这个问题,有两种办法:
1. 将编译放到arm的硬件中去做。
这个肯定没有问题,事实上,在我没有找到交叉编译的方法之前,就是这么做的。但是这种方法的话,后续做Jenkins发布的时候,就需要新增加一个arm环境的机器,还得装软件,太麻烦。
2. 交叉编译,编译在x86电脑上搞
与是观察python3 setup.py build_ext --inplace的具体操作流程。这里参考了这位大神的文章(很详细)
cython代码编译和setup.py文件编写_cython setup_damonlearning的博客-CSDN博客
再观察打印的流程,发现实际上,整个过程包含3步:
1. 生成c文件。这个用cython ***.pyd就可以。
2. 利用gcc,和生成的c文件,去编译生成中间,就是.o文件
3. 利用gcc进行链接,生成so文件。
上述这3个步骤,第一步,与架构无关,我比较了一下,在arm环境下生成的c和在x86下生成的c,一模一样。后面两步,就和最终so运行的环境相关了。如果在x86下编译,就用x86下的gcc,反之,用arm下的gcc。说到这里,其实经常搞交叉编译的同学,就已经清楚怎么做后续的操作了。
不过,有2个地方比较搞,
1. 就是我的x86电脑是64位的,然后我的arm编译是32位的(arm-linux-gnueabihf-gcc),结果编译的时候,就横竖不行,报错是硬件不匹配。没办法,只能将编译器改为64位的编译器,幸亏实际的硬件也是64位的。
2. 编译过程指定的头文件的版本
我的x86电脑安装的python是3.8的,arm中实际使用的python是3.7的。然后两者的头文件就有差异。导致某些包,在3.8中的存在一个函数,但是在3.7的环境中,该函数不存在,从而发生故障找不到符号。解决办法就是执行第二步的时候,-I指定include头文件夹时,将arm环境中的python头文件夹,拷贝一份到x86电脑上,然后gcc -I该文件夹。
经过这样的操作,最后在x86下编译出来的so文件,在arm下也可以使用