cmake第三课--安装自己编写的头文件和共享库(代码片段)

guoshuai-ouc guoshuai-ouc     2022-12-29     385

关键词:

CMake第三课  安装自己编写的头文件和共享库

一.完整过程

手把手教你学CMake,上一节讲到了安装文件。这一节我们将自己动手写一个动态库和一个静态库,并安装头文件和共享库以供其他程序使用 。下一节,我们将编写程序,应用这一节安装的头文件和库文件。本节还是以输出 Hello World 字符串为例进行讲解。

====================================================================================

绝对路径:/home/guo/cmake_practice/3(工程目录)

----------------------------------------------------------

目标:

1.建立一个静态库和动态库,提供 HelloFunc 函数供其他程序编程用,HelloFunc向终端输出 Hello World 字符串。

2.安装头文件与共享库(包含静态库和动态库)。

----------------------------------------------------------

工程目录结构(按照下面结构添加文件夹和文件)

1.一个空文件夹 build

2.在主工程目录(/home/guo/cmake_practice/3)建一个CMakeLists.txt文件

PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib) 

3.一个lib文件夹(/home/guo/cmake_practice/3/lib) 建立两个源文件 hello.cpp 与 hello.h  和 一个CMakeLists.txt

lib/hello.h内容:

#ifndef HELLO_H
#define HELLO_H
#include <iostream>
using namespace std;
int HelloFunc();
#endif

lib/hello.cpp内容:

#include "hello.h"
int HelloFunc()

    cout<<"Hello World!"<<endl;
    return 0;

lib/CMakeLists.txt内容:

CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )  #声明要求的 cmake 最低版本
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello SHARED $LIBHELLO_SRC)
SET(LIBRARY_OUTPUT_PATH $PROJECT_BINARY_DIR/lib)

ADD_LIBRARY(hello_static STATIC $LIBHELLO_SRC)
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

INSTALL(TARGETS hello hello_static
       LIBRARY DESTINATION include/lib
       ARCHIVE DESTINATION include/lib)
INSTALL(FILES hello.h DESTINATION include/hello)

----------------------------------------------------------

外部编译

cd build cmake -DCMAKE_INSTALL_PREFIX=/home/guo/cmake_practice/3 ..  (指定绝对路径 <prefix>)

make

make install

这样我们就可以将头文件和共享库分别安装到/home/guo/cmake_practice/3/include/hello 和/home/guo/cmake_practice/3/include/lib中了。

====================================================================================

 

二.详细解释

1.ADD_LIBRARY基本语法:ADD_LIBRARY(libname   [SHARED|STATIC|MODULE]

                                             [EXCLUDE_FROM_ALL]

                                             source1 source2 ... sourceN)

  • 在写libname时,你不需要写全 libhello.so,只需要填写 hello 即可,cmake 系统会自动为你生成libhello.X。
  • libhello.X类型有三种:SHARED动态库;STATIC静态库;MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
  • EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手工构建。

2.SET_TARGET_PROPERTIES基本语法:    SET_TARGET_PROPERTIES(target1 target2 ...                       

                                                           PROPERTIES prop1 value1

                                                           prop2 value2 ...)

这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本。

----------------------------------------------------------

3.首先生成动态库

ADD_LIBRARY(hello   SHARED   $LIBHELLO_SRC) 
SET(LIBRARY_OUTPUT_PATH      $PROJECT_BINARY_DIR/lib)

   在 <prefix>/lib 目录得到一个 libhello.so,这就是我们期望的共享库。

4.上述步骤实现了生成动态库,接下来要生成同名静态库就有些麻烦了

  • 我们不能用ADD_LIBRARY(hello STATIC $LIBHELLO_SRC)再来添加静态库。如果这样做,我们会发现静态库根本没有被构建,仍然只生成了一个动态库。因为 hello 作为一个 target 是不能重名的,所以,静态库构建指令无效。所以我们换了个名字创建,用了ADD_LIBRARY(hello_static  STATIC  $LIBHELLO_SRC)这条指令。
  • 但按照一般的习惯,静态库名字跟动态库名字应该是一致的,只是扩展名不同,即:静态库名为 libhello.a  动态库名为libhello.so ;因为不能重名,所以对静态库换一个名字,再重命名。看能不能生成:       
ADD_LIBRARY(hello_static STATIC $LIBHELLO_SRC)
SET_TARGET_PROPERTIES(hello_static  PROPERTIES  OUTPUT_NAME  "hello")

 这样对静态库重命名也不能同时得到 libhello.so/libhello.a 这两个库。因为:cmake 在构建一个新的 target 时,会尝试清理掉其他使用这个名字的库。 即,在构建 libhello.a 时,就会清理掉 libhello.so.

  • 为了解决被清理这个问题,再次使用 SET_TARGET_PROPERTIES 定义CLEAN_DIRECT_OUTPUT 属性。向 lib/CMakeLists.txt 中添加:
SET_TARGET_PROPERTIES(hello        PROPERTIES  CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES  CLEAN_DIRECT_OUTPUT 1)

这时候,我们再次进行构建,会发现 build/lib 目录中同时生成了 libhello.so 和libhello.a

----------------------------------------------------------

5.按照规则,动态库是应该包含一个版本号的。

为了实现动态库版本号,我们仍然需要使用 SET_TARGET_PROPERTIES 指令。具体使用方法如下:

SET_TARGET_PROPERTIES(hello  PROPERTIES  VERSION 1.2  SOVERSION 1)

VERSION 指代动态库版本,SOVERSION 指代 API 版本。将上述指令加入 lib/CMakeLists.txt 中,重新构建看看结果。

在 build/lib 目录会生成:

libhello.so.1.2 

libhello.so.1->libhello.so.1.2

libhello.so ->libhello.so.1

6.安装共享库和头文件

以上面的例子,我们需要将 libhello.a, libhello.so.x 以及 hello.h 安装到系统目录,才能真正让其他人开发使用,在本例中我们

将 hello 的共享库安装到<prefix>/include/lib目录;将 hello.h 安装到<prefix>/include/hello 目录。

INSTALL(TARGETS hello hello_static          
        LIBRARY DESTINATION include/lib
        ARCHIVE DESTINATION include/lib)
INSTALL(FILES hello.h DESTINATION include/hello)

注意:静态库要使用 ARCHIVE 关键字!

 

 

 

 

 

 

 

 




使用 cmake 安装动态库

】使用cmake安装动态库【英文标题】:Installingdynamiclibraryusingcmake【发布时间】:2020-11-0219:03:36【问题描述】:我有自己编写的C++/Qt库。我知道对于它的分发,cmake必须安装.dll(或Linux的.so)文件和头文件。于是我写了以下CMakeLists... 查看详情

第三课文件系统(上)

unix_c_03.txt====================第三课文件系统(上)====================一、系统调用------------应用程序-----------+||v|各种库|(C/C++标准库、Shell命令和脚本、|X11图形程序及库)|||v|系统调用<----------+(内核提供给外界访问的接口函数,调用这... 查看详情

将第三方共享库与 Python ctypes 集成

】将第三方共享库与Pythonctypes集成【英文标题】:Integratingthirt-partysharedlibrarywithPythonctypes【发布时间】:2017-05-0812:35:15【问题描述】:我需要编写一个Python程序来调用一些函数并从第三方共享库中获取JSON响应(一个unicode字符串... 查看详情

clion(cmake工具)中如何引入第三方库(代码片段)

前言因为自己最近在学Redis,想要在C++中获取到Redis内存数据库中的数据,需要使用Redis客户端来连接Redis传输命令并接收数据,在Redis官方网站上推荐的客户端中选择了acl-redis。而Clion是一款非常优秀的C++集成开发环境,Clion选择... 查看详情

如何在我的 cmake 项目中包含另一个 cmake 项目的头文件?

...题描述】:我正在尝试包含另一个CMake项目作为我项目的第三方库。问题是我不能包含上述库中的标题。我尝试使用add_subdirectory函数添加库,但它似乎不起作用。这是我的CMak 查看详情

链接 Yaml-cpp 和 Armadillo 共享库的 CMake 项目

...411:46:39【问题描述】:我正在使用Linux(飞跃42.3)。我想编写一个CMakeList.txt文件,该文件创建包含我的代码的共享库以及yaml-cpp和犰狳库,以便在另一个代码中使用它。所以:是先从各自的包和 查看详情

如何将第三方类库编译自己的动态库文件中

...和静态库的介绍请点击),但是不排除项目中有些依赖的第三方还是使用的静态库。那么这种情况下就可以考虑,将第三方静态库做一个二次封装。一来和业务代码进行隔离,方便以后第三方库的升级,二来将静态库封装进动态... 查看详情

cmake:构建程序的多个版本

...faprogram【发布时间】:2010-07-1906:41:23【问题描述】:我想编写一个cmake脚本,它将针对多个版本的头文件编译相同的源代码。其目的是能够轻松创建与API早期版本向后兼容的共享库。我正在寻找有关执行此操作的最佳方法的示例... 查看详情

CMake 添加和删除宏定义以编译共享库/可执行文件

】CMake添加和删除宏定义以编译共享库/可执行文件【英文标题】:CMakeAddandRemoveaMacrodefinitiontocompileSharedLibrary/Executable【发布时间】:2019-11-2909:06:50【问题描述】:我有一个c++代码,我需要以两种方式编译,一个共享库和一个可执... 查看详情

cmake:共享库和静态库的排序重要吗?

...】:2016-04-2020:57:51【问题描述】:我正在创建一个二进制文件并链接依赖项。所有二进制文件都将链接到libpthread.so发布模式二进制文件将链接到libtcmalloc.a我发现库的顺序很重要。如果我按如下方式指定对target_link_librar 查看详情

使用 snap 安装共享库

】使用snap安装共享库【英文标题】:Installsharedlibraryusingsnap【发布时间】:2019-02-0307:28:09【问题描述】:我有一个项目,它是由cmake构建的,我想用snap打包。项目包括可执行文件和库(让我们调用ita和liba)。我的snapcraft.yaml文件... 查看详情

cmake--静态库与动态库构建(代码片段)

...供其他程序编程使用,HelloFunc向终端输出HelloWorld字符串。安装头文件与共享库。1.代码与CMakeList.txt文件编写首先建立t3目录,用于存放本节涉及到的工程t3目录下创建lib目录用来存代码在t3目录下建立CMakeLists.txt,PROJECT(HELLOLIB)ADD_SUBDIR... 查看详情

cmake开篇词

...文件,多文件,多文件夹文件,静态库,动态库和依赖于第三方库的CMakeLists.txt编写方法。 查看详情

将 C 和 C++ 与 CMake 混合

...编写的项目(在Linux上),现在想使用提供.h和.c源文件的第三方C++库。我将.c文件重命名为.cpp,然后将此库包含在C项目中。但是编译时出现如下错误:unknowntypename‘class’补充:第三方库在这里https://github.com/0xmalloc/c- 查看详情

在 Windows 上使用 CMake 和 MinGW 链接 LLVM 库

...该项目被拆分为一个库和“驱动程序”可执行文件,它们自己的CMakeL 查看详情

使用 qmake 下载和构建第三方库

】使用qmake下载和构建第三方库【英文标题】:Downloadandbuildthird-partylibrarieswithqmake【发布时间】:2017-07-0116:06:43【问题描述】:在CMake项目中,我使用了ExternalProject_Add函数来增加可移植性并减少在我自己的Git存储库中存储不必要... 查看详情

用cmake设置visualstudio工程中第三方库(代码片段)

...//www.cnblogs.com/xuhui24/p/6234569.html用CMake设置VisualStudio工程中第三方库较大的工程文件中一般会调用动态库或者静态库,如果这些库文件是当前工程包含的项目,CMake会自动识别并添加Debug和Release编译时需要的库文件路径和文件名,... 查看详情

makefile第三课:c语言的编译(代码片段)

目录C语言的编译前言1.FundamentalCompiling2.ComilingC2.1Preprocessing2.2GeneratingAssemblyLanguage2.3SourceFiletoObjectFile2.4SingleSourcetoExecutable2.5MultipleSourcestoExecutable3.CreatingaStaticLibrary4.CreatingaSharedLibrary5.总体概括5.1编译过程5.2编译过程命令5.3库5.3.1静... 查看详情