Windows下Cmake生成動態庫install命令失敗、導入庫概念

Windows下Cmake生成動態庫install失敗、導入庫概念

摘要:

  • Windows下cmake install命令安裝動態庫文件失敗
  • .dll.a和.dll文件的區別
  • 動態庫、靜態庫和導入庫

一、Windows下cmake install命令安裝動態庫文件失敗

1.1 問題

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.ajvm

1.2 深刻分析

查閱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 the MACOSX_BUNDLE property are treated as BUNDLE targets on OS X.
  • Static libraries are treated as ARCHIVE targets, except that those marked with the FRAMEWORK property are treated as FRAMEWORK targets on OS X. Module libraries are always treated as LIBRARY 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;
  • 非DLL平臺,共享庫被當作LIBRARY;
  • DLL平臺,共享庫的DLL部分被當作RUNTIME,導入庫視爲ARCHIVE; 索引基於Windows的系統包括(Cygwin)是DLL平臺。
  • 目標庫視爲OBJECTS
  • ARCHIVE, LIBRARY, RUNTIME, OBJECTS, and FRAMEWORK改變後續屬性所做用的目標的類型。若是不指定,則安裝屬性適用全部目標類型。 若是僅給出一個,則將僅安裝該類型的目標(可用於僅安裝DLL或導入庫)。

經過開始的CMakeLists代碼看到,因爲註釋了RUNTIME行,故在Windows下不會安裝動態庫。(Windows下會安裝到RUNTIME屬性對應的目錄)。ui

1.3 官方解釋

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 and myStaticLib to <prefix>/lib/static.
On non-DLL platforms mySharedLib will be installed to <prefix>/lib and /some/full/path.
On DLL platforms the mySharedLib 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和.dll的區別

*.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)文件兼做動態庫和導入庫。大多數連接器能夠在建立動態庫時爲動態庫構建導入庫。

四、cmake 3.13開始支持安裝其餘目錄所建立的目標

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.

相關文章
相關標籤/搜索