• 此文为:轻松入门cmake系列教程

有时我们只需要编译出动态库,静态库,然后等着让其它程序去使用。让我们看下这种情况该如何使用cmake

实验

实验一:生成静态库

编写代码

项目结构如下:

  • [CMakeLists.txt] - 包含你希望运行的 CMake 命令
cmake_minimum_required(VERSION 3.5)project(hello_library)############################################################
# Create a library
#############################################################Generate the static library from the library sources
add_library(hello_library STATICsrc/hello.cpp)target_include_directories(hello_libraryPUBLIC${PROJECT_SOURCE_DIR}/include)############################################################
# Create an executable
############################################################# Add an executable with the above sources
add_executable(hello_binarysrc/main.cpp)# link the new hello_library target with the hello_binary target
target_link_libraries(hello_binaryPRIVATEhello_library)
  • [include/static/hello.h] - 要包含的头文件
#ifndef __HELLO_H__
#define __HELLO_H__class Hello
{public:void print();
};#endif
  • [src/hello.cpp] - 要编译的源文件

#include <iostream>#include "static/hello.h"void Hello::print()
{std::cout << "Hello Static Library!" << std::endl;
}
  • [src/main.cpp] - 具有main的源文件
#include "static/hello.h"int main(int argc, char *argv[])
{Hello hi;hi.print();return 0;
}

一些理论

(1)添加共享库

  • add_library()指定从某些源文件创建库。调用方式如下:
add_library(hello_library STATICsrc/hello.cpp)
  • 此命令将使用add_library()调用中的源代码创建一个名为libhello_library.a的静态库

    • add_library: 生成动态库或静态库

      • 第1个参数指定库的名字;
      • 第2个参数决定是动态还是静态,如果没有就默认静态;
      • 第3个参数指定生成库的源文件
  • 如上一节所述,我们按照现代 CMake 的建议,将源文件直接传递给add_library调用。
  • set_target_properties: 设置输出的名称,还有其它功能,如设置库的版本号等等

(2)添加头文件目录

  • 在本例中,我们使用target_include_directory()函数将include目录包含在库中,并将范围设置为PUBLIC。
target_include_directories(hello_libraryPUBLIC${PROJECT_SOURCE_DIR}/include
)
  • 这将导致包含的目录在以下位置使用:

    • 在编译该库时
    • 在编译链接至该库的任何其他目标时。
  • 作用域的含义是:
    • PRIVATE - 将目录添加到此目标的include目录中
    • INTERFACE - 将该目录添加到任何链接到此库的目标的include目录中(不包括自己)。
    • PUBLIC - 它包含在此库中,也包含在链接此库的任何目标中。
  • 提示:
    • 对于公共头文件,让你的include文件夹使用子目录“命名空间”通常是个好主意。传递给target_include_directories的目录将是你的Include目录树的根目录,并且你的C++文件应该包含从那里到你要使用的头文件的路径。
    • 在本例中,你可以看到我们按如下方式执行操作。使用此方法意味着,在项目中使用多个库时,头文件名冲突的可能性较小。比如:
#include "static/hello.h"

(3)链接库

  • 在创建使用库的可执行文件时,你必须告诉编译器有关库的信息。这可以使用target_link_library()函数来完成。
add_executable(hello_binarysrc/main.cpp
)target_link_libraries(hello_binaryPRIVATEhello_library
)
  • 这告诉CMake在链接时将hello_library与hello_binary可执行文件链接起来。它还将从hello_library传递任何具有PUBLIC或INTERFACE作用范围的include目录到hello_binary。
  • 编译器调用它的一个示例是:
/usr/bin/c++ CMakeFiles/hello_binary.dir/src/main.cpp.o -o hello_binary -rdynamic libhello_library.a

构建

[oceanstar@localhost demo]$ mkdir  build[oceanstar@localhost demo]$ cd build/[oceanstar@localhost build]$ cmake  ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done$ make
Scanning dependencies of target hello_library
[ 25%] Building CXX object CMakeFiles/hello_library.dir/src/hello.cpp.o
[ 50%] Linking CXX static library libhello_library.a
[ 50%] Built target hello_library
Scanning dependencies of target hello_binary
[ 75%] Building CXX object CMakeFiles/hello_binary.dir/src/main.cpp.o
[100%] Linking CXX executable hello_binary
[100%] Built target hello_binary

实验二:生成动态库

编写代码

项目结构如下:

  • [CMakeLists.txt] - 包含你希望运行的 CMake 命令
cmake_minimum_required(VERSION 3.5)project(hello_library)############################################################
# Create a library
#############################################################Generate the shared library from the library sources
add_library(hello_library SHARED src/Hello.cpp
)
add_library(hello::library ALIAS hello_library)target_include_directories(hello_libraryPUBLIC ${PROJECT_SOURCE_DIR}/include
)############################################################
# Create an executable
############################################################# Add an executable with the above sources
add_executable(hello_binarysrc/main.cpp
)# link the new hello_library target with the hello_binary target
target_link_libraries(hello_binaryPRIVATE hello::library
)
  • [include/shared/hello.h] - 要包含的头文件
#ifndef __HELLO_H__
#define __HELLO_H__class Hello
{public:void print();
};#endif
  • [src/hello.cpp] - 要编译的源文件
#include <iostream>#include "shared/hello.h"void Hello::print()
{std::cout << "Hello Static Library!" << std::endl;
}
  • [src/main.cpp] - 具有main的源文件

#include "shared/hello.h"int main(int argc, char *argv[])
{Hello hi;hi.print();return 0;
}

一些理论

(1)添加共享库

  • add_library()指定从某些源文件创建共享库。调用方式如下:
add_library(hello_library SHAREDsrc/Hello.cpp
)
  • 这将使用传递给add_library()函数的源码文件创建一个名为libhello_library.so的共享库。

(2)别名目标

顾名思义,别名目标是目标的替代名称,可以在只读上下文中替代真实的目标名称。

add_library(hello::library ALIAS hello_library)
  • ALIAS类似于“同义词”。ALIAS目标只是原始目标的另一个名称。因此ALIAS目标的要求是不可修改的——您无法调整其属性、安装它等。
  • 如下所示,这允许你在将目标链接到其他目标时使用别名引用该目标。(hello::library等效于hello_library

(3)链接共享库

  • 链接共享库与链接静态库相同。创建可执行文件时,请使用target_link_library()函数指向库。
add_executable(hello_binarysrc/main.cpp
)target_link_libraries(hello_binaryPRIVATEhello::library
)
  • 这告诉CMake使用别名目标名称将hello_library链接到hello_binary可执行文件。
  • 链接器调用它的一个示例是:
/usr/bin/c++ CMakeFiles/hello_binary.dir/src/main.cpp.o -o hello_binary -rdynamic libhello_library.so -Wl,-rpath,/home/matrim/workspace/cmake-examples/01-basic/D-shared-library/build

构建

$ mkdir build$ cd 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/matrim/workspace/cmake-examples/01-basic/D-shared-library/build$ make
Scanning dependencies of target hello_library
[ 50%] Building CXX object CMakeFiles/hello_library.dir/src/Hello.cpp.o
Linking CXX shared library libhello_library.so
[ 50%] Built target hello_library
Scanning dependencies of target hello_binary
[100%] Building CXX object CMakeFiles/hello_binary.dir/src/main.cpp.o
Linking CXX executable hello_binary
[100%] Built target hello_binary$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  hello_binary  libhello_library.so  Makefile$ ./hello_binary
Hello Shared Library!

实验三:仅生成库但是不使用库

编写代码

项目结构如下:

/*
** testFunc.c
*/#include <stdio.h>
#include "testFunc.h"void func(int data)
{printf("data is %d\n", data);
}
/*
** testFunc.h
*/#ifndef _TEST_FUNC_H_
#define _TEST_FUNC_H_void func(int data);#endif

最外层的CMakeLists.txt内容如下:

cmake_minimum_required (VERSION 2.8)project (demo)#向当前工程添加存放源文件的子目录
add_subdirectory (lib_testFunc)

lib_testFunc目录下的CMakeLists.txt如下:

aux_source_directory (. SRC_LIST)# 使用${SRC_LIST}为原材料生成一个叫做testFunc_shared 的动态库
add_library (testFunc_shared SHARED ${SRC_LIST})
# 使用${SRC_LIST}为原材料生成一个叫做testFunc_static 的静态库
add_library (testFunc_static STATIC ${SRC_LIST})# 将testFunc_shared 重新命名为 libtestFunc.so
set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")
# 将testFunc_static  重新命名为 libtestFunc.a
set_target_properties (testFunc_static PROPERTIES OUTPUT_NAME "testFunc")# 设置 库文件的默认输出路径
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

命令:

  • set_target_properties: 设置输出的名称,还有其它功能,如设置库的版本号等等

预定义变量:

  • LIBRARY_OUTPUT_PATH: 库文件的默认输出路径,这里设置为工程目录下的lib目录

编译

现在,让我们进入build目录下运行cmake …,成功后再运行make:

cd到lib目录下进行查看,发现已经成功生成了动态库和静态库,

ps:可以看出前面使用set_target_properties重新定义了库的输出名字,如果不用set_target_properties也可以,那么库的名字就是add_library里定义的名字,只是我们连续2次使用add_library指定库名字时,这个名字不能相同,而set_target_properties可以把名字设置为相同,只是最终生成的库文件后缀不同,这样相对来说会好看点。

add_library

普通库

add_library(<name> [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL][source1] [source2] [...])
  • <name>

    • 表示库文件的名字,该库文件会根据命令里列出的源文件来创建。
    • < name>对应于逻辑目标名称,并且在项目中必须是全局唯一的。
    • 构建的库的实际文件名是基于本机平台的约定(如lib< name>.a或< name>.lib)构建的。
  • [STATIC | SHARED | MODULE] 指定要创建的库的类型
    • SHARED:

      • 动态库。动态库是动态链接并在运行时加载的
      • 如果库不导出任何符号,则不能将其声明为SHARED库
    • STATIC:静态库。静态库是在链接其他目标时使用的目标文件存档
    • MODULE:
      • 模块库是没有链接到其他目标的插件,但可以在运行时使用类似dlopen的功能动态加载
      • 在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
  • EXCLUDE_FROM_ALL:这个库不会被默认构建,除非有其他的组件依赖或者手工构建。
  • [source1] [source2] [...]:指定生成库的源文件

对象库

add_library(<name> OBJECT [<source>...])

创建一个对象库。对象库编译源文件,但不归档或者将它们的目标文件链接到库中。相反,add_library()或者add_executable()创建的其他目标可以使用$< TARGET_OBJECT:objlib>形式的表达式作为源引用对象
,其中objlib是对象库名称。例如:

add_library(... $<TARGET_OBJECTS:objlib> ...)
add_executable(... $<TARGET_OBJECTS:objlib> ...)

将包括objlib的目标文件在一个库和一个可执行文件,连同那些从自己的源编译。对象库可能只包含编译源、头文件和其他不会影响普通库链接的文件(例如.txt)。它们可能包含生成此类源的自定义命令,但不包含PRE_BUILD、PRE_LINK或POST_BUILD命令。一些原生构建系统(如Xcode)可能不喜欢只有对象文件的目标,所以考虑添加至少一个真正的源文件到任何引用$的目标。

3.12新版功能:可以用target_link_libraries()链接到对象库。

总结

命令总结:

命令 说明 示例
add_library 生成动态库或静态库 add_library (testFunc_shared SHARED ${SRC_LIST})
set_target_properties 设置输出的名称 set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")

预定义变量总结:

预定义变量 说明
LIBRARY_OUTPUT_PATH 库文件的默认输出路径

cmake:add_library生成静态库和动态库相关推荐

  1. CMake 常用总结二:CMake 生成静态库与动态库

    引言 CMake 实践帮助我们对 CMake 有一个系统全面的了解,并且有大量示例以供参考,至少在实际项目中可以让我们有能力看懂并修改项目中现有的 CMake . 阅读完 CMake 实践文档,认为自 ...

  2. HelloWorld CMake Demo 03:CMake中构建静态库与动态库及其使用

    继续完善Hello World,建立它的共享库,包括静态库和动态库. 本节的任务: 1,建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc向终端输出Hello W ...

  3. android jni通过cmake使用第三方静态库和动态库

    google 官方现在推荐使用cmake来构建jni. 本人正好工作需要使用第三方的静态库和动态库,写此文 权当做个记录. 首先修改app的build.gradle文件 ndk {abiFilter ...

  4. CMake I 编译静态库、动态库和对象库

    目录 一.源文件 1.Message.h 2.Message.cpp 3.helloworld.cpp 二.CMakeLists.txt 1.源文件 2.CMake语言说明 (1)cmake_mini ...

  5. gcc生成静态库和动态库,以及OpenCV3.4.11的安装和实例

    文章目录 一.用gcc生成静态库和动态库 (1).hello使用库实例 1.创建目录并编写hello代码 2.gcc编译得到.o文件 3.静态库的使用 4.动态库的使用 5.静态库与动态库的对比 (2 ...

  6. 用gcc生成静态库和动态库和使用opencv库编写打开摄像头压缩视频

    文章目录 一.用gcc生成静态库和动态库 1.编辑生成程序hello.h.hello.c.main.c 2.将hello.c生成.o文件 3.使用静态库 4.动态库的使用 二.a与.so库文件的生成与 ...

  7. GCC生成静态库和动态库

    目录 1)阅读.理解和学习材料"用gcc生成静态库和动态库.pdf"和"静态库.a与.so库文件的生成与使用.pdf",请在Linux系统(Ubuntu)下如实 ...

  8. Linux下用gcc生成静态库和动态库及练习使用OpenCV

    我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为 静态库和动态库两种.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库.动态库在程序编译时并不会被连接到目标代码中,而 ...

  9. linux 中如何将文件粘贴到usr下的lib内,学会在Linux下GCC生成和使用静态库和动态库...

    一.基本概念1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主 ...

最新文章

  1. python爬取单个网页照片!
  2. hdu 1548 A strange lift
  3. SAP ME55 不能审批含有Delete Item的采购申请单据
  4. c语言中指针中 - 和 。的区别?
  5. android 中间凹背景_Android实现边缘凹凸的View
  6. RH4 构建ORACLE ASM
  7. Caffe学习-手写数字识别
  8. 【心电信号】基于matlab心电信号特征提取+分析处理【含Matlab源码 289期】
  9. SQL数据库的创建及其详细操作(作业)
  10. 聚簇索引与非聚簇索引
  11. 生活随记 - 火星梦
  12. Git版本回退的两种方式及回退方式推荐
  13. org.apache.flink.util.FlinkRuntimeException: Exceeded checkpoint tolerable failure threshold
  14. Linux操作系统基础之用户管理
  15. 离线地图-geoserver
  16. Delphi中资源文件使用详解
  17. 用python编写万年历
  18. 详解 Tree-structured Parzen Estimator(TPE)
  19. matlab画出拟合的曲线,matlab画出拟合曲线
  20. 树莓派DS18B20温度传感器获取温度

热门文章

  1. 贪婪洞窟2如何修改服务器,贪婪洞窟2改造系统详解-改造系统概率分析
  2. 机器学习中火爆的对抗学习是什么,有哪些应用?
  3. 计算机函数公式的英文表达式,Houdini Expression functions 函数表达式中英文对照(二)...
  4. uniapp调用手机摄像头_uniapp原生插件开发之调用原生方法(android)
  5. Hibernate: null java.sql.SQLException: 要执行的 SQL 语句不得为空白或空值
  6. 反转!南大通报“教师性侵学生”事件,举报人因读研时未获国奖虚假举报
  7. 水下传感器网络研究——第5章 路由协议
  8. java计算机毕业设计南通大学福利发放管理系统源代码+数据库+系统+lw文档
  9. 学生学籍管理系统简单设计(上)
  10. 商城产品属性数据库设计