cmake 02 static lib
组织为静态和动态库
通常的项目都会划分模块,模块以库的形式进行链接(动态或静态),在 cmake 中进行这一构建操作也是比较简单。
还是原来的 helloworld 项目,现在从 helloworld3 拷贝到 helloworld4 。原来直接写在 main 中的输出部分,现在提取出一个 sayHello 函数供重复调用。
增加一个 lib 目录,里面增加 hello.h 和 hello.c ,内容分别为 ::
#ifndef HELLO_H
#define HELLO_H
void sayHello();
#endif
和 ::
#include <stdio.h>
#include "hello.h"
void sayHello()
{
printf("Hello, world!\n");
}
在 lib 中增加一个 CMakeLists.txt ::
SET(SRC_LIST hello.c)
ADD_LIBRARY(hello_shared SHARED ${SRC_LIST})
SET_TARGET_PROPERTIES(hello_shared PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_shared PROPERTIES VERSION 1.2 SOVERSION 1)
ADD_LIBRARY(hello_static STATIC ${SRC_LIST})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES VERSION 1.2 SOVERSION 1)
INSTALL(TARGETS hello_shared;hello_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include)
ADD_LIBRARY 指令指示生成一个库目标文件,可指定库的类型为 SHARED 或 STATIC 。
SET_TARGET_PROPERTIES 指令设置目标的属性,其中 CLEAN_DIRECT_OUTPUT 部分用于指示在生成具有相同名字的(OUTPUT_NAME)的目标时,是否清理上次生成的内容。由于这罗的动态和静态库都使用 hello 这个名字,因此需要设置此不见标志。
这个配置文件同时生成了动态连接库和静态连接库,并把头文件安装到 include 目录。
引用动态库
修改 src 中的 main.c ::
#include int main(int argc, char* argv[]){ } ADD_SUBDIRECTORY(lib) ADD_EXECUTABLE(hello main.c) INSTALL(TARGETS hello DESTINATION bin) TARGET_LINK_LIBRARIES 指示链接到目标库。由于我们的库与源代码在同一个 cmake 构建系统中,可直接用目标名 hello_shared 或 hello_static,否则应该用库文件名。链接时,如果链接库放在非系统特定的库目录下,那么需要通过 LINK_DIRECTORIES(路径) 指定库的搜索路径,或者直接用绝对路径。 如果无法在 CMakeLists.txt 中指定 INCLUDE_DIRECTORIES 和 LINK_DIRECTORIES ,还可以通过 shell 变量 CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH,在 cmake 构建时传递给 cmake 。 然后,在 CMakeLists.txt 中通过 FIND_PATH 指令来判断是否找到相应的头文件路径,并包含进来 :: FIND_PATH(myHeader hello.h) ENDIF(myHeader) FIND_PATH(变量名 NAMES 需要查找的文件名列表 PATHS 待查找的路径列表) 顶层目录中的 CMakeLists.txt 保持不变,用来构建其它文件。 同样,在 build 目录中,进行构建 :: (mkdir -p build; cd build; cmake -DCMAKE_INSTALL_PREFIX=$PWD/usr; make install) usr/ 要注意,直接运行 ./usr/bin/hello 时,会报告无法找到 libhello.so.1 的错误(如果是链接到静态库 hello_static 则不会出现此错误) :: /usr/bin/hello: error while loading shared libraries: libhello.so.1: cannot open shared object file: No such file or directory LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/usr/lib ./usr/bin/hello
#include "hello.h"sayHello();
return 0;
并在 src 中的 CMakeLists.txt 中,包含 lib 目录,以及让 hello 可执行文件链接到生成的库 ::
INCLUDE_DIRECTORIES(lib)
TARGET_LINK_LIBRARIES(hello hello_shared)
INCLUDE_DIRECTORIES 指定 include 时要包含的头文件搜索路径。
IF(myHeader)INCLUDE_DIRECTORIES(${myHeader})
FIND_PATH 用法为 ::
类似地,可用 CMAKE_LIBRARY_PATH 和 FIND_LIBRARY 判断库是否存在。
生成后,看 build 中的 usr ,有以下的目录树 ::
├── bin
│ ├── hello
│ └── runhello.sh
├── include
│ └── hello.h
├── lib
│ ├── libhello.a
│ ├── libhello.so -> libhello.so.1
│ ├── libhello.so.1 -> libhello.so.1.2
│ └── libhello.so.1.2
└── share└── doc
└── HELLO
├── hello.txt
└── README
这是由于系统默认的库搜索路径在 /etc/ld.so.config 中指定,可通过 LD_LIBRARY_PATH 变量暂时指定一个路径,即在 build 目录下 ::
就会正确地运行和输出。