install()命令指定在安裝時運行的規(guī)則。有如下幾種形式:
install(TARGETS <target>... [...])
install(IMPORTED_RUNTIME_ARTIFACTS <target>... [...])
install({FILES | PROGRAMS} <file>... [...])
install(DIRECTORY <dir>... [...])
install(SCRIPT <file> [...])
install(CODE <code> [...])
install(EXPORT <export-name> [...])
install(RUNTIME_DEPENDENCY_SET <set-name> [...])
一、命令簡介
intall()命令為工程生成安裝規(guī)則,同一個源文件目錄下的安裝規(guī)則按照intall()命令的調(diào)用順序在安裝時(也就是使用make install時)執(zhí)行。
intall()命令有多個形式,其中有一些是針對文件和目標(biāo)對象定義安裝選項。下面介紹該命令的幾個通用選項:
-
DESTINATION
指定文件將要安裝的目錄,可以是相對路徑也可以是絕對路徑。
如果是相對路徑,會以CMAKE_INSTALL_PREFIX變量(Unix/Linux下默認(rèn)值是/usr/local,Windows下的默認(rèn)值是C:/Program Files/${PROJECT_NAME})內(nèi)容為前綴。類Unix系統(tǒng)下可以在安裝時通過DESTDIR環(huán)境變量(參考DESTDIR,備注:DESTDIR是DESTination DIRectory的縮寫)重定位整個安裝路徑。例如文件的安裝前綴默認(rèn)是/usr/local/,當(dāng)執(zhí)行make DESTDIR=/package/stage install命令后,安裝前綴會變?yōu)?code>/package/stage/usr/local。
如果是絕對路徑,會直接使用該路徑作為安裝路徑,不會做任何改動。
因為cpack(cpack可執(zhí)行文件是一個CMake打包程序,它可以以各種格式生成安裝程序和源程序包)安裝生成器不支持絕對路徑,要使用相對路徑。沒有必要使用預(yù)置的CMAKE_INSTALL_PREFIX變量來生成絕對路徑,因為只要DESTINATION指定的是相對路徑,那么會自動使用CMAKE_INSTALL_PREFIX變量作為前綴。
-
PERMISSIONS
為安裝文件指定權(quán)限,合法的權(quán)限選擇有:OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, SETUID, SETGID,在有些平臺,該選項會被忽略,無法起作用。
-
CONFIGURATIONS
為安裝規(guī)則指定構(gòu)建配置(例如Debug、Release等),CONFIGURATIONS只會使用緊跟它的值,如果要指定多個構(gòu)建配置,需要使用install()命令多次,例如:分別指定Debug配置和Release配置:
install(TARGETS target CONFIGURATIONS Debug RUNTIME DESTINATION Debug/bin)
install(TARGETS target CONFIGURATIONS Release RUNTIME DESTINATION Release/bin)
注意:CONFIGURATIONS需要放在RUNTIME DESTINATION之前。
-
COMPONENT
指定與安裝規(guī)則關(guān)聯(lián)的安裝組件名稱,例如runtime或development。在指定組件安裝期間,只有與給定組件名稱關(guān)聯(lián)的安裝規(guī)則才會被執(zhí)行。除非使用EXCLUDE_FROM_ALL選項,否則會在完整安裝過程中安裝所有組件。
未指定該選項,則會創(chuàng)建一個默認(rèn)的組件名Unspecified,可以通過CMAKE_INSTALL_DEFAULT_COMPONENT_NAME變量來改變默認(rèn)的組件名。
-
EXCLUDE_FROM_ALL
3.6版本新增。在完整安裝過程中,指定排除掉的文件。排除的文件只會被安裝在特定的組件中。
-
RENAME
如果想在安裝過程中,使用與原文件不同的文件名,可以通過該選項來指定安裝文件的名字,重命名只允許應(yīng)用于單個文件的安裝命令。
-
OPTIONAL
該選項指明當(dāng)被安裝的文件不存在時,不會當(dāng)做錯誤處理。
不同版本的變更點:
3.1版本新增:安裝文件命令在安裝期間可以打印信息,使用CMAKE_INSTALL_MESSAGE變量可以控制打印哪些信息。
3.11版本新增:install()中的許多選項會隱式創(chuàng)建安裝文件路徑中保包含的目錄。這些被創(chuàng)建的目錄的權(quán)限可以通過CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS來指定,否則在類Unix系統(tǒng)會根據(jù)uname規(guī)則來創(chuàng)建,Windows系統(tǒng)不受影響。
3.14版本的變更點:通過add_subdirectory()命令添加的子目錄,子目錄的安裝規(guī)則,會被插入到父目錄安裝規(guī)則中,與父目錄的安裝規(guī)則按照申明的順序執(zhí)行。(可以參考CMP0082)
3.22版本的變更點:環(huán)境變量CMKE_INSTALL_MODE可以重新指定intall()的拷貝行為。
二、命令使用
2.1 install()命令的調(diào)用過程
1、編寫一個靜態(tài)庫 --- 已完成
2、編寫一個可執(zhí)行文件 --- 已完成
3、將靜態(tài)庫和可執(zhí)行文件安裝到不同目錄(盡可能多的演示install命令)
4、通過提供cmake文件,讓庫的使用者能找到該庫(可以參考find_library或find_package命令) --- 已完成
5、執(zhí)行cmake install安裝庫和可執(zhí)行文件 --- 已完成
6、編寫測試程序,使用安裝之后的庫 --- 已完成
三、命令詳解
3.1 安裝目標(biāo)
命令的格式為:
install(TARGETS targets... [EXPORT <export-name>]
[RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[NAMELINK_COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
[NAMELINK_ONLY|NAMELINK_SKIP]
] [...]
[INCLUDES DESTINATION [<dir> ...]]
)
-
TARGETS
TARGETS指定安裝目標(biāo)的規(guī)則,這里的目標(biāo)有如下幾種:
ARCHIVE:
- 靜態(tài)庫(例外情況:在
macOS系統(tǒng)下標(biāo)記為FRAMEWORK目標(biāo)的除外)DLL導(dǎo)入庫(在所有的基于Windows系統(tǒng)包括Cygwin,它們使用.lib擴(kuò)展名稱。相比之下.dll庫是RUNTIME目標(biāo)下包含的)- 在
AIX系統(tǒng),可以通過使能ENABLE_EXPORTS來為可執(zhí)行文件創(chuàng)建鏈接器導(dǎo)入文件
LIBRARY:
- 共享庫(兩種例外情況:屬于
RUNTIME目標(biāo)下的DLLs以及,macOS下屬于FRAMEWORK目標(biāo)下的)
RUNTIME:
- 可執(zhí)行文件(例外情況:在
macOS系統(tǒng)下標(biāo)記為MACOSX_BUNDLE目標(biāo)的除外)DLLs(在所有的基于Windows系統(tǒng)包括Cygwin,注意附帶的導(dǎo)入庫屬于ARCHIVE目標(biāo))
OBJECTS(3.9版本新增):
- 關(guān)聯(lián)到對象庫的對象文件
FRAMEWORK:
- 在
macOS系統(tǒng)下,被標(biāo)記為FRAMEWORK特性的的靜態(tài)庫和共享庫都會被當(dāng)做FRAMEWORK目標(biāo)
BUNDLE:
- 在
macOS系統(tǒng)下,被標(biāo)記為MACOSX_BUNDLE特性的可執(zhí)行文件會被當(dāng)做BUNDLE目標(biāo)
PUBLIC_HEADER:
- 在非
Apple平臺,與庫相關(guān)的PUBLIC_HEADER文件會被安裝到PUBLIC_HEADER指定的目錄中。因此在Apple平臺,FRAMEWORK庫會忽略該參數(shù),相關(guān)文件會被安裝到合適的框架目錄下
PRIVATE_HEADER:
- 與
PUBLIC_HEADER類似,但是作用于PRIVATE_HEADER文件
RESOURCE:
- 與
PUBLIC_HEADER和PRIVATE_HEADER類似,但是作用于RESOURCE文件
FILE_SET <set>(3.23版本新增):
- 文件集合通過
target_sources(FILE_SET)命令定義,如果文件集合<set>存在并且是PUBLIC或INTERFACE,那么集合中的文件會被安裝到目的路徑。相對文件集合基路徑的目錄結(jié)果會被保留,例如文件集合的基路徑是/XXX/YYY,在文件集合中的某個文件路徑為/XXX/YYY/myinstalldir/myfile.h,那么在安裝目的路徑下,會按照myinstalldir/myfile.h目錄結(jié)構(gòu)進(jìn)行安裝。
上述目標(biāo)類型的個數(shù)可以指定0個、1個或多個。當(dāng)目標(biāo)類型指定多個,每個指定的目標(biāo)類型后的安裝選項只會作用于該目標(biāo)或文件類型;當(dāng)指定0個目標(biāo)類型,則安裝選項會作用于所有的目標(biāo)類型;當(dāng)指定1個目標(biāo)類型時,則安裝選項只對該指定的目標(biāo)類型生效。
對于常規(guī)的可執(zhí)行文件、靜態(tài)庫文件、共享庫文件,DESTINATION安裝選項不是必須的,因為在未提供DESTINATION選項時,會從變量GNUInstallDirs獲取一個默認(rèn)值,如果該變量也未定義,會設(shè)置為內(nèi)置的默認(rèn)值。對于PUBLIC_HEADER和PRIVATE_HEADER指定與安裝目標(biāo)關(guān)聯(lián)的公共頭文件、私有頭文件、文件集合,也是一樣的規(guī)則。一般來說,模塊庫、Apple捆綁包、框架需要提供安裝路徑。接口和對象庫可以不提供安裝路徑,但是他們的處理會有差別。
下表顯示了當(dāng)未提供安裝目錄選項時,不同目標(biāo)類型關(guān)聯(lián)的變量和內(nèi)置默認(rèn)值。
| 目標(biāo)類型 | GNUInstallDirs變量 | 內(nèi)置默認(rèn)值 |
|---|---|---|
| RUNTIME | ${CMAKE_INSTALL_BINDIR} | bin |
| LIBRARY | ${CMAKE_INSTALL_BINDIR} | lib |
| ARCHIVE | ${CMAKE_INSTALL_BINDIR} | lib |
| PRIVATE_HEADER | ${CMAKE_INSTALL_INCLUDEDIR} | include |
| PUBLIC_HEADER | ${CMAKE_INSTALL_INCLUDEDIR} | include |
| FILE_SET (頭文件類型) | ${CMAKE_INSTALL_INCLUDEDIR} | include |
-
NAMELINK_COMPONENT
3.12版本新增,在一些系統(tǒng)下,通常會有一個符號鏈接指向一個帶版本號的共享庫,例如:lib<name>.so -> lib<name>.so.1。lib<name>.so.1為so庫名,lib<name>.so即為名稱鏈接,指向?qū)嶋H的so庫。這樣就允許使用鏈接器使用-l<name>來找到真實的lib<name>.so.1庫。NAMELINK_COMPONENT選項影響的就是共享庫名稱鏈接組件的安裝。
來看一個例子:
install(TARGETS mylib
LIBRARY
COMPONENT Libraries
NAMELINK_COMPONENT Development
PUBLIC_HEADER
COMPONENT Development
)
在上面的例子中,有兩種目標(biāo)類型:LIBRARY和PUBLIC_HEADER,其中LIBRARY下包含Libraries組件和Development組件,PUBLIC_HEADER下包含Development組件。
- 如果僅僅選擇安裝
Development組件,那么會安裝頭文件和名稱鏈接文件,但不會安裝庫文件。(此時安裝的名稱鏈接是懸空的,沒有實際的庫文件可以指向,因此鏈接器會找不到庫文件)。- 如果僅僅選擇安裝
Libraries組件,那么會安裝庫文件,但不會安裝頭文件和名稱鏈接文件。
該選項的典型應(yīng)用場景是包管理器,將運行時包和開發(fā)包分開。例如,在Debian系統(tǒng),庫文件為運行時包,而頭文件和名稱鏈接是開發(fā)包(意味著不安裝也不會影響系統(tǒng)運行,但是如果需要基于該庫做開發(fā),那么需要頭文件和名稱鏈接)。
-
NAMELINK_ONLY
該選項會導(dǎo)致在安裝庫目標(biāo)時,只安裝名稱鏈接文件。在沒有名稱鏈接的平臺或者庫文件未帶版本號,則該選項不起任何作用。并且該選項只能用于LIBRARY目標(biāo)下,否則會出錯。
當(dāng)指定NAMELINK_ONLY,NAMELINK_COMPONENT和COMPONENT都可以用來指定名稱鏈接的安裝,但是更推薦使用COMPONENT。
-
NAMELINK_SKIP
該選項與NAMELINK_ONLY起到相反的作用,當(dāng)安裝庫目標(biāo)時,只會安裝庫文件,而不會安裝名稱鏈接。如果NAMELINK_SKIP和NAMELINK_ONLY同時使用,那么庫文件和名稱鏈接都會安裝。在沒有名稱鏈接的平臺或者庫文件未帶版本號,該選項會安裝庫文件,該選項只能用于LIBRARY目標(biāo)下,否則會出錯。
當(dāng)指定NAMELINK_SKIP,NAMELINK_COMPONENT不起作用,因此不建議同時使用NAMELINK_SKIP和NAMELINK_COMPONENT。
-
EXPORT
該選項將安裝目標(biāo)文件與與名為<export-name>的導(dǎo)出關(guān)聯(lián)起來。該選項必須出現(xiàn)在任何其他安裝目標(biāo)選項之前。若要安裝導(dǎo)出文件本身,需要調(diào)用install(EXPORT)命令。如果使用了EXPORT選項,并且目標(biāo)包含了PUBLIC或INTERFACE文件集合,他們必須指定FILE_SET選項,所有與目標(biāo)關(guān)聯(lián)的PUBLIC或INTERFACE文件集合都包含在導(dǎo)出中。
-
INCLUDES DESTINATION
當(dāng)時用install(EXPORT)命令導(dǎo)出時,該選項指定了會被添加到<targets>目標(biāo)屬性INTERFACE_INCLUDE_DIRECTORIES的目錄列表。如果是相對路徑,會被當(dāng)成相對于$<INSTALL_PREFIX>的路徑。
-
RUNTIME_DEPENDENCY_SET
3.21版本新增。該選項會將安裝可執(zhí)行文件、共享庫、模塊目標(biāo)時的所有運行時依賴添加到指定的運行時依賴集合。運行時依賴集合可以通過install(RUNTIME_DEPENDENCY_SET)安裝。
RUNTIME_DEPENDENCY_SET與RUNTIME_DEPENDENCIES是互斥的。
-
RUNTIME_DEPENDENCIES
3.21版本新增。該選項會將安裝可執(zhí)行文件、共享庫、模塊目標(biāo)時的所有運行時依賴與目標(biāo)一起安裝。使用RUNTIME, LIBRARY,FRAMEWORK以及通用的參數(shù)來決定安裝這些依賴的的屬性(例如DESTINATION、COMPONENT等)。
RUNTIME_DEPENDENCIES在語義上等價于以下命令:
install(TARGETS ... RUNTIME_DEPENDENCY_SET <set-name>) install(RUNTIME_DEPENDENCY_SET <set-name> args...)
<set-name>是隨機產(chǎn)生的集合名稱,args...是install(RUNTIME_DEPENDENCY_SET)支持的選項,有如下取值:
DIRECTORIESPRE_INCLUDE_REGEXESPRE_EXCLUDE_REGEXESPOST_INCLUDE_REGEXESPOST_EXCLUDE_REGEXESPOST_INCLUDE_FILESPOST_EXCLUDE_FILES
可以在單個的install(TARGETS)命令中指定一個或多個目標(biāo)屬性。一個目標(biāo)也可能被多次安裝到不同的位置。以一個例子來說明一下:
假設(shè)需要安裝
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動態(tài)鏈接庫會被安裝到<prefix>/lib和/some/full/path,其導(dǎo)入庫會被安裝到<prefix>/lib/static和/some/full/path。
3.3版本新增:DESTINATION參數(shù)可以使用生成器表達(dá)式(用$<...>來定義)。
3.13版本新增:install(TARGETS)可以安裝在其他目錄創(chuàng)建的目標(biāo),當(dāng)使用這種交叉目錄安裝規(guī)則時,在子目錄運行cmake install命令無法保證來自其他目錄目標(biāo)是最新的??梢允褂?code>target_link_libraries()或add_dependencies()來保證這種目錄外的目標(biāo)在指定子目錄運行安裝規(guī)則前被執(zhí)行構(gòu)建。
3.2 安裝導(dǎo)入運行時的構(gòu)件
3.21版本新增,命令的格式為:
install(IMPORTED_RUNTIME_ARTIFACTS targets...
[RUNTIME_DEPENDENCY_SET <set-name>]
[[LIBRARY|RUNTIME|FRAMEWORK|BUNDLE]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
] [...]
)
IMPORTED_RUNTIME_ARTIFACTS指定導(dǎo)入目標(biāo)運行時構(gòu)件的安裝規(guī)則。當(dāng)工程需要將外部的可執(zhí)行文件或模塊綁定到內(nèi)部的安裝,就需要使用它。LIBRARY, RUNTIME, FRAMEWORK, BUNDLE這些選項與前面安裝TARGETS里面的介紹的語義相同。只有導(dǎo)入的運行是構(gòu)件會被安裝(FRAMEWORK庫、MACOSX_BUNDLE可執(zhí)行文件、BUNDLE CFBundles這三者除外)。例如:與DLL相關(guān)的導(dǎo)入庫的頭文件不會被安裝。FRAMEWORK庫、MACOSX_BUNDLE可執(zhí)行文件、BUNDLE CFBundles這三種情況,整個目錄都會被安裝。
RUNTIME_DEPENDENCY_SET選項會將導(dǎo)入的可執(zhí)行文件、共享庫、模塊庫的運行時構(gòu)件添加到<set-name>中,然后就可以使用install(RUNTIME_DEPENDENCY_SET)進(jìn)行安裝。
3.3 安裝文件
命令的格式為:
install(<FILES|PROGRAMS> files...
TYPE <type> | DESTINATION <dir>
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])
注意:如果只是安裝頭文件,可以考慮使用
target_sources(FILE_SET)中定義的文件集合命令替代。關(guān)聯(lián)目標(biāo)的頭文件集合,會作為目標(biāo)的一部分安裝。
FILES指定了一個工程安裝文件的規(guī)則。如果給定的文件是相對路徑,那么會解析成當(dāng)前源文件路徑的相對路徑。如果未指定PERMISSIONS參數(shù),被安裝的文件權(quán)限默認(rèn)為OWNER_WRITE, OWNER_READ, GROUP_READ, ORLD_READ(也就是644)。
PROGRAMS和FILES的區(qū)別只在默認(rèn)安裝文件的權(quán)限上,除了OWNER_WRITE, OWNER_READ, GROUP_READ, ORLD_READ,PROGRAMS也包含了OWNER_EXECUTE, GROUP_EXECUTE, WORLD_EXECUTE權(quán)限,(也就是PROGRAMS的默認(rèn)權(quán)限是755)。PROGRAMS安裝的對象是非目標(biāo)(target)的程序,例如shell腳本。
files...列表可以使用發(fā)生器表達(dá)式(語法為$<...>),但是必須為全路徑。
TYPE和DESTINATION必須提供一個(不需要同時提供)。TYPE參數(shù)指定待安裝文件的通用類型。根據(jù)不同的TYPE,會從對應(yīng)的GNUInstallDirs變量獲取安裝目的路徑,如果未提供GNUInstallDirs變量,會使用內(nèi)建默認(rèn)值。下表匯總了不同TYPE文件對應(yīng)的GNUInstallDirs變量值和內(nèi)建的默認(rèn)值。
| TYPE參數(shù) | GNUInstallDirs變量 | 內(nèi)置默認(rèn)值 |
|---|---|---|
| BIN | ${CMAKE_INSTALL_BINDIR} | bin |
| SBIN | ${CMAKE_INSTALL_SBINDIR} | sbin |
| LIB | ${CMAKE_INSTALL_LIBDIR} | lib |
| INCLUDE | ${CMAKE_INSTALL_INCLUDEDIR} | include |
| SYSCONF | ${CMAKE_INSTALL_SYSCONFDIR} | etc |
| SHAREDSTATE | ${CMAKE_INSTALL_SHARESTATEDIR} | com |
| LOCALSTATE | ${CMAKE_INSTALL_LOCALSTATEDIR} | var |
| RUNSTATE | ${CMAKE_INSTALL_RUNSTATEDIR} | <LOCALSTATE dir>/run |
| DATA | ${CMAKE_INSTALL_DATADIR} | <DATAROOT dir> |
| INFO | ${CMAKE_INSTALL_INFODIR} | <DATAROOT dir>/info |
| LOCALE | ${CMAKE_INSTALL_LOCALEDIR} | <DATAROOT dir>/locale |
| MAN | ${CMAKE_INSTALL_MANDIR} | <DATAROOT dir>/man |
| DOC | ${CMAKE_INSTALL_DOCDIR} | <DATAROOT dir>/doc |
如果希望安裝頭文件到工程相關(guān)的子目錄,那么需要提供一個安裝目錄而不是使用上表的目錄。因此使用文件集合替代install(FILE)是更好的選擇。
一些類型的內(nèi)建默認(rèn)值會使用DATAROOT作為前綴,DATAROOT使用CMAKE_INSTALL_DATAROOTDIR變量(其內(nèi)建默認(rèn)值是share),不能直接使用DATAROOT作為TYPE參數(shù),需要使用DATA。
為了讓包符合分布式文件系統(tǒng)布局策略,如果一個工程必須要指定DESTINATION,推薦的做法是使用合適的GNUInstallDirs變量作為前綴。這樣會允許包的維護(hù)者通過合適的緩存變量設(shè)置來控制安裝目錄。下面是一個例子,展示了按照上述意見,將鏡像安裝到指定工程的文檔子目錄下。
include(GNUInstallDirs)
install(FILES logo.png DESTINATION ${CMAKE_INSTALL_DOCDIR}/myproj)
3.4新增:DESTINATION參數(shù)可以使用生成器表達(dá)式(用$<...>來定義)。
3.20新增:通過RENAME指定安裝重命名也可以使用生成器表達(dá)式(用$<...>來定義)。
3.4 安裝目錄
命令的格式為:
install(DIRECTORY dirs...
TYPE <type> | DESTINATION <dir>
[FILE_PERMISSIONS permissions...]
[DIRECTORY_PERMISSIONS permissions...]
[USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>] [EXCLUDE_FROM_ALL]
[FILES_MATCHING]
[[PATTERN <pattern> | REGEX <regex>]
[EXCLUDE] [PERMISSIONS permissions...]] [...])
注意:如果是安裝頭文件目錄子樹,可以考慮使用
target_sources(FILE_SET)中定義的文件集合命令替代。文件集合不僅僅是保持了目錄結(jié)構(gòu),它也關(guān)聯(lián)目標(biāo)的頭文件,會作為目標(biāo)的一部分安裝。
DIRECTORY安裝一個或多個目錄的內(nèi)容到指定的目標(biāo)路徑,目錄結(jié)構(gòu)會原封不動的拷貝到目標(biāo)路徑。每個目錄名稱的最后一個組成部分會被拼接到目標(biāo)路徑,但是可以通過在末尾添加斜杠/來避免(因為尾部的/表明目錄最后的組成部分是空)。如果目錄名稱是相對路徑,那么該目錄會解析成相對于當(dāng)前源目錄的路徑。如果未給定輸入目錄名,那么目的路徑會創(chuàng)建但是不會安裝任何東西。FILE_PERMISSIONS和DIRECTORY_PERMISSIONS選項分別指定了安裝到目標(biāo)路徑的文件和目錄的權(quán)限。如果指定了USE_SOURCE_PERMISSIONS未指定FILE_PERMISSIONS選項,那么安裝的文件權(quán)限會從原目錄結(jié)果拷貝。如果未指定權(quán)限,那么文件的權(quán)限會按照FILES命令的默認(rèn)權(quán)限(也就是644),目錄的權(quán)限會安裝PROGRAMS命令的默認(rèn)權(quán)限(也就是755)。
3.1新增:當(dāng)指定MESSAGE_NEVER選項,文件安裝狀態(tài)輸出信息會被禁止。
可以通過PATTERN或REGEX選項來控制安裝目錄的顆粒度,這些匹配選項會指定通配符選項或者正則表達(dá)式來匹配輸入目錄的文件和目錄。他們可以用來將某些選項(見下文)應(yīng)用于遇到的目錄和文件子集。與表達(dá)式匹配的是每個輸入文件或目錄的全路徑。PATTERN僅僅匹配文件名,模式匹配發(fā)生在全路徑最后文件名部分(文件名前需要帶/);REGEX則會匹配全路徑的任何一個部分,但可以使用/或$來模擬REGEX的行為。
默認(rèn)情況下所有文件和目錄都會被安裝,FILES_MATCHING選項必須出現(xiàn)在第一個匹配選項之前,以禁止安裝未被任何表達(dá)式匹配的文件(不包括目錄)。例如:
install(DIRECTORY src/ DESTINATION doc/myproj FILES_MATCHING PATTERN "*.png")
會從原文件樹中提取圖像文件并安裝到目標(biāo)路徑。
跟隨PATTERN或REGEX也可以使用一些string(REGEX)中描述的選項,會用來匹配的文件或目錄。EXCLUDE選項會跳過匹配的文件或者目錄,PERMISSIONS則會重新定義匹配到的文件或目錄的權(quán)限,例如:
install(DIRECTORY icons scripts/ DESTINATION share/myproj PATTERN "CVS" EXCLUDE PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)
icons會被安裝到share/myproj/icons(目錄的末尾的組成部分icons會被拷貝到目的路徑),而scripts目錄會被安裝到share/myproj(scripts/最后的/意味著目錄的最末尾的組成部分是空)。icons目錄會按照默認(rèn)權(quán)限安裝,而scripts目錄的內(nèi)容會按照指定的權(quán)限安裝,任何包含CVS會被排除不會安裝到目第路徑。
TYPE和DESTINATION兩個選項需要提供一個(且只能提供一個),TYPE指定了將會被安裝到目標(biāo)路徑的通用文件類型,此時目的路徑會從GNUInstallDirs變量中獲取,當(dāng)該變量沒有定義則會從內(nèi)置默認(rèn)值中獲取。也可以通過DESTINATION顯示指定安裝路徑。下表顯示了不同類型對應(yīng)的GNUInstallDirs變量值和內(nèi)建默認(rèn)值:
| TYPE參數(shù) | GNUInstallDirs變量 | 內(nèi)置默認(rèn)值 |
|---|---|---|
| BIN | ${CMAKE_INSTALL_BINDIR} | bin |
| SBIN | ${CMAKE_INSTALL_SBINDIR} | sbin |
| LIB | ${CMAKE_INSTALL_LIBDIR} | lib |
| INCLUDE | ${CMAKE_INSTALL_INCLUDEDIR} | include |
| SYSCONF | ${CMAKE_INSTALL_SYSCONFDIR} | etc |
| SHAREDSTATE | ${CMAKE_INSTALL_SHARESTATEDIR} | com |
| LOCALSTATE | ${CMAKE_INSTALL_LOCALSTATEDIR} | var |
| RUNSTATE | ${CMAKE_INSTALL_RUNSTATEDIR} | <LOCALSTATE dir>/run |
| DATA | ${CMAKE_INSTALL_DATADIR} | <DATAROOT dir> |
| INFO | ${CMAKE_INSTALL_INFODIR} | <DATAROOT dir>/info |
| LOCALE | ${CMAKE_INSTALL_LOCALEDIR} | <DATAROOT dir>/locale |
| MAN | ${CMAKE_INSTALL_MANDIR} | <DATAROOT dir>/man |
| DOC | ${CMAKE_INSTALL_DOCDIR} | <DATAROOT dir>/doc |
一些類型的內(nèi)建默認(rèn)值會使用DATAROOT作為前綴,DATAROOT使用CMAKE_INSTALL_DATAROOTDIR變量(其內(nèi)建默認(rèn)值是share),不能直接使用DATAROOT作為TYPE參數(shù),需要使用DATA。
為了讓包符合分布式文件系統(tǒng)布局策略,如果一個工程必須要指定DESTINATION,推薦的做法是使用合適的GNUInstallDirs變量作為前綴。這樣會允許包的維護(hù)者通過合適的緩存變量設(shè)置來控制安裝目錄。
3.4新增:DESTINATION參數(shù)可以使用生成器表達(dá)式(用$<...>來定義)。
3.5新增:dirs...參數(shù)也可以使用生成器表達(dá)式。
3.5 定制安裝邏輯
命令的格式為:
install([[SCRIPT <file>] [CODE <code>]] [ALL_COMPONENTS | COMPONENT <component>] [EXCLUDE_FROM_ALL] [...])
SCRIPT會在安裝期間調(diào)用指定的CMake腳本,如果腳本是相對路徑,那么會解析成相對于當(dāng)前源文件目錄的相對路徑。
CODE會在安裝期間調(diào)用指定的CMake代碼,代碼是通過雙引號包含的一串字符。例如install(CODE "MESSAGE(\"Sample install message.\")"),會在安裝期間打印一跳消息。
3.21新增:當(dāng)指定ALL_COMPONENTS選項,定制的安裝腳本代碼會在每個組成部分安裝的時候執(zhí)行,該選項與COMPONENT互斥。
3.14新增:<file>和<code>可以使用生成器表達(dá)式(對于<file>,此時引用的是文件名字而不是文件內(nèi)容)。
3.6 安裝導(dǎo)出
命令的格式為:
install(EXPORT <export-name> DESTINATION <dir>
[NAMESPACE <namespace>] [[FILE <name>.cmake]|
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[EXPORT_LINK_INTERFACE_LIBRARIES]
[COMPONENT <component>]
[EXCLUDE_FROM_ALL])
install(EXPORT_ANDROID_MK <export-name> DESTINATION <dir> [...])
EXPORT將會生成并安裝一個CMake文件,該CMake文件包含將目標(biāo)從安裝樹導(dǎo)出信息到其他工程的代碼。<export-name>關(guān)聯(lián)的是使用install(TARGETS)命令中使用EXPORT選項指定的名稱。
FILE:生成的CMake文件默認(rèn)名為<export-name>.cmake,可以通過FILE指定其他名稱,但必須是以.cmake為后綴的名稱。NAMESPACE:該選項會在寫入導(dǎo)入文件中的信息前添加名稱<namespace>。CONFIGURATIONS:指定該選項,僅當(dāng)安裝了其中一個命名配置時,才會安裝導(dǎo)入文件,并且導(dǎo)入文件只會引用匹配的目標(biāo)配置。EXPORT_LINK_INTERFACE_LIBRARIES:匹配(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?屬性的內(nèi)容會被導(dǎo)出。COMPONENT:指定該選項,其后列出的<component>會隱式依賴于導(dǎo)出集合中提到的所有組件。為了依賴的工程被合適的構(gòu)建,導(dǎo)出的<name>.cmake文件要求每個導(dǎo)出的組件順序呈現(xiàn)。例如,一個工程可能定義Runtime和Development兩個組件,其中Runtime中包含動態(tài)庫文件,Development中包含靜態(tài)庫和頭文件。導(dǎo)出集合通常也是Development的一部分,但是它會從Runtime和Development兩個組件中導(dǎo)出目標(biāo)。因此Development組件安裝時,Runtime組件也需要被安裝,反過來不成立。如果安裝Development組件時未安裝Runtime,嘗試鏈接的工程會出現(xiàn)構(gòu)建錯誤。像APT、RPM等包管理器,通常會將Runtime組件作為Development的依賴,在包的元數(shù)據(jù)中列出來,確保如果頭文件和CMake導(dǎo)出文件存在時庫文件被安裝。
3.7新增:除了CMake語言文件,EXPORT_ANDROID_MK模式可以用來指定導(dǎo)出到andriod ndk構(gòu)建系統(tǒng),該模式接收的參數(shù)與普通的導(dǎo)出模式一致。Andriod NDK支持預(yù)構(gòu)建靜態(tài)或動態(tài)庫。該模式允許cmake構(gòu)建andriod ndk系統(tǒng)可用的庫,包含使用庫所需的標(biāo)記或定義。
EXPORT命令在幫助外部工程使用當(dāng)前工程構(gòu)建和安裝的目標(biāo)時非常有用,例如:
install(TARGETS myexe EXPORT myproj DESTINATION bin)
install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)
install(EXPORT_ANDROID_MK myproj DESTINATION share/ndk-modules)
可執(zhí)行文件myexe會被安裝到<prefix>/bin,并通過生成<prefix>/lib/myproj/myproj.cmake和<prefix>/share/ndk-modules/Android.mk將其導(dǎo)出。外部工程可以加載這些文件,通過使用導(dǎo)出目標(biāo)mp_myexe,可以從安裝樹中包含并引用myexe可執(zhí)行文件,就像myexe文件是外部工程構(gòu)建的一樣。
3.7 安裝運行時依賴
3.21新增,命令的格式為:
install(RUNTIME_DEPENDENCY_SET <set-name>
[[LIBRARY|RUNTIME|FRAMEWORK]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[NAMELINK_COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
] [...]
[PRE_INCLUDE_REGEXES regexes...]
[PRE_EXCLUDE_REGEXES regexes...]
[POST_INCLUDE_REGEXES regexes...]
[POST_EXCLUDE_REGEXES regexes...]
[POST_INCLUDE_FILES files...]
[POST_EXCLUDE_FILES files...]
[DIRECTORIES directories...]
)
安裝通過一個或多個
install(TARGETS)或install(IMPORTED_RUNTIME_ARTIFACTS)命令創(chuàng)建的運行時的依賴集合。屬于運行時依賴集合的目標(biāo)依賴,在DLL平臺被安裝到RUNTIME目的路徑,在非DLL平臺下被安裝到LIBRARY目的路徑。macOS下的框架被安裝到FRAMEWORK目的路徑。通過生成樹構(gòu)建的目標(biāo),除非通過install(TARGETS)命令進(jìn)行安裝,否則它或者它的依賴不會作為運行時依賴被安裝。
生成的安裝腳本通過在生成樹上調(diào)用file(GET_RUNTIME_DEPENDENCIES)來計算運行時依賴。生成樹可執(zhí)行文件通過EXECUTABLES參數(shù)傳遞,生成樹共享庫文件通過LIBRARIES參數(shù)傳遞,生成樹模塊通過MODULES參數(shù)傳遞。在macOS下,如果可執(zhí)行文件的其中之一是MACOSX_BUNDLE,那么可執(zhí)行文件通過BUNDLE_EXECUTABLE傳遞。file(GET_RUNTIME_DEPENDENCIES)僅支持在Windows、Linux和macOS系統(tǒng)下收集運行時依賴,install(RUNTIME_DEPENDENCY_SET)也有同樣的限制。
以下選項作為相關(guān)參數(shù)轉(zhuǎn)發(fā)到file(GET_RUNTIME_DEPENDENCIES)命令:
DIRECTORIES <directories>PRE_INCLUDE_REGEXES <regexes>PRE_EXCLUDE_REGEXES <regexes>POST_INCLUDE_REGEXES <regexes>POST_EXCLUDE_REGEXES <regexes>POST_INCLUDE_FILES <files>POST_EXCLUDE_FILES <files>
生成安裝腳本
注意:不推薦使用該特性,請使用
cmake的--install參數(shù)替代。
install()命令會在構(gòu)建目錄下生成cmake_install.cmake文件,內(nèi)部用于安裝目標(biāo)文件,也會被CPack使用??梢允謩油ㄟ^cmake -P命令調(diào)用該腳本文件,它可以接收幾個變量作為參數(shù):
COMPONENT:指定該變量表明只安裝單個CPack組件,而不是全部安裝。例如,如果只想安裝Development組件,那么運行cmake -DCOMPONENT=Development -P cmake_install.cmake。BUILD_TYPE:如果使用的是多配置生成器,那么指定該變量來改變構(gòu)建類型。例如,安裝Debug配置,運行命令cmake -DBUILD_TYPE=Debug -P cmake_install.cmake。DESTDIR:這是一個環(huán)境變量而不是CMake變量,可以通過該變量來改變類Unix系統(tǒng)下的安裝路徑前綴,上文有介紹該變量的用法和效果。