是否有可能让CMakebuild立同一个库的静态和共享版本?

同样的来源,所有这一切,只是想要一个静态和共享的版本。 容易做到?

是的,这是相当容易的。 只需使用两个“add_library”命令:

add_library(MyLib SHARED source1.c source2.c) add_library(MyLibStatic STATIC source1.c source2.c) 

即使你有很多的源文件,你也可以把源码列表放在一个cmakevariables中,这样做还是很容易的。

在Windows上,您应该为每个库指定一个不同的名称,因为共享和静态都有一个“.lib”文件。 但是在Linux和Mac上,你甚至可以给两个库命名(例如libMyLib.a和libMyLib.so):

 set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib) 

但是我不build议同时给库的静态和dynamic两个版本。 我更喜欢使用不同的名称,因为这样可以更容易地在链接到库的工具的编译行中select静态链接和dynamic链接。 通常我select像libMyLib.so(共享)和libMyLib_static.a(静态)的名称。 (这些将是在Linux上的名称。)

从CMake版本2.8.8开始,您可以使用“对象库” 来避免重复编译目标文件 。 使用克里斯托弗·布伦斯(Christopher Bruns)的一个带有两个源文件的库

 # list of source files set(libsrc source1.c source2.c) # this is the "object library" target: compiles the sources only once add_library(objlib OBJECT ${libsrc}) # shared libraries need PIC set_property(TARGET ${objlib} PROPERTY POSITION_INDEPENDENT_CODE 1) # shared and static libraries built from the same object files add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>) add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>) 

从CMake文档 :

对象库编译源文件,但不会将其对象文件存档或链接到库中。 相反,由add_library()或add_executable()创build的其他目标可以使用$forms的expression式作为源来引用对象,其中objlib是对象库名称。

简单地说, add_library(objlib OBJECT ${libsrc})命令指示CMake将源文件编译为*.o目标文件。 这两个*.o文件的集合在两个add_library(...)命令中被称为$<TARGET_OBJECT:objlib> ,它们调用适当的库创build命令,从相同的一组目标文件构build共享库和静态库。 如果你有很多源文件,那么编译*.o文件可能会花费很长时间; 用对象库只编译一次。

你付出的代价是目标文件必须被构build为位置无关的代码,因为共享库需要这个(静态库不关心)。 请注意,与位置无关的代码可能效率较低,所以如果您的目标是获得最佳性能,那么您应该使用静态库。 此外,分发静态链接的可执行文件更容易。

通常不需要为您的目的复制ADD_LIBRARY调用。 只要利用

 $> man cmake | grep -A6 '^ *BUILD_SHARED_LIBS$' BUILD_SHARED_LIBS Global flag to cause add_library to create shared libraries if on. If present and true, this will cause all libraries to be built shared unless the library was explicitly added as a static library. This variable is often added to projects as an OPTION so that each user of a project can decide if they want to build the project using shared or static libraries. 

同时在-DBUILD_SHARED_LIBS:BOOL = ON中build立第一个(在一个源代码外的目录中),而在另一个

这确实是可能的。 正如@Christopher Bruns在他的回答中所说,你需要添加两个版本的库:

 set(libsrc source1.c source2.c source3.c) add_library(mylib-static STATIC ${libsrc}) add_library(mylib-shared SHARED ${libsrc}) 

然后,如此处所述,您需要指定两个目标应使用相同的输出名称,而不是覆盖彼此的文件:

 SET_TARGET_PROPERTIES(mylib-static PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(mylib-shared PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1) 

这样,您将同时获得libmylib.a和libmylib.so(在Linux上)或mylib.lib和mylib.dll(在Windows上)。