3. CMake 系列 – 分模块编译&安装项目

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

出处:https://www.cnblogs.com/standardzero/p/10793746.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119544.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 接口400是什么错误_接口报500是什么错误

    接口400是什么错误_接口报500是什么错误原文地址:https://blog.csdn.net/lw1242189467/article/details/80048407首先,遇到400问题,最大几率是出现了数据类型不一致的问题,简单来说是Controller层不用正确读取你发送请求附带的参数。该例是我前端传送JSON格式,使用postmen接收。一.发现400错误的,第一步确认postmen中发送的数据类型是json。比如Headers中Content-Type类型是application/json;或是前端代码Ajax中添加:conten

    2022年9月27日
    3
  • Windows系统下JBOSS服务器下载安装

    Windows系统下JBOSS服务器下载安装Windows系统下JBOSS服务器下载安装JDK的安装Jboss的介绍Jboss下载Jboss安装JDK的安装首先安装JDK,配置环境变量(PATH,CLASSPATH,JAVA_HOME)。可以参照:Windows环境下JDK安装与环境变量配置Jboss的介绍JBOSS是EJB的服务器,就像Tomcat是JSP服务器一样,就是服务器的一种。JBoss代码遵循LGPL许可,可以在任何商业应用中免费使用,而不用支付费用。Jboss的详细介绍可以参照:jboss的百度百科。Jboss下载Jbo

    2022年10月3日
    3
  • redis manager教程_下载万能钥匙并安装

    redis manager教程_下载万能钥匙并安装一、下载RedisDesktopManagerhttps://pan.baidu.com/s/1Jvr9MbgFn4UJh4M1AMo3gA提取码:3i9b二、安装RedisDesktopManager下一步即可三、连接Redis服务器四、RedisDesktopManager的使用

    2022年8月30日
    4
  • navigator.appName

    navigator.appName找了很多的参考,无外乎两句话,兼容性和缅怀网景我就很好奇,到底在兼容什么然后翻到一篇外文的提问,里面提及了DOM0然后去了解了一下DOM0…看了介绍之后,就是不太推荐使用的标签监听属性on事件名,不过这文章有提到DOM0具有极好的跨浏览器优势,所以可能appName就是在这方面的支持吧,如果有知道的大佬请留个言,解释一下吧,老纠结了….

    2025年11月1日
    4
  • c语言用命令行打开文件_c语言无法打开文件

    c语言用命令行打开文件_c语言无法打开文件linux文件操作(打开及关闭)Linux文件描述符简介当一个进程获取文件的访问权时,通常指打开一个文件时,内核返回一个文件描述符,进程可以通过文件描述符进行后续的操作。文件描述符是一组正整数,每一个文件被打开时,内核都会打开一个大于或等于0的文件描述符。文件描述符012这是linux系统保留的三个文件描述符。0代表标准输入stdin1代表标准输出stdout2代表错误输出s…

    2025年6月17日
    3
  • 想要复制网页的文字网页不让复制_如何复制文字

    想要复制网页的文字网页不让复制_如何复制文字作者:iamlaosong当我们需要复制网页上的内容时,往往会碰到不能复制的情况,面对这个问题,不同的情况有不同的应对方法,比如禁止JavaScript运行,查看源代码,另存为网页文件等。这些方法也可以用,现在有个更通用的办法是QQ屏幕截图所带的功能,不管网页用的什么技术,能看见就可以复制,特别适合不太懂技术的人。要用QQ截图功能,QQ肯定是要登录的,然后用浏览器打开需要复制文字的网页,按QQ屏幕截图快捷键Ctrl+Alt+A选择需要复制文字的区域,在弹出的菜单中点击“翻译”或者“屏幕识图”两个按钮

    2022年10月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号