Windows下Cmake生成库install命令失败、导入库
摘要:
- Windows下cmake install命令对动态库文件失败
- .dll.a和.dll文件的区别
- 动态库、静态库和导入库
1、Windows下cmake install命令安装动态库文件失败
cmake(V3.10.2) 从源文件生成库,在Windows下,以MinGW Makefiles
(其他未测试)为生成类型,最终会生成libXXX.dll, libXXX.dll.a, libXXX.a
类型的库文件。
CMakeLists中install代码如下:
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
,即说明动态库安装失败。
于是修改CMakeLists.txt如下:
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
。
2、关于.dll.a和.dll的区别
*.dll.a不是静态库,而是导入库。libXXXS.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://*.com/questions/185326/whats-a-dll-a-file
3、动态库、静态库、导入库
静态库(也称为归档)由直接编译并链接到程序中的例程组成。编译使用静态库的程序时,程序所使用的静态库的所有功能都将成为可执行文件的一部分。在Windows上,静态库通常具有.lib扩展名,而在linux上,静态库通常具有.a(archive)扩展名。
静态库的一个优点是,用户只需发布可执行文件即可。由于库成为程序的一部分,这将确保程序始终使用正确版本的库。另外,因为静态库成为程序的一部分,所以可以像为自己的程序编写的功能一样使用它们。
缺点是,由于库的副本成为使用它的每个可执行文件的一部分,这可能会造成大量的空间浪费。静态库也不容易升级——要更新库,需要替换整个可执行文件。
动态库(也称为共享库)由运行时加载到应用程序中的子程序组成。当编译使用动态库的程序时,库不会成为可执行文件的一部分,而是作为单独的单元保留。在Windows上,动态库通常具有.dll(动态链接库)扩展名,而在Linux上,动态库通常具有.so(共享对象)扩展名。
动态库的一个优点是许多程序可以共享一个副本,这节省了空间。
动态库可以升级到一个新版本,而不必替换使用它的所有可执行文件。
由于动态库未链接到程序中,因此使用动态库的程序必须显式加载并与动态库交互。这种机制可能会让人困惑,并使与动态库的交互变得不易处理。为了使动态库更易于使用,可以使用导入库。
导入库是让加载和使用动态库的过程变得自动化的库。在Windows上,这通常是通过与动态库(.dll)同名的小型静态库(.lib)来完成的。小型静态库在编译时链接到程序中,然后动态库的功能可以像静态库一样有效地使用。在Linux上,共享对象(.so)文件兼作动态库和导入库。大多数链接器可以在创建动态库时为动态库构建导入库。
4、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.