CMake是一种跨平台编译工具,CMake主要是编写CMakeLists.txt文件,然后通过cmake命令将CMakeLists.txt文件转化为make所需要的Makefile文件,最后用make命令编译源码生成可执行程序或者库文件。
指令是大小写无关的,参数和变量是大小写相关的
CMakeLists.txt常见指令
1、cmake_minimum_required(VERSION 2.6)命令
#指定CMake编译最低要求版本
例:CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
2、PROJECT(
#给项目命名
PROJECT(TEST)
3、ADD_SUBDIRECTORY命令
#该命令告诉CMake去子目录中查看可用的CMakeLists.txt文件
4、ADD_EXECUTABLE命令
#将hello.cpp生成可执行文件hello
ADD_EXECUTABLE(hello ${SOURCE})
5、ADD_LIBRARY命令
#变量SRC_LIST_CPP 与SRC_LIST_C 指定生成test动态库 默认生成静态库 SHARED指定生成库类型为动态库
ADD_LIBRARY(test SHARED ${SRC_LIST_CPP} ${SRC_LIST_C})
ADD_LIBRARY(test STATIC util.cpp) # 生成静态库
6、FILE命令
#收集c/c++文件并赋值给变量SRC_LIST_CPP ${PROJECT_SOURCE_DIR}代表区当前项目录
FILE(GLOB SRC_LIST_CPP ${PROJECT_SOURCE_DIR}/src/*.cpp)
7、INCLUDE_DIRECTORIES命令
#指定头文件目录
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
8、LINK_DIRECTORIES命令
#指定链接库文件目录
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/lib)
9、TARGET_LINK_LIBRARIES命令
#指定hello 链接库test
TARGET_LINK_LIBRARIES(hello test)
10、AUX_SOURCE_DIRECTORY命令
#AUX_SOURCE_DIRECTORY(dir VAR) 发现一个目录下所有的源代码文件并将列表存储在一个变量中
AUX_SOURCE_DIRECTORY(. SRC_LIST) # 搜索当前目录下的所有.cpp文件,放到SRC_LIST变量中
8、SET命令
#用来显式的定义变量
例子:
#用变量代替值,例子中定义SRC_LST代替后面的字符串
SET (SRC_LST main.c test.c)
#指定生成库文件的目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
变量名 | 含义 |
---|---|
JECT_NAME | project命令中写的项目名 |
KE_VERSION | 当前使用CMake的版本 |
KE_SOURCE_DIR | 工程顶层目录,即入口CMakeLists文件所在路径 |
JECT_SOURCE_DIR | 同CMAKE_SOURCE_DIR |
KE_BINARY_DIR | 工程编译发生的目录,即执行cmake命令进行项目配置的目录,一般为build |
JECT_BINARY_DIR | 同CMAKE_BINARY_DIR |
KE_CURRENT_SOURCE_DIR | 当前处理的CMakeLists.txt所在的路径 |
KE_CURRRENT_BINARY_DIR | 当前处理的CMakeLists.txt中生成目标文件所在编译目录 |
KE_CURRENT_LIST_FILE | 输出调用这个变量的CMakeLists.txt文件的完整路径 |
KE_CURRENT_LIST_DIR | 当前处理的CMakeLists.txt文件所在目录的路径 |
KE_INSTALL_PREFIX | 指定make install命令执行时包安装路径 |
KE_MODULE_PATH | find_package命令搜索包路径之一,默认为空 |
KE_BUILD_TYPE | 编译选项,Release或者Debug,如set(CMAKE_BUILD_TYPE “Release”) |
KE_CXX_FLAGS | 编译标志,设置C++11编译,set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -std=c++11”) |
#指定CMake编译最低要求版本3.6
cmake_minimum_required(VERSION 3.6)
#CMAKE_BUILD_TYPE 代替后面的字符串RelWithDebInfo CACHE STRING "build type"
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type")
#给项目命名tutorial
project(tutorial
LANGUAGES C CXX
)
#CMAKE_RUNTIME_OUTPUT_DIRECTORY 代替后面的字符串${PROJECT_SOURCE_DIR}
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR})
if(ANDROID)
#指定链接库文件目录${OPENSSL_LINK_DIR}
link_directories(${OPENSSL_LINK_DIR})
else()
find_library(LIBRT rt)
find_package(OpenSSL REQUIRED)
endif()
find_package(workflow REQUIRED CONFIG HINTS ..)
#指定头文件目录${OPENSSL_INCLUDE_DIR} ${WORKFLOW_INCLUDE_DIR}
include_directories(${OPENSSL_INCLUDE_DIR} ${WORKFLOW_INCLUDE_DIR})
#指定链接库文件目录${WORKFLOW_LIB_DIR}
link_directories(${WORKFLOW_LIB_DIR})
if (KAFKA STREQUAL "y")
find_path(SNAPPY_INCLUDE_PATH NAMES snappy.h)
#指定头文件目录${SNAPPY_INCLUDE_PATH}
include_directories(${SNAPPY_INCLUDE_PATH})
endif ()
if (WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP /wd4200")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4200 /std:c++14")
else ()
#CMAKE_C_FLAGS代替后面的字符串"${CMAKE_C_FLAGS} -Wall -fPIC -pipe -std=gnu90"
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fPIC -pipe -std=gnu90")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -pipe -std=c++11 -fno-exceptions")
endif ()
#TUTORIAL_LIST代替后面的字符串
set(TUTORIAL_LIST
tutorial-00-helloworld
tutorial-01-wget
tutorial-04-http_echo_server
tutorial-05-http_proxy
tutorial-06-parallel_wget
tutorial-07-sort_task
tutorial-08-matrix_multiply
tutorial-09-http_file_server
tutorial-11-graph_task
tutorial-15-name_service
tutorial-20-reducer
)
if (APPLE)
set(WORKFLOW_LIB workflow pthread OpenSSL::SSL OpenSSL::Crypto)
elseif (ANDROID)
set(WORKFLOW_LIB workflow ssl crypto c)
else ()
set(WORKFLOW_LIB workflow pthread OpenSSL::SSL OpenSSL::Crypto ${LIBRT})
endif ()
foreach(src ${TUTORIAL_LIST})
string(REPLACE "-" ";" arr ${src})
list(GET arr -1 bin_name)
#将${src}.cc生成可执行文件${bin_name}
add_executable(${bin_name} ${src}.cc)
#指定${bin_name}链接库${WORKFLOW_LIB}
target_link_libraries(${bin_name} ${WORKFLOW_LIB})
endforeach()
if (NOT REDIS STREQUAL "n")
set(TUTORIAL_LIST
tutorial-02-redis_cli
tutorial-03-wget_to_redis
)
foreach(src ${TUTORIAL_LIST})
string(REPLACE "-" ";" arr ${src})
list(GET arr -1 bin_name)
add_executable(${bin_name} ${src}.cc)
target_link_libraries(${bin_name} ${WORKFLOW_LIB})
endforeach()
endif()
if (NOT MYSQL STREQUAL "n")
set(TUTORIAL_LIST
tutorial-12-mysql_cli
)
foreach(src ${TUTORIAL_LIST})
string(REPLACE "-" ";" arr ${src})
list(GET arr -1 bin_name)
add_executable(${bin_name} ${src}.cc)
target_link_libraries(${bin_name} ${WORKFLOW_LIB})
endforeach()
endif()
if (KAFKA STREQUAL "y")
add_executable("kafka_cli" "tutorial-13-kafka_cli.cc")
target_link_libraries("kafka_cli" wfkafka ${WORKFLOW_LIB} z snappy lz4 zstd)
endif ()
set(DIR10 tutorial-10-user_defined_protocol)
add_executable(server ${DIR10}/server.cc ${DIR10}/message.cc)
add_executable(client ${DIR10}/client.cc ${DIR10}/message.cc)
target_link_libraries(server ${WORKFLOW_LIB})
target_link_libraries(client ${WORKFLOW_LIB})
set_target_properties(server PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/${DIR10})
set_target_properties(client PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/${DIR10})