步骤 10:选择静态或共享库

在本节中,我们将展示如何使用变量 BUILD_SHARED_LIBS 来控制 add_library() 的默认行为,并允许控制如何构建没有显式类型的库(STATICSHAREDMODULEOBJECT)。

要完成此操作,我们需要将 BUILD_SHARED_LIBS 添加到顶级 CMakeLists.txt 中。我们使用 option() 命令,因为它使用户可以选择该值是 ON 还是 OFF

CMakeLists.txt
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

接下来,我们需要为我们的静态和共享库指定输出目录。

CMakeLists.txt
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

最后,更新 MathFunctions/MathFunctions.h 以使用 dll 导出定义

MathFunctions/MathFunctions.h
#if defined(_WIN32)
#  if defined(EXPORTING_MYMATH)
#    define DECLSPEC __declspec(dllexport)
#  else
#    define DECLSPEC __declspec(dllimport)
#  endif
#else // non windows
#  define DECLSPEC
#endif

namespace mathfunctions {
double DECLSPEC sqrt(double x);
}

在这一点上,如果您构建所有内容,您可能会注意到链接失败,原因是我们正在将没有位置无关代码的静态库与具有位置无关代码的库结合在一起。解决办法是显式设置 SqrtLibrary 的目标属性 POSITION_INDEPENDENT_CODE,以便在构建共享库时为 True

MathFunctions/CMakeLists.txt
  # state that SqrtLibrary need PIC when the default is shared libraries
  set_target_properties(SqrtLibrary PROPERTIES
                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                        )

定义 EXPORTING_MYMATH,表示我们正在 Windows 上构建时使用 declspec(dllexport)

MathFunctions/CMakeLists.txt
# define the symbol stating we are using the declspec(dllexport) when
# building on windows
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")

练习:我们修改了 MathFunctions.h 以使用 dll 导出定义。使用 CMake 文档,你能否找到一个帮助程序模块来简化此操作?