红联Linux门户
Linux帮助

使用cmake来进行项目管理

发布时间:2017-06-21 10:46:08来源:cnblogs.com/lochan作者:092000
cmake是一个跨平台的,高度抽象的安装编译工具。cmake通过生成Makefile来使项目得以构建。相比于Makefile,cmake的优点包括:1)跨平台,2)比Makefile抽象程度高,更适合管理大型项目。下面一步一步摸索cmake应该如何使用。
 
①安装
鄙人用的是ubuntu,所以可以直接sudo apt-get install cmake即可。
如果是centos,请通过sudo yum install cmake安装。
也可以通过源码进行安装,都非常简单。
由于我们用c和c++来进行实验,所以还需要安装c和c++编译环境,sudo apt-get install gcc g++
 
②一个最简单的样例
cmake识别CMakeLists.txt文件,并根据配置生成Makefile,然后就可以使用make进行后续操作了。
我们建立一个目录tmp
mkdir tmp
然后,创建一个hello.c文件,内容如下:
092000@ubuntu:~/tmp$ ls
hello.c
092000@ubuntu:~/tmp$ cat hello.c 
#include "stdio.h"
int main(){
printf("hello world!\n");
return 0;
}
092000@ubuntu:~/tmp$ 
然后,我们创建一个CMakeLists.txt文件,内容如下:
092000@ubuntu:~/tmp$ ls
CMakeLists.txt  hello.c
092000@ubuntu:~/tmp$ cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
PROJECT(HelloWorld)
ADD_EXECUTABLE(runhello hello.c)
092000@ubuntu:~/tmp$ 
这个CMakeLists.txt可以这样来解读,第一行定义相对这个project需要的最小的cmake版本号,自己定义。第二行是工程的名字,也由自己定义。第四行的意思是根据xy_test.c生成一个可执行文件xytest。
到这里,我们可以运行命令cmake了,注意后面一定要接路径。
092000@ubuntu:~/tmp$ cmake .
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- 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
-- Configuring done
-- Generating done
-- Build files have been written to: /home/092000/tmp
092000@ubuntu:~/tmp$ ls
CMakeCache.txt  cmake_install.cmake  hello.c
CMakeFiles      CMakeLists.txt       Makefile
092000@ubuntu:~/tmp$ 
我们可以发现,cmake后多了1个目录和4个文件,其中,Makefile是我们所关心的,因为有了Makefile,我们可以执行make命令。
092000@ubuntu:~/tmp$ make
Scanning dependencies of target runhello
[100%] Building C object CMakeFiles/runhello.dir/hello.c.o
Linking C executable runhello
[100%] Built target runhello
092000@ubuntu:~/tmp$ ls
CMakeCache.txt  cmake_install.cmake  hello.c   runhello
CMakeFiles      CMakeLists.txt       Makefile
092000@ubuntu:~/tmp$ 
执行make命令没有任何错误,在当前位置多了一个runhello文件,这就是我们在CMakeList.txt中定义生成的可执行文件。
092000@ubuntu:~/tmp$ ./runhello 
hello world!
092000@ubuntu:~/tmp$ 
运行文件,成功得到预期结果。说明cmake已经成功使用了。
 
③一些应用场景
接下来介绍几个常用的内容,包括,1)外部构建,2)包含头文件,3)使用自己的(动/静)态库
所谓的外部构建是相对于内部构建而言的,刚才我们演示的样例就是内部构建,所有的临时文件都生成在工程的根目录,使得场面一度十分混乱,眼花缭乱,外部构建就是专门用一个目录(一般是build)来保存中间过程的各种文件和生成文件。别小看这一点,在文件数量很多的情况下使很重要的。
一般而言,使用cmake来管理项目时,会在每一个需要的子目录下都有一个CMakeLists.txt文件,相当于每个文件管各自的事情。
由于内容比较多,我就不一步一步来做,先贴出我这个简单项目的整体框架。
092000@ubuntu:~$ tree test/
test/
├── build
├── CMakeLists.txt
├── include
│   ├── addadd.h
│   └── decdec.h
├── lib
│   ├── addadd.c
│   ├── CMakeLists.txt
│   └── decdec.c
└── src
    ├── CMakeLists.txt
    └── xy_test.c
4 directories, 8 files
092000@ubuntu:~$ 
显然这个项目(test)下有4个目录,根目录下就有CMakeLists.txt文件,而在lib和src目录下也分别有该名字的文件。在这个项目中,include目录保存了所需要的头文件,lib目录中是两个库,而且还是源码的形式存在的。src中就是我们的主程序。其实所有的代码都非常简短,但是我把声明放在了include下头文件中,定义放在了lib库文件中,具体使用实在src中的xy_test.c中来调用的。
请看下面的具体内容。
092000@ubuntu:~/test$ cat include/addadd.h 
int addxy(int, int);
092000@ubuntu:~/test$ cat include/decdec.h 
int decxy(int, int);
092000@ubuntu:~/test$ cat lib/addadd.c 
#include "addadd.h"
int addxy(int x, int y){
return x+y;
}
092000@ubuntu:~/test$ cat lib/decdec.c 
#include "decdec.h"
int decxy(int x, int y){
return x-y;
}
092000@ubuntu:~/test$ 
所有的功能代码都实现了详细的分块,对于大项目来说,维护是很方便的。
为了有更风骚的实现,我们对addxy用静态库,对decxy用动态库。
主程序的功能也很简单,就是实现调用库中的两个函数。
092000@ubuntu:~/test$ cat src/xy_test.c 
#include "stdio.h"
#include "addadd.h"
#include "decdec.h"
int main(){
int a=3, b=7;
printf("a+b=%d,\ta-b=%d\n", addxy(a,b), decxy(a,b));
return 0;
}
092000@ubuntu:~/test$ 
三个CMakeLists.txt的内容分别设为
092000@ubuntu:~/test$ cat CMakeLists.txt 
cmake_minimum_required(VERSION 2.8)
PROJECT(xy_test)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
#自定义的头文件搜索路径
LINK_DIRECTORIES(${PROJECT_BINARY_DIR}/lib)
#自定义的库文件搜索路径
ADD_SUBDIRECTORY(lib)
#添加一个子目录lib,会解析子目录下的CMakeLists.txt
ADD_SUBDIRECTORY(src bin)
#同理,在工作目录生成的目录名为bin
092000@ubuntu:~/test$ 
092000@ubuntu:~/test$ cat lib/CMakeLists.txt 
SET(LIB_ADD_SRC addadd.c)
#SET 本质只是定义变量
ADD_LIBRARY(add_xy STATIC ${LIB_ADD_SRC})
#把addadd.c编译成静态库,库名为add_xy,生成文件libadd_xy.a
SET(LIB_DEC_SRC decdec.c)
ADD_LIBRARY(dec_xy SHARED ${LIB_DEC_SRC})
#把decdec.c编译成动态库,库名为dec_xy,生成文件libdec_xy.so
092000@ubuntu:~/test$ 
092000@ubuntu:~/test$ cat src/CMakeLists.txt 
ADD_EXECUTABLE(xytest xy_test.c)
#根据主程序生成可执行文件xytest
TARGET_LINK_LIBRARIES(xytest libadd_xy.a libdec_xy.so)
#连接两个库
092000@ubuntu:~/test$ 
由于每一句都有注释,这里就不多说了。
由于我们需要使用外部构建,因此我们进入到build目录,然后再运行cmake命令。
092000@ubuntu:~/test$ cd build/
092000@ubuntu:~/test/build$ cmake ..
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- 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
-- Configuring done
-- Generating done
-- Build files have been written to: /home/092000/test/build
092000@ubuntu:~/test/build$ l
bin/  CMakeCache.txt  CMakeFiles/  cmake_install.cmake  lib/  Makefile
092000@ubuntu:~/test/build$ 
cmake命令成功运行,我们发现多了一些目录和文件,最重要的是有了Makefile。
其中bin目录和lib目录分别对应我们前面根目录中CMakeLists.txt中两句ADD_SUBDIRECTORY的定义。
紧接着我们可以运行make。
092000@ubuntu:~/test/build$ make
Scanning dependencies of target add_xy
[ 33%] Building C object lib/CMakeFiles/add_xy.dir/addadd.c.o
Linking C static library libadd_xy.a
[ 33%] Built target add_xy
Scanning dependencies of target dec_xy
[ 66%] Building C object lib/CMakeFiles/dec_xy.dir/decdec.c.o
Linking C shared library libdec_xy.so
[ 66%] Built target dec_xy
Scanning dependencies of target xytest
[100%] Building C object bin/CMakeFiles/xytest.dir/xy_test.c.o
Linking C executable xytest
[100%] Built target xytest
092000@ubuntu:~/test/build$ l bin/
CMakeFiles/  cmake_install.cmake  Makefile  xytest*
092000@ubuntu:~/test/build$ 
终于在build/bin目录下出现了xytest可执行文件,说明成功了。
两个生成的库文件在build/lib目录下。
092000@ubuntu:~/test/build$ ./bin/xytest 
a+b=10,    a-b=-4
092000@ubuntu:~/test/build$ rm lib/libdec_xy.so 
092000@ubuntu:~/test/build$ ./bin/xytest 
./bin/xytest: error while loading shared libraries: libdec_xy.so: cannot open shared object file: No such file or directory
092000@ubuntu:~/test/build$ 
我们发现生成的可执行文件可以正常运行,但是如果我们删除了动态库文件,程序就不能执行了。这是显然的,因为我们用的是动态库连接。
如果我们对src中的主程序或对lib中的库文件源码做了任何修改,只需要到build目录下重新运行make命令即可。如果我们需要增加库或其他文件,则需要对相应CMakeLists.txt文件修改,重新cmake生成MakeFile。
 
本文永久更新地址:http://www.linuxdiyf.com/linux/31634.html