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.