CMake概述
不同平台编译的问题
GNU Make,MS nmake,这些Make工具遵循着不同的规范和标准,所执行的Makefile格式千差万别。为了跨平台生成Makefile,CMake应时而生。
Cmake组成
CMake是一个构建系统,始于1999年,其开发公司Kitware设计其的目的是提供一组工具,实现在不同平台上配置、构建、测试和部署项目。 CMake软件工具集,主要包括:
- CMake:对可执行文件和库的构建
- CTest:测试相关
- CPack:打包
- CDash:测试结果面板展示
这些软件工具集构成的项目时序图如下所示:
CMake的使用分为两部分:
- 程序管理:书写CMakeList.txt这个文件
- 程序构建:通过CMake生成makefile等平台支持的构建文件
在linux平台下使用CMake生成Makefile并编译的流程如下:
CMakeLists.txt
基本概念
- 命令:即CMake中的函数,大部分情况下是设置“变量”
- 变量:内部变量or自定义变量
- 包or库
简单实例
- 最基本的CMakeLists.txt应该包含的东西
# 设置最低CMake版本
cmake_minimum_required(VERSION 3.5)
# 工程名称 版本号 使用的语言(c++)
project(test VERSION 0.1 LANGUAGES CXX)
# 非必须,设置工程包含当前目录
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# 设置c++标准为c++11,且强制c++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找qt5中的库文件,REQUIRED表示为必须的
find_package(QT5 COMPONENTS Widgets REQUIRED)
# 设置自定义变量,将四个文件设置为PROJECT_SOURCES变量
set(PROJECT_SOURCES
main.cpp
widget.cpp
widget.h
widget.ui
)
#添加一个可执行文件,名字是test
add_executable(test
${PROJECT_SOURCES}
)
# test这个可执行文件需要一个第三方库,即Qt5中的Widgets
target_link_libraries(test Qt5::Widgets)
- 库文件怎么搞?
# 这是一个名为add的库文件
cmake_minimum_required(VERSION 3.14)
project(add LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#写两个是因为要兼容QT5和QT6
find_package(QT NAMES QT6 QT5 COMPONETNTS Core REQUIRED)
find_package(QT${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
#与add_executable不同,此处library明显告诉是在生成一个库文件
add_library(add SHARED
add_global.h
add.cpp
add.h
)
target_link_libraries(add PRIVATE Qt${QT_VERSION_MAJOR}::core)
#额外的宏定义 在库add中增加ADD_LIBRARY
target_compile_definitions(add PRIVATE ADD_LIBRARY)
在库中增加宏定义的原因是因为一些头文件有一些条件宏定义,如下
#add_globar.h
#ifndef ADD_GLOBAL_H
#define ADD_GLOBAL_H
#include<QtCore/qglobar.h>
#if defined(ADD_LIBRARY)
# define ADD_EXPORT Q_DECL_EXPORT
#else
# define ADD_EXPORT Q_DECL_IMPORT
#endif
#endif
如上有一个自定义的库,但由于不是包,不能使用find_package命令,不必须通过如下方式引用
cmake_minimum_required(VERSION 3.5)
project(test VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-finput-charset=GBK)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
set(PROJECT_SOURCES
main.cpp
widget.cpp
widget.h
widget.ui
)
# 告诉编译器头文件要去哪里找
#${CMAKE_CURRENT_SOURCE_DIR}就是指当前CMakeLists.txt所在目录
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../
)
# 告诉编译器库文件本身要去哪里找
link_directories(
${CMKAE_CURRENT_SOURCE_DIR}/../build-add-unknown-Debug/
)
add_executable(test
${PROJECT_SOURCES}
)
target_link_libraries(test Qt5::Widgets)
# 指定要加载的libadd.so库即可
target_link_libraries(test libadd.so)
- 多库之间存在依赖问题
如上有两个程序,一个可执行文件test和一个库add,且test依赖于add 如何考虑这种情况的编译
cmake_minimum_required(VERSION 3.14)
project(ProgramOne Languages CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#通过add_subdirectory实现多程序管理
add_subdirectory(add)
add_subdirectory(test)
可以看到不管是根目录还是子目录,都重复出现了变量的设置。但父目录设置的一些变量会被应用于子目录,对于target_开头的命令其不会被子目录共享(因此其只适用于子对象)。
- make install
为了使所需文件不分散放置在各个源代码目录中,通常希望自动将编译好的文件放置在一个统一的目录中,可以
#通过FILES指定要安装哪些头文件,通过DESTINATION指定文件要放置的目录,如果不使用DESTINATION,则默认安装到默认目录相对于(CMAKE_INSTALL_PREFIX的lib目录)
install(FILES add_global.h add.h
DESTINATION include/add
)
#通过TARGEST指定要安装生成的库文件
install(TARGETS add
)
#不使用DESTINATION则表示安装到默认目录(相对于CMAKE_INSTALL_PREFIX的bin目录)
install(TARGETS test
)
#根据文件的类型指定放置的位置
install(TARGET add
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
- target_开头命令
target_开头命令不是一个全局命令,是一个只针对当前当前特定编译目标的设置
target_include_directories(test PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
target_compile_options(test PRIVATE -finput-charset=GBK)
补充的一些函数
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
|
+--- main.cc
|
+--- MathFunctions.cc
|
+--- MathFunctions.h
#法一
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo2)
# 指定生成目标
add_executable(Demo main.cc MathFunctions.cc)
#法二
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo2)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
|