cmake学习笔记-1

因为Clion是用cmake来构建工程的,特地学一些简单的东西

基本操作

对于一个工程,首先要设置

  • cmake版本
  • 工程名
  • c++的标准
1
2
3
cmake_minimum_required(VERSION 3.8)
project(Fat32)
set(CMAKE_CXX_STANDARD 11)

然后,配置源文件的路径,可以将源文件设置成一个变量,然后生成可执行文件

1
2
3
4
5
6
7
8
9
10
11
12
13
#配置单个或者多个
set(Source ./source.cpp)
set(Source ./source1.cpp ./source2.cpp)
#配置整个文件夹中的源文件
aux_source_directory(./source Source)
#如果需要,可以链接库,例如gtest,pthread等等,这些库必须是能在环境变量中搜的到的,也就是可以直接-l[lib]
LINK_LIBRARIES(gtest)
LINK_LIBRARIES(gtest_main)
LINK_LIBRARIES(pthread)
#如果需要,可以设置可执行文件输出的路径
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY [path])
#生成可执行文件
add_executable(Exec ${Source})

option和configure_file

有时候我们需要自定义编译,这时可以设置optionconfigure_file

注意,option和缓存相关,上次的结果会影响下次的默认设置,完全自定义需要手动设置所有的option

1
2
3
4
config.h.in:

#cmakedefine PYTHON2
#cmakedefine ATUO
1
2
3
4
5
6
7
option(AUTO "choose the version of python automatically" ON)
option(PYTHON2 "version python2" OFF)
#将config.h.in的内容设置好后覆盖config.h,然后再编译
configure_file(
"config.h.in"
"${PROJECT_SOURCE_DIR}/src/config.h"
)

链接动态库

详细

cmake支持某些库,具体可以使用cmake --help-module-list查看

如果是支持的模块,可以使用find_package()查找,然后一些变量会被设置

1
2
3
4
5
<NAME>_VERSION_STRING //版本
<NAME>_FOUND //是否找到
<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES //头文件的路径
<NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS //lib的路径
<NAME>_DEFINITIONS
1
2
3
4
find_package(PythonLibs)
#链接
add_executable(target .....)
target_link_libraries(target ${PYTHON_LIBRARIES})

字符串替换

我们可以操作字符串变量,进行匹配,替换

1
2
3
string( REPLACE ".cpp" "" testname ${testsourcefile}) //一般替换
string( REGEX REPLACE "(.[1-9]).*" "" version ${PYTHONLIBS_VERSION_STRING} ) //正则替换
string(替换模式 替换字符串 目标字符串 输出字符串 输入字符串)

IF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if()
else()
endif()

#例如
if(AUTO)
if(version STREQUAL 2)
MESSAGE("choose python2 automatically")
set(PYTHON2 ON)
else()
MESSAGE("choose python3 automatically")
set(PYTHON2 OFF)
endif()
else()
if(PYTHON2)
if(NOT (version STREQUAL 2))
#if you use python2.x, set the include_dir and libraries_dir
#you can use "find / -name "libpython2*" " to get the path of your lib
set(PYTHON_INCLUDE_DIRS /usr/include/python2.7)
set(PYTHON_LIBRARIES /usr/lib/libpython2.7.dylib)
endif()
MESSAGE("choose python 2")
else()
MESSAGE("choose python 3")
endif()
endif()

具体例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
cmake_minimum_required(VERSION 3.11)
project(PythonCaller)
set(CMAKE_CXX_STANDARD 11)
find_package(PythonLibs)

aux_source_directory(./test/version_test VersionTest)
MESSAGE(${PYTHON_INCLUDE_DIRS})

#get the version of python, format : [2-3].*, use the regex "(.[1-9]).*"
STRING( REGEX REPLACE "(.[1-9]).*" "" version ${PYTHONLIBS_VERSION_STRING} )

MESSAGE("Defalut : Python3")

option(AUTO "choose the version of python automatically" ON)
option(PYTHON2 "version python2" OFF)

if(AUTO)
if(version STREQUAL 2)
MESSAGE("choose python2 automatically")
set(PYTHON2 ON)
else()
MESSAGE("choose python3 automatically")
set(PYTHON2 OFF)
endif()
else()
if(PYTHON2)
if(NOT (version STREQUAL 2))
#if you use python2.x, set the include_dir and libraries_dir
#you can use "find / -name "libpython2*" " to get the path of your lib
set(PYTHON_INCLUDE_DIRS /usr/include/python2.7)
set(PYTHON_LIBRARIES /usr/lib/libpython2.7.dylib)
endif()
MESSAGE("choose python 2")
else()
MESSAGE("choose python 3")
endif()
endif()

configure_file(
"config.h.in"
"${PROJECT_SOURCE_DIR}/src/config.h"
)

include_directories(${PYTHON_INCLUDE_DIRS})
add_executable(version_test ${VersionTest})
target_link_libraries(version_test ${PYTHON_LIBRARIES})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#Project Setting
cmake_minimum_required(VERSION 3.8)
project(Fat32)
set(CMAKE_CXX_STANDARD 11)

LINK_LIBRARIES(gtest)
LINK_LIBRARIES(gtest_main)
LINK_LIBRARIES(pthread)

#Path Setting
aux_source_directory(./VFS MAIN)
aux_source_directory(./UnitTesting TEST)
set(FATLIB FAT/fat.cpp)
link_directories(./cmake-build-debug)

#Generate dymanic Library
add_library(fat SHARED ${FATLIB})

#Generate Unit Test
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./unit_test)
#add_executable(UnitTest ${TEST} ${FATLIB})


#Generate Main
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./terminal)
add_executable(Terminal ${MAIN})
target_link_libraries(Terminal libfat.dylib)

#Generate Commands
aux_source_directory(./cmd CMD)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./bin)

foreach( testsourcefile ${CMD} )
string( REPLACE ".cpp" "" testname ${testsourcefile})
string( REPLACE "./cmd/" "" testname ${testname})
MESSAGE(${testname})
add_executable(${testname} ${testsourcefile})
target_link_libraries(${testname} libfat.dylib)
endforeach( testsourcefile ${CMD})

aux_source_directory(./tinyEditor editor)
add_executable(edit ./tinyEditor/editor.cpp ./tinyEditor/main.cpp ./tinyEditor/fat32_editor.cpp ./FAT/fat.cpp)