Project-level namespaces
使用第三方庫時,與程式鍊結的庫目標名稱必須是唯一的,但不同的第三方庫可能會使用相同的庫目標名稱,這有可能會導致衝突,因此引入命名空間可以解決這個目標名稱唯一性問題。
所以今天會用一個常見的日誌庫 Google Logging Library 為範例。
有些專案會要求使用者在鍊結他們提供的庫時,要加上命名空間,防止鍊結到錯誤的庫。
target_link_libraries(target_name PUBLIC project_name::library_name)
$ git clone https://github.com/google/glog.git
$ cd glog
$ mkdir build
$ cd build
$ cmake -S .. -B build -G "Unix Makefiles"
$ make
$ sudo make install
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/libglog.so.0.7.0
-- Installing: /usr/local/lib/libglog.so.1
-- Installing: /usr/local/lib/libglog.so
-- Installing: /usr/local/include/glog/export.h
-- Installing: /usr/local/include/glog/logging.h
-- Installing: /usr/local/include/glog/raw_logging.h
-- Installing: /usr/local/include/glog/stl_logging.h
-- Installing: /usr/local/include/glog/vlog_is_on.h
-- Installing: /usr/local/include/glog/log_severity.h
-- Installing: /usr/local/include/glog/platform.h
-- Installing: /usr/local/lib/pkgconfig/libglog.pc
-- Installing: /usr/local/lib/cmake/glog/glog-modules.cmake <----⭐ 第一個
-- Installing: /usr/local/lib/cmake/glog/glog-config.cmake<----⭐ 第二個
-- Installing: /usr/local/lib/cmake/glog/glog-config-version.cmake<----⭐ 第三個
-- Installing: /usr/local/lib/cmake/glog/glog-targets.cmake<----⭐ 第四個
-- Installing: /usr/local/lib/cmake/glog/glog-targets-noconfig.cmake<----⭐ 第五個
安裝完後,會發現在 glog 安裝了五個 .cmake 檔案。
其中有兩個是我們之前使用過的
通常,讓專案的函式庫擁有命名空間的通常就是以下這兩個.cmake檔了,內容是設定目標的屬性。
P.S. 如果使用以下的命令讓此專案用Debug模式編譯,targets-xxx.cmake 會變成 targets-release.cmake,因為今天沒有指定編譯模式,因此產生的檔案會是 targets-noconfig.cmake
$ cmake -DCMAKE_BUILD_TYPE=Release ..
在使用 target_link_libraries 鍊結 glog 的時候,會發現使用到了命名空間。
cmake_minimum_required(VERSION 3.22)
# 根據自己的cmake版本來設定最小版本,要小於當前版本
project(cmake_totorial VERSION 1.0.0 LANGUAGES CXX)
# 設定專案名稱為cmake_totorial,版本為1.0.0,且此項目使用C++
find_package(glog REQUIRED)
# 尋找 glogConfig.cmake,REQUIRED 將其設定為必要項目,若找不到則會報錯
message(STATUS "glog_FOUND: ${glog_FOUND}")
message(STATUS "glog_INCLUDE_DIRS: ${glog_INCLUDE_DIRS}")
message(STATUS "glog_LIBRARY_DIRS: ${glog_LIBRARY_DIRS}")
message(STATUS "glog_LIBRARIES: ${glog_LIBRARIES}")
message(STATUS "glog_VERSION: ${glog_VERSION}")
# 顯示glog提供的資訊
add_executable(main src/main.cpp)
# 將main.cpp編譯成可執行文件main
target_link_libraries(main PUBLIC glog::glog)
# 將在glog這個命名空間中的庫鍊結到執行檔main
#include <iostream>
#include <glog/logging.h>
int main(int argc, char* argv[])
{
google::InitGoogleLogging(argv[0]);
// 初始化glog库
FLAGS_logtostderr = 1;
// 設定日誌輸出到終端上
LOG(INFO) << "Hello, World!";
// 輸出日誌
return 0;
}
$ cd Main/build
$ cmake ..
查看輸出訊息可以發現,glog只有提供版本資訊,鍊結方式也不是像OpenCV那樣讓使用者將${OpenCV_LIBS}變數拿去鍊結可執行檔,而是使用命名空間內的glog::glog庫,所以每一個專案的使用方式都不盡相同,在使用第三方庫前都要小心地閱讀手冊。
kai@esoc:~/2023_iT_CMake/Day25/Main/build$ cmake ..
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- glog_FOUND: 1
-- glog_INCLUDE_DIRS:
-- glog_LIBRARY_DIRS:
-- glog_LIBRARIES:
-- glog_VERSION: 0.7.0
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kai/2023_iT_CMake/Day25/Main/build
$ make
$ ./main
在終端上會輸出執行時間與所在行數,是一個方便 Debug 專案的日誌庫。
kai@esoc:~/2023_iT_CMake/Day25/Main/build$ ./main
I20231015 18:02:44.320850 92741 main.cpp:8] Hello, World!