附带源码CMake工程目录结构
附录A已经介绍过,本系列文章是由CMake构建工具组织的,以glib_markup和glib_regex为例,目录结构举例如下:
glib_examples
├── CMakeCommonFile.txt
├── CMakeCustomCommonFile.txt
├── CMakeLists.txt
├── compile_and_exec_all_examples.sh
├── glib_markup
│ ├── CMakeLists.txt
│ ├── glib_markup_basic
│ │ ├── CMakeLists.txt
│ │ ├── glib_markup_xml_parser.c
│ │ └── xml_basic.xml
│ └── glib_markup_element
│ ├── CMakeLists.txt
│ ├── glib_markup_get_element.c
│ └── xml_element.xml
└── glib_regex
├── CMakeLists.txt
├── glib_regex_replace
│ ├── CMakeLists.txt
│ └── glib_regex_replace_some_string.c
└── glib_regex_string_split
├── CMakeLists.txt
└── glib_regex_string_split.c
附带源码各CMake内容
以下是附带源码目录结构重要CMake文件说明。
glib_examples
├── CMakeCommonFile.txt(根目录公共CMake文件)
├── CMakeCustomCommonFile.txt(根目录用户自定义CMake文件)
├── CMakeLists.txt(根目录CMake主文件)
├── glib_markup(子目录,一个大的功能模块,包含多个示例程序目录)
│ ├── CMakeLists.txt(子目录CMake主文件)
│ ├── glib_markup_basic(示例程序目录,一个完整功能的演示)
│ │ ├── CMakeLists.txt(示例程序CMake主文件)
└── …
下面是各CMake文件的内容。
根目录公共CMake文件内容
根目录公共头文件定义了GLib库的头文件及库文件路径。
#########################################################################
###### BEGIN: Use System GLib library
SET(GLIB_INCLUDE_DIR "/usr/include/glib-2.0")
SET(GLIB_CONFIG_INCLUDE_DIR "/usr/lib64/glib-2.0/include")
## No Need To Set LINK_DIRECTORIES()
###### END: Use System GLib library
###### BEGIN: Use Custom GLib library
#SET(GLIB_INCLUDE_DIR "/opt/glib-2.56.4/include/glib-2.0")
#SET(GLIB_CONFIG_INCLUDE_DIR "/opt/glib-2.56.4/lib/glib-2.0/include")
#LINK_DIRECTORIES(/opt/glib-2.56.4/lib)
###### END: Use Custom GLib library
#########################################################################
SET(GLIB_LINK_LIB "glib-2.0")
MACRO(GLIB_GET_CURRENT_DIR_NAME curdir result)
STRING(REGEX REPLACE "/$" "" CURRENT_FOLDER_ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR})
STRING(REGEX REPLACE ".*/(.*)" "\\1" CURRENT_FOLDER ${CURRENT_FOLDER_ABSOLUTE})
SET(${result} ${CURRENT_FOLDER})
ENDMACRO(GLIB_GET_CURRENT_DIR_NAME curdir result)
MACRO(GLIB_GET_SUBDIR_LIST curdir result)
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
SET(dirlist "")
FOREACH(child ${children})
IF(IS_DIRECTORY ${curdir}/${child})
LIST(APPEND dirlist ${child})
ENDIF()
ENDFOREACH()
SET(${result} ${dirlist})
ENDMACRO(GLIB_GET_SUBDIR_LIST result curdir)
根目录用户自定义CMake文件内容
用户自定义CMake文件,用户可在本文件下新增全局宏。本文件内预设了四个宏,分别对应四个不同的参数,只有第一个宏实现了真正的功能,即将指定文件拷贝到编译目录下,其他函数均为打印调试信息,未实现具体功能,若有需要,使用者可自行修改或补充。
SET (execute_custom_command_1 "YES")
SET (execute_custom_command_2 "NO")
SET (execute_custom_command_3 "NO")
SET (execute_custom_command_4 "NO")
MACRO(GLIB_EXECUTE_CUSTOM_COMMAND_1 arg1)
FILE (COPY ${CMAKE_CURRENT_SOURCE_DIR}/${arg1} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
ENDMACRO(GLIB_EXECUTE_CUSTOM_COMMAND_1 arg1)
MACRO(GLIB_EXECUTE_CUSTOM_COMMAND_2 arg1 arg2)
message("(TODO)arg1:${arg1}, arg2:${arg2}")
ENDMACRO(GLIB_EXECUTE_CUSTOM_COMMAND_2 arg1 arg2)
MACRO(GLIB_EXECUTE_CUSTOM_COMMAND_3 arg1 arg2 arg3)
message("(TODO)arg1:${arg1}, arg2:${arg2}, arg3:${arg3}")
ENDMACRO(GLIB_EXECUTE_CUSTOM_COMMAND_3 arg1 arg2 arg3)
MACRO(GLIB_EXECUTE_CUSTOM_COMMAND_4 arg1 arg2 arg3 arg4)
message("(TODO)arg1:${arg1}, arg2:${arg2}, arg3:${arg3}, arg4:${arg4}")
ENDMACRO(GLIB_EXECUTE_CUSTOM_COMMAND_4 arg1 arg2 arg3 arg4)
根目录CMake主文件
CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
# include common file
include( CMakeCommonFile.txt )
# get subdir list from current dir
GLIB_GET_SUBDIR_LIST(${CMAKE_CURRENT_SOURCE_DIR} subdir_list)
# add subdir, exclude build dir
FOREACH(subdir ${subdir_list})
if(NOT(${subdir} STREQUAL "build"))
ADD_SUBDIRECTORY (${subdir})
endif(NOT(${subdir} STREQUAL "build"))
ENDFOREACH(subdir)
子目录CMake主文件
CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
# include common file
include( ../CMakeCommonFile.txt )
# get subdir list from current dir
GLIB_GET_SUBDIR_LIST(${CMAKE_CURRENT_SOURCE_DIR} subdir_list)
# add subdir, exclude build dir
FOREACH(subdir ${subdir_list})
if(NOT(${subdir} STREQUAL "build"))
ADD_SUBDIRECTORY (${subdir})
endif(NOT(${subdir} STREQUAL "build"))
ENDFOREACH(subdir)
示例程序CMake主文件
本文件为示例程序目录下的CMake主文件,有两点需要说明:
- 一般情况下,execute_custom_command_1是不需要被调用的,但由于xml解析需要一个预置的xml文件,编译时又需要拷贝到编译目录,因此用到了用户自定义公共头文件。
- 示例程序目录下可以有多个
*c,*cpp
文件,也可以包含一个叫subdir的目录,这些*c,*cpp
文件最终编译的目标二进制文件为示例程序的目录名。
cmake_minimum_required (VERSION 2.8)
# include common file
INCLUDE( ../../CMakeCommonFile.txt )
INCLUDE( ../../CMakeCustomCommonFile.txt )
# set current directory name as target name
GLIB_GET_CURRENT_DIR_NAME(${CMAKE_CURRENT_SOURCE_DIR} CURRENT_DIR_NAME)
# set var
SET (TARGET_NAME ${CURRENT_DIR_NAME})
# like -I
INCLUDE_DIRECTORIES(
${GLIB_INCLUDE_DIR}
${GLIB_CONFIG_INCLUDE_DIR}
)
# like -L and -Wl,-rpath=
#LINK_DIRECTORIES(${GLIB_DIR}/lib/glib-2.0/)
# target name
PROJECT (${TARGET_NAME})
# execute custom command
IF (${execute_custom_command_1} MATCHES "YES")
GLIB_EXECUTE_CUSTOM_COMMAND_1("xml_collect_attributes.xml")
ENDIF ()
# add custom source files
FILE (GLOB CURRENT_SOURCES "*.c" "*.cpp" "./subdir/*.c" "./subdir/*.cpp")
FILE (GLOB CURRENT_INCLUDES "*.h" "*.hpp" "./subdir/*.h" "./subdir/*.hpp")
SET (CURRENT_SRCS ${CURRENT_SOURCES} ${CURRENT_INCLUDES})
ADD_EXECUTABLE (${TARGET_NAME} ${CURRENT_SRCS})
# add src
#AUX_SOURCE_DIRECTORY (. DIR_SRCS)
#ADD_EXECUTABLE (${TARGET_NAME} ${DIR_SRCS})
# like -lglib-2.0
TARGET_LINK_LIBRARIES(${TARGET_NAME} ${GLIB_LINK_LIB})