cmake(V3.10.2) 從源文件生成動態庫,在Windows下,以MinGW Makefiles
(其餘未測試)爲生成類型,最終會生成libXXX.dll, libXXX.dll.a, libXXX.a
類型的庫文件。 CMakeLists中install代碼以下:html
add_library(XXX SHARED ${SRCS}) add_library(XXXS STATIC ${SRCS}) ... install(TARGETS XXX XXXS # install(TARGETS myExe XXX XXX # RUNTIME DESTINATION ${CMAKE_SOURCE_DIR}/install/bin LIBRARY DESTINATION ${InstallDir}/lib ARCHIVE DESTINATION ${InstallDir}/lib/static)
在Linux下會分別在${InstallDir}/lib
和${InstallDir}/lib/static
下生成libXXX.so,libXXXS.a
。 可是Windows下,lib目錄下無動態庫libXXX.dll
(build文件夾下存在),在lib/static
目錄下有libXXX.dll.a, libXXXS.a
,即說明動態庫安裝失敗。linux
因而修改CMakeLists.txt以下:app
if(UNIX) install(TARGETS XXX XXXS # install(TARGETS myExe XXX XXX # RUNTIME DESTINATION ${CMAKE_SOURCE_DIR}/install/bin LIBRARY DESTINATION ${InstallDir}/lib ARCHIVE DESTINATION ${InstallDir}/lib/static) else(UNIX) install(TARGETS XXX DESTINATION ${InstallDir}/lib) install(TARGETS XXXS DESTINATION ${InstallDir}/lib/static) endif(UNIX)
修改後編譯、安裝,能夠看到在Windows對應版本的${InstallDir}/lib
下出現了libXXX.dll.a, libXXX.dll
,而且在${InstallDir}/lib/static
下有libXXXS.a
。jvm
查閱cmake文檔後知道:ide
install(TARGETS targets... [EXPORT <export-name>] [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE] [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL] [NAMELINK_ONLY|NAMELINK_SKIP] ] [...] [INCLUDES DESTINATION [<dir> ...]] )
- The
TARGETS
form specifies rules for installing targets from a project. There are six kinds of target files that may be installed: ARCHIVE, LIBRARY, RUNTIME, OBJECTS, FRAMEWORK, and BUNDLE.- Executables are treated as
RUNTIME
targets, except that those marked with theMACOSX_BUNDLE
property are treated as BUNDLE targets on OS X.- Static libraries are treated as
ARCHIVE
targets, except that those marked with theFRAMEWORK
property are treated asFRAMEWORK
targets on OS X. Module libraries are always treated asLIBRARY
targets.- For non-DLL platforms shared libraries are treated as
LIBRARY
targets, except that those marked with the FRAMEWORK property are treated as FRAMEWORK targets on OS X.- For DLL platforms the DLL part of a shared library is treated as a RUNTIME target and the corresponding import library is treated as an ARCHIVE target.
- All Windows-based systems including Cygwin are DLL platforms.
- Object libraries are always treated as
OBJECTS
targets.- The
ARCHIVE, LIBRARY, RUNTIME, OBJECTS, and FRAMEWORK
arguments change the type of target to which the subsequent properties apply. If none is given the installation properties apply to all target types. If only one is given then only targets of that type will be installed (which can be used to install just a DLL or just an import library).
要點翻譯以下:測試
RUNTIME
;ARCHIVE
,模塊庫(Module libraries)當作LIBRARY
;LIBRARY
;DLL
部分被當作RUNTIME
,導入庫視爲ARCHIVE
; 索引基於Windows的系統包括(Cygwin)是DLL平臺。OBJECTS
;ARCHIVE, LIBRARY, RUNTIME, OBJECTS, and FRAMEWORK
改變後續屬性所做用的目標的類型。若是不指定,則安裝屬性適用全部目標類型。 若是僅給出一個,則將僅安裝該類型的目標(可用於僅安裝DLL或導入庫)。經過開始的CMakeLists代碼看到,因爲註釋了RUNTIME
行,故在Windows下不會安裝動態庫。(Windows下會安裝到RUNTIME
屬性對應的目錄)。ui
One or more groups of properties may be specified in a single call to the TARGETS form of this command. A target may be installed more than once to different locations. Consider hypothetical targets myExe, mySharedLib, and myStaticLib. The code:this
install(TARGETS myExe mySharedLib myStaticLib RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/static) install(TARGETS mySharedLib DESTINATION /some/full/path)
will install
myExe
to<prefix>/bin
andmyStaticLib
to<prefix>/lib/static
.
On non-DLL platformsmySharedLib
will be installed to<prefix>/lib
and/some/full/path
.
On DLL platforms themySharedLib
DLL will be installed to<prefix>/bin
and/some/full/path
and its import library will be installed to<prefix>/lib/static
and/some/full/path
.spa
安裝狀況:翻譯
myExe
--> <prefix>/bin
myStaticLib
--> <prefix>/lib/static
Non-DLL
platforms:mySharedLib
--> <prefix>/lib
和 /some/full/path
DLL
platforms:mySharedLib
--> <prefix>/bin
和 /some/full/path
mySharedLib-import-library
--> <prefix>/lib/static
和 /some/full/path
*.dll.a不是靜態庫,而是導入庫。libXXXS.a是靜態庫。
在1
中的安裝結果裏,僅ARCHIVE
屬性起做用,並同時安裝了導入庫(libXXX.dll.a)和靜態庫(libXXXS.a)。從而可知.dll.a是導入庫。
Naming the output file libjvm.dll.a will allow gcc to recognize it as a library named jvm. The .dll.a suffix indicates (by convention) that it is an import library, rather than a static library (which would simply be named libjvm.a, again by convention). https://stackoverflow.com/questions/185326/whats-a-dll-a-file
靜態庫(也稱爲歸檔)由直接編譯並連接到程序中的例程組成。編譯使用靜態庫的程序時,程序所使用的靜態庫的全部功能都將成爲可執行文件的一部分。在Windows上,靜態庫一般具備.lib擴展名,而在linux上,靜態庫一般具備.a(archive)擴展名。 靜態庫的一個優勢是,用戶只需發佈可執行文件便可。因爲庫成爲程序的一部分,這將確保程序始終使用正確版本的庫。另外,由於靜態庫成爲程序的一部分,因此能夠像爲本身的程序編寫的功能同樣使用它們。 缺點是,因爲庫的副本成爲使用它的每一個可執行文件的一部分,這可能會形成大量的空間浪費。靜態庫也不容易升級——要更新庫,須要替換整個可執行文件。
動態庫(也稱爲共享庫)由運行時加載到應用程序中的子程序組成。當編譯使用動態庫的程序時,庫不會成爲可執行文件的一部分,而是做爲單獨的單元保留。在Windows上,動態庫一般具備.dll(動態連接庫)擴展名,而在Linux上,動態庫一般具備.so(共享對象)擴展名。 動態庫的一個優勢是許多程序能夠共享一個副本,這節省了空間。 動態庫能夠升級到一個新版本,而沒必要替換使用它的全部可執行文件。
因爲動態庫未連接到程序中,所以使用動態庫的程序必須顯式加載並與動態庫交互。這種機制可能會讓人困惑,並使與動態庫的交互變得不易處理。爲了使動態庫更易於使用,可使用導入庫。
導入庫是讓加載和使用動態庫的過程變得自動化的庫。在Windows上,這一般是經過與動態庫(.dll)同名的小型靜態庫(.lib)來完成的。小型靜態庫在編譯時連接到程序中,而後動態庫的功能能夠像靜態庫同樣有效地使用。在Linux上,共享對象(.so)文件兼做動態庫和導入庫。大多數連接器能夠在建立動態庫時爲動態庫構建導入庫。
According to this bugreport, install(TARGETS) command flow accepts only targets created within the same directory.
Since CMake 3.13 install(TARGETS) can work even with targets created in other directories. install(TARGETS) can install targets that were created in other directories. When using such cross-directory install rules, running make install (or similar) from a subdirectory will not guarantee that targets from other directories are up-to-date.