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:这个模块是测试addsub模块程序。

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目录的相对路径; 但务必注意: abcabc/有很大的区别: 如果目录名不以/结尾,那么这个目录将被安装为目标路径下的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 系列 - 分模块编译&安装项目的更多相关文章

  1. 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. ...

  2. 分模块创建maven项目(一)

    maven是一个项目构建和管理的工具. 我们可以通过maven仓库可以实现管理构建(主要是JAR还包括:WAR,ZIP,POM等等). 我们可以通过maven插件可以实现编译源代.产生Javadoc文 ...

  3. mac下Nginx+lua模块编译安装

    Nginx的nb之处就不说了,lua也是一个小巧的脚本语言,由标准C编写而成,几乎可以运行在所有的平台上,也非常强大,其他特性请自行度娘.nginx_lua_module是由淘宝的工程师清无(王晓哲) ...

  4. 创建分模块的maven项目

    折腾了我2天的maven,整理一下,以后做个参考 一.什么是maven项目: Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. Maven ...

  5. luajit+nginx+上传模块+lua模块编译安装

    git clone https://github.com/fdintino/nginx-upload-module.git git clone https://github.com/openresty ...

  6. 分模块的maven项目调试时报Source not found的解决办法

    一.背景 通常在开发中,我们经常会拆分我们的项目为一个个maven子工程,然后用一个父项目进行集成,并且子项目还会继承自父项目.当我们对这些项目进行debug调试的时候往往会在eclipse中出现so ...

  7. 分模块创建maven项目(二)

    1.新建Parent项目,MavenProject 2.新建子模块项目,MavenProject 右击项目名 --> NEW --> other 结果,在parent上运行会打出两个包,一 ...

  8. Linux编译安装MySQL5.6

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/4311061.html ...

  9. Debian/Ubuntu手动编译安装MongoDB C++11驱动及驱动测试

    本文章仅限cnblogs网站内转载!请某网站自觉,遵纪守法,尊重原创! 系统环境情况: 最小化.无桌面环境 新安装的Debian 8 Server 版本操作系统虚拟机一台 手动编译安装MongoDB ...

随机推荐

  1. PHP抓取网页内容经验总结

    用php 抓取页面的内容在实际的开发当中是非常有用的,如作一个简单的内容采集器,提取网页中的部分内容等等,抓取到的内容在通过正则表达式做一下过滤就得到了你想要的内容,至于如何用正则表达式过滤,在这里就 ...

  2. Java实现字符串倒序输出的几种方法

    1. 最容易想到的估计就是利用String类的toCharArray(),再倒序输出数组的方法了. import javax.swing.JOptionPane; public class Rever ...

  3. 网站SSL证书在线检测

    网站SSL证书在线检测 http://web.chacuo.net/netsslcheck OpenSSL命令行工具的证书操作 http://blog.csdn.net/a351945755/arti ...

  4. 最近无意中看到一个讲解spring mvc的系列,从源码的角度讲解,特记录下来,供以后反复学习

    SpringMVC深度探险(一) —— SpringMVC前传 SpringMVC深度探险(二) —— SpringMVC概览 SpringMVC深度探险(三) —— DispatcherServle ...

  5. linux查看及修改文件权限以及相关

    linux查看及修改文件权限以及相关 查看文件权限的语句: 在终端输入: ls -l xxx.xxx (xxx.xxx是文件名)那么就会出现相类似的信息,主要都是这些: -rw-rw-r-- 一共有1 ...

  6. Mui 下拉刷新,刷新完成功能实现

    Mui中,正在刷新后,就直接回弹了,没有刷新完成这个过程,然后我就在中间添加了一个过程.   代码如下:   //-----------日期格式化------------- function form ...

  7. Unity3D MonoBehaviour的生命周期(lifecycle)

    官方的事件函数的执行顺序中有详解(Link:Execution Order of Event Functions) (图片来源:http://whatiseeinit.blogspot.com/201 ...

  8. goto语句引起的crosses initialization of XXX

    1. 背景 goto语句虽然目前已经不提倡使用,但是用起来还是很方便,尤其是老代码中见的比较多. 在改动有goto语句的老代码时需要特别注意,是否跳过来资源的释放.有用变量的初始化等等. 很久之前写c ...

  9. Spring4学习笔记二:Bean配置与注入相关

    一:Bean的配置形式 基于XML配置:在src目录下创建 applicationContext.xml  文件,在其中进行配置. 基于注解配置:在创建bean类时,通过注解来注入内容.(这个不好,因 ...

  10. HTML解析库Gumbo简单使用记录

    目录 Gumbo简介 使用记录 1.GumboNode的类型 2.简单的使用 Gumbo简介 Gumbo是谷歌开源的一个纯C编写的HTML解析库,性能很好,就是用起来比较麻烦. github地址htt ...