CMakeList笔记

  • 定义

    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})

你可能感兴趣的:(C++,c++)