代码之家  ›  专栏  ›  技术社区  ›  gct

是否可以让cmake同时构建同一个库的静态版本和共享版本?

  •  116
  • gct  · 技术社区  · 15 年前

    相同的源代码,所有这些,只需要一个静态的和共享的版本。容易做吗?

    4 回复  |  直到 6 年前
        1
  •  109
  •   Christopher Bruns    15 年前

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

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

    即使您有许多源文件,您也会将源列表放在一个cmake变量中,所以仍然很容易做到。

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

    set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
    

    但我不建议将库的静态版本和动态版本命名为相同的名称。我更喜欢使用不同的名称,因为这样可以更容易地为链接到库的工具选择编译行上的静态链接和动态链接。通常我选择libmylib.so(共享)和libmylib-static.a(静态)这样的名称。(这些是Linux上的名称。)

        2
  •  63
  •   Lekensteyn    6 年前

    由于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 docs :

    对象库编译源文件,但不存档或链接 他们的目标文件到一个库中。而其他目标则由 add_library() add_executable() 可以使用 形式的表达 $<TARGET_OBJECTS:objlib> 作为来源,在哪里 objlib是对象库名称。

    简单地说, add_library(objlib OBJECT ${libsrc}) 命令指示cmake将源文件编译为 *.o 对象文件。这一系列 * 然后文件被称为 $<TARGET_OBJECT:objlib> 在这两个 add_library(...) 调用相应库创建命令的命令,这些命令从 同一套 对象文件的。如果您有很多源文件,那么编译 * 文件可能需要相当长的时间;使用对象库,只编译一次。

    您所付出的代价是,对象文件必须作为独立于位置的代码构建,因为共享库需要这样做(静态libs不在乎)。请注意,与位置无关的代码可能效率较低,因此如果您的目标是获得最大的性能,那么您将使用静态库。此外,更容易分发静态链接的可执行文件。

        3
  •  22
  •   Yaroslav Halchenko    12 年前

    通常不需要为您的目的重复添加库调用。只是利用

    $> 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和off在另一个目录中构建第一个(在一个源目录中)时

        4
  •  -2
  •   Alexander Amelkin    8 年前

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

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

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

    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)
    

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

    推荐文章