CMmake
简介
简单来讲,cmake是一个跨平台的makefile生成器。大型项目的额makefile实在是太繁琐了。学习cmake就是在学习其语法。一般来讲,只有在使用c/c++做一个大项目的时候才用得到cmake
基本命令简介
project
1
| PROJECT(<projectname> [CXX] [C] [Java])
|
指定生成项目的名字,可选项目语言(默认位全选)
同时 cmake 系统也帮助我们预定义了
PROJECT_BINARY_DIR 指向生成的项目的路径(build) 和
PROJECT_SOURCE_DIR 指向项目源文件的路径(source)
MESSAGE
1
| MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display")
|
这个指令用于向终端输出用户定义的信息,包含了三种类型:
- SEND_ERROR,产生错误,生成过程被跳过。
- SATUS,输出前缀为—的信息。
- FATAL_ERROR,立即终止所有 cmake 过程.
1
| MESSAGE(STATUS "build " ${PROJECT_BINARY_DIR} " source " ${PROJECT_SOURCE_DIR})
|
SET
显式地定义变量
1
| SET(SRC_LIST main.c t1.c t2.c)
|
将 main.c t1.c t2.c 定义为源文件列表
ADD_EXECUTABLE
生成可执行文件
1
| ADD_EXECUTABLE(hello ${SRC_LIST})
|
ADD_SUBDIRECTORY
位当前目录添加一个子目录
1
| ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
|
INSTALL
CMAKE_INSTALL_PREFIX
DESTINATION 定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候
CMAKE_INSTALL_PREFIX 其实就无效了。如果你希望使用 CMAKE_INSTALL_PREFIX 来定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是
${CMAKE_INSTALL_PREFIX}/<DESTINATION 定义的路径>
1 2 3 4 5 6 7 8 9
| INSTALL(TARGETS myrun mylib mystaticlib RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION libstatic )
上面的例子会将: 可执行二进制 myrun 安装到${CMAKE_INSTALL_PREFIX}/bin 目录 动态库 libmylib 安装到${CMAKE_INSTALL_PREFIX}/lib 目录 静态库 libmystaticlib 安装到${CMAKE_INSTALL_PREFIX}/libstatic 目录
|
普通文件的安装
1 2 3 4 5
| INSTALL(FILES files... DESTINATION <dir> )
|
ADD_LIBRARY
1 2 3
| ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
|
SET_TARGET_PROPERTIES
1 2 3
| SET_TARGET_PROPERTIES(target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ...)
|
GET_TARGET_PROPERTY
1 2 3 4 5 6 7
| 与他对应的指令是: GET_TARGET_PROPERTY(VAR target property) 具体用法如下例,我们向 lib/CMakeListst.txt 中添加: GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME) MESSAGE(STATUS “This is the hello_static OUTPUT_NAME:”${OUTPUT_VALUE}) 如果没有这个属性定义,则返回 NOTFOUND.
|
INCLUDE_DIRECTORIES
1 2
| 现在我们在 src/CMakeLists.txt 中添加一个头文件搜索路径,方式很简单,加入: INCLUDE_DIRECTORIES(/usr/include/hello)
|
LINK_DIRECTORIES
1
| LINK_DIRECTORIES(directory1 directory2 ...)
|
这个指令非常简单,添加非标准的共享库搜索路径,比如,在工程内部同时存在共享库和可 执行二进制,在编译时就需要指定一下这些共享库的路径。这个例子中我们没有用到这个指 令。
TARGET_LINK_LIBRARIES
1 2 3 4 5
| TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ...) 这个指令可以用来为 target 添加需要链接的共享库,本例中是一个可执行文件,但是同样 可以用于为自己编写的共享库添加共享库链接。
|
cmake 学习 assimp的经验
项目文件目录
1 2 3 4 5 6 7 8 9 10 11 12 13
| code contrib doc include samples tests tools readme.md CMakeLists.txt
|
特点:
- 对别的项目的依赖不使用自己编译好的lib或者dll,而是直接使用源文件。估计编译assimp的时候把这些源文件都编译了一遍
- code文件夹就放自己的代码。
- include文件夹就负责对外提供接口。
- 只使用两个CMakeLists.txt,根目录下的负责项目的整体信息描述,code目录下的负责对文件的编译。
cmake 编写
太复杂了,我现在并看不懂。但并不像我这样每一个模块编写一个CMakeLists.txt进行cmake,而是根目录下的负责项目的整体信息描述,code目录下的负责对文件的编译。
项目编译
- 首先按照上面的文件目录进行编排。
- 编写CMakeLists.txt 文件
- 最好编译成动态链接库,不然没有办法将项目的静态依赖库lib文件包含在内。
- 若项目的依赖中存在动态库,比如assimp 时,就没办法将其包含在内了,只能让用户显式地使用assimp.
- 将项目的头文件列举出来保存到include文件夹中,这里面的就是提供给用户的接口,将不想提供给用户的接口删除即可。
- 记得cmake中进行install,将所有需要提供给用户的文件全部放在最显眼的地方。
CMakeLists.txt 编写
我现在对编译有关的知识了解甚少,所以现在只能使用一些最基础的东西,日后会对编译有更深得了解。
cmake的最下版本要求
确定项目的名称
确定项目的目录安排
确定项目的包含目录和库目录
确定项目生成目标位置
确定项目的额依赖
确定目标使用的文件并安排成组
确定目标工程的筛选器
编译项目
安装项目
Demo list
XYY_Game_Engine 的构建示例
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
| cmake_minimum_required (VERSION 3.20)
project(XYY_Game_Engine)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_LIST_DIR})
set(CODE_ROOT_PATH ${CMAKE_CURRENT_LIST_DIR}/code/)
set(BUILD_PATH ${CMAKE_CURRENT_LIST_DIR}/build/)
set(LIB_PATH ${BUILD_PATH}/../lib/)
set(DLL_PATH ${BUILD_PATH}/../dll/)
set(INCLUDE_PATH_CODE ${CMAKE_CURRENT_LIST_DIR}/include/) set(INCLUDE_PATH_CONTRIB ${CMAKE_CURRENT_LIST_DIR}/contrib/include/)
set(LIBRARY_PATH_CONTRIB ${CMAKE_CURRENT_LIST_DIR}/contrib/lib/)
set(TEST_PATH ${CMAKE_CURRENT_LIST_DIR}/build/test/)
INCLUDE_DIRECTORIES(${INCLUDE_PATH_CONTRIB}) INCLUDE_DIRECTORIES(${TEST_PATH}/include)
LINK_DIRECTORIES(${LIBRARY_PATH_CONTRIB}) LINK_DIRECTORIES(${LIB_PATH})
function(SetDefaultTargetProperties target) set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${LIB_PATH} LIBRARY_OUTPUT_DIRECTORY ${LIB_PATH} RUNTIME_OUTPUT_DIRECTORY ${DLL_PATH} ) endfunction()
add_subdirectory(${CODE_ROOT_PATH})
INSTALL(TARGETS XYY_Game_Engine LIBRARY DESTINATION ${CMAKE_CURRENT_LIST_DIR}/lib/ )
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/dll/Debug/XYY_Game_Engine.dll) INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/dll/Debug/XYY_Game_Engine.dll DESTINATION ${CMAKE_CURRENT_LIST_DIR}/bin/ ) endif()
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/dll/assimp-vc142-mt.dll) INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/dll/assimp-vc142-mt.dll DESTINATION ${CMAKE_CURRENT_LIST_DIR}/bin ) endif()
INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/bin/assimp-vc142-mt.dll DESTINATION ${CMAKE_CURRENT_LIST_DIR}/build/test/Release )
INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/bin/XYY_Game_Engine.dll DESTINATION ${CMAKE_CURRENT_LIST_DIR}/build/test/Release ) INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/bin/assimp-vc142-mt.dll DESTINATION ${CMAKE_CURRENT_LIST_DIR}/build/test/Debug ) INSTALL(FILES ${CMAKE_CURRENT_LIST_DIR}/bin/XYY_Game_Engine.dll DESTINATION ${CMAKE_CURRENT_LIST_DIR}/build/test/Debug )
FILE( GLOB_RECURSE Header_Driver ${CODE_ROOT_PATH}/Driver/*.hpp ) FILE( GLOB_RECURSE Header_Driver_LocalDriver ${CODE_ROOT_PATH}/Driver/LocalDriver/*.h ) FILE( GLOB_RECURSE Header_Driver_Global ${CODE_ROOT_PATH}/Driver/GlobalDriver/*.h )
FILE( GLOB_RECURSE Header_Element ${CODE_ROOT_PATH}/Element/*.h )
FILE( GLOB_RECURSE Header_Resource ${CODE_ROOT_PATH}/Resource/*.h )
FILE( GLOB_RECURSE Header_Scene ${CODE_ROOT_PATH}/Scene/*.h )
FILE( GLOB_RECURSE Header_Sync ${CODE_ROOT_PATH}/Sync/*.h ) INSTALL( FILES ${Header_Driver} DESTINATION ${INCLUDE_PATH_CODE}/Driver/ ) INSTALL( FILES ${Header_Driver_LocalDriver} DESTINATION ${INCLUDE_PATH_CODE}/Driver/LocalDriver/ ) INSTALL( FILES ${Header_Driver_Global} DESTINATION ${INCLUDE_PATH_CODE}/Driver/GlobalDriver/ ) INSTALL( FILES ${Header_Element} DESTINATION ${INCLUDE_PATH_CODE}/Element/ ) INSTALL( FILES ${Header_Resource} DESTINATION ${INCLUDE_PATH_CODE}/Resource/ ) INSTALL( FILES ${Header_Scene} DESTINATION ${INCLUDE_PATH_CODE}/Scene/ ) INSTALL( FILES ${Header_Sync} DESTINATION ${INCLUDE_PATH_CODE}/Sync/ ) INSTALL( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/code/Scxmlexample DESTINATION ${CMAKE_CURRENT_LIST_DIR}/include/ ) INSTALL( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/code/resources DESTINATION ${CMAKE_CURRENT_LIST_DIR}/include/ ) INSTALL( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/code/GLSL DESTINATION ${CMAKE_CURRENT_LIST_DIR}/include/ )
INSTALL( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/Scxmlexample DESTINATION ${TEST_PATH}/ )
INSTALL( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/resources DESTINATION ${TEST_PATH}/ )
INSTALL( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include DESTINATION ${TEST_PATH}/ )
add_subdirectory(test)
|
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
FILE(GLOB_RECURSE SOURCE_CODE Driver/* Driver/LocalDriver/* Driver/GlobalDriver/* Element/* Resource/* Scene/* Sync/* ${INCLUDE_PATH_CONTRIB}/*.c )
FILE( GLOB_RECURSE SRC_Driver Driver/*.hpp ) source_group(Driver FILES ${SRC_Driver}) FILE( GLOB_RECURSE SRC_Driver_LocalDriver Driver/LocalDriver/* ) source_group(Driver//LocalDriver FILES ${SRC_Driver_LocalDriver}) FILE( GLOB_RECURSE SRC_Driver_Global Driver/GlobalDriver/* ) source_group(Driver//GlobalDriver FILES ${SRC_Driver_Global})
FILE( GLOB_RECURSE SRC_Element Element/* ) source_group(Element FILES ${SRC_Element})
FILE( GLOB_RECURSE SRC_Resource Resource/* ) source_group(Resource FILES ${SRC_Resource})
FILE( GLOB_RECURSE SRC_Scene Scene/* ) source_group(Scene FILES ${SRC_Scene})
FILE( GLOB_RECURSE SRC_Sync Sync/* ) source_group(Sync FILES ${SRC_Sync})
FILE( GLOB_RECURSE SRC_Scxmlexample ${CODE_ROOT_PATH}/Scxmlexample/*.xml ) source_group(Scxmlexample FILES ${SRC_Scxmlexample})
FILE( GLOB DEPENDENCE_LIB ${LIBRARY_PATH_CONTRIB}/*.lib )
add_library(XYY_Game_Engine SHARED ${SOURCE_CODE} ${SRC_Scxmlexample}) SetDefaultTargetProperties(XYY_Game_Engine)
target_link_libraries(XYY_Game_Engine opengl32 glfw3.lib assimp-vc142-mt.lib tinyxml.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib )
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
FILE( GLOB_RECURSE SRC_Scxmlexample_test ${CODE_ROOT_PATH}/Scxmlexample/*.xml ) source_group(Scxmlexample FILES ${SRC_Scxmlexample_test})
add_executable(test1 test1.cpp ${SRC_Scxmlexample_test}) ADD_DEPENDENCIES(test1 XYY_Game_Engine) target_link_libraries(test1 XYY_Game_Engine)
add_executable(test2 test2.cpp ${SRC_Scxmlexample_test}) ADD_DEPENDENCIES(test1 XYY_Game_Engine) target_link_libraries(test2 XYY_Game_Engine)
|