1、Linux下C+开发(四)动、静态库与安装操作本系列Linux下的C+开发,主要分为两大部分,第一部分讲解Linux下C+的开发流程及一些基础知识,第二部分讲解Cmake的使用,初步计划如下:1,Linux下C+的开发流程及基础知识介绍2,cmake简述及CMakeLists基本语句语法3,多目录工程4,动,静态库及安装操作5,模块的使用及自定义模块6,Linux下各种IDE介绍和对比今天主要给大家介绍的就是第二部分的第三节:动、静态库及安装操作安装安装操作操作这里讲到的安装操作类似一种自动化的复制我们首先看一下本次项目的结构将工程项目中的各种类型的文件安装到指定的目录中去将cmake/3/C
2、OPYRIGHT安装到cmake/install_dir/doc 将cmake/3/README安装到cmake/install_dir/doc 将cmake/3/doc/hello.txt安装到cmake/install_dir/doc将cmake/3/runhello.sh安装到cmake/install_dir/bin将输出的二进制文件二进制文件也安装到cmake/install_dir/bin安装安装操作操作接下来看如何在CMakeLists.txt中具体实现这些步骤cmake_minimum_required(VERSION 2.6)PROJECT(demo3)MESSAGE(STA
3、TUS This is BINARY dir$demo3_BINARY_DIR)MESSAGE(STATUS This is SOURCE dir$demo3_SOURCE_DIR)#add executable fileADD_SUBDIRECTORY(./src)#set CMAKE_INSTALL_PREFIXSET(CMAKE_INSTALL_PREFIX/home/liqi/workspace/cmake/install_dir)MESSAGE(STATUS CMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX)#install some filesI
4、NSTALL(PROGRAMS runhello.sh DESTINATION bin)INSTALL(DIRECTORY doc/DESTINATION doc)INSTALL(FILES COPYRIGHT README DESTINATION doc)主目录的CMakeLists.txtADD_EXECUTABLE(hello hello.c)#set output pathSET(EXECUTABLE_OUTPUT_PATH$CMAKE_BINARY_DIR/bin)#MESSAGE($EXECUTABLE_OUTPUT_PATH)INSTALL(TARGETS hello RUNTI
5、ME DESTINATION bin)src目录下的CMakeLists.txt安装安装操作操作CMAKE_INSTALL_PREFIX变量变量CMAKE_INSTALL_PREFIX变量类似于configure 脚本的 prefix常见的使用方法看 起来是这个样子:cmake-DCMAKE_INSTALL_PREFIX=/usr.如果没有额外定义,那么CMAKE_INSTALL_PREFIX变量默认为/usr/local DESTINATION定义了安装的路径如果路径以/开头,那么指的是绝对路径,这时候 CMAKE_INSTALL_PREFIX其实就无效了如果你希望使用CMAKE_INSTA
6、LL_PREFIX来 定义安装路径,就要写成相对路径,即不要以/开头那么安装后的路径就是$CMAKE_INSTALL_PREFIX/安装安装操作操作 INSTALL(TARGETS targets.ARCHIVE|LIBRARY|RUNTIME DESTINATION PERMISSIONS permissions.CONFIGURATIONS Debug|Release|.COMPONENT OPTIONAL .)参数中的TARGETS后面跟的就是我们通过ADD_EXECUTABLE或者ADD_LIBRARY定义的 目标文件,可能是静态库、动态库、可执行二进制 INSTALL(FILES f
7、iles.DESTINATION PERMISSION permissions.CONFIGURATIONS Debug|Release|.COMPONENT RENAME OPTIONAL)可用于安装一般文件,并可以指定访问权限,文件名是此指令所在路安装安装操作操作INSTALL(PROGRAMS files.DESTINATION PERMISSIONS permissions.CONFIGURATIONS Debug|Release|.COMPONENT RENAME OPTIONAL)非目标文件的可执行程序安装(比如脚本之类)安装后权限为:OWNER_EXECUTE,GROUP_EXE
8、CUTE,和WORLD_EXECUTE,即755权限 INSTALL(DIRECTORY dirs.DESTINATION FILE_PERMISSIONS permissions.DIRECTORY_PERMISSIONS permissions.USE_SOURCE_PERMISSIONS CONFIGURATIONS Debug|Release|.COMPONENT PATTERN|REGEX EXCLUDE PERMISSIONS permissions.)PATTERN用于使用表达式进行过滤PERMISSIONS用于指定PATTERN过滤后的文件 权限。INSTALL(SCRIPT
9、CODE .)SCRIPT参数用于在安装时调用cmake脚本文件(也就是.cmake文件)CODE参数用于执行CMAKE指令,必须以双引号括起来。比如:INSTALL(CODE MESSAGE(Sample install message.)动、静态库动、静态库动态库:动态库:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在静态库:静态库:静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库本次示例工程文件结构如左图所示 hello.c与hello.h将被用来生成动态库和静态库并且将生成的库文件放到下面lib文件夹中#cma
10、ke versioncmake_minimum_required(VERSION 2.8.3)#project namePROJECT(demo4)#add subdirectoryADD_SUBDIRECTORY(library)#set prefixSET(CMAKE_INSTALL_PREFIX/home/liqi/workspace/cmake/install_dir)MESSAGE(STATUS CMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX)主目录下的主目录下的CMakeLists.txtCMakeLists.txt#set source va
11、riableSET(LIBHELLO_SRC hello.c)#add executable#ADD_EXECUTABLE(demo4 hello.h hello.c)#set output pathSET(LIBRARY_OUTPUT_PATH$PROJECT_BINARY_DIR/lib)#SET(EXECUTABLE_OUTPUT_PATH$PROJECT_BINARY_DIR/bin)#add libraryADD_LIBRARY(hello SHARED$LIBHELLO_SRC)ADD_LIBRARY(hello_static STATIC$LIBHELLO_SRC)#change
12、 static library propertySET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME hello)#change CLEAN_DIRECT_OUPUT propertiesSET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)#add shared library version numberSET_TARGET_P
13、ROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)#install librariesINSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)#install include fileINSTALL(FILES hello.h DESTINATION include)library library目录下的目录下的CMakeLists.txtCMakeLists.txt ADD_LIBRARY(libname SHARED|STATIC
14、|MODULE EXCLUDE_FROM_ALL source1 source2.sourceN)SHARED 动态库STATIC 静态库 MODULE 在使用dyld的系统有效,如果不支持dyld,则被当作SHARED对待EXCLUDE_FROM_ALL参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手 工构建GET_TARGET_PROPERTY(VAR target property)GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME)MESSAGE(STATUS“This is the hello_static
15、OUTPUT_NAME:”$OUTPUT_VALUE)如果没有这个属性定义,则返回NOTFOUNDSET_TARGET_PROPERTIES(target1 target2.PROPERTIES prop1 value1 prop2 value2.)这条指令可以用来设置输出的名称,对于动态库还可以用来指定动态库版本和API版本例如:SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME hello)SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)SET_TARG
16、ET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)VERSION指代动态库版本,SOVERSION指代API版本Dynamic Link Library“Dll hell”动态库新版本覆盖旧版本,但是却不兼容老版本 ()Linux 上的Dll,叫shared library 它有三个名字1.共享库本身的文件名(real name),其通常包含版本号,比如libmath.so.1.1.1234共享库的命
17、名必须如 libname.so.x.y.z最前面使用前缀”lib”,中间是库的名字和后缀”.so”,最后三个数字是版本号。x是主版本号(Major Version Number),y是次版本号(Minor Version Number),z是发布版本号(Release Version Number)2.动态库的so-name(Short for shared object name),其是应用程序加载dll 时候,其寻找共享库用的文件名。其格式为lib+math+.so+(major version number)其只包含major version number,换句话说,也就是只要其接口没有
18、变,应用程序都可以用,不管你其后minor build version or build version。软连接(Symbol Link);readelf-d sharelibrary;ldconfig3.共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib+math+.so,比如libmath.so。其是不带任何版本信息的。在共享库编译过程中,连接(link)阶段,编译器将生成一个共享库及real name,同时将共享库的soname,写在共享库文件里的文件头里面。可以用命令 readelf-d sharelibrary 去查看。如用GCC的“-l
19、”参数链接共享库libtXXX.so.3.8.1,只需要在编译器命令行指定-l XXX 即可,省略了前缀和版本信息。编译器会根据当前环境,在系统中的相关路径(往往由-L参数指定)查找最新版本的XXX库。这个XXX就是共享库的“链接名”LinuxLinux动态库的版本控制动态库的版本控制动、静态库的使用动、静态库的使用最后,我们来使用我们自己刚刚建立的库创建库与使用库可以在一个工程中进行在生成库的时候我们就可以添加一个test二进制文件二进制文件并运行它来检测我们的库是否成功生成INCLUDE_DIRECTORIES(/home/liqi/workspace/cmake/install_dir/
20、include)LINK_DIRECTORIES(/home/liqi/workspace/cmake/install_dir/lib)#SET(LIB/home/liqi/workspace/cmake/install_dir/lib/libhello.so)ADD_EXECUTABLE(demo5 main.c)#MESSAGE(STATUS EXT_LIB=$LIB)#SET(EXECUTABLE_OUTPUT_PATH$CMAKE_BINARY_DIR/bin)TARGET_LINK_LIBRARIES(demo5 hello.so)动、静态库的使用动、静态库的使用cmake_mini
21、mum_required(VERSION 2.8.3)PROJECT(demo5)ADD_SUBDIRECTORY(src bin)主目录下的主目录下的CMakeLists.txtCMakeLists.txt s src rc目录下的目录下的CMakeLists.txtCMakeLists.txtLINK_DIRECTORIES(directory1 directory2.)这个指令非常简单,添加非标准的共享库搜索路径,比如,在工程内部同时存在共享库和可 执行二进制,在编译时就需要指定一下这些共享库的路径TARGET_LINK_LIBRARIES(target library1 library2 .)这个指令可以用来为target添加需要链接的共享库,本例中是一个可执行文件,但是同样可以用于为自己编写的共享库添加共享库链接动、静态库的使用动、静态库的使用使用ldd指令,查看是否库文件链接成功了