码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-09-06 16:25:11      阅读:1531      评论:0      收藏:0      [点我收藏+]

标签:span   输出   习惯   clu   了解   size   规则   生成   UNC   

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第三课--安装自己编写的头文件和共享库

标签:span   输出   习惯   clu   了解   size   规则   生成   UNC   

原文地址:https://www.cnblogs.com/guoshuai-ouc/p/cmake_lib.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!