一、常用命令
1.指定最小版本
//设置cmake需要的最低版本号
cmake_minimum_required(VERSION 3.6)
2.设置项目名称
//生成test.sln的工程名称
project(test)
3.基本指令
//生成可执行程序
add_executable(test, main.cpp)
//生成静态库
add_library(libstatic STATIC libstatic.cpp)
//生成动态库
add_library(dlldemo SHARED libdemo.cpp)
//遍历子文件夹中的CMakeLists.txt
add_subdirectory(subdir)
//设置包含的目录
include_directories(${PROJECT_SOURCE_DIR}/include)
//搜索所有的cpp文件
aux_source_directory(. SRC_LIST)
//自定义搜索
file(GLOB SRC "*.cpp" "subdir1/*cpp")
//连接库
target_link_libraries(test libadd.lib)
//将dll lb安装到指定的文件夹下
install(TARGETS libswap
RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin
LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/lib
ARCHIVE DESTINATION ${PROJECT_SOURCE_DIR}/lib)
//将文件中的.h文件安装到指定文件夹下
file(GLOB head_files *.h)
install(FILES ${head_files} DESTINATION ${PROJECT_SOURCE_DIR}/include)
4.设置变量
//在编译选项中加入C++11支持
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
//将当前编译的静态库或者动态库输出到当前项目文件夹lib子目录下
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
//设定可执行二进制文件的目录
set( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
//设置变量的值,用一个变量代替多个
set(SRC main.cpp test.cpp)
5.打印消息
//输出正常
message(STATUS "build type:")
//输出警告
message(WARNING "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")
//输出错误
message(FATAL_ERROR "Opencv Not Found!")
6.常用变量
变量名 | 含义 |
---|---|
PROJECT_NAME | project 命令中写的项目名 |
CMAKE_VERSION | 当前使用CMake的版本 |
CMAKE_SOURCE_DIR | 工程顶层目录,即入口CMakeLists文件所在路径 |
PROJECT_SOURCE_DIR | 工程顶层目录,即入口CMakeLists文件所在路径 |
CMAKE_BINARY_DIR | 工程编译发生的目录,即执行cmake命令进行项目配置的目录,一般为build |
PROJECT_BINARY_DIR | 同CMAKE_BINARY_DIR |
CMAKE_CURRENT_SOURCE_DIR | 当前处理的CMakeLists.txt所在的路径 |
CMAKE_INSTALL_PREFIX | 指定make install 命令执行时包安装路径 |
LIBRARY_OUTPUT_PATH | 重新定义目标链接库文件的存放位置 |
EXECUTABLE_OUTPUT_PATH | 重新定义目标二进制可执行文件的存放位置 |
CMAKE_MODULE_PATH | 定义了cmake 模块(XXX.cmake)所在的路径 |
7.开关选项
变量名 | 含义 |
---|---|
CMAKE_BUILD_TYPE | 编译选项,Release或者Debug,如set(CMAKE_BUILD_TYPE "Release") |
CMAKE_CXX_FLAGS | 设置C++11编译,set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") |
CMAKE_C_FLAGS | 设置C编译选项 |
CMAKE_CXX_COMPILER | 指定C编译器 |
CMAKE_C_COMPILER | 指定C++编译器 |
BUILD_SHARED_LIBS | 控制默认的库编译方式。如果未进行设置,使用ADD_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库,如果 set(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库 |
8.链接外部库
在CMakeLists.txt中使用第三方库需要知道头文件、lib和dll。
find_package的作用就是去寻找该库的头文件位置、库文件位置以及库文件名称,并将其设为变量,返回提供给CMakeLists.txt其他部分使用。
find_pacage()方法签名如下:
find_package(<package> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
QUITE 参数指代,当查找出错时,屏蔽 message() 的输出。 REQUIRED 参数指代,当找不到 package 时,终止过程。
现在用 XXX 代表要查找的 package 名字
find_pacakge(XXX REQUIRED)
会设置一系列变量。
XXX_FOUND 代表库是否查找成功
XXX_INCLUDE_DIRS 代表头文件的路径
XXX_LIBRARIES 代表库文件的路径
两种模式搜索库:
-
Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成。
以opencv为例,并且该lib需要设置到环境变量中
//查找opencv
find_package(OpenCV REQUIRED)//(包的名称及最低版本)找到后面需要库和头文件的包
if (OpenCV_FOUND)
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}" \n)
#include headers
include_directories(${OpenCV_INCLUDE_DIRS})
#target generation
add_executable(OpenCV_test main.cpp)
#link libraries
target_link_libraries(OpenCV_test ${OpenCV_LIBS})
else ()
message(FATAL_ERROR "Could not locate OpenCV" \n)
endif()
- Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake或者XXX-config.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。
1.法一
set(libtest_DIR E:/test/3rdparty)
find_package(libtest_DIR REQUIRED)
2.法二
//Find 3rdparty/libtest
find_package(libtest REQUIRED HINTS "${CMAKE_SOURCE_DIR}/3rdparty")
if(NOT libtest_FOUND)
message(FATAL_ERROR "libtest Not Found!")
endif()
include_directories(${libtest_DIR})
target_link_libraries(main "${libtest_DIR}/libtest.lib")
在3rdparty/libtest的文件夹下创建一个libtestConfig.cmake文件,内容如下:
include(FindPackageHandleStandardArgs)
9.例子
9.1 单个cpp
cmake_minimum_required(VERSION 3.6)
# Name the project
project(LEETCODE)
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_executable(LeetCode src/LeetCode.cpp)
message(${PROJECT_SOURCE_DIR})
message(${CMAKE_INSTALL_PREFIX})
# Install the executeable program in the bin folder of the
# current project directory.
install(TARGETS LeetCode DESTINATION ${PROJECT_SOURCE_DIR}/bin)
9.2 多个cpp和外部库
cmake_minimum_required(VERSION 3.6)
# Name the project
project(test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
find_package(add REQUIRED HINTS "${CMAKE_SOURCE_DIR}/3rdparty")
if(NOT add_FOUND)
message(FATAL_ERROR "lib add Not Found")
endif()
include_directories(${PROJECT_SOURCE_DIR}/include ${add_DIR})
#add_executable(test src/main.cpp src/swap/swap.cpp)
#遍历目录中的所有文件
#file(GLOB_RECURSE SRC_LIST "*.cpp" "*.c")
#message(STATUS ${SRC_LIST})
add_executable(test src/main.cpp src/swap/swap.cpp)
target_link_libraries(test ${add_DIR}/libadd.lib)
install(TARGETS test DESTINATION ${PROJECT_SOURCE_DIR}/bin)
9.3 多个cpp和子文件中文件编译成dll
//libswap在编译的时候生成dll
cmake_minimum_required(VERSION 3.6)
# Name the project
project(test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
find_package(add REQUIRED HINTS "${CMAKE_SOURCE_DIR}/3rdparty")
if(NOT add_FOUND)
message(FATAL_ERROR "lib add Not Found")
endif()
include_directories(${PROJECT_SOURCE_DIR}/include ${add_DIR})
add_subdirectory(./src/swap)
add_executable(test src/main.cpp)
#win生成的libswap在lib/Debug文件夹下,Release模式在Release文件夹下
#target_link_libraries(test ${add_DIR}/libadd.lib ${PROJECT_SOURCE_DIR}/lib/Debug/libswap.lib)
#直接使用libswap就可以
target_link_libraries(test ${add_DIR}/libadd.lib libswap)
install(TARGETS test DESTINATION ${PROJECT_SOURCE_DIR}/bin)
//swap文件下的CMakeLists.txt
aux_source_directory(. SUB_SRC)
file(GLOB head_files *.h)
add_library(libswap SHARED ${SUB_SRC})
#set(head_files swap.h 1.h ${PROJECT_SOURCE_DIR}/3rdparty/add/add.h)
install(FILES ${head_files} DESTINATION ${PROJECT_SOURCE_DIR}/include)
#将dll lb安装到制定的文件夹下
install(TARGETS libswap
RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin
LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/lib
ARCHIVE DESTINATION ${PROJECT_SOURCE_DIR}/lib)
//main.cpp
#include "swap.h"
#include "add.h"
#include <string>
int main()
{
CTest obj(2,8);
obj.swap();
dllTest::CAdd add;
std::cout<<"dll sum = "<< add.sum(1, 6);
dllTest::show();
}
#pragma once
#ifdef libswap_EXPORTS
#ifdef __GNUC__
#ifndef __linux__
#define DLL_TEST_API __attribute__((dllexport))
#else
#define DLL_TEST_API __attribute__((visibility("default")))
#endif
#else
#define DLL_TEST_API __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#ifndef __linux__
#define DLL_TEST_API __attribute__((dllimport))
#else
#define DLL_TEST_API __attribute__((visibility("default")))
#endif
#else
#define DLL_TEST_API
#endif
#endif
#include <iostream>
class DLL_TEST_API CTest
{
public:
CTest(int a, int b)
{
this->a = a;
this->b = b;
}
void swap();
private:
int a;
int b;
};
//swap.cpp
#include "swap.h"
void CTest::swap()
{
std::cout<<"before:"<<std::endl;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
int temp;
temp = a;
a = b;
b = temp;
std::cout<<"after:"<<std::endl;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
}