我是靠谱客的博主 重要小白菜,最近开发中收集的这篇文章主要介绍cmake 基本命令 & 交叉编译配置 & 模块的编写,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

cmake 基本命令:

cmake_minimum_required(VERSION 2.8.2 FATAL_ERROR)

project("ProjName")

// 不推荐使用add_definitions来设置编译选项,因为其作用如同cmake -D
add_definitions(
    -std=c++11 # Or -std=c++0x
    -Wall
    -Wfatal-errors
    -DXXX      #等于gcc -DXXX
    # Other flags
)

// 一般通过下条语句设置编译选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wfatal-errors -fPIC")

//变量:CMAKE_PREFIX_PATH: Path used for searching by FIND_XXX(), with appropriate suffixes added. e.g: find_package 
set(CMAKE_PREFIX_PATH /path/path/path)

//引用环境变量
export FOO=/use/lib  # 在bash中
$ENV{FOO}  # 在CMakeLists.txt中

//头文件路径
include_directories(
	include
	relative/path
	/absolute/path/
)

//链接库目录
link_directories(directory1 directory2 ...)

//链接函数库
target_link_libraries(a.out mylib ompl)	//可以是cmake中的target,也可以是某个目录中的库文件,如 libompl.so,等同于 gcc -lompl

//源文件路径,在子目录中
add_subdirectory (
	someDirectory
	src/otherDirecotry
)

//寻找某个目录中的所有源文件,格式:aux_source_directory(<dir> <variable>)
aux_source_directory(src _srcFiles)

//生成库文件
add_library(mylib [SHARED|STATIC] 
  mylib.cpp
  other.cpp
)

//生成可执行程序
add_executable(a.out
	main.cpp 
	src/func.cpp
)

//设置变量
set(someVariable "some string")

//打印消息
message(STATUS "some status ${someVariable}")

//list操作
list(REMOVE_ITEM _srcFiles "src/f4.cpp")	//从变量中去掉某一项
list(APPEND <list> <element> [<element> ...])	//添加某一项到变量中

//检查编译器是否支持某一个编译选项
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
        message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

常用 find_package 找 boost 库和头文件:

# Put this in your CMakeLists.txt file (change any options from OFF to ON if you want):

set(Boost_USE_STATIC_LIBS OFF)  # 不写这几个就是默认设置
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF) 

find_package(Boost 1.59.0 COMPONENTS *boost libraries here*  REQUIRED)  // 如果只是头文件库,则不需要写 COMPONENTS, 直接 find_package(Boost 1.59.0 xxx REQUIRED)

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS}) 
    add_executable(progname file1.cxx file2.cxx) 
    target_link_libraries(progname ${Boost_LIBRARIES})
endif()
# Obviously you need to put the libraries you want where I put *boost libraries here*. 
# For example, if you're using the filesystem and regex library you'd write:

find_package(Boost 1.59.0 COMPONENTS filesystem regex REQUIRED)  # 一般包含头文件是 <boost/xxx/*>, 则 COMPONENTS 后面就写 xxx

cmake marco & function

set(var "ABC")

macro(Moo arg)  # 定义macro
  message("arg = ${arg}")
  set(arg "abc")
  message("# After change the value of arg.")
  message("arg = ${arg}")
endmacro()
message("=== Call macro ===")
Moo(${var})  # 调用macro

function(Foo arg)  # 定义函数
  message("arg = ${arg}")
  set(arg "abc")
  message("# After change the value of arg.")
  message("arg = ${arg}")
endfunction()
message("=== Call function ===")
Foo(${var})  # 调用函数
and the output is

=== Call macro ===
arg = ABC
# After change the value of arg.
arg = ABC
=== Call function ===
arg = ABC
# After change the value of arg.
arg = abc

#注意,marco的调用相当于c/c++的预编译器,只会进行字符串替换(这就是为啥 arg 没有被改变);而函数则可以进行变量操作

//常用变量

CMAKE_SOURCE_DIR ( 相当于工程根目录 )

this is the directory, from which cmake was started, i.e. the top level source directory

CMAKE_CURRENT_SOURCE_DIR
this is the directory where the currently processed CMakeLists.txt is located in

PROJECT_SOURCE_DIR ( =CMAKE_SOURCE_DIR 相当于工程根目录 )
contains the full path to the root of your project source directory, i.e. to the nearest directory where CMakeLists.txt contains the PROJECT() command

CMAKE_PREFIX_PATH (用于找 Findxxx.cmake文件,找 库 和 头文件)
Path used for searching by FIND_XXX(), with appropriate suffixes added.

CMAKE_INSTALL_PREFIX ( 安装目录 )
Install directory used by install.
If “make install” is invoked or INSTALL is built, this directory is prepended onto all install directories. This variable defaults to /usr/local on UNIX and c:/Program Files on Windows.
例如cmake .. -DCMAKE_INSTALL_PREFIX=/my/paht/to/install

cmake 配置交叉编译环境:

// cmake的交叉编译环境设置,创建文件toolchain.cmake,添加以下内容:

# 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/arm/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER /opt/arm/arm-linux-gnueabihf-g++)

# where is the target environment 
SET(CMAKE_FIND_ROOT_PATH  /opt/arm/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)

// If this file is named toolchain.cmake and is located in your home directory
// and you are building in the subdirectory build then you can do:

~/src$ cd build
~/src/build$ cmake -DCMAKE_TOOLCHAIN_FILE=~/toolchain.cmake ..

注意: 在交叉编译的时候,如果某些 FindXXX.cmake 模块中有类似 pkg_search_module 或者 pkg_check_modules 等命令,则会有点问题:

FindXXX.cmake modules, which rely on executing a binary tool like pkg-config may have problems, since the pkg-config of the target platform cannot be executed on the host. Tools like pkg-config should be used only optional in FindXXX.cmake files.

可以找到相应的模块的 FindXXX.cmake 替换其 pkg-config

如果不想让 pkg-config 被执行,可以试着:

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)  // 即不让cmake的 find_program 去host环境中找可执行文件,所以 pkg_search_module 这种命令应该会失败。

如果 cmake cache了一些变量,需要重新运行cmake,只需要删除 CMakeCache.txt 文件即可


关于如何编写自己的 Findxxx.cmake 文件:

尊重原作,以下部分复制了该作者的部分文件内容,see link

set(MYSIMPLEPACKAGE_ROOT_DIR
	"${MYSIMPLEPACKAGE_ROOT_DIR}"
	CACHE
	PATH
	"Directory to search")

if(CMAKE_SIZEOF_VOID_P MATCHES "8")
	set(_LIBSUFFIXES /lib64 /lib)
else()
	set(_LIBSUFFIXES /lib)
endif()

find_library(MYSIMPLEPACKAGE_LIBRARY
	NAMES
	mysimplepackage
	PATHS
	"${MYSIMPLEPACKAGE_ROOT_DIR}"
	PATH_SUFFIXES
	"${_LIBSUFFIXES}")

# Might want to look close to the library first for the includes.
get_filename_component(_libdir "${MYSIMPLEPACKAGE_LIBRARY}" PATH)

find_path(MYSIMPLEPACKAGE_INCLUDE_DIR
	NAMES
	mysimplepackage.h
	HINTS
	"${_libdir}" # the library I based this on was sometimes bundled right next to its include
	"${_libdir}/.."
	PATHS
	"${MYSIMPLEPACKAGE_ROOT_DIR}"
	PATH_SUFFIXES
	include/)

# There's a DLL to distribute on Windows - find where it is.
set(_deps_check)
if(WIN32)
	find_file(MYSIMPLEPACKAGE_RUNTIME_LIBRARY
		NAMES
		mysimplepackage.dll
		HINTS
		"${_libdir}")
	set(MYSIMPLEPACKAGE_RUNTIME_LIBRARIES
		"${MYSIMPLEPACKAGE_RUNTIME_LIBRARY}")
	get_filename_component(MYSIMPLEPACKAGE_RUNTIME_LIBRARY_DIRS
		"${MYSIMPLEPACKAGE_RUNTIME_LIBRARY}"
		PATH)
	list(APPEND _deps_check MYSIMPLEPACKAGE_RUNTIME_LIBRARY)
else()
	get_filename_component(MYSIMPLEPACKAGE_RUNTIME_LIBRARY_DIRS
		"${MYSIMPLEPACKAGE_LIBRARY}"
		PATH)
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MySimplePackage
	DEFAULT_MSG
	MYSIMPLEPACKAGE_LIBRARY
	MYSIMPLEPACKAGE_INCLUDE_DIR
	${_deps_check})

if(MYSIMPLEPACKAGE_FOUND)
	set(MYSIMPLEPACKAGE_LIBRARIES "${MYSIMPLEPACKAGE_LIBRARY}")
	set(MYSIMPLEPACKAGE_INCLUDE_DIRS "${MYSIMPLEPACKAGE_INCLUDE_DIR}")
	mark_as_advanced(MYSIMPLEPACKAGE_ROOT_DIR)
endif()

mark_as_advanced(MYSIMPLEPACKAGE_INCLUDE_DIR
	MYSIMPLEPACKAGE_LIBRARY
	MYSIMPLEPACKAGE_RUNTIME_LIBRARY)

哈,家里的小工厂,占个位: http://www.herofireworks.com/

最后

以上就是重要小白菜为你收集整理的cmake 基本命令 & 交叉编译配置 & 模块的编写的全部内容,希望文章能够帮你解决cmake 基本命令 & 交叉编译配置 & 模块的编写所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部