install解釋:
TARGETS版本的install命令
install(TARGETS targets... [EXPORT <export-name>]
[[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP]
] [...])
TARGETS格式的install命令規定了安裝工程中的目標(targets)的規則。有5中可以被安裝的目標文件:ARCHIVE,LIBRARY,RUNTIME,FRAMEWORK,和BUNDLE。除了被標記為MACOSX_BUNDLE屬性的可執行文件被當做OS X上的BUNDLE目標外,其他的可執行文件都被當做RUNTIME目標。靜態鏈接的庫文件總是被當做ARCHIVE目標。模塊庫總是被當做LIBRARY目標。對於動態庫不是DLL格式的平台來說,動態庫會被當做LIBRARY目標來對待,被標記為FRAMEWORK的動態庫是例外,它們被當做OS X上的FRAMEWORK目標。對於DLL平台而言,動態庫的DLL部分被當做一個RUNTIME目標而對應的導出庫被當做是一個ARCHIVE目標。所有基於Windows的系統,包括Cygwin,都是DLL平台。ARCHIVE,LIBRARY,RUNTIME和FRAMEWORK參數改變了后續屬性會加諸之上的目標的類型。如果只給出了一種類型,那么只有那種類型的目標會被安裝(這樣通常只會安裝一個DLL或者一個導出庫。)
PRIVATE_HEADER,PUBLIC_HEADER,和RESOURCE選項的功能是,在非蘋果平台上,將后續的屬性應用在待安裝的一個FRAMEWORK共享庫目標的相關文件上。這些選項定義的規則在蘋果系統上會被忽略掉,因為相關的文件將會被安裝到framework文件夾內的合適位置。參見PRIVATE_HEADER,PUBLIC_HEADER和RESOURCE目標屬性中更為詳細的解釋。
可以指定NAMELINK_ONLY或者NAMELINK_SKIP選項作為LIBRARY選項。在一些平台上,版本化的共享庫有一個符號鏈接,比如lib<name>.so -> lib<name>.so.1,其中“lib<name>.so.1”是so庫文件名(soname)而“lib<name>.so”是一個符號鏈接,當指定“-l<name>”選項時,鏈接器將會查找這個符號鏈接。如果一個庫目標已經被安裝,NAMELINK_ONLY選項表示僅僅安裝符號鏈接;而NAME_SKIP選項則表示僅僅安裝庫文件而不是符號鏈接。當兩種選項都沒有給出時,動態庫的兩個部分都會被安裝。在那些版本化的共享庫沒有符號鏈接或者庫沒有被版本化的平台,選項NAMELINK_SKIP安裝這個庫,而NAMELINK_ONLY選項什么都不會安裝。參見VERSION和SOVERSION目標屬性,獲取關於創建版本化共享庫的更多細節。
在該命令的TARGETS版本的一次調用中,可以一次性指定一個或多個屬性組。一個目標也可以被多次安裝到不同的位置。假設有三個目標myExe,mySharedLib和myStaticLib,下面的代碼
install(TARGETS myExe mySharedLib myStaticLib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
install(TARGETS mySharedLib DESTINATION /some/full/path)
將會把myExe安裝到<prefix>/bin目錄下,把myStaticLib安裝到<prefix>/lib/static目錄下。在非-DLL平台上,mySharedLib將會被安裝到<prefix>/lib和/some/full/path下。在DLL平台上,mySharedLib DLL將會被安裝到<prefix>/bin和/some/full/path路徑下,它的導出庫會被安裝到<prefix>/lib/static和/some/full/path路徑下。
其中<prefix>一般在configure時候指定.
EXPORT選項將已經安裝的目標文件和一個名為<export-name>的導出文件關聯起來。它必須出現在所有RUNTIME,LIBRARY或者ARCHIVE選項之前。為了實際安裝導出文件本身(export file),調用install(EXPORT)。參見下述install命令EXPORT版本的文檔獲取更多的細節。
將EXCLUDE_FROM_ALL設置為true時,安裝一個目標會造成未定義的行為。
引用網址: http://www.qtchina.net/?q=archive/story/2007/9/23
(五) 靜態庫與動態庫構建
Submitted by liuguangzhao on Sun, 2007-09-23 20:58
in
Document
讀者雲,太能羅唆了,一個Hello World就折騰了兩個大節。OK,從本節開始,我們不
再折騰Hello World了,我們來折騰Hello World的共享庫。
本節的任務:
1,建立一個靜態庫和動態庫,提供HelloFunc函數供其他程序編程使用,HelloFunc
向終端輸出Hello World字符串。
2,安裝頭文件與共享庫。
一,准備工作:
在/backup/cmake目錄建立t3目錄,用於存放本節涉及到的工程
二,建立共享庫
cd /backup/cmake/t3
mkdir lib
在t3目錄下建立CMakeLists.txt,內容如下:
PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib)
在lib目錄下建立兩個源文件hello.c與hello.h
hello.c內容如下:
#include “hello.h”
void HelloFunc()
{
printf(“Hello Worldn”);
}
hello.h內容如下:
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
void HelloFunc();
#endif
在lib目錄下建立CMakeLists.txt,內容如下:
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
三,編譯共享庫:
仍然采用out-of-source編譯的方式,按照習慣,我們建立一個build目錄,在build
目錄中
cmake ..
make
這時,你就可以在lib目錄得到一個libhello.so,這就是我們期望的共享庫。
如果你要指定libhello.so生成的位置,可以通過在主工程文件CMakeLists.txt中修
改ADD_SUBDIRECTORY(lib)指令來指定一個編譯輸出位置或者
在lib/CMakeLists.txt中添加
SET(LIBRARY_OUTPUT_PATH <路徑>)來指定一個新的位置。
這兩者的區別我們上一節已經提到了,所以,這里不再贅述,下面,我們解釋一下一個新的
指令ADD_LIBRARY
ADD_LIBRARY(libname [SHARED|STATIC|MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
你不需要寫全libhello.so,只需要填寫hello即可,cmake系統會自動為你生成
libhello.X
類型有三種:
SHARED,動態庫
STATIC,靜態庫
MODULE,在使用dyld的系統有效,如果不支持dyld,則被當作SHARED對待。
EXCLUDE_FROM_ALL參數的意思是這個庫不會被默認構建,除非有其他的組件依賴或者手
工構建。
四,添加靜態庫:
同樣使用上面的指令,我們在支持動態庫的基礎上再為工程添加一個靜態庫,按照一般的習
慣,靜態庫名字跟動態庫名字應該是一致的,只不過后綴是.a罷了。
下面我們用這個指令再來添加靜態庫:
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
然后再在build目錄進行外部編譯,我們會發現,靜態庫根本沒有被構建,仍然只生成了
一個動態庫。因為hello作為一個target是不能重名的,所以,靜態庫構建指令無效。
如果我們把上面的hello修改為hello_static:
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
就可以構建一個libhello_static.a的靜態庫了。
這種結果顯示不是我們想要的,我們需要的是名字相同的靜態庫和動態庫,因為target名
稱是唯一的,所以,我們肯定不能通過ADD_LIBRARY指令來實現了。這時候我們需要用到
另外一個指令:
SET_TARGET_PROPERTIES,其基本語法是:
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
這條指令可以用來設置輸出的名稱,對於動態庫,還可以用來指定動態庫版本和API版本。
在本例中,我們需要作的是向lib/CMakeLists.txt中添加一條:
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
這樣,我們就可以同時得到libhello.so/libhello.a兩個庫了。
與他對應的指令是:
GET_TARGET_PROPERTY(VAR target property)
具體用法如下例,我們向lib/CMakeListst.txt中添加:
GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME)
MESSAGE(STATUS “This is the hello_static
OUTPUT_NAME:”${OUTPUT_VALUE})
如果沒有這個屬性定義,則返回NOTFOUND.
讓我們來檢查一下最終的構建結果,我們發現,libhello.a已經構建完成,位於
build/lib目錄中,但是libhello.so去消失了。這個問題的原因是: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
五,動態庫版本號
按照規則,動態庫是應該包含一個版本號的,我們可以看一下系統的動態庫,一般情況是
libhello.so.1.2
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.2
為了實現動態庫版本號,我們仍然需要使用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
六,安裝共享庫和頭文件
以上面的例子,我們需要將libhello.a, libhello.so.x以及hello.h安裝到系統目
錄,才能真正讓其他人開發使用,在本例中我們將hello的共享庫安裝到<prefix>/lib
目錄,將hello.h安裝到<prefix>/include/hello目錄。
利用上一節了解到的INSTALL指令,我們向lib/CMakeLists.txt中添加如下指令:
INSTALL(TARGETS hello hello_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include/hello)
注意,靜態庫要使用ARCHIVE關鍵字
通過:
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
make install
我們就可以將頭文件和共享庫安裝到系統目錄/usr/lib和/usr/include/hello中了。
七,小結:
本小節,我們談到了:
如何通過ADD_LIBRARY指令構建動態庫和靜態庫。
如何通過SET_TARGET_PROPERTIES同時構建同名的動態庫和靜態庫。
如何通過SET_TARGET_PROPERTIES控制動態庫版本
最終使用上一節談到的INSTALL指令來安裝頭文件和動態、靜態庫。
在下一節,我們需要編寫另一個高級一點的Hello World來演示怎么使用我們已經構建的
構建的共享庫libhello和外部頭文件。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/czjjun/archive/2008/08/01/2753237.aspx