# TestCMake **Repository Path**: hybyy/test-cmake ## Basic Information - **Project Name**: TestCMake - **Description**: cmake学习教程 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-04-10 - **Last Updated**: 2023-04-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 学习cmake 1,安装mingw-w64编译器 2,安装CMake 3,安装vscode 4,安装vscode插件C/C++、cmake、cmake tools 5,单文件运行,g++ ./main.cpp ==> ./a.exe 不带调试信息的执行文件 6,ls 查看生成的文件大小 7,g++ -g ./main.cpp -o my.exe //-g带调试信息,-o重命名 8,./my.exe 9,有调试信息的才可以断点调试 10,点击运行键 11,点击创建launch.json文件 12,点击C++(GDB/LLDB) 13,打开launch.json文件,修改 "program": "${workspaceFolder}/my.exe", //运行文件的路径 "miDebuggerPath":"D:/cyh/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/gdb.exe" //编译器的路径 14,点击启动调试运行 备注1: ${workspaceFolder} :表示当前workspace文件夹路径,也即C:\Users\admin\Desktop\test ${workspaceRootFolderName}:表示workspace的文件夹名,也即test ${file}:文件自身的绝对路径,也即C:\Users\admin\Desktop\test\.vscode\launch.json ${relativeFile}:文件在workspace中的路径,也即.vscode\launch.json ${fileBasenameNoExtension}:当前文件的文件名,不带后缀,也即launch ${fileBasename}:当前文件的文件名,launch.json ${fileDirname}:文件所在的文件夹路径,也即C:\Users\admin\Desktop\test\.vscode ${fileExtname}:当前文件的后缀,也即.json ${lineNumber}:当前文件光标所在的行号 ${env:PATH}:系统中的环境变量 备注2: preLaunchTask字段, 配置调试时,修改代码不需要重新GCC编译,直接调试 15,删除my.exe 16,g++ -g ./main.cpp -o ./.vscode/launch.exe 17,配置launch.json中的preLauncherTask字段 18,运行,弹错误框,点击配置任务,点击使用模板创建task.json, 点击other,创建task.json成功。 19,参考cmake_test_1工程配置task.json { { "version": "0.2.0", "configurations": [ { "version": "0.2.0", "configurations": [], "compounds": [] }, { // 配置名称,将会在启动配置的下拉菜单中显示 "name": "C++ Launch (GDB)", // 配置类型,这里只能为cppdbg "type": "cppdbg", // 请求配置类型,可以为launch(启动)或attach(附加) "request": "launch", // 调试器启动类型,这里只能为Local "launchOptionType": "Local", // 生成目标架构,一般为x86或x64, // 可以为x86, arm, arm64, mips, x64, amd64, x86_64 "targetArchitecture": "x86", // 将要进行调试的程序的路径 "program": "${workspaceRoot}", // miDebugger的路径,注意这里要与MinGw的路径对应 "miDebuggerPath":"D:\\mingw\\bin\\gdb.exe", // 程序调试时传递给程序的命令行参数,一般设为空即可 "args": [], // 设为true时程序将暂停在程序入口处,一般设置为false "stopAtEntry": false, // 调试程序时的工作目录,一般为${workspaceRoot}即代码所在目录 "cwd": "${workspaceRoot}", // 调试时是否显示控制台窗口,一般设置为true显示控制台 "externalConsole": true, // 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc "preLaunchTask": "g++"   } ] } } 20, VSCode里有一个Native Debug插件能大大简化launch.json和tasks.json配置 { // https://code.visualstudio.com/docs/editor/tasks "version": "2.0.0", "tasks": [ { "label": "Build", // 任务的名字叫Build,注意是大小写区分的,等会在launch中调用这个名字 "type": "shell", // 任务执行的是shell命令,也可以是 "command": "g++", // 命令是g++ "args": [ "'-Wall'", "'-std=c++17'", //使用c++17标准编译 "'${file}'", //当前文件名 "-o", //对象名,不进行编译优化 "'${fileBasenameNoExtension}.exe'", //当前文件名(去掉扩展名) ], // 所以以上部分,就是在shell中执行(假设文件名为filename.cpp) // g++ filename.cpp -o filename.exe "group": { "kind": "build", "isDefault": true // 任务分组,因为是tasks而不是task,意味着可以连着执行很多任务 // 在build组的任务们,可以通过在Command Palette(F1) 输入run build task来运行 // 当然,如果任务分组是test,你就可以用run test task来运行 }, "problemMatcher": [ "$gcc" // 使用gcc捕获错误 ], } ] } =================================================== { // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format // tasks.json这个文件是定义调试开始前要执行的任务,即(或者绝大多数是)编译程序, 定义了用于编译程序的编译器,所输出的文件格式,使用的语言标准等 "version": "2.0.0", "tasks": [ { "label": "Compile", // 任务名称,与launch.json的preLaunchTask相对应 "command": "g++", // 要使用的编译器, C就写gcc "args": [ "${file}", "-o", // 指定输出文件名,不加该参数则默认输出a.exe,Linux下默认a.out "${fileDirname}/${fileBasenameNoExtension}.out", "-g", // 生成和调试有关的信息 //"-Wall", // 开启额外警告 "-static-libgcc", // 静态链接 "-std=c11" // C语言最新标准为c11,或根据自己的需要进行修改比如C++17 ], // 编译命令参数 "type": "shell", // 可以为shell或process,前者相当于先打开shell再输入命令,后者是直接运行命令 "group": { "kind": "build", "isDefault": true // 设为false可做到一个tasks.json配置多个编译指令,需要自己修改本文件,我这里不多提 }, "presentation": { "echo": true, "reveal": "always", // 在“终端”中显示编译信息的策略,可以为always,silent,never。具体参见VSC的文档 "focus": true, // 设为true后可以使执行task时焦点聚集在终端 "panel": "shared" // 不同的文件的编译信息共享一个终端面板 }, //"problemMatcher": "$gcc" } ] } 20,多文件编译 g++ -g ./main.cpp ./swap.cpp -o ./.vscode/launch.exe 21,使用CMake, 首先新建CMakeLists.txt文件,配置这个文件,进入命令面板,输入cmake选择CMake config, 弹出一条小的输入框,选择GCC 8.1.0 编译器,最下面的状态栏会显示8.1.0 22,cd ./build/ 23,在终端输入 cmake .. 24,在终端输入 mingw32-make.exe 生成 launch.exe文件在build目录下 25,修改.vscode目录下的launch.json文件的可执行目录配置 26,如果要自动生成tasks.json文件,进入命令面板,输入tasks, 选择tasks configure, 再选择g++,就会自动生成了 27,点击运行键 28,tasks.json也加入cmake,参考cmake_test_4 29,点击运行 30,如果第一遍报错,删除build文件夹中的CMakeCache.txt文件 Cmake编译的CmakeLists.txt # cmake 的版本要求 cmake_minimum_required(VERSION 3.14) # 项目名称 project(myCppPractice) # 设置 Debug 模式 set(CMAKE_BUILD_TYPE "Debug") # 设置源文件根目录,并设置别名为DIR_ROOT aux_source_directory(. DIR_ROOT) # 设置myCppPractice版本标准 set(CMAKE_CXX_STANDARD 14) # 项目包含哪些 文件 add_executable(${PROJECT_NAME} main.cpp Actor.cpp AnimSpriteComponent.cpp BGSpriteComponent.cpp Component.cpp Game.cpp Math.cpp Ship.cpp SpriteComponent.cpp) # 声明三方库位置路径 set(SDL2_DIR D:/program/resource/x86_64-w64-mingw32) # headers头文件位置 include_directories(${SDL2_DIR}/include) # 推荐使用find_package和find_library寻找共享库的绝对路径,再传给target_link_libraries使用。 find_library(SDL2MAIN SDL2main ${SDL2_DIR}/lib) find_library(SDL2 SDL2 ${SDL2_DIR}/lib) find_library(SDL2IAMGE SDL2_image ${SDL2_DIR}/lib) # 链接库 target_link_libraries(${PROJECT_NAME} mingw32 ${SDL2MAIN} ${SDL2} ${SDL2IAMGE}) #1.cmake verson,指定cmake版本 cmake_minimum_required(VERSION 3.5) add_compile_options(-std=c++11) #2.project name,指定项目的名称,一般和项目的文件夹名称对应 PROJECT(TcpTool) #3.head file path,头文件目录 INCLUDE_DIRECTORIES( include ) #4.source directory,源文件目录 AUX_SOURCE_DIRECTORY(src DIR_SRCS) #5.set environment variable,设置环境变量,编译用到的源文件全部都要放到这里,否则编译能够通过,但是执行的时候会出现各种问题, #比如"symbol lookup error xxxxx , undefined symbol" SET(TEST_MATH ${DIR_SRCS} ) #6.set output directory target file set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./bin/) #7.add executable file,添加要编译的可执行文件 ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_MATH}) #8.add link library,添加可执行文件所需要的库,比如我们用到了libm.so(命名规则:lib+name+.so),就添加该库的名称 TARGET_LINK_LIBRARIES(${PROJECT_NAME} m) #install(TARGETS ${PROJECT_NAME} DESTINATION bin) #add_executable(demo demo.cpp) # 生成可执行文件 #add_library(common STATIC util.cpp) # 生成静态库 声明 cmake 最低版本 定义cmake的最低版本时2.8 cmake_minimun_required(VERSION 2.8) 可以在终端中查看cmake的版本 cmake -version 输出如下 cmake version 3.2.2 这里需要注意两点,如果不定义需要的版本可能会报个warning,如果有强迫症或者追求完美,还是把这行代码写上吧。第二点,不要定义的版本比自己安装的版本还高,那样估计就是直接编译不通过了。 声明 cmake 工程名字 project( HelloSLAM ) PROJECT_SOURCE_DIR 项目根目录,也就是CmakeLists.txt目录的绝对路径。 设置 cmake 编译模式 set( CMAKE_BUILD_TYPE “Debug” ) 添加c++11标准支持 注意等式左右两端不要加空格 set(CMAKE_CXX_FLAGS “-std=c++11”) 有的时候可能会遇到,一定要注意是大写的O,不是数字0 set(CMAKE_CXX_FLAGS “-std=c++11 -O3”) 其中,参数CMAKE_CXX_FLAGS含义是: set compiler for c++ language 而后面的-O3(是字母opq的o,大写的欧)是用来调节编译时的优化程度的,最高为-O3,最低为-O0(即不做优化) -Ox这个参数只有在CMake -DCMAKE_BUILD_TYPE=Release时有效,因为debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化,而 release 版的不需要调试信息但需要优化。 添加变量 下面讲解如何为程序添加版本号和带有使用版本号的头文件。 set(KEY VALUE)接受两个参数,用来声明变量。 在camke语法中使用KEY并不能直接取到VALUE,必须使用${KEY}这种写法来取到VALUE。 Create variables used for exporting in SophusConfig.cmake set( Sophus_INCLUDE_DIR ${PROJECT_SOURCE_DIR} ) 添加依赖 find_package( Sophus REQUIRED ) find_package( Pangolin ) opencv find_package( OpenCV REQUIRED ) include_directories( ${OpenCV_INCLUDE_DIRS} ) eigen include_directories( “/usr/include/eigen3/” ) pcl find_package( PCL REQUIRED COMPONENT common io ) include_directories( ${PCL_INCLUDE_DIRS} ) add_definitions( ${PCL_DEFINITIONS} ) 在CMakeLists.txt如果需要使用第三方库,那么需要知道三个东西 去哪里找头文件(.h等) 对应于GCC的参数 -I 去哪里找库文件(.so/.lib/.ddl等) 对应于GCC的参数 -L 需要链接的库文件名称 对应于GCC的参数 -l 比如我需要链接第三方库curl,那么在CMakeLists.txt中可以书写如下: include_directories(/usr/include) # 对应于-I target_link_libraries(target curl) # 对应于 -L和-l find_package的作用就是去寻找该库的头文件位置、库文件位置以及库文件名称,并将其设为变量,返回提供给CMakeLists.txt其他部分使用。 添加头文件 include_directories( “/usr/include/eigen3” ) include_directories( ${Pangolin_INCLUDE_DIRS} ) include_directories( ${Sophus_INCLUDE_DIRS} ) 添加一个可执行程序 语法:add_executable( 程序名 源代码文件 ) add_executable( helloSLAM helloSLAM.cpp ) 构建静态库 add_library( hello libHelloSLAM.cpp ) 生成静态库".a"文件 构建静动态库或者共享库 add_library( hello_shared SHARED libHelloSLAM.cpp ) 生成动态库".so"文件 add_executable( useHello useHello.cpp ) 构建大型项目时可以为使用这个库添加一个开关 在项目根目录下的CMakeLists.txt文件中添加如下代码: option (USE_MYMATH “Use tutorial provided math implementation” ON) 将库文件链接到可执行程序上 target_link_libraries( useHello hello_shared ) target_link_libraries( imageBasics ${OpenCV_LIBS} ) target_link_libraries( joinMap ${OpenCV_LIBS} ${PCL_LIBRARIES} ) 指定安装地址 第一种方式: 使用 CMAKE_INSTALL_PREFIX 来指定 cmake -DCMAKE_INSTALL_PREFIX=/usr … 第二种方式: 修改cmake文件,加入: SET(CMAKE_INSTALL_PREFIX < install_path >) Debug和Release版本 debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化,、 release 版的不需要调试信息但需要优化。这些特性在 gcc/g++ 中是通过编译时的参数来决定的,如果将优化程度调到最高需要设置参数-O3,最低是 -O0 即不做优化;添加调试信息的参数是 -g -ggdb ,如果不添加这个参数,调试信息就不会被包含在生成的二进制文件中。 例 PROJECT(main) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET(CMAKE_SOURCE_DIR .) SET(CMAKE_CXX_FLAGS_DEBUG"ENVCXXFLAGS−O0−Wall−g−ggdb")SET(CMAKECXXFLAGSRELEASE"ENV{CXXFLAGS} -O0 -Wall -g -ggdb")SET(CMAKE_CXX_FLAGS_RELEASE"ENVCXXFLAGS−O0−Wall−g−ggdb")SET(CMAKE  C ​      XX  F ​      LAGS  R ​      ELEASE"ENV{CXXFLAGS} -O3 -Wall") AUX_SOURCE_DIRECTORY(. DIR_SRCS) ADD_EXECUTABLE(main ${DIR_SRCS}) 两个变量 CMAKE_CXX_FLAGS_DEBUG 和CMAKE_CXX_FLAGS_RELEASE, 分别用于 debug 和 release 的编译选项。编辑 CMakeList.txt 后需要执行 ccmake 命令生成 Makefile 。在进入项目的根目录,输入 “ccmake .” 进入一个图形化界面。 调试手段 message 打印信息,类似于 echo/printf ,主要用于查cmake文件的语法错误。 set(mysql_use_test_sources ${SOURCES_DIRECTORY}/test_sources/mysql_user_accounts.cpp) message(“mysql_use_test_sources : ${mysql_use_test_sources}”) CMake常用变量 CMAKE_STATIC_LIBRARY_PREFIX 静态库前缀, Linux下默认为lib CMAKE_STATIC_LIBRARY_SUFFIX 静态库后缀,Linux下默认为.a CMAKE_SHARED_LIBRARY_PREFIX 动态库前缀,Linux下默认为lib CMAKE_SHARED_LIBRARY_SUFFIX 动态库后缀,Linux下默认为.so CMAKE_BUILD_TYPE 指定基于make的产生器的构建类型(Release,Debug) CMAKE_C_FLAGS *.C文件编译选项,如 -std=c99 -O3 -march=native CMAKE_CXX_FLAGS *.CPP文件编译选项,如 -std=c++11 -O3 -march=native CMAKE_RUNTIME_OUTPUT_DIRECTORY 生成可执行文件路径 CMAKE_LIBRARY_OUTPUT_DIRECTORY 生成库的文件夹路径