步驟 10:選擇靜態或共享函式庫

在本節中,我們將展示如何使用 BUILD_SHARED_LIBS 變數來控制 add_library() 的預設行為,並允許控制如何建置沒有明確類型(STATICSHAREDMODULEOBJECT)的函式庫。

為了實現這一點,我們需要將 BUILD_SHARED_LIBS 添加到頂層的 CMakeLists.txt。我們使用 option() 命令,因為它允許使用者選擇該值應為 ONOFF

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 文件,您可以找到簡化此操作的輔助模組嗎?