利用cmake管理工程
来源:互联网 发布:java list《map 编辑:程序博客网 时间:2024/04/29 23:37
近期由于做一个项目,需要重写Makefile,开始打算用GUN的aotu tools,但是考虑到上手不易,而且用起来复杂,最后用了cmake替换。情况还不错。自己也顺便总结了cmake的一些常用方法及注意事项。我特意写了一个最小化的项目说明cmake的注意事项。
1.源代码
首先建立项目工程目录prg,目录及结构如下:
.
├── build
├── CMakeLists.txt
├── hello.h
├── lib
│ ├── CMakeLists.txt
│ └── hello.c
└── main
├── CMakeLists.txt
└── main.c
项目中包括三个目录,build目录用于实现外部编译,用于存放编译中产生的文件,lib目录用于生成库,main目录用于其它源码。
这几个文件的内容如下:
1. prg/CMakeLists.txt
project(main)cmake_minimum_required(VERSION 2.8)include_directories(.)set(lib_src)add_definitions(-static)add_subdirectory(lib)add_subdirectory(main)
2. prg/hello.h
int hello(void);
3. prg/lib/hello.c
#include <stdio.h>#include <hello.h>int hello(){printf("*****************************\n");printf("Hello world\n");printf("*****************************\n");return 0;}
4. prg/lib/CMakeLists.txt
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)set(hello_src hello.c)add_library(hello STATIC ${hello_src})#add_library(hello SHARED ${hello_src})
5. prg/main/main.c
#include <stdio.h>#include <hello.h>int main(){printf("Using lib hello\n");hello();printf("filnished\n");return 0;}
6. prg/main/CMakeLists.txt
set(main_src main.c)list(APPEND lib_src hello)add_custom_command(TARGET mainPRE_LINKWORKING_DIRECTORY ${BINARY_ROOT_DIR}/liblink_directories(${BINARY_ROOT_DIR}/lib))add_executable(main ${main_src})#target_link_libraries(main "hello")target_link_libraries(main ${lib_src})
2. 编译源代码
进入prg/build目录
[ycwang@ycwang:lib]$ cd build/[ycwang@ycwang:build]$ cmake ..
会输出以下内容:
[ycwang@ycwang:build]$ cmake ../-- 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-- Configuring done-- Generating done-- Build files have been written to: /home/ycwang/desktop/myself/c-program/cmake/lib/build这时已经生成了项目的Makefile
[ycwang@ycwang:build]$ makeScanning dependencies of target hello[ 50%] Building C object lib/CMakeFiles/hello.dir/hello.c.oLinking C static library libhello.a[ 50%] Built target helloScanning dependencies of target main[100%] Building C object main/CMakeFiles/main.dir/main.c.oLinking C executable main[100%] Built target main完成编译。
可见CMake的编译及生成特别简单。
3. cmake中需要注意的地方
由于cmake是在传统的GNU的Makefile之上抽象出的一层,封装了Makefile的一些命令。还是需要值得注意一些差别的。
1.如何加入交叉编译
由于嵌入式平台使用交叉编译工具链比较频繁。用cmake如何使用这些工具呢?
编写一个cmake的脚本Toolchain-mips.cmake,放在prg目录下。
# specify the cross compilerset(DIRECTORY /opt/mipseltools-gcc412-glibc261/bin/)set(PREF ${DIRECTORY}mipsel-linux-)set(CMAKE_C_COMPILER ${PREF}gcc)set(CMAKE_CXX_COMPILER ${PREF}g++)#message(STATUS ${CMAKE_C_COMPILER})# where is the target environment set(CMAKE_FIND_ROOT_PATH /opt/mipseltools-gcc412-glibc261/bin/)# search for programs in the build host directoriesset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)# for libraries and headers in the target directoriesset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)然后在运行cmake 时
cmake -DCMAKE_TOOLCHAIN_FILE=../Toolchain-mips.cmake ../其中的-DCMAKE_TOOLCHAIN_FILE参数是必须的,如果您硬是要把这些命令直接写在CMakeFiles.txt中,那么运行cmake时,它会先去寻找系统中的工具链,然后再读取CMakeFiles.txt中的内容。无法配置成交叉编译的环境。
2. 利用cmake生成源代码的流程图
[ycwang@ycwang:build]$ cmake ../ --graphviz=test.dot会在配置完之后产生test.dot文件,利用dot命令转换
[ycwang@ycwang:build]$ dot -Tjpg test.dot -o test.jpg生成的test.jpg的效果图如下所示
3. 动态库与静态库的问题
在prg/lib/CMakeLists.txt的代码中有这么一行,
add_library(hello STATIC ${hello_src})
第一个参数可以是STATIC或者是SHARED,对应着最后的target_link_library中是静态库或者是动态库生成最终的可执行文件。如果没有生成静态库,那么传递给编译器的参数-static将不会起作用。
4. 项目中包括可裁剪的库的问题
如果项目本身是以模块形式生成出来的,而且可以利用宏开关动态的裁剪编译的模块。也就意味着生成的动态或者静态库在变化着。可以在判断编译这个模块的代码中加入
list(APPEND virable modname),最后把virable这个变量传到target_link_library中。最后会按照裁剪的结果生成最终的程序。
如果你的项目中有库,那么需要在最后生成可执行文件时保证先把库生成出来,再做最后的链接,可以用add_custom_command函数,使用方法如prg/main/CMakeLists.txt所示。
4.总结
总的来说,cmake上手比较快,而且使用方使,适合管理大型的项目,但是cmake本身是一门语言,要用精通需要了解很多内容。如果你对Make的基本流程比较熟,知道一般的编译流程,然后再去理解cmake在编译流程的各个阶段分别做了哪些事儿,上手速度会更快。
- 利用cmake管理工程
- 利用CMake管理QT5.5+VTK6.3+ITK4.8+Opencv3.0工程
- OpenCV使用Cmake来管理工程
- 利用CMake生成动态或静态链接库工程
- 利用CMake和OpenCV源代码生成Visual Studio工程
- 利用CMake和OpenCV源代码生成Visual Studio工程
- NPAPI插件开发详细记录:利用cmake生成插件工程
- 利用CMake和OpenCV源代码生成Visual Studio工程
- 利用CMake生成动态或静态链接库工程
- Cmake管理工程时如何使用外部程序库
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- myeclise搭建springside3.3.4开发环境
- Create menu by javascript dynamically
- 继承中的各种方法研究
- 解析XML字符串(一)
- 基于C/C++/BCB的文件操作
- 利用cmake管理工程
- win2008WEB服务器集群实践
- StretchBit 翻转图片 透明
- build/core/main.mk:129: *** stop。 停止。『 android make后报JDK报错的解决方法』
- 判断链表是否有环及两链表是否相交
- IE中XML字符串原理(二)
- 小试Annotation来配置DWR
- vc 每次按F5运行都提示重新编译
- js 时刻获取时间