转载自 http://zhixinliu.com/2016/02/01/2016-02-01-cmake-cross-compile/

CMake交叉编译

CMake的使用,以及如何将一个项目移植到Android。

CMake的用法

先让我们简单学习回顾一下cmake的基本知识:

基本流程

以linux平台为例,使用 CMake 生成 Makefile 并编译的流程如下:

编写 CMake 配置文件 CMakeLists.txt 。
执行命令 cmake Path-to-Cmakelist/CMakeLists.txt 生成 Makefile。
使用 make 命令进行编译。
语法
CMakeLists文件可以包含comments,commands,以及 空行。
注释以#开头
command:包含命令名字,括号,用空格分开的参数 comand(arg1 arg2 …)
所有的空白行都会被忽略。

基本的命令
project
project:用来声明项目的名字,也可以指定项目的开发语言
project(projectname [cxx] [c] [java] [none])
如果没有指定语言,那么CMake默认指定为c和c++
在每一个project出现的CMakeLists.txt,CMake都会创建一个top level的IDE project文件。这个project会包括出现在该CMakeLists.txt中的所有的targets,以及它所有的subdirecotry, 用add_subdirectory命令来指定。

set
set命令用来定义或者修改变量或者lists
和set对应的remove命令

add_executable / add_library
用来定义what executable/libs to build, 并且指定source 文件。

另外一些命令可以从这里找到:
https://cmake.org/cmake/help/v3.0/manual/cmake-variables.7.html
https://cmake.org/Wiki/CMake_Useful_Variables

关于cmake在普通项目中的用法,请参考这篇文章:cmake入门实践

交叉编译

现在移动开发越老越火,我们免不了会将一些项目porting到Android/iOS平台,这个时候就要用到交叉编译:即在你host宿主机上(例如你用的Ubuntu电脑)要生成target目标机(例如Android手机)的程序。在编译的过程中会涉及到相关头文件的切换和编译器的选择以及环境变量的改变等,今天就来看看CMake是如何来做交叉编译的。

首先需要明确以下几点:

CMake不能自动判断出目标机系统,需要我们指定。
一般情况下Build出来的可执行文件是不能直接运行在宿主机上。
编译过程中不能用宿主机上的原声头文件和库,而是需要用到一套不同的头文件和库。
CMAKE_TOOLCHIAIN_FILE

这个应该是CMake交叉编译中最重要的概念。正如前面提到过的,CMake不知道你的目标平台是什么、用什么编译起、如何编译等等,所以你需要提供预设一些变量到CMake,其中最为方便的一个方法就是将相关的变量设置都放进一个文件(cmake脚本)中去,然后将该文件通过CMAKE_TOOLCHIAIN_FILE传递给CMake, 例如:

cmake -D CMAKE_TOOLCHIAIN_FILE="/path/to/my-cmake-toolchain-file" …
此处我们假设要执行的CMakeLists file在上一级目录中。

下面将要在这个文件中需要设置的几个重要的变量分两大类依次介绍一下。

设置目标系统以及Toolchain
CMAKE_SYSTEM_NAME:
在toolchain脚本中必须要设置的变量,只有当CMAKE_SYSTEM_NAME这个变量被设置了,CMake才认为此时正在交叉编译,它会额外设置一个变量CMAKE_CROSSCOMPILING为TRUE。

CMAKE_SYSTEM_NAME即目标机target所在的操作系统名称,比如ARM或者Linux你就需要写”Linux”,如果Android平台你就写”Android”,如果你的嵌入式平台没有相关OS你即需要写成”Generic”.

CMAKE_SYSTEM_PROCESSOR:
这个是可选项,但是在移动开发中很重要,代表目标系统的硬件或者CPU型号,例如ARM,X86 etc。

CMAKE_C_COMPILER:
即C语言编译器,这里可以将变量设置成完整路径或者文件名

CMAKE_CXX_COMPILER:
C++编译器。

搜索查找外部依赖
稍微大一点的项目都会用到一些外部依赖库或者tool,CMake提供了FIND_PROGRAM(), FIND_LIBRARY(), FIND_FILE(), FIND_PATH() and FIND_PACKAGE() 等命令来进行外部依赖的搜索查找。

但是有个问题,假如我们在给一个ARM处理器的移动设备做交叉编译,其中需要寻找libjpeg.so,假如FIND_PACKAGE(JPEG) 返回的是/usr/lib/libjpeg.so,那么这就会有问题,因为找到的这个so库只是给你的宿主机系统(例如一个x86的Ubuntu主机)服务的,不能用于Arm系统。所以你需要告诉CMake去其它地方去查找,这个时候你就咬配置以下的变量了:

CMAKE_FIND_ROOT_PATH:
代表了一系列的相关文件夹路径的根路径的变更,比如你设置了/opt/arm/,所有的Find_xxx.cmake都会优先根据这个路径下的/usr/lib,/lib等进行查找,然后才会去你自己的/usr/lib和/lib进行查找.

CMAKE_FIND_ROOT_PATH_MODE_PROGRAM:
对FIND_PROGRAM()起作用,有三种取值,NEVER,ONLY,BOTH,第一个表示不在你CMAKE_FIND_ROOT_PATH设置的目录下进行查找,第二个表示只在这个路径下查找,第三个表示先查找这个路径,再查找全局路径

CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
对FIND_LIBRARY()起作用,表示在链接的时候的库的相关选项,因此这里需要设置成ONLY来保证我们的库是在交叉环境中找的.

一个小例子

附上一个CMake官方文档中的toolchian file的小例子,这样我们就会对如何写toolchain文件有了感性认识:

# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)# specify the cross compiler
SET(CMAKE_C_COMPILER   /opt/eldk-2007-01-19/usr/bin/ppc_74xx-gcc)
SET(CMAKE_CXX_COMPILER /opt/eldk-2007-01-19/usr/bin/ppc_74xx-g++)# where is the target environment
SET(CMAKE_FIND_ROOT_PATH  /opt/eldk-2007-01-19/ppc_74xx /home/alex/eldk-ppc74xx-inst)# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

执行起来也很简单,如下:

~/src$ cd build
~/src/build$ cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-eldk-ppc74xx.cmake …

Cmake 交叉编译相关推荐

  1. linux使用cmake交叉编译arm32程序

    linux使用cmake交叉编译arm32程序 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 文章目录 linux使用cmake交叉 ...

  2. 脱离AS在windows下使用CMake交叉编译for Android

    脱离AS在windows下使用CMake交叉编译for Android 前言 可能有Android开发经验并搞过jni的撸友知道,使用Android ndk 中的ndk-build 结合Android ...

  3. 在windows上,用cmake 交叉编译arm程序

    在windows上,用cmake 交叉编译arm程序.生成器用nijia(或用MinGW,此时, cmake执行时,指定生成器为 -G "MinGW Makefiles", 编译用 ...

  4. linux cmake 交叉编译配置 简介

    很多时候,我们在开发的时候是面对嵌入式平台,因此由于资源的限制需要用到相关的交叉编译.即在你host宿主机上要生成target目标机的程序.里面牵扯到相关头文件的切换和编译器的选择以及环境变量的改变等 ...

  5. cmake交叉编译android,CMake Android 交叉编译

    众所周知,AS现在可以利用Grandle调用cmake,实现c++代码在Android平台上的交叉编译.但是大多是情况下,项目代码不是从零开发,而是在现有代码的基础上移植到Android平台上.这种情 ...

  6. cmake交叉编译mbedtls,open62541笔记

    1.编译mbedtls 1.mkdir build //创建生成文件保存路径 2.选择交叉编译器,两种方法: ①直接将编译器设置到环境变量 export CC=/gcc路径/ export CXX=/ ...

  7. windows下CMake交叉编译Android环境OpenCV(为了加入ffmpeg)

    参考博客: https://www.jianshu.com/p/550c85024c49 https://blog.csdn.net/airgreen/article/details/10894458 ...

  8. ubuntu cmake交叉编译时报错:没有那个文件或目录

    https://gitee.com/lovelydett/FTP_client?_from=gitee_search 今天,编译laoyuan发来的ftp时出现问题,运行build.sh报错: 原因, ...

  9. cmake交叉编译时链接到x86库的问题

    编译链接时报错: /home/toolchain/gcc/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/../../../../aarch64-linux-gnu/bi ...

最新文章

  1. DataBinding的双向绑定实现原理
  2. 计算机考研 电路,模拟电路 请高手来帮忙
  3. BUUCTF Dig the way
  4. python更改数据框指定位置的数据_python – 更改数据框中多个loc的最快方法
  5. python 线程安全的数据类型_详解python多线程、锁、event事件机制的简单使用
  6. 找回Win8.1(windows server 2012 R2)的双拼
  7. Airpal安装部署
  8. SSI指令使用详解(转)
  9. sql两张表,分组或row_number()取最新的记录SQL
  10. 服务器维护需要log日志,IBM HTTP server for i的日志维护
  11. 终于有了MSDN上的Blog
  12. centos7开机无法进入图形界面,出现 sda assuming drive cache write through
  13. python 选择文件对话框插件_Python DearPyGui 常用控件一
  14. iPhone--什么是解锁
  15. 全球与中国的前50家最佳网站
  16. 区分: 间宾直宾(双宾语) 宾补(复合宾语)
  17. 猜叔叔的出生年月日 今年的植树节(2012年3月12日),小明和他的叔叔还有小伙伴们一起去植树。
  18. Linux配置ipv6
  19. Perceiver_General Perception with Iterative Attention稿
  20. 常用的 shall 命令 及 语法

热门文章

  1. GridView中HyperLinkField的链接使用JavaScript问题
  2. usaco Healthy Holsteins
  3. java编程 linux_Linux下java编程
  4. java内部类的权限符,static介绍、内部类、final、权限修饰符的作用范围,
  5. linux下date -d,linux date -d的一些用法
  6. php偶尔500,python – 偶尔500错误
  7. php输出带的字符串吗,php输出含有“#”字符串的方法
  8. c 使用腾讯云mysql_腾讯云使用笔记一: 环境搭建
  9. php 面试mysql,mysql中优化必读
  10. python迷宫问题求最短路径_用栈求解迷宫问题的所有路径及最短路径程序