交叉编译

交叉编译时候包含的文件和链接的库都不是Host可以运行的文件,如下为交叉编译时候,配置的环境信息

#toolchain cmake file 

SET(CMAKE_SYSTEM_NAME Linux)
SET(TOOLCHAIN_DIR "/home/xx/softwares/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux")
SET(3RDPART_LIBS_DIR "/home/xx/install") #specify the cross compiler
SET(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-gcc CACHE FILEPATH "Archiver")
SET(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-g++ CACHE FILEPATH "Archiver")
#SET(CMAKE_GFORTRAN ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-gfortran)
SET(CMAKE_AR ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-ar CACHE FILEPATH "Archiver")
SET(CMAKE_AS ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-as CACHE FILEPATH "Archiver")
SET(CMAKE_LD ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-ld CACHE FILEPATH "Archiver")
SET(CMAKE_NM ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-nm CACHE FILEPATH "Archiver")
SET(CMAKE_STRIP ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-strip CACHE FILEPATH "Archiver") # where is the target environment
SET(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR} ${3RDPART_LIBS_DIR}) # 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)

1. 设置系统和交叉编译链

CMAKE_SYSTEM_NAME: 这个参数是利用cmake进行交叉编译必须设置的,通常都是Linux或者Windows,声明要利用cmake创建运行在目标系统上的文件。如果要创建运行在没有操作系统的嵌入式环境,该参数要设置成Generic.如果CMAKE_SYSTEM_NAME进行了预先设置,CMAKE_CROSSCOMPLING经会被自动置位为True.所以可以被用来测试时候在交叉编译环境进行编译。

CMAKE_SYSTEM_VERSION:可选项,目标系统的版本,用的不多。

CMAKE_SYSTEM_PROCESS:可选项,目标系统的处理器,只有在目标程序要运行在不同硬件平台时候才需要进行设置针对不同的对象。它可以被用来做一些编译器编译选项的快速设定。

CMAKE_C_COMPLIER: C语言编译器,例如在shell中修改变量CC指向交叉编译的C编译器export CC=arm-linux-guneabihf-gcc, 或者在CMakeLists.txt内设置 SET(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-gcc),但是这句话只有写到PROJECT( project_name)之前才会起作用,或者将一系列设置写在toolchain.cmake文件中,详情在后面补充。

CMAKE_CXX_COMPLIER:CXX编译器,如果其是交叉编译工具,二者只需要声明一个。

2. 主机环境

CMAKE_HOST_SYSTEM_NAME,CMAKE_HOST_SYSTEM_VERSION,CMAKE_HOST_SYSTEM_PROCESSOR,CMAKE_HOST_SYSTEM除了交叉环境编译情况下,主机和目标机器的变量值一样。

3. 查找外部软件

一般工程都包含一些外部依赖的库或者工具,cmake提供给我们一些变量可以进行查找FIND_PROGRAM(), FIND_LIBRARY(), FIND_FILE(), FIND_PATH() and FIND_PACKAGE() 查找文件和返回结果。FIND_PACKAGE()其实并不进行查找,而是通过执行FindXXX.cmake模块,进而调用FIND_PROGRAM(), FIND_LIBRARY(), FIND_FILE(), FIND_PATH()去查找文件。例如当你编译软件时候,希望程序链接文件 /usr/lib/libjpeg.so,FIND_PACKAGE(JPEG)会直接在主机的相对位置查找此链接文件,所以我们必须设定CMake在指定的位置查找需要的文件。

下面的设置可以帮助我们完成相应的操作

CMAKE_FIND_ROOT_PATH: 这是一个文件夹列表,如果你的目标环境安装在/opt/eldk/ppc_74xx,配置CMAKE_FIND_ROOT_PATH指向此处,然后FIND_LIBRARY(BZ2_LIB bz2)将会搜索/opt/eldk/ppc_74xx/lib, /opt/eldk/ppc_74xx/usr/lib, /lib, /usr/lib 之后会将 /opt/eldk/ppc_74xx/usr/lib/libbz2.so 作为结果返回。CMAKE_FIND_ROOT_PATH默认设置为空。如果设置之后,cmake默认会首先搜索具有这个前缀的位置下文件,之后去其他位置查找。每个FIND_XXX()可以通过参数NO_CMAKE_FIND_ROOT_PATH, ONLY_CMAKE_FIND_ROOT_PATH 和CMAKE_FIND_ROOT_PATH_BOTH设置查找范围或者采用对所有的FIND_XXX()都起作用的的参数CMAKE_FIND_ROOT_PATH_MODE_PROGRAM, CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 和 CMAKE_FIND_ROOT_PATH_MODE_INCLUDE进行设置。如果你的工程不仅需要toolchain里面的工具,还有目标平台的附加库。我们还需要为这些依赖包建立一个安装文件夹,例如$HOME/eldk-ppc_74xx-inst/,同时需要添加这个位置进去CMAKE_FIND_ROOT_PATH,之后FIND_XXX()才可以在这些位置进行查找。如果之后你build packages在你的目标平台上面,也要安装在这个文件夹内。

CMKAE_FIND_ROOT_PATH_MODE_PROGRAM: 这个变量为FIND_PROGRAM命令设置默认选项,可以是NEVER,ONLY,BOTH(默认). NEVER:CMAKE_ROOT_PATH将会被FIND_PROGRAM()忽略,除非显示使能。ONLY:FIND_PROGRAM只在CMAKE_FIND_ROOT_PATH为前缀的目录下查找需要的文件;BOTH,先在CMAKE_FIND_ROOT_PATH查找之后再去其他位置。在大多数情形下,FIND_PROGRAM()用来查找可以被EXECUTABLE_PROCESS() 或者 ADD_CUSTOM_COMMAND()执行的程序。所以在大多数情况下,主机的可执行程序是必须的,所以CMAKE_FIND_ROOT_PATH_MODE_PROGRAM通常被设置成为NEVER。

CMAKE_FIND_ROOT_PATH_MODE_LIBRARY: FIND_LIBRARY()命令的默认设置,设置链接需要的文件目录,通常都位于目标系统内,所以一般设置成为ONLY;

CMAKE_FIND_ROOT_PATH_MODE_INCLUDE: FIND_FILE()和FIND_PATH()的默认设置,用来查找include文件目录,文件通常位于目标机器中,所以一般设置为ONLY,我们也可以通过设置NO_CMAKE_FIND_ROOT_PATH, ONLY_CMAKE_FIND_ROOT_PATH 和CMAKE_FIND_ROOT_PATH_BOTH为FIND_FILE()和FIND_PATH()限定文件的查找位置。

4. Toolchain File
为了每次编译方便,特别是目标系统一直不变时,可以将所有的设置包含在CMAKE_TOOLCHAIN_FILE内。例如从linux到嵌入式linux on PowerPC的.cmake文件设置如下

# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION ) # specify the cross compiler
SET(CMAKE_C_COMPILER /opt/eldk---/usr/bin/ppc_74xx-gcc)
SET(CMAKE_CXX_COMPILER /opt/eldk---/usr/bin/ppc_74xx-g++) # where is the target environment
SET(CMAKE_FIND_ROOT_PATH /opt/eldk---/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)

如果toolchain文件的名字为Toolchain-eldk-ppc74xx.cmake 并且位置在$HOME,采取外部编译措施的话,配置代码如下:

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

或者采取替代方式,把所有配置都写在同一个CMakeLists.txt内部,但是会导致每次移植程序都需要重写一遍

#指定交叉编译,注意此部分必须放在project前面,否则cmake还会自动去找自带的gcc,这种方式和使用toolchain.cmake效果一样
SET(CMAKE_C_COMPILER "/usr/local/arm/linux_arm_2416eabi/bin/arm-s3c2416-linux-gnueabi-gcc")
SET(CMAKE_CXX_COMPILER "/usr/local/arm/linux_arm_2416eabi/bin/arm-s3c2416-linux-gnueabi-g++")
SET(CMAKE_AR "/usr/local/arm/linux_arm_2416eabi/bin/arm-s3c2416-linux-gnueabi-ar")
SET(CMAKE_LD "/usr/local/arm/linux_arm_2416eabi/bin/arm-s3c2416-linux-gnueabi-ld")
SET(CMAKE_NM "/usr/local/arm/linux_arm_2416eabi/bin/arm-s3c2416-linux-gnueabi-nm")
SET(CMAKE_STRIP "/usr/local/arm/linux_arm_2416eabi/bin/arm-s3c2416-linux-gnueabi-strip")
PROJECT(hello)

但是这种toolchian file在需要大量程序移植到相同的机器上的时候,相对于替代方式,可以一直使用这个文件不同重复设置。二者都是通过提前设置编译器配置交叉编译工具链的。

如果你的编译器依照默认(没有特殊flags或者文件)情况下不能创建一个简单的程序,我们只能强制使用声明的编译器

INCLUDE(CMakeForceCompiler)

# this one is important
SET(CMAKE_SYSTEM_NAME  eCos) # specify the cross compiler
CMAKE_FORCE_C_COMPILER(arm-elf-gcc GNU)
CMAKE_FORCE_CXX_COMPILER(arm-elf-g++ GNU) # where is the target environment
SET(CMAKE_FIND_ROOT_PATH   /home/alex/src/ecos/install ) # 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)

CMAKE_FORCE_XXX_COMPILER()宏声明force cmake 识别出complier,第二个参数是complier ID.

A toolchain for crosscompiling for Win32 using mingw32 might look like this:

# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++
SET(CMAKE_C_COMPILER i486-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i486-mingw32-g++)
SET(CMAKE_RC_COMPILER i486-mingw32-windres) # here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/i486-mingw32) # adjust the default behaviour of the FIND_XXX() commands: search headers and libraries in the target environment,
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

5. Using executables in the build created during the build

In some cases during a build executables are created which are then used in ADD_CUSTOM_COMMAND() or ADD_CUSTOM_TARGET() during the same build process.When cross compiling this won't work without modifications because the executables cannot run on the build host. Starting with CMake 2.6 it is possible to "import" executable targets into a CMake project. When cross compiling this has to be used to import executables built in a native build into the cross-build. This can be done like this:

# when crosscompiling import the executable targets from a file
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file from a native build")
INCLUDE(${IMPORT_EXECUTABLES})
ENDIF(CMAKE_CROSSCOMPILING) ... # only build the generator if not crosscompiling
IF(NOT CMAKE_CROSSCOMPILING)
ADD_EXECUTABLE(mygenerator mygen.cpp)
TARGET_LINK_LIBRARIES(mygenerator ${SOME_LIBS})
ENDIF(NOT CMAKE_CROSSCOMPILING) # then use the target name as COMMAND, CMake >= 2.6 knows how to handle this
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.c
COMMAND mygenerator foo.dat -o ${CMAKE_CURRENT_BINARY_DIR}/generated.c
DEPENDS foo.dat ) ...
# export the generator target to a file, so it can be imported (see above) by another build
# the IF() is not necessary, but makes the intention clearer
IF(NOT CMAKE_CROSSCOMPILING)
EXPORT(TARGETS mygenerator FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake )
ENDIF(NOT CMAKE_CROSSCOMPILING)

So during the native build the target "mygenerator" will be built and used in ADD_CUSTOM_COMMAND(). As command only the target name is used. CMake >= 2.6.0 recognizes this and creates the dependencies and will use the path to the created executable when executing the command. At the end the EXPORT() function (since CMake 2.6.0) is called, which "exports" the listed targets to the file ${CMAKE_BINARY_DIR}/ImportExecutables.cmake, which will look like this:

ADD_EXECUTABLE(mygenerator IMPORT)
SET_TARGET_PROPERTIES(mygenerator PROPERTIES
LOCATION /home/alex/build-native/bin/mygenerator )

This file is then included when cross compiling, it either has to be specified using -D or via the cmake GUI. Then later on the command for actually building mygenerator is excluded. In ADD_CUSTOM_COMMAND() mygenerator will be recognized as an imported target and it will be used when executing the command.

If the executable mygenerator also has to be built when cross compiling, then some more logic needs to be added, e.g. like this:

# when crosscompiling import the executable targets from a file
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file from a native build")
INCLUDE(${IMPORT_EXECUTABLES})
ENDIF(CMAKE_CROSSCOMPILING) ... # always build the executable
ADD_EXECUTABLE(mygenerator mygen.cpp)
TARGET_LINK_LIBRARIES(mygenerator ${SOME_LIBS}) # but use different names for the command
IF(CMAKE_CROSSCOMPILING)
SET(mygenerator_EXE native-mygenerator)
ELSE(CMAKE_CROSSCOMPILING)
SET(mygenerator_EXE mygenerator)
ENDIF(CMAKE_CROSSCOMPILING) # then use the target name as COMMAND, CMake >= 2.6 knows how to handle this
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.c
COMMAND ${mygenerator_EXE} foo.dat -o ${CMAKE_CURRENT_BINARY_DIR}/generated.c
DEPENDS foo.dat ) ...
# export the generator target to a file, so it can be imported (see above) by another build
# the IF() is not necessary, but makes the intention clearer
# use the NAMESPACE option of EXPORT() to get a different target name for mygenerator when exporting
IF(NOT CMAKE_CROSSCOMPILING)
EXPORT(TARGETS mygenerator FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake NAMESPACE native- )
ENDIF(NOT CMAKE_CROSSCOMPILING)

CMakefile for Cross-Platform Compling - 1的更多相关文章

  1. “CMake”这个名字是“cross platform make”

    cmake_百度百科 https://baike.baidu.com/item/cmake/7138032?fr=aladdin CMake 可以编译源代码.制作程序库.产生适配器(wrapper). ...

  2. Comparing Xamarin and Delphi XE5 to Xcode for Cross Platform Mobile App Development

    Comparing Xamarin and Delphi XE5 to Xcode for Cross Platform Mobile App Development If you are consi ...

  3. V4 Reduce Transportable Tablespace Downtime using Cross Platform Incremental Backup (Doc ID 2471245.1)

    V4 Reduce Transportable Tablespace Downtime using Cross Platform Incremental Backup (Doc ID 2471245. ...

  4. Gtest:Using visual studio 2017 cross platform feature to compile code remotely

    参考:使用Visual Studio 2017作为Linux C++开发工具 前言 最近在学Gtest单元测试框架,由于平时都是使用Source Insight写代码,遇到问题自己还是要到Linux下 ...

  5. Cross Platform Note: STD C++ Preprocessor directives & pre-defined macros

    ref: http://www.cplusplus.com/doc/tutorial/preprocessor/ concolusion: directives: #define #undef #in ...

  6. Cross platform GUI for creating SSL certs with OpenSSL

    Someone said: from : https://micksmix.wordpress.com/2012/08/09/xca-cross-platform-gui-for-creating-s ...

  7. Cross platform

    值得学习的C/C++语言开源项目 (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html ...

  8. Customize Netbeans Platform Splash Screen and About Dialog

    原帖一直打不开,通过谷歌翻译找到的 http://blogs.kiyut.com/tonny/2007/10/18/customize-netbeans-platform-splash-screen- ...

  9. A quick introduction to Source Insight for seamless development platform between Linux and Windows

    前言 Source Insight是一个面向项目开发的程序编辑器和代码浏览器,它拥有内置的对C/C++, C#和Java等程序的分析.能分析源代码并在工作的同时动态维护它自己的符号数据库,并自动显示有 ...

  10. Linux下服务器端开发流程及相关工具介绍(C++)

    去年刚毕业来公司后,做为新人,发现很多东西都没有文档,各种工具和地址都是口口相传的,而且很多时候都是不知道有哪些工具可以使用,所以当时就想把自己接触到的这些东西记录下来,为后来者提供参考,相当于一个路 ...

随机推荐

  1. 21天学通C++_Day3_Part1

    今天奔跑吧兄弟来杭电了,决定不去看,宅在科协继续啃(反正去了也看不到咯),继续继续,今天白天没课,希望可以更两个. 0.C风格字符串 在数组中间把某个字符替换成‘\0’并不会改变数组的长度,但是显示时 ...

  2. 深入了解ZooKeeper(二)

    在上篇博客<<深入了解ZooKeeper(一)>>中我们知道了分布式协调技术.分布式锁的实现和zookeeper服务机制,接下来将进一步了解zookeeper究竟能为我们做了什 ...

  3. Windows下运行Hadoop

    Windows下运行Hadoop,通常有两种方式:一种是用VM方式安装一个Linux操作系统,这样基本可以实现全Linux环境的Hadoop运行:另一种是通过Cygwin模拟Linux环境.后者的好处 ...

  4. oscache使用经历

    oscache作为一款老的本地缓存,应用场景主要有页面缓存和对象缓存.这里拿在maven项目中使用oscache作为对象缓存举例说明下用法: 1.导入jar包 <dependency> & ...

  5. Tomcat起了一个测试桩,调用该测试桩无响应

    有时在测试新业务流程时因为涉及多个不同接口的调用,而这些被调用的服务端因为网络权限或开发进度问题暂时对我们不可达,那么我们可以通过模拟接口返回来完成我们新业务的测试.这次碰到的问题是我明明起了该测试桩 ...

  6. Oracle配置文件tnsnames.ora新增链接后连接报错:ORA-12154: TNS:无法解析指定的标识符

    一个空格引发的血案:在tnsnames. ora文件中新加了一个配置,该配置估计当时是拷的别人的直接粘贴上去的,然后发现用pl/sql连接就一直报错了,后面排除了用户名和密码问题和后,仔细看了该文件才 ...

  7. JVM知识整理和学习(转载并修改)

    JVM是虚拟机,也是一种规范,他遵循着冯·诺依曼体系结构的设计原理. 冯·诺依曼体系结构中,指出计算机处理的数据和指令都是二进制数,采用存储程序方式不加区分的存储在同一个存储器里,并且顺序执行,指令由 ...

  8. leetcode 21.Merge Two Sorted Lists ,java

    题目: Merge two sorted linked lists and return it as a new list. The new list should be made by splici ...

  9. 2016女生赛 HDU 5710 Digit-Sum(数学,思维题)

    Digit-Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total S ...

  10. Java-Maven-Runoob:Maven 仓库

    ylbtech-Java-Maven-Runoob:Maven 仓库 1.返回顶部 1. Maven 仓库 在 Maven 的术语中,仓库是一个位置(place). Maven 仓库是项目中依赖的第三 ...