3. CMake 系列 - 分模块编译&安装项目
1. 项目目录结构
test2
├── add
│ ├── add.c
│ ├── add.h
│ └── CMakeLists.txt
├── build
├── CMakeLists.txt
├── example
│ ├── CMakeLists.txt
│ ├── test_add.c
│ └── test_sub.c
└── sub
├── CMakeLists.txt
├── sub.c
└── sub.h
说明:
add: 这个模块是加法模块,会生成动态库和静态库。
sub:这个模块是减法模块,会生成动态库和静态库。
example:这个模块是测试add和sub模块程序。
CMakeLists.txt:这里有4个CMakeLists.txt,顶层CMakeLists.txt文件管理其它模块CMakeLists.txt文件,每个模块CMakeLists.txt文件都只需管理自己编译。
2. 相关代码
2.1 add 模块
add.h
#ifndef _ADD_H
#define _ADD_H
int add(const int a, const int b);
#endif
add.c
#include "add.h"
int add(const int a, const int b)
{
return a+b;
}
CMakeLists.txt
# 递归获取目录下所有的C文件
file(GLOB_RECURSE c_files ./*.c)
# 递归获取目录下所有的h文件
file(GLOB_RECURSE h_files ./*.h)
#生成动态库和静态库
add_library(add_lib_shared SHARED ${c_files})
add_library(add_lib_static STATIC ${c_files})
#将动态库和静态库的名字设置为 add
set_target_properties(add_lib_shared PROPERTIES OUTPUT_NAME "add")
set_target_properties(add_lib_static PROPERTIES OUTPUT_NAME "add")
#设置动态库版本
set_target_properties(add_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)
#安装动态库和静态库
INSTALL(TARGETS add_lib_shared add_lib_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
#安装头文件
INSTALL(FILES ${h_files} DESTINATION include)
2.2 sub 模块
sub.h
#ifndef _SUB_H
#define _SUB_H
int sub(const int a, const int b);
#endif
sub.c
#include "sub.h"
int sub(const int a, const int b)
{
return a - b;
}
CMakeLists.txt
#递归获取目录下所有的C文件
file(GLOB_RECURSE c_files ./*.c)
# 递归获取目录下所有的h文件
file(GLOB_RECURSE h_files ./*.h)
#生成动态库和静态库
add_library(sub_lib_shared SHARED ${c_files})
add_library(sub_lib_static STATIC ${c_files})
#将动态库和静态库的名字设置为 sub
set_target_properties(sub_lib_shared PROPERTIES OUTPUT_NAME "sub")
set_target_properties(sub_lib_static PROPERTIES OUTPUT_NAME "sub")
#设置动态库版本
set_target_properties(sub_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)
#设置动态库版本
set_target_properties(sub_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)
#安装动态库和静态库
INSTALL(TARGETS sub_lib_shared sub_lib_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
#安装头文件
INSTALL(FILES ${h_files} DESTINATION include)
2.3 测试模块
test_add.c
#include "add.h"
#include <stdio.h>
int main(int argc, char **argv)
{
int a = 10;
int b = 8;
printf("%d + %d = %d\n", a, b, add(a, b));
return 0;
}
test_sub.c
#include "sub.h"
#include <stdio.h>
int main(int argc, char **argv)
{
int a = 10;
int b = 8;
printf("%d - %d = %d\n", a, b, sub(a, b));
return 0;
}
CMakeLists.txt
# 添加头文件路径
include_directories(${PROJECT_SOURCE_DIR}/add)
include_directories(${PROJECT_SOURCE_DIR}/sub)
# 添加第三方库(add)头文件路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 生成执行文件
add_executable(test_add test_add.c)
add_executable(test_sub test_sub.c)
# 链接库文件
target_link_libraries(test_add add)
target_link_libraries(test_sub sub)
# 安装执行文件
INSTALL(TARGETS test_add test_sub
RUNTIME DESTINATION bin)
2.4 顶层 CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
#设置库文件输出目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#设置执行文件输出目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 添加子目录
add_subdirectory(add)
add_subdirectory(sub)
add_subdirectory(example)
说明:
顶层CMakeLists.txt管理子目录的CMakeLists.txt, 从而实现模块化编译和管理。
3. 编译 & 安装
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/home/mark/code/cmake/test2/_install ..
$ make
$ make install
$ cd ..
$ tree _install
查看效果
_install/
├── bin
│ ├── test_add
│ └── test_sub
├── include
│ ├── add.h
│ └── sub.h
└── lib
├── libadd.a
├── libadd.so -> libadd.so.1
├── libadd.so.1 -> libadd.so.1.0
├── libadd.so.1.0
├── libsub.a
├── libsub.so -> libsub.so.1
├── libsub.so.1 -> libsub.so.1.0
└── libsub.so.1.0
说明:
-DCMAKE_INSTALL_PREFIX:指定安装目录,需要是绝对路径。
4. 项目安装基本语法
4.1 安装target
语法:
INSTALL(TARGETS targets...
[[ARCHIVE|LIBRARY|RUNTIME]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS
[Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL]
] [...])
targets: 一般填执行文件、动态库、静态库。
ARCHIVE: 特指静态库。
LIBRARY: 特指动态库。
RUNTIME: 特指执行文件。
dir: 安装路径,一般配合CMAKE_INSTALL_PREFIX使用,即表示为${CMAKE_INSTALL_PREFIX}/dir。若是dir以/开头,表示绝对路径,即不使用CMAKE_INSTALL_PREFIX变量。
一个例子:
#安装动态库和静态库
INSTALL(TARGETS sub_lib_shared sub_lib_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
# 安装执行文件
INSTALL(TARGETS test_add test_sub
RUNTIME DESTINATION bin)
4.2 安装普通文件
语法
INSTALL(FILES files... DESTINATION <dir>
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[RENAME <name>] [OPTIONAL])
使用方法和上述方法类似,举个简单的例子,就大概知道怎么用了。
一个例子
#安装头文件
INSTALL(FILES ${h_files} DESTINATION include)
4.3 安装目录和脚本
语法
INSTALL(DIRECTORY dirs... DESTINATION <dir>
[FILE_PERMISSIONS permissions...]
[DIRECTORY_PERMISSIONS permissions...]
[USE_SOURCE_PERMISSIONS]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[[PATTERN <pattern> | REGEX <regex>]
[EXCLUDE] [PERMISSIONS permissions...]] [...])
说明
dirs:DIRECTORY 后面连接的路径是所在Source目录的相对路径; 但务必注意: abc和 abc/有很大的区别: 如果目录名不以/结尾,那么这个目录将被安装为目标路径下的abc,如果目录名以/结尾,代表将这个目录中的内容安装到目标路径,但不包括这个目录本身。
pattern: 使用正则表达式进行过滤.
permissions: 用于指定pattern过滤后的文件权限。
举例说明
INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj
PATTERN "CVS" EXCLUDE
PATTERN "scripts/*"
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
GROUP_EXECUTE GROUP_READ)
这条指令的执行结果是:将icons 目录安装到 <prefix>/share/myproj,
将scripts/中的内容安装到<prefix>/share/myproj不包含目录名为CVS
的目录,对于scripts/*文件指定权限为OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ。
3. CMake 系列 - 分模块编译&安装项目的更多相关文章
- OpenCV使用CMake和MinGW的编译安装
官方教程:https://wiki.qt.io/How_to_setup_Qt_and_openCV_on_Windows 软件环境: Qt:5.11 CMake-3.14.4 OpenCV-4.1. ...
- 分模块创建maven项目(一)
maven是一个项目构建和管理的工具. 我们可以通过maven仓库可以实现管理构建(主要是JAR还包括:WAR,ZIP,POM等等). 我们可以通过maven插件可以实现编译源代.产生Javadoc文 ...
- mac下Nginx+lua模块编译安装
Nginx的nb之处就不说了,lua也是一个小巧的脚本语言,由标准C编写而成,几乎可以运行在所有的平台上,也非常强大,其他特性请自行度娘.nginx_lua_module是由淘宝的工程师清无(王晓哲) ...
- 创建分模块的maven项目
折腾了我2天的maven,整理一下,以后做个参考 一.什么是maven项目: Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. Maven ...
- luajit+nginx+上传模块+lua模块编译安装
git clone https://github.com/fdintino/nginx-upload-module.git git clone https://github.com/openresty ...
- 分模块的maven项目调试时报Source not found的解决办法
一.背景 通常在开发中,我们经常会拆分我们的项目为一个个maven子工程,然后用一个父项目进行集成,并且子项目还会继承自父项目.当我们对这些项目进行debug调试的时候往往会在eclipse中出现so ...
- 分模块创建maven项目(二)
1.新建Parent项目,MavenProject 2.新建子模块项目,MavenProject 右击项目名 --> NEW --> other 结果,在parent上运行会打出两个包,一 ...
- Linux编译安装MySQL5.6
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/4311061.html ...
- Debian/Ubuntu手动编译安装MongoDB C++11驱动及驱动测试
本文章仅限cnblogs网站内转载!请某网站自觉,遵纪守法,尊重原创! 系统环境情况: 最小化.无桌面环境 新安装的Debian 8 Server 版本操作系统虚拟机一台 手动编译安装MongoDB ...
随机推荐
- [NOI导刊2010提高]黑匣子
OJ题号:洛谷1801 思路:建立一个大根堆.一个小根堆.大根堆维护前i小的元素,小根堆维护当前剩下的元素. #include<cstdio> #include<queue> ...
- 图的 储存 深度优先(DFS)广度优先(BFS)遍历
图遍历的概念: 从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础.图的 ...
- BZOJ1166 : [Baltic2008]Magical Stones
考虑二分答案,转化为求有多少$\leq lim$的数满足条件. 从两侧往中间进行数位DP,设$f[l][r][j][x][y][z][pre][suf]$表示当前准备填的两个位置是$l$和$r$,已经 ...
- Cocos Creator的小点
声明的时候,变量如此:但用的时候就变成了border,找了很久的问题,一直没找到啊,后来就发现命名的时候和内置的一定不要太相似否则后悔的只能是自己: cc.Class({ extends: cc.Co ...
- Ubuntu16.04基于Anaconda(py3.6)安装TensorFlow(CPU)的方法
安装tensorflow(cpu版) 对anaconda命令的熟悉,可以参考http://www.jianshu.com/p/d2e15200ee9b 官方的建议是即时你有gpu,但也可以先装一个cp ...
- 使用 IntraWeb (37) - TIWApplication
每个访问用户都会拥有一个它的实例(WebApplication), 它除了承载 Session(会话)数据, 还要记忆着用户的浏览器信息.登陆信息等等; 另外, 窗体的建立也都依附(Owner)于它, ...
- MongoDB的学习--索引类型和属性(转)
原文链接:MongoDB的学习--索引类型和属性 索引类型 MongDB的索引分为以下几种类型:单键索引.复合索引.多键索引.地理空间索引.全文本索引和哈希索引 单键索引(Single Field I ...
- iOS:NSFileHandle和NSFileManger的使用
一.介绍 利用NSFilehandle类提供的方法,允许更有效地使用文件. 一般而言,处理文件时都要经历以下三个步骤: 1.打开文件,并获取一个NSFileHandle对象,以便在后面的I/O操作中引 ...
- C# windows 桌面控件的扩展
今天一同事 需要一个Windows from下 GridView的嵌套的控件,于是就去找了以前自己写的一些form 控件,发现居然没有人下载.同时查找以前的下载包也比较费时,于是乎就搞一个文章. 运行 ...
- Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片
一.问题描述 使用LruCache.AsyncTask实现批量图片的加载并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)加载图片,并放入缓存中 2.及时移除 ...