cmake 入门学习

https://alenstar.github.io/post/cmake_template/

 

首先我们来看看我们的工程目录结构

$ tree myproject

myproject  # 工程目录
├── CMakeLists.txt # 入口CMakeLists.txt文件
├── example.c
├── include  # 头文件目录
│   ├── arch.h
│   ├── base.h
│   ├── common.h
│   └── data.h
├── LICENSE
├── README.md
└── src  # 源代码目录
    ├── arch.c
    ├── base.c
    ├── CMakeLists.txt  # 子CMakeLists.txt文件
    ├── common.c
    └── data.c

入口CMakeLists.txt文件分析

# 设置最低cmake版本要求
cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR) 

#支持 pkg-config
include(FindPkgConfig)
#检查 libcurl cairo 等模块, 并获取它们的LIBS和INCLUDE, 结果保存到变量 LB_LIBS_XXX 中
# LB_LIBS_INCLUDE_DIRS # 保存包含路径
# LB_LIBS_LIBRARIES # 保存连接库
pkg_check_modules(LB_LIBS REQUIRED libcurl cairo)


# 设置项目名称
project(myproject) 

# 检查编译目录和源码是否为同一目录, 如果是则提示错误
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
    message(FATAL_ERROR "Do not build in-source.\nPlease remove CMakeCache.txt and the CMakeFiles/ directory.\nThen: mkdir build ; cd build ; cmake .. ; make")
endif()

if( CMAKE_BUILD_TYPE STREQUAL "Release" )
    add_definitions(-DNODEBUG)
else()
    add_definitions(-DDEBUG)
	#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O0 -ggdb")
	#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -ggdb")
	#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O0 -ggdb")
	#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ggdb")
endif()
	
set(CMAKE_CXX_STANDARD 11)

# 设置变量 PROJECT_NAME 并初始化, 使用 ${XXX} 引用, 如: ${PROJECT_NAME} 
set(PROJECT_NAME "xxx")

add_definitions(-DDEBUG) # 添加宏定义

# 设置CMAKE_C_FLAGS, `${CMAKE_C_FLAGS}` 可取出CMAKE_C_FLAGS的值
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb") 

# 添加include目录(-l)
include_directories(src) 
include_directories(include) 

# 设置 XXX_TESTS 为 OFF
set(XXX_TESTS OFF CACHE BOOL "")
# 添加子目录, 子目录要包含CMakeLists.txt文件
add_subdirectory(src) 

# 添加可执行文件 example 的生成规则, 后面接依赖文件或者文件列表
add_executable(example example.c) 
# 设置可执行文件 example 的链接库, 后面接的可以是系统库, 也可以是 子目录下的自定义库
target_link_libraries(example lib) 

# 检测是否配置了编译类型[Release|Debug], 如果没有配置则配置为Release
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING
  "Choose the type of build, options are: Debug Profile Release Asan Ubsan." FORCE)
endif(NOT CMAKE_BUILD_TYPE)

子CMakeLists.txt文件

cmake_minimum_required(VERSION 2.6) # cmake 版本要求
project(lib) # 项目名称

# 设置option 
# 可以在 add_subdirectory(xxx) 时用 set(XXX OFF|ON CACHE BOOL "") 来设置值
#        名称 描述        默认值[ON | OFF]
# option(XXX "描述 ... " ON) 
option(XXX_TESTS "Build xxx tests and enable testing" ON)
option(XXX_STATIC "Build static library" ON)
option(XXX_SHARED "Build shared library" ON)

# 根据 option 条件编译
# if 语句 支持逻辑运算 [AND | OR | NOT] ; #支持else分支: if() else() endif()
if(XXX_TESTS) 
  # TODO
  # enable_testing()
  # add_subdirectory(test testdir)
endif()

# 设置包含目录( `./` 当前目录)
include_directories(./) 

# 设置文件列表SRC_FILES (自定义名称) 的文件内容( 包含的文件 )
set(SRC_FILES arch.c base.c common.c data.c) 

# 添加静态库 lib 的生成规则, 依赖 SRC_FILES
add_library(lib STATIC ${SRC_FILES}) 
# 添加动态态库 lib 的生成规则, 依赖 SRC_FILES
add_library(lib_shared SHARED ${SRC_FILES}) 

构建项目

为了保持项目目录的干净, 我们一般会在build目录下进行构建

$ mkdir build # 创建构建目录
$ cd build # 进入构建目录
$ cmake .. # 从上级目录构建, 构建产生的临时文件和目标文件将在当前目录生成
$ make # 生成目标

添加 c++11 支持

添加一个编译器选项 add_compile_options(-std=c++11) # CMake 2.8.12 or newer不过这种方式不够灵活

使用set来设置cmake内置变量

set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11

为特定目标进行设置, set_target_properties 可以为要生成的目标设置属性 PROPERTIES 以实现不同目标的差异处理

set_target_properties(myTarget PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)

设置运行时库搜索路径 (gcc -Wl,-rpath=./)

set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "./")

设置链接时库搜索路径 (gcc -L./)

LINK_DIRECTORIES("./lib")

其他-使用自定义动态/静态库

# copy local file 拷贝文件
configure_file(${CMAKE_SOURCE_DIR}/libsqlite3.so ${CMAKE_BINARY_DIR}/libsqlite3.so COPYONLY)

# add local library 添加库文件
add_library(sqlite3 SHARED IMPORTED) # or STATIC instead of SHARED

# 设置库文件属性(文件路径,头文件目录)
set_target_properties(sqlite3 PROPERTIES
   IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/libsqlite3.so"
   INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/include")

# 添加到链接目标
target_link_libraries(<TARGET> sqlite3)

使用自定义命令

# 添加命令, OUTPUT 输出, COMMAND 命令
add_custom_command(
    OUTPUT  ${CMAKE_BINARY_DIR}/message.proto3.pb.cc
    COMMAND ${PROTOC} --cpp_out=${CMAKE_BINARY_DIR} --proto_path=${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/message.proto3
)
# 添加到 OUTPUT 到 SRCS 变量中 (OUTPUT必须被依赖,否则不会执行命令)
List (APPEND SRCS  ${CMAKE_BINARY_DIR}/message.proto3.pb.cc)

包含cmake格式的配置文件

include(xxxx.cmake)

包含子工程

# 添加子目录, 子目录要包含CMakeLists.txt文件
add_subdirectory(subdir) 

OS define

if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
    set(WINDOWS TRUE)
    message(WARNING "only for Windows")
else()
    set(LINUX TRUE)
    message(WARNING "only for linux")
endif()

cross build

if(BUILD_FOR_ARM)
    SET(CROSS_TOOLS_PATH /opt/crosstools/arm-2009q3/bin/arm-none-linux-gnueabi)
    SET(CROSS_ROOT_PATH /opt/crosstools/sys-root)

    # 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   ${CROSS_TOOLS_PATH}-gcc)
    SET(CMAKE_CXX_COMPILER ${CROSS_TOOLS_PATH}-g++)

    # where is the target environment
    SET(CMAKE_FIND_ROOT_PATH  ${CROSS_ROOT_PATH})

    # 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)
endif()

使用文件配置交叉编译工具链

# 文件 arm-none-linux-gnueabi-gcc.cmake
SET(CROSS_TOOLS_PATH /opt/crosstools/arm-2009q3/bin/arm-none-linux-gnueabi)
SET(CROSS_ROOT_PATH /opt/crosstools/sys-root)

# 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   ${CROSS_TOOLS_PATH}-gcc)
SET(CMAKE_CXX_COMPILER ${CROSS_TOOLS_PATH}-g++)

# where is the target environment
SET(CMAKE_FIND_ROOT_PATH  ${CROSS_ROOT_PATH})

# 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)
# 使用交叉工具链编译工程
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../arm-none-linux-gnueabi-gcc.cmake ..
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值