从原理上讲,CMake只是在帮助我们自动生成MakeFile而己。我们编译程序还是要make一下的。
我写了一个简单的示例,内容我们不需要关心,只关心其文件结构就行了。如下:
.
|-- CMakeLists.txt
|-- main.cpp
`-- person
|-- CMakeLists.txt
|-- person.cpp
`-- person.h
在./目录与 person/都添加了一个CMakeLists.txt文件。
如下./CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.0)
project(StudyCmake CXX)
message(STATUS "project source: " ${PROJECT_SOURCE_DIR})
message(STATUS "project binary: " ${PROJECT_BINARY_DIR})
add_subdirectory(person)
include_directories(person)
#set (main_src main.cpp)
aux_source_directory(. main_src)
message(STATUS "Source files : " ${main_src})
add_executable(StudyCmake ${main_src})
target_link_libraries(StudyCmake person)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
message(STATUS "executable output path: " ${EXECUTABLE_OUTPUT_PATH})
第1行:cmake_minimum_required(VERSION 3.0),这个最好有,表示版本信息。
第2行:project(StudyCmake CXX),注明工程名称与编译的语言。CXX表示C++,C表示C。还有别的语言可选。这行语句的执行,会生成两个变量:
> PROJECT_SOURCE_DIR 工程源码路径
> PROJECT_BINARY_DIR 生成的可执行文件路径
第3-4行:message(STATUS "project source" ${PROJECT_SOURCE_DIR},这是一条信息打印语句。当cmake执行到这一句,会向终端输出相应的信息。这种信息分几种,这里是STATUS表示是状态信息,除了这个还有:
> SEND_ERROR 产生错误,生成过程被跳过
> FATAL_ERROR 立即终止cmake
取变量的值是${变量名},如:${PROJECT_SOURCE_DIR}。
在CMakeLists.txt里,变量名是区分大小写的,但命令不分大小写。如message与MESSAGE是等价的。但STATUS不等价于status。
第5行:add_subdirectory(person),cmake执行到这句时,就会跳入./person目录,读取person目录下的CMakeLists.txt文件。./person/CMakeLists.txt文件稍候再讲解。
这里,跟随cmake的执行过程,打开./person/CMakeLists.txt:
aux_source_directory(. person_src)
message(STATUS "Print files : " ${person_src})
add_library(person ${person_src})
这个文件里的出现一个新的命令:add_library(person ${person_src}),添加了一静态库person,由${person_src}生成。而person_src变量就是./person/目录下所有的源文件。
好回到主目标下的CMakeLists.txt文件:
第6行:include_directories(person),将./person加入头文件搜索路径。这样以来,在main.cpp文件里include "person.h"就不需要写成#include "person/person.h"了。
第7行:set(main_src main.cpp),将main_src变量设置为"main.cpp"。上面这条命令前加了#,表示注释了。CMakeLists.txt里的注释与Shell里的注释类似。
第8行:aux_source_directory(. main_src),将.目录下所有的源文件名称赋给main_src。这句命令与set(main_src main.cpp)是等价了。只不过aux_source_directory命令是通过去查目录所得,而set得写明。
第10行:add_executable(StudyCmake ${main_src}),添加一个可执行文件输出。由${make_src}生成StudyCmake可执行程序。这语话并不是以cmake执行的时候就完成可执行文件的生成,而是说我们要生成这么一个可执行文件。
第11行:target_link_libraries(StudyCmake person),设置链接,将person与StudyCmake目标一起链接。person是静态库目标。
好!关于CMakeLists.txt的内容就讲完了。下面我们在cmake一下。
通常,我们不会在源码目录下直接执行cmake,而是在源码目录下建一个build目录。然后进入这个目录,再执行cmake ..
$ mkdir build
$ cd build/
$ cmake ..
-- The CXX compiler identification is GNU 4.4.7
-- 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
-- project source: /home/hevake_lcj/Workspace/C++/StudyCMake
-- project binary: /home/hevake_lcj/Workspace/C++/StudyCMake/build
-- Print files : ./person.cpp
-- Source files : ./main.cpp
-- executable output path: /home/hevake_lcj/Workspace/C++/StudyCMake/build/bin
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hevake_lcj/Workspace/C++/StudyCMake/build
cmake在执行过程中,不是立限就生成什么文件,而是通过解释上面的CMakeLists.txt文件里的命令来读取我们的意图。解释完之后,cmake才真正知道我们想到它做什么。最后才根据我们的意图生成对应的MakeFile与相关的目录层次。
cmake执行完之后,在build目录下就会生成很多文件,其中最主要的是生成了MakeFile。
前面我也说了cmake只不过是帮助我们生成MakeFile而己,真正的编译还得make一下才行。那就make一下好了。
$ make
Scanning dependencies of target person
[ 50%] Building CXX object person/CMakeFiles/person.dir/person.cpp.o
Linking CXX static library libperson.a
[ 50%] Built target person
Scanning dependencies of target StudyCmake
[100%] Building CXX object CMakeFiles/StudyCmake.dir/main.cpp.o
Linking CXX executable bin/StudyCmake
[100%] Built target StudyCmake
好了,我就先学到这里,相信日常的实用还是够用了。不够用的时候再学。
更多技能请参考:http://my.oschina.net/chen0dgax/blog/151894