CMake学习笔记——基础篇
2018-02-03 12:33
369 查看
最近看到好多开源项目的编译配置文件都是使用CMake写的,于是花些时间学习,并做备忘整理
这篇文档以一个简单的项目为例,对CMake的常用命令进行介绍
主要包括了包含头文件路径、生成库、生成二进制文件等功能。不包括安装、测试等功能
command(arg1 arg2 …) 指令参数使用括弧括起来,参数之间使用空格或分号分开
指令大小写无关,参数和变量是大小写相关的
CMAKE_MINIMUM_REQUIRED(VERSION version [FATAL_ERROR])
指定此CMakefiles.txt支持的最小CMak
4000
e版本
这条指令建议添加到顶层的CMakefiles.txt中
PROJECT(projectname [CXX] [C] [Java])
定义工程名称,如果名称中有空格,需要使用引号括起来
如果需要还可以指定工程支持的语言。
这个指令隐式定义了两个cmake变量:
同时cmake系统预定义了
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
设置变量
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
添加头文件搜索路径。路径之间使用空格分隔。如果路径中包含空格,可使用双引号括起来
可以通过AFTER或者BEFORE参数,来控制添加的路径在已有路径的前面还是后面
LINK_DIRECTORIES(dir1 dir2 …)
添加非标准的共享库搜索路径
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)
向终端输出信息。
EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH
指定最终生成的二进制文件存放的位置(不包含中间文件)
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制文件存放位置
ADD_DEFINITIONS(-Ddef1 -Ddef2 …)
向C/C++编译器添加编译参数, 参数之间用空格分隔
也可以使用 CMAKE_C_FLAGS 或 CMAKE_CXX_FLAGS 为 C/C++ 设置编译选项
ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
生成一个库文件
在不支持dyld的系统中,MODULE被当作SHARED对待
SET_TARGET_PROPERTIES(target1 target2 … PROPERTIES prop1 value1 prop2 value2 …)
用来设置输出的名称,对于动态库,还可以用来指定动态库版本或API版本
它对应的指令是: GET_TARGET_PROPERTY(VAR target property)
ADD_EXECUTABLE(target source …)
生成一个名为 target 的可执行文件
CMake会自动处理依赖关系,所以source中不需要列出头文件
PS: CMake是根据同名来查询头文件的?如果这样,非同名头文件是否应该被添加到source?
TARGET_LINK_LIBRARIES(dir1 dir2 …)
添加非标准的共享库搜索路径
注意事项
在工程下创建build目录,进入build目录,运行
切忌在工程目录下执行
如果需要看到make的详细过程,可以使用make VERBOSE=1 命令来进行编译
这篇文档以一个简单的项目为例,对CMake的常用命令进行介绍
主要包括了包含头文件路径、生成库、生成二进制文件等功能。不包括安装、测试等功能
一些语法规则
变量使用${ }方式取值command(arg1 arg2 …) 指令参数使用括弧括起来,参数之间使用空格或分号分开
指令大小写无关,参数和变量是大小写相关的
一个简单的例子
目录结构
. ├── CMakeLists.txt ├── include │ └── hello.h └── src ├── CMakeLists.txt ├── lib │ ├── CMakeLists.txt │ └── hello.c └── src ┊ ├── CMakeLists.txt ┊ └── main.c
源码
./CMakeLists.txt
cmake_minimum_required(VERSION 3.9) project(HELLO) set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) set(LIBRARY_DIR ${PROJECT_BINARY_DIR}/output/libs) set(BIN_DIR ${PROJECT_BINARY_DIR}/output/bin) include_directories(${INCLUDE_DIR}) link_directories(${LIBRARY_DIR}) MESSAGE(STATUS "##PROJECT_SOURCE_DIR is " ${PROJECT_SOURCE_DIR}) MESSAGE(STATUS "##PROJECT_BINARY_DIR is " ${PROJECT_BINARY_DIR}) set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR}) set(LIBRARY_OUTPUT_PATH ${LIBRARY_DIR}) add_subdirectory(src)
CMAKE_MINIMUM_REQUIRED(VERSION version [FATAL_ERROR])
指定此CMakefiles.txt支持的最小CMak
4000
e版本
这条指令建议添加到顶层的CMakefiles.txt中
PROJECT(projectname [CXX] [C] [Java])
定义工程名称,如果名称中有空格,需要使用引号括起来
如果需要还可以指定工程支持的语言。
这个指令隐式定义了两个cmake变量:
<projectname>_BINARY_DIR以及
<projectname>_SOURCE_DIR,前者指向编>译路径,后者为工程路径
同时cmake系统预定义了
PROJECT_BINARY_DIR和
PROJECT_SOURCE_DIR变量,分别与
<projectname>_BINARY_DIR与
<projectname>_SOURCE_DIR一致
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
设置变量
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
添加头文件搜索路径。路径之间使用空格分隔。如果路径中包含空格,可使用双引号括起来
可以通过AFTER或者BEFORE参数,来控制添加的路径在已有路径的前面还是后面
LINK_DIRECTORIES(dir1 dir2 …)
添加非标准的共享库搜索路径
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)
向终端输出信息。
SEND_ERROR产生错误,生成过程被跳过;
STATUS输出前缀为-的信息;
FATAL_ERROR立即终止所有cmake过程
EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH
指定最终生成的二进制文件存放的位置(不包含中间文件)
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制文件存放位置
EXCLUDE_FROM_ALL参数含义是将这个目录从编译过程中排除
./src/CMakeLists.txt
add_subdirectory(src) add_subdirectory(lib)
./src/lib/CMakeLists.txt
set(SRC_LIST hello.c) # set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/output/lib) # add_library(libhello ${SRC_LIST}) add_definitions(-DLIBHELLO_BUILD) add_library(hello_shared SHARED ${SRC_LIST}) set_target_properties(hello_shared PROPERTIES OUTPUT_NAME "hello") set_target_properties(hello_shared PROPERTIES VERSION 1.2 SOVERSION 1) add_library(hello_static STATIC ${SRC_LIST}) set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")
ADD_DEFINITIONS(-Ddef1 -Ddef2 …)
向C/C++编译器添加编译参数, 参数之间用空格分隔
也可以使用 CMAKE_C_FLAGS 或 CMAKE_CXX_FLAGS 为 C/C++ 设置编译选项
ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
生成一个库文件
在不支持dyld的系统中,MODULE被当作SHARED对待
SET_TARGET_PROPERTIES(target1 target2 … PROPERTIES prop1 value1 prop2 value2 …)
用来设置输出的名称,对于动态库,还可以用来指定动态库版本或API版本
它对应的指令是: GET_TARGET_PROPERTY(VAR target property)
./src/src/CMakeLists.txt
set(LIB_LIST hello.so) set(SRC_LIST main.c) # set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/output/bin) add_executable(hello ${SRC_LIST}) target_link_libraries(hello ${LIB_LIST})
ADD_EXECUTABLE(target source …)
生成一个名为 target 的可执行文件
CMake会自动处理依赖关系,所以source中不需要列出头文件
PS: CMake是根据同名来查询头文件的?如果这样,非同名头文件是否应该被添加到source?
TARGET_LINK_LIBRARIES(dir1 dir2 …)
添加非标准的共享库搜索路径
./include/hello.h
#ifndef _HELLO_H #define _HELLO_H #if defined _WIN32 #if LIBHELLO_BUILD ┊ #define LIBHELLO_API __declspec(dllexport) #else ┊ #define LIBHELLO_API __declspec(dllimport) #endif #else #define LIBHELLO_API #endif LIBHELLO_API void hello(); #endif
./src/lib/hello.c
#include <stdio.h> #include <stdlib.h> void hello() { printf("hello\n"); }
./src/src/main.c
#include <stdio.h> #include <stdlib.h> #include "hello.h" int main(int argc, char *argv[]) { hello(); return 0; }
构建工程
构建命令# cmake -G <generator name> <path-to-source>
-G <generator name>告诉CMake应该产生什么类型的项目文件
注意事项
在工程下创建build目录,进入build目录,运行
cmake -G "Unix Makefiles" ../,此时会在build目录下生成Makefile以及一些中间文件
切忌在工程目录下执行
cmake -G "Unix Makefiles" ./,因为这样会在工程目录下生成Makefile和一些中间文件,>这些文件不能通过命令清理
如果需要看到make的详细过程,可以使用make VERBOSE=1 命令来进行编译
相关文章推荐
- Spring.NET学习笔记13——AOP的概念(基础篇) Level 200
- 《加密与解密》--基础篇学习笔记
- Python学习笔记(基础篇)_002_类型转换
- Python学习笔记——基础篇(1): 变量及其类型
- ASP.NET基础篇--2、学习笔记
- Android程序开发学习笔记系列——基础篇(附源码)
- Java学习笔记 - 基础篇
- 鸟哥Linux私房菜_基础篇(第二版)_第八章学习笔记
- cmake 学习笔记(一)
- cmake 学习笔记(二) - 1+1=2 - 博客频道 - CSDN.NET
- 基础中的基础篇PHP . MYSQL .我的学习笔记
- cmake 学习笔记(一)
- cmake 学习笔记(二)
- Ext第一周 史上最强学习笔记---GridPanel(基础篇)
- python学习笔记三之函数(基础篇)
- 鸟哥Linux私房菜_基础篇(第二版)_第一章学习笔记
- CMake 学习笔记整理(3)
- cmake 学习笔记(二)
- python学习笔记-基础篇-day03 python历史、32bit和64bit系统的区别,系统运行机制浅析
- cmake 学习笔记