mysql交叉编译 cmake_用CMake代替makefile进行跨平台交叉编译

在开始介绍如何使用CMake编译跨平台的静态库以前,先讲讲我在没有使用CMake以前所趟过的坑。由于不少开源的程序,好比png,都是自带编译脚本的。咱们可使用下列脚原本进行编译:html

1linux

2android

3ios

./configure  --prefix=/xxx/xx --enable-static=YESc++

makegit

make installgithub

相信手动在类Unix系统上面编译过开源程序的同窗对上面的命令确定很是熟悉。更悲惨的是,有些开源库是不提供configure配置文件的,只有一个Makefile或者Makefile.gcc。个人体会是,Makefile是一个很复杂的东西,没有必定的积累咱们是看不懂的,更别说去修改它了。而本文的CMake能够更傻瓜更简单地达到咱们的目的,你不须要理会复杂的makefile语法。Just follow me!编程

若是不配置编译器和一些编译、连接参数,这样的操做,最后编译出来的静态库只能在本系统上面被连接使用。好比你在mac上面运行上面的命令,编译出来的静态库就只能给mac程序连接使用。若是在Linux上面运行上述命令,则也只能给Linux上面的程序所连接使用。若是咱们想要在Mac上面编译出ios和android的静态库,就必需要用到交叉编译。windows

要进行交叉编译,通常来讲要指定目标编译平台的编译器,一般是指定一个CC环境变量,根据编译的是c库仍是c++库,要分别指定C_flags和CXX_flag,固然还须要指定c/c++和系统sdk的头文件包含路径。总之,很是之繁琐。xcode

为何要使用CMake

为何咱们不使用autoconf?为何咱们不使用QMake,JAM,ANT呢?具体缘由你们能够参考我在本文最后的参考连接里面的《Mastering CMake》一书的第一章。我本身使用CMake的感觉就是:我原来编写bash,配置configure参数,读各个开源库的INSTALL文件(由于不一样库的configure参数有差异),配置各类编译flag,头文件包含等。最后3天时间,折腾了png和jepg两个库的编译。固然,中间我还写了android和linux的编译脚本。而换用CMake之后,我2天时间编译完了Box2D,spine和Chipmunk的编译。而且配置脚本至关简单,添加新的库,基本上只是拷贝脚本,修改一两个参数便可。有了CMake,编译跨平台静态库和生成跨平台可执行程序So Easy!

编写CMakeLists.txt

编写一个静态库的CMake配置文件过程以下:(这里我以Box2D为例)

一、指定头文件和源文件

1

2

3

4

5

include_directories(

${CMAKE_CURRENT_SOURCE_DIR}

)

file(GLOB_RECURSE box2d_source_files"${CMAKE_CURRENT_SOURCE_DIR}/Box2D/*.cpp")

个人CMakeLists.txt和Box2D的文件结构关系以下图所示:

1a55ff4933ff42995658a3ec2409ebf8.png

这里的${CMAKE_CURRENT_SOURCE_DIR}表示CMakeLists.txt所在的目录。而GLOB_RECURSE能够递归地去搜索Box2D目录下面全部的.cpp文件来参与静态库的编译。而include_directories和file指令,显而易见,它们是用来指定静态库的头文件和实现文件。

注:指定头文件的原则是:能够多引入,但不能缺。交叉编译本质也是编译,所以基本的要求是语法没问题,若是必要的头文件缺乏了天然编译会失败!因此,原则上能够把整个根目录的头文件都引入进去,不过这样虽然省事,可是会致使生成的库文件体积过大,可是会更保险一些,好比:

1

2

3

4

5

include_directories(

"../../../myWindows"

"../../../"#很残暴地引入了整个根目录

"../../../include_windows"

)

二、添加环境变量(可选, added by 编程小翁, 博客园)

1

add_definitions( -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -DENV_UNIX -DBREAK_HANDLER -DUNICODE -D_UNICODE)

若是须要判断平台,能够这么写:

1

2

3

4

IF(APPLE)

add_definitions(-DENV_MACOSX)

FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation )

ENDIF(APPLE)

其中-D_FILE_OFFSET_BITS=64表示定义一个环境变量_FILE_OFFSET_BITS且值为64。添加环境变量用在何时呢?咱们经常能够在一些开源的项目工程代码中看到这样的形式:

1

2

3

4

5

#ifdef _UNICODE

AString name = nameWindowToUnix2(fileName);

#else

const char * name = nameWindowToUnix(fileName);

#endif

以上代码中_UNICODE就是环境变量,那像这种变量该经过何时定义呢?一种是像上面同样经过add_definitions写咱们的编译脚本CMakeLists.txt,另外一种是新建一个.h文件,写在里面而后引用。两种方式彻底等效,我在个人交叉编译工程中实践过。例如,上面的add_definitions能够转化为:

1

2

3

4

5

6

7

#define FILE_OFFSET_BITS    64

#define _LARGEFILE_SOURCE    1

#define _REENTRANT           1

#define ENV_UNIX            1

#define BREAK_HANDLER       1

#define UNICODE             1

#define _UNICODE            1

三、设置库的名字跟类型

1

add_library(Box2D STATIC ${box2d_source_files})

这里add_library表示最终编译为一个库,static表示是静态库,若是想编译动态库,能够修改成shared. 至此,一个静态库的配置就完成了。固然,由于这个库没有包括其它外部的头文件,因此会比较简单。但这也远比本身写一个Makefile要简单N倍,请记住这句话。

以上就是编写一个CMakeLists.txt配置文件的所有必要过程,一些更复杂的配置文件可能会增长一些其余东西,不过以上部分是基本逃不掉的。只要包含以上步骤就能成功交叉编译出目标平台的库文件。下面是一个完整的CMakeLists.txt文件示例(文件名不能改):

710c693ea6df43639a0ca97f.html

710c693ea6df43639a0ca97f.html

1 cmake_minimum_required(VERSION 3.2)

2

3 #一、添加头文件目录,能够多引用,可是不能缺,由于缺了就编译不过

4 include_directories(

5 "../../../myWindows"

6 "../../../"

7 "../../../include_windows"

8 )

9

10 #二、添加环境变量,请结合实际项目要求,不是必须的

11 add_definitions( -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -DENV_UNIX -DBREAK_HANDLER -DUNICODE -D_UNICODE)

12

13 IF(APPLE)

14 add_definitions(-DENV_MACOSX)

15 FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation )

16 ENDIF(APPLE)

17

18 #三、源文件

19 file(GLOB_RECURSE src_files

20 "../../../../C/7zCrc.c"

21 "../../../../C/7zCrcOpt.c"

22 "../../../../C/7zStream.c"

23 "../../../../C/Aes.c"

24 "../../../../C/Alloc.c"

25 "../../../../C/Bra.c"

26 "../../../../C/Bra86.c"

27 )

28

29 #四、设置生成静态库以及名称

30 add_library(myLibName STATIC ${src_files})

31

32 IF(APPLE)

33 TARGET_LINK_LIBRARIES(myLibName ${COREFOUNDATION_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})

34 ELSE(APPLE)

35

36 IF(HAVE_PTHREADS)

37 TARGET_LINK_LIBRARIES(myLibName ${CMAKE_THREAD_LIBS_INIT})

38 ENDIF(HAVE_PTHREADS)

39 ENDIF(APPLE)

710c693ea6df43639a0ca97f.html

编译iOS静态库

咱们有了配置完毕的CMakeLists.txt文件,但不要觉得这样就万事大吉了!不知道你发现了没,上述内容并不涉及目标平台的相关信息,所以编译出来的库只能在运行该配置文件的当前系统上使用。如今须要配合接下来的操做才能最终达到目的。

编译iOS库,通常要先使用cmake指令生成xcode工程,再用xcode工程运行编译出静态库(也就是工程的product是静态库,而不是**.app)。插播一段MAC系统下cmake安装与使用方法介绍:

710c693ea6df43639a0ca97f.html

MAC默认是没有cmake指令的。要测试你的MAC是否已经装过cmake,能够这样作:打开Terminal,输入cmake --version,若是已经安装,则会显示具体的版本号;不然就是没安装或者没配置成功。

一、从这里http://mac.softpedia.com/get/Development/Compilers/CMake.shtml下载cmake.app,而后安装到默认位置;

二、将cmake.app与terminal相连接。打开terminal,输入如下命令:export PATH=/Applications/CMake.app/Contents/bin:$PATH

三、配置成功。此次再输入cmake就有效了。不过,以上连接只对本terminal窗口有效,一旦关闭或者其余新建的terminal一样要再作一遍!

710c693ea6df43639a0ca97f.html

回到iOS交叉编译上来,使用cmake命令生成xcode工程能够这么作:

1

cmake -GXcode .

经过该命令能够生成一个project.xcodeproject工程。可是,上述命令并不包含任何关于iOS的信息,所以该xcode工程只能用于MAC库的编译。不过咱们能够借助ios-cmake开源项目。 下载iOS_64.cmake这个toolchain文件,而后使用下列命令来生成ios工程:

1

cmake -DCMAKE_TOOLCHAIN_FILE=iOS_64.cmake  -DCMAKE_IOS_DEVELOPER_ROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/ -DCMAKE_IOS_SDK_ROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/  -GXcode .

这个过程很容易出错,出错了不要慌,根据terminal的提示大胆地更改iOS_64.cmake(记得提早备份)。我也是一步步调试过来的,如下的iOS_64.cmake是我本身更改后的,SDK是iOS8.3,Xcode6.3,若是环境跟我同样的话理论上说能够直接使用个人.cmake:

710c693ea6df43639a0ca97f.html 个人iOS_64.cmake

若是上面的操做都没错,就会顺利生成一个project.xcodeproject文件,打开后记得作下面几件事情:

一、设置Product->Scheme->Edit Scheme为release模式

二、其余设置如图:

8ec7288b97661504b1201f22502c9914.png

3aa8efd8dc3f684cfc29ce4199362659.png

设置完毕后,点击运行,就能生成.a静态库了。这时候,你可使用下面的命令测试一下生成的静态库是否真的是iOS下的库。

打开terminal,cd到.a所在目录,假设静态库名字为libMyLib.a,输入: lipo -info libMyLib.a ,若是显示 Architectures in the fat file: lib7z_C++_938.a are: armv7 arm64  就说明操做无误了。而后,尽情享用你的静态库吧!

编译linux静态库(含64位和32位)

编译linux的静态库是很是简单的,只须要安装好cmake之后,运行如下命令便可:

1

2

cmake .

make

注意,若是是64位的系统,那么这样只能生成64位的静态库。想要编译出32位的静态库,则必需要先安装32位系统的编译工具链。

1

2

3

4

sudo apt-get install libx32gcc-4.8-dev

sudo apt-get install libc6-dev-i386

sudo apt-get install lib32stdc++6

sudo apt-get install g++-multilib

而后,只须要指定cxx_flags为-m32便可,对应的CMake的写法为:

1

set(CMAKE_CXX_FLAGS"${CMAKE_CXX_FLAGS} -m32")

最后用cmake生成makefile并make便可生成32位的静态库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值