CMake是一个跨平台的自动化建构系统,他使用一个名为CMakeLists.txt的文件来描述构建过程,可以产生标准的构建文件,如Unix的Makefile或Windows Visual C++的projects/workspaces。文件CMakeLists.txt需要手工编写,也可以通过编写脚本进行半自动的生成。CMake提供了比autoconfig更简洁的语法。在Linux平台下使用CMake生成Makefile并编译的流程如下:
1、编写CMakeLists.txt
2、执行命令:"cmake PATH"生成Makefile(PATH是CMakeLists.txt所在的目录)。
3、使用Make命令进行编译。
源代码的目录结构
--CMakeSample | +--CMakeLists.txt | +--cmake | +--modules | +FindTHREAD_DB.cmake +--src | +--CMakeLists.txt | +--hello | +--CMakeLists.txt | +--hello.h | +--hello.cpp +--sample | +--CMakeLists.txt | +--main.cpp
在这个例子我模拟以下情况
1、在一个目录下生成一个静态库
2、在另一个目录中生成一个可执行程序,并引用了前一个静态库。
3、查找外部库,(这里例子是在系统的默认路径下查找,这是不必要的,纯粹是为介绍而设的,实际也没有使用)。
PROJECT(cmakesample) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) #Appends the cmake/modules path inside the MAKE_MODULE_PATH variable which stores the # directories of additional CMake modules SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH}) ADD_SUBDIRECTORY(src)
1、PROJECT(cmakesample)命名项目的名称。
2、CMAKE_MINIMUM_REQUIRED(VERSION 2.6)声明了CMake的版本要求。
3、SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})指定了一些自己写的CMake模版所存放的地址,比如FindTHREAD_DB.cmake。其中PROJECT_SOURCE_DIR是代码的根目录,也可以使用cmakesample_SOURCE_DIR来替代,cmakesample就是项目名称。
4、ADD_SUBDIRECTORY(src)指定了代码所在的子目录。
INCLUDE_DIRECTORIES(hello) SUBDIRS(hello sample)
1、INCLUDE_DIRECTORIES(hello)指定了头文件所在的目录,只有src下的子目录中的 CMakeLists.txt可用,假设外面还有一层跟src同一级别的目录,那么这句话对另一个目录下的CMakeLists.txt无效。其实这句话可以放在sample里的CMakeLists.txt里,不过此时需要改成INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/hello)。
2、SUBDIRS(hello sample)相当于分别写ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample)
AUX_SOURCE_DIRECTORY(. DIR_HELLO_SRCS) ADD_LIBRARY(hello STATIC ${DIR_HELLO_SRCS})
ADD_LIBRARY(hello_static STATIC ${DIR_HELLO_SRCS}) SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello") SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) ADD_LIBRARY(hello_shared SHARED ${DIR_HELLO_SRCS}) SET_TARGET_PROPERTIES(hello_shared PROPERTIES OUTPUT_NAME "hello") SET_TARGET_PROPERTIES(hello_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET(DIR_SRCS main.cpp) ADD_EXECUTABLE(sample ${DIR_SRCS}) TARGET_LINK_LIBRARIES(sample hello) INSTALL(TARGETS sample RUNTIME DESTINATION bin)1、SET(DIR_SRCS main.cpp)把变量DIR_SRCS赋值为"main.cpp"。也是通过AUX_SOURCE_DIRECTORY(. DIR_SRCS )来实现。
# # configuration to find DB_CXX library # # Include dir find_path(THREAD_DB_INCLUDE_DIR NAMES thread_db.h PATHS /usr/include/ /usr/local/include/ ) # Finally the library itself find_library(THREAD_DB_LIBRARY NAMES thread_db PATHS /usr/lib/ /usr/local/lib/ )
1、find_path(THREAD_DB_INCLUDE_DIR NAMES thread_db.h PATHS /usr/include/ /usr/local/include/)在目录“/usr/include"和"/usr/local/include"下查找thread_db.h,如果找到则把目录名赋给THREAD_DB_INCLUDE_DIR
2、find_library(THREAD_DB_LIBRARY NAMES thread_db PATHS /usr/lib/ /usr/local/lib/)在目录"/usr/lib"和"/usr/local/lib"下查找libthread_db.so,如果找到则把库文件的绝对路径赋给THREAD_DB_LIBRARY
为了纯粹测试,我们就修改./src/sample/CMakeLists.txt为:
FIND_PACKAGE(THREAD_DB REQUIRED) MARK_AS_ADVANCED( THREAD_DB_INCLUDE_DIR THREAD_DB_LIBRARY ) MESSAGE(STATUS ${THREAD_DB_INCLUDE_DIR}, ${THREAD_DB_LIBRARY}) SET(DIR_SRCS main.cpp) ADD_EXECUTABLE(sample ${DIR_SRCS}) TARGET_LINK_LIBRARIES(sample hello) INSTALL(TARGETS sample RUNTIME DESTINATION bin)
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- /home/dylan/Public/CMakeSample
-- /usr/include,/usr/lib/libthread_db.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dylan/Public/CMakeSample/build