CMAKE的使用

5 分钟阅读

最简单方式

  1. 新建hello.cpp源码文件,如下

    #include<stdio.h>
       
    int main() {
        printf("hello world\n");
    }
    
  2. 新建CMakeLists.txt,内容如下

    add_executable(hello hello.cpp)
    
  3. 执行mkdir build && cd build && cmake ..

  4. 执行make,生成hello

CMakeLists.txt

cmake版本检查

cmake_minimum_required ( VERSION 3.0)

命名项目名称

project(hello) 定义名称为hello

project(hello C)定义为C语言工程

project(hello C CXX)定义为C和C++语言工程

**同时生成变量PROJECT_NAME = hello **

MESSAGE

MESSAGE("project:${PROJECT_NAME}") 显示字符串project:hello

MESSAGE(STATUS "project:${PROJECT_NAME}") 显示-- project:hello

MESSAGE(FATAL_ERROR "project:${PROJECT_NAME}") 显示信息并停止编译

指定路径

  • 头文件 include_directories("${CMAKE_CURRENT_LIST_DIR}/include")
  • 库路径 link_directories(""${CMAKE_CURRENT_LIST_DIR}/lib")
  • 指定源文件(不推荐)
    • aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src ${hello_src})  不包含子目录
    • FILE(GLOB_RECURSE ${hello_src} "*.cpp")   指定源文件,包含子目录
    • add_executable(hello ${hello_src}) 调用

生成目标

生成库

add_library(hello SHARED hello.c) 生成libhello.so

add_library(hello STATIC hello.c) 生成libhello.a

add_library(helloobj OBJECT hello.c) 将源文件打包

add_library(hello STATIC ${hello_src} $<TARGET_OBJECTS:helloobj>) 源不同形式

生成可执行文件

add_executable(hello hello.c) 生成hello可执行文件

add_executable(hello ${hello_src} $<TARGET_OBJECTS:helloobj>) 源不同形式

链接库

target_link_libraries(hello common) 链接libcommon.so

target_link_libraries(hello common.a) 指定链接libcommon.a,同理common.so

添加子目录

  • add_subdirectory(subdir) 注意subdir必须是子目录,必须存在CMakeLists.txt文件。

  • add_subdirectory(otherdir subobj) 此处otherdir可以不是子目录,subobj是编译输出子目录。

  • 子目录的CMakeLists.txt中可以定义新的project,也可以不定义。

  • 子目录共享父目录变量,父目录不共享子目录变量。

    比如父目录变量${VAR} = abc,子目录将${VAR}改成 bcd,回到父目录还是${VAR} = abc

变量

路径变量

当在build目录下执行cmake path时,path是CMakeLists.txt的路径,这种情况下路径信息如下:

代码路径
  • CMAKE_SOURCE_DIR 根部CMakeLists.txt的路径,此处是path;与是否是子工程无关
  • PROJECT_SOURCE_DIR = hello_SOURCE_DIR 当前工程代码路径,此处是path;假如在子工程中,该变量是子工程CMakeLists.txt路径。
  • CMAKE_CURRENT_SOURCE_DIR 当前正在执行的CMakeLists.txt路径。
编译路径
  • CMAKE_BINARY_DIR 根部编译路径,也就是执行cmake的路径,此处是build;与子工程无关
  • PROJECT_BINARY_DIR = hello_BINARY_DIR 当前工程编译路径,此处是build;与是否子工程有关
  • CMAKE_CURRENT_BINARY_DIR 当前执行编译的路径。
举例说明

/test 路径下存在CMakeLists.txt, /test/sub 路径也存在CMakeLists.txt,在/test/build目录下执行cmake ..,得到的路径信息如下:

#/test/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(test)
MESSAGE("${PROJECT_NAME}")             # test
MESSAGE("${CMAKE_SOURCE_DIR}")         # /test
MESSAGE("${CMAKE_BINARY_DIR}")         # /test/build
MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}") # /test
MESSAGE("${CMAKE_CURRENT_BINARY_DIR}") # /test/build
MESSAGE("${PROJECT_SOURCE_DIR}")       # /test
MESSAGE("${PROJECT_BINARY_DIR}")       # /test/build
MESSAGE("${test_SOURCE_DIR}")          # /test
MESSAGE("${subtest_SOURCE_DIR}")       # /test/sub
ADD_SUBDIRECTORY(sub)
add_executable(this_test test.cpp)

#test/sub/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(subtest)
MESSAGE("${PROJECT_NAME}")             # subtest
MESSAGE("${CMAKE_SOURCE_DIR}")         # /test
MESSAGE("${CMAKE_BINARY_DIR}")         # /test/build
MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}") # /test/sub
MESSAGE("${CMAKE_CURRENT_BINARY_DIR}") # /test/build/sub
MESSAGE("${PROJECT_SOURCE_DIR}")       # /test/sub
MESSAGE("${PROJECT_BINARY_DIR}")       # /test/build/sub
MESSAGE("${test_SOURCE_DIR}")          # /test
MESSAGE("${subtest_SOURCE_DIR}")       # /test/sub
add_executable(subtest subtest.cpp)

编辑器变量

set(CMAKE_CXX_COMPILER "clang++" ) # 显示指定使用的C++编译器
set(CMAKE_CXX_FLAGS "-std=c++11") # c++11
set(CMAKE_CXX_FLAGS "-g") # 调试信息
set(CMAKE_CXX_FLAGS "-Wall") # 开启所有警告
set(CMAKE_CXX_FLAGS_DEBUG "-O0" ) # 调试包不优化
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG " ) # release包优化