cmake的一点点初步使用
cmake的一点点初步使用 https://cmake.org/
-------------
cmake打包程序。
1.开源跨平台
2.构建build,测试test,打包软件package sofrware的工具软件.
3.cmake的配置文件简单易懂,不依赖于其他平台的编译器
4.使用cmake配置文件来控制软件的编译过程,生成器generator生成指定项目文件(native makefile,MinGW Makefiles,Ninja,Visual Studio)等等的workspaces。
通过,对应的编译软件,最终编译成目标程序。
cmake命令,在那个目录下执行,就会搜索CMakeLists.txt,并在当前目录下生成相关文件(如果在代码目录执行,会在代码文件目录,会污染代码目录)。
所以一般是,建立build目录,和bin目录,在build目录中执行cmake ..(在上一级目录找CMakeLists.txt), build目录生成处理文件,最终可执行文件在bin中
一 ,简单的cmake
1 先看下目录结构 (-I表示忽略的目录)
$ tree . -I "bin|build|lib|src" . |-- CMakeLists.txt |-- fun1.c |-- fun2.c |-- include | |-- fun1.h | `-- fun2.h `-- test01.c 1 directory, 6 files
# 指定 CMake 的最低版本要求 cmake_minimum_required(VERSION 3.10.0) #定义项目的名称和使用的编程语言 project(code1 VERSION 0.1.0 LANGUAGES C) #指定要生成的可执行文件和其源文件 add_executable(code1 test01.c fun1.c fun2.c)
如果文件夹有很多源码文件总不能一个一个添加吧,这里用到 aux_source_directory(. SRC_LIST)
# 指定 CMake 的最低版本要求 cmake_minimum_required(VERSION 3.10.0) #定义项目的名称和使用的编程语言 project(code1 VERSION 0.1.0 LANGUAGES C) #将当前目录.的所有源码文件保存在SRC_LIST变量中 aux_source_directory(. SRC_LIST) #指定要生成的可执行文件和其源文件 add_executable(code1 ${SRC_LIST})
2 最后在build目录下执行 cmake ..
二 , cmake正规的组织结构
$ tree . . |-- CMakeLists.txt |-- bin |-- build |-- include | |-- fun1.h | `-- fun2.h |-- lib `-- src |-- fun1.c |-- fun2.c `-- test01.c 5 directories, 6 files
# 指定 CMake 的最低版本要求 cmake_minimum_required(VERSION 3.10.0) #定义项目的名称和使用的编程语言 project(code1 VERSION 0.1.0 LANGUAGES C) # bin目录下将来存最终生成的可执行文件 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #将当前目录.的src所有源码文件保存在SRC_LIST变量中 aux_source_directory(src SRC_LIST) # 指定头文件目录include include_directories(include) #指定要生成的可执行文件和其源文件 add_executable(code1 ${SRC_LIST})
这里介绍几个cmake的变量, EXECUTABLE_OUTPUT_PATH :可执行文件生成路径;PROJECT_SOURCE_DIR :项目的路径。
set()设置变量;include_directories()设置头文件目录;aux_source_directory()设置源码路径。
三, cmake处理编译动态库静态库
1.创建并处理自制动态库windows下(单个CMakeLists.txt )
$ tree . . |-- CMakeLists.txt |-- build `-- src |-- include | `-- mylib.h |-- lib | |-- module1.cpp | `-- module2.cpp `-- main.cpp
四个文件内容
mylib.h
#pragma once // 跨平台导出宏(Windows 专用) #ifdef _WIN32 #ifdef LIB_BUILDING #define LIB_API __declspec(dllexport) #else #define LIB_API __declspec(dllimport) #endif #else #define LIB_API #endif namespace MOD1 { LIB_API int add(int a, int b); LIB_API int subtract(int a, int b); } namespace MOD2 { LIB_API int add(int a, int b); LIB_API int subtract(int a, int b); }
module1.cpp
#include <iostream> #include "mylib.h" namespace MOD1 { int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } }
module2.cpp
#include <iostream> #include "mylib.h" namespace MOD2 { int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } }
main.cpp
#include <iostream> #include "mylib.h" int main(){ std::cout << MOD1::add(1,2)<< std::endl; std::cout << MOD2::add(5,2)<< std::endl; return 0; }
CMakeLists.txt
###项目设置######################### cmake_minimum_required(VERSION 3.10) # 指定最低 CMake 版本 project(MyProject VERSION 1.0) # 定义项目名称和版本 # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 包含头文件路径 include_directories(${PROJECT_SOURCE_DIR}/src/include) ###动态库设置######################### # 创建动态库 add_library(MyLib SHARED src/lib/module1.cpp src/lib/module2.cpp ) # 设置公共头文件路径 target_include_directories(MyLib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> ) # 关键:定义宏**_BUILDING,让头文件知道当前是“构建 DLL” target_compile_definitions(MyLib PRIVATE LIB_BUILDING) # 可选:统一输出目录(更整洁) set_target_properties(MyLib PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) ###主程序设置######################### # 找自定库的路径 #find_library(MyLib ${PROJECT_SOURCE_DIR}/lib) # 创建可执行程序 add_executable(MyApp src/main.cpp) # 链接动态库(直接写目标名!CMake 自动处理 .lib 路径) target_link_libraries(MyApp PRIVATE MyLib) # 👇 关键:Windows 下自动复制 .dll 到 .exe 目录 (不添加手动复制dll到可执行程序也可以) if(WIN32) add_custom_command(TARGET MyApp POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyLib> # MyLib.dll $<TARGET_FILE_DIR:MyApp> # 目标:MyApp.exe 所在目录 COMMENT "Copying MyLib.dll to MyApp directory" ) endif()
2.创建并处理自制动态库windows下(多个CMakeLists.txt 子工程)
项目结构(推荐) 这种结构清晰、可扩展,适合中小型到大型项目。
MyProject/ ├── CMakeLists.txt # 根 CMake ├── MathLib/ # 动态库模块 │ ├── CMakeLists.txt │ ├── include/MathLib.h │ └── src/MathLib.cpp └── MyApp/ # 主程序 ├── CMakeLists.txt └── main.cpp
第一步:编写动态库代码
MathLib/include/MathLib.h
#pragma once // 跨平台导出宏(Windows 专用) #ifdef _WIN32 #ifdef MATHLIB_BUILDING #define MATHLIB_API __declspec(dllexport) #else #define MATHLIB_API __declspec(dllimport) #endif #else #define MATHLIB_API #endif namespace Math { MATHLIB_API int add(int a, int b); MATHLIB_API int subtract(int a, int b); }
MathLib/src/MathLib.cpp
#include "MathLib.h" namespace Math { int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } }
第二步:MathLib/CMakeLists.txt(构建 DLL)
# 创建动态库 add_library(MathLib SHARED src/MathLib.cpp ) # 设置公共头文件路径(供 MyApp 使用) target_include_directories(MathLib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> ) # 关键:定义宏,让头文件知道当前是“构建 DLL” target_compile_definitions(MathLib PRIVATE MATHLIB_BUILDING) # 可选:统一输出目录(更整洁) set_target_properties(MathLib PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
PUBLIC表示:任何链接MathLib的目标,都会自动获得include/路径。
第三步:主程序代码
MyApp/main.cpp
#include <iostream> #include "MathLib.h" // 来自 MathLib/include/ int main() { std::cout << "10 + 5 = " << Math::add(10, 5) << "\n"; std::cout << "10 - 3 = " << Math::subtract(10, 3) << "\n"; return 0; }
第四步:MyApp/CMakeLists.txt(引用 DLL)
# 创建可执行程序 add_executable(MyApp main.cpp) # 链接动态库(直接写目标名!CMake 自动处理 .lib 路径) target_link_libraries(MyApp PRIVATE MathLib) # 👇 关键:Windows 下自动复制 .dll 到 .exe 目录 if(WIN32) add_custom_command(TARGET MyApp POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MathLib> # 源:MathLib.dll $<TARGET_FILE_DIR:MyApp> # 目标:MyApp.exe 所在目录 COMMENT "Copying MathLib.dll to MyApp directory" ) endif()
$<TARGET_FILE:MathLib>会自动解析为Debug/MathLib.dll或Release/MathLib.dll,完全匹配当前配置!
第五步:根 CMakeLists.txt
cmake_minimum_required(VERSION 3.16) project(MyProject LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 添加子模块 add_subdirectory(MathLib) add_subdirectory(MyApp)
构建步骤(VS2022 + CMake)
方法一:用命令行(推荐)
# 在 MyProject 目录下 mkdir build cd build # 生成 VS2022 项目(x64) cmake .. -G "Visual Studio 17 2022" -A x64 # 构建 Release 版本 cmake --build . --config Release # 运行(自动找到 DLL!) .\Release\MyApp.exe
方法二:用 VS2022 IDE
- 打开 VS2022 → 文件 → 打开 → CMake... → 选择
MyProject/CMakeLists.txt - VS 会自动加载项目
- 顶部选择 x64-Release
- 右键
MyApp→ 设为启动项 - 按 F5 运行!
10 + 5 = 15 10 - 3 = 7
构建后目录结构(build/ 下)
build/ ├── bin/ │ └── Release/ │ ├── MathLib.dll ← 动态库 │ └── MyApp.exe ← 可执行文件(同目录,运行无忧) ├── lib/ │ └── Release/ │ └── MathLib.lib ← 导入库(链接时用) └── MyProject.sln ← VS 解决方案
💡 因为用了
add_custom_command,运行时绝不会报“找不到 MathLib.dll”!
3.使用链接器默认目录下的动态库
4.使用指定目录下的动态库
四,cmake 综合处理上面的情况
https://blog.csdn.net/hhltaishuai/article/details/123795718
https://www.runoob.com/cmake/cmake-basic.html
扩展:cake
https://www.bilibili.com/video/BV1nw411C71Z
https://www.bilibili.com/video/BV1EuWKevE23
gcc编译:
https://www.bilibili.com/video/BV192pZeTE9B
使用CMake生成动态链接库(.dll和.so)和静态链接库(.lib和.a)的方法
https://blog.csdn.net/weixin_43325228/article/details/143139745

浙公网安备 33010602011771号