[笔记]CMake学习

简介: [笔记]CMake学习

前言

文件夹目录格式

目录
     src
         add
                add.cpp
                add.h
         sum
            sum.cpp
            sum.h
     build
     example
               CMakeList.txt
               test.cpp
     CMakeList.txt

~/CMakeList.txt 是总配置 整个项目的Cmake配置 包括CMake版本。

~/example/CMakeList.txt 是子项目配置 一般就配置编译文件。

一、构建可执行程序

cmake_minimum_required(VERSION 3.0)
project(day1)
add_executable(day1 main.cpp add.cpp)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
#aux_source_directory(. DIR_SRCS)
#add_executable(day1 ${DIR_SRCS})

二、多文件构建可执行程序

cmake_minimum_required(VERSION 3.0)
project(day2)
aux_source_directory(. DIR_SRCS)
aux_source_directory(./src/add DIR_SRCS)
aux_source_directory(./src/sum DIR_SRCS)
#message("DIR_SRCS = ${DIR_SRCS}") # 打印
add_executable(day2 ${DIR_SRCS}) 
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
#aux_source_directory(. DIR_SRCS)
# 生成可执行程序
#add_executable(day1 ${DIR_SRCS})

三、生成动态/静态库

cmake_minimum_required(VERSION 3.0)
project(day3)
aux_source_directory(. DIR_SRCS)
aux_source_directory(./src/add DIR_SRCS)
aux_source_directory(./src/sum DIR_SRCS)
message("DIR_SRCS = ${DIR_SRCS}")
#add_executable(day3 ${DIR_SRCS})
#生成libday3.so 动态库
add_library(day3 SHARED  ${DIR_SRCS})
#生成libday3.a 静态库
#add_library(day3 STATIC  ${DIR_SRCS})

四、测试使用动态/静态库

生成动态库SHARED,静态库STATIC

#add_library(day3 SHARED  ${DIR_SRCS})

如何调用生成的动态/静态库 三个命令即可

include_directories(xxx) #添加include路径
link_directories(xxx) #给编译器添加库目录
target_link_libraries(target_name lib_name ...) #给目标添加依赖库

!!!Linux下使用readelf xxx -d 可以看程序的链接库

五、同时生成库和测试

几个新变量

CMAKE_PROJECT_NAME,PROJECT_BINARY_DIR,CMAKE_CURRENT_SOURCE_DIR

# 设置二进制可执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 设置库文件输出路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

生成myProject_shared动态库文件

add_library(${CMAKE_PROJECT_NAME}_shared SHARED ${DIR_SRCS})
# 链接需要用到的库文件pthread
#target_link_libraries(${CMAKE_PROJECT_NAME}_shared pthread)
# 修改库文件名称为myProject,系统自动改为libmyProject
set_target_properties(${CMAKE_PROJECT_NAME}_shared PROPERTIES 
  OUTPUT_NAME "${CMAKE_PROJECT_NAME}")

生成myProject_static静态库文件

add_library(${CMAKE_PROJECT_NAME}_static STATIC ${DIR_SRCS})
# 链接需要用到的库文件pthread
#target_link_libraries(${CMAKE_PROJECT_NAME}_static pthread)
# 修改库文件名称为myProject,系统自动改为libmyProject
set_target_properties(${CMAKE_PROJECT_NAME}_static PROPERTIES 
  OUTPUT_NAME "${CMAKE_PROJECT_NAME}")

下面这个命令会调用example 文件夹下的CMakeLists.txt 文件

add_subdirectory(example)

example 下面的CMakeLists.txt
aux_source_directory(. TEST_SRC_LIST)
foreach(TEST_SRC ${TEST_SRC_LIST})
    STRING(REGEX REPLACE "^\\./|\\.c[a-zA-Z0-9_]*$" "" TEST_EXE_NAME ${TEST_SRC})  # 字符串处理,去掉前面路径和后缀
    message(STATUS "添加测试程序:${TEST_EXE_NAME}")
    add_executable(${TEST_EXE_NAME} ${TEST_SRC})
    target_link_libraries(${TEST_EXE_NAME} ${CMAKE_PROJECT_NAME}_shared )
endforeach(TEST_SRC ${TEST_SRC_LIST})

六、生成win和linux的动态库

6.1 CMakeLists.txt 如何在区别平台

if(WIN32)
...
elseif(APPLE)
else()
...
endif()
if(ANDROID)
else()
endif()

注意win生成动态库需要加入

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

window 的动态库,会带一个.lib 文件,这个文件只是在编译时候需要,运行时候不需要

window 动态库xx.dll,xx.lib(一般会附带不是必须)

window 静态库 xx.lib

linux 动态库 libxx.so

linux 静态库 libxx.a

七、宏变量设置

如果想在写代码时候定义一个宏变量

应用场景,假设设计一套接口,但有两种算法实现,用到了两个不同的第三方库

#ifdef USE_Detect_A

#elif USE_Detect_B

#endif

CMakeList.txt

cmake_minimum_required(VERSION 3.0 )
project(day1)
# 是否使用自己的 Math库
option (USE_Detect_A "Use provided math implementation" ON)
option (USE_Detect_B "Use provided math implementation" OFF)
# 用于测试替换用的变量
if(USE_Detect_A)
message("USE_Detect_A #############")
add_definitions(-DUSE_Detect_A)
elseif(USE_Detect_B)
message("USE_Detect_B #############")
add_definitions(-DUSE_Detect_B)
else()
message("USE_Detect #############")
add_definitions(-DUSE_Detect)
endif()
add_compile_options(-std=c++11)
add_executable(day1 main.cpp )
#include <stdio.h>
int main()
{
    #ifdef USE_Detect
    printf(" USE_Detect i = %d add(%f %f) = %f ", i, a, b, c);
    #elif USE_Detect_A
    printf(" USE_Detect_A i = %d add(%f %f) = %f ", i, a, b, c);
    #elif USE_Detect_B
    printf(" USE_Detect_B i = %d add(%f %f) = %f ", i, a, b, c);
    #endif
    }
}
编译命令
cmake .. -DUSE_Detect_B=ON

八、cmake 中的install

install 相当于将库和头文件 导出到某个路径

#安装目录 执行cmake生成的时候 指定安装目录
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/testInstall
set(INSTALL_PATH_LIB lib)
set(INSTALL_PATH_INCLUDE include)
install(DIRECTORY src/sum DESTINATION ${INSTALL_PATH_INCLUDE} FILES_MATCHING PATTERN "*.h")
install(DIRECTORY src/add DESTINATION ${INSTALL_PATH_INCLUDE} FILES_MATCHING PATTERN "*.h")
#lib库的安装
if(WIN32)
install(TARGETS ${CMAKE_PROJECT_NAME}_shared RUNTIME DESTINATION ${INSTALL_PATH_LIB})
else()
install(TARGETS ${CMAKE_PROJECT_NAME}_shared LIBRARY DESTINATION ${INSTALL_PATH_LIB})
endif()
install(TARGETS ${CMAKE_PROJECT_NAME}_static ARCHIVE DESTINATION ${INSTALL_PATH_LIB})

也可以安装多个

INSTALL(TARGETS myrun mylib mystaticlib
       RUNTIME DESTINATION bin
       LIBRARY DESTINATION lib
       ARCHIVE DESTINATION libstatic
)

九、模板

可参考我sdl_learn项目cmake模板

SDL地址

十、常用配置

10.1 移除某文件

list(REMOVE_ITEM WINDOWS_FILE “WXDumpFile.cpp” “WXDumpFile.h” “WXLog.h” “WXLog.cpp”)

10.2 添加筛选器

FILE(GLOB USBMUXD_SRC usbmuxd/.h usbmuxd/.cpp)

source_group(usbmuxd FILES ${USBMUXD_SRC})

10.3 搜索路径和库

10.3.1 find_path

搜索指定头文件路径

FIND_PATH(myCeres NAMES ceress.h PATHS /ceres/include/ceres NO_DEFAULT_PATH)

10.3.2 find_library

查找库所在目录

FIND_LIBRARY(RUNTIME_LIB mylib /usr/lib /usr/local/lib NO_DEFAULT_PATH)

10.3.3 find_package

使用find_package引入外部依赖包

10.4 设置cpp标准

set(CMAKE_CXX_STANDARD 11)

相关文章
|
1月前
|
JSON 开发工具 开发者
CMake进阶教程:深入FetchContent与ExternalProject模块
CMake进阶教程:深入FetchContent与ExternalProject模块
79 0
|
3月前
|
Kubernetes NoSQL Unix
cmake入门学习笔记
cmake入门学习笔记
|
4月前
|
Java Linux 编译器
CMake从入门到弃坑
CMake 说明 cmake的定义是什么 ?-----高级编译配置工具 当多个人用不同的语言或者编译器开发一个项目,最终要输出一个可执行文件或者共享库(dll,so等等)这时候神器就出现了-----CMake!
87 1
|
5月前
|
存储 Shell
CMake01快速上手
本文旨在快速上手并且使用cmake,更多深入内容请参考后续的blog。
|
8月前
|
C++
CMAKE学习
CMAKE学习
52 0
CMake实战(一)
CMake和Autotools一样,都是项目构建工具。可以简单理解为,帮助我们生成Makefile,方便编译。
CMake实战(二)
上一篇《CMake实战(一)》我们是把所有文件放在同一个目录下,而平常开发时,我们会将源文件进行分类,放到不同的目录下。接下来我们来看一下具体要怎么操作。
CMake实战(三)
前面两篇《CMake实战(一)》,《CMake实战(二)》,主要是介绍单目录和多目录的编译,接下来看一下自定义编译选项和交叉编译。
CMake教程10:编写CMake中遇到的问题
CMake教程10:编写CMake中遇到的问题
945 0
现代cmake--阅读笔记2
现代cmake--阅读笔记2
188 0