pretty code

顯示具有 cmake 標籤的文章。 顯示所有文章
顯示具有 cmake 標籤的文章。 顯示所有文章

2023年7月20日 星期四

vcpkg + cmake + x64-windows-static

vcpkg + cmake 的方式在 build VC 專案時,預設是動態連結,而 vcpkg 的機制也很貼心的會將相關 DLL 複製一份到你的輸出資料夾中。

但如果我們想要靜態編譯又該如何做呢?

以下是使用 PCL example 裡面的 qt_visualizer 為例說明:

注意:不是每個函式庫都能靜態編譯,像 qt5-webengine 就不支援

01. 先安裝 x64-windows-static 相關函式庫,C 槽至少要有 300 GB 空間比較保險。

vcpkg install pcl[core, qt, vtk]:x64-windows-static

中間有遇到某些函式庫會安裝失敗,但去 buildtrees 下的 log 又看不出所以然,我的解決方式是單獨編譯就會成功,但如果是有相關性的不能這樣單獨編譯,否則可能會失敗,但這可能又跟電腦環境有關,故只能 by case 解決。

02. 在 CMakeLists.txt 加上相關指令。

project(pcl_visualizer)
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) 

上面這個是讓 VS 專案使用靜態編譯,雖然 CMake 有另一個 MSVC_RUNTIME_LIBRARY 可以設定 property,但據我測試的結果無法成功。

add_executable(${PROJECT_NAME} ${project_SOURCES})
target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} ${QTX}::Widgets)
target_link_libraries(XYZ C:/src/vcpkg/installed/x64-windows-static/lib/pcl_io_ply.lib) 

如果有遇到 pcl visualizer parse 相關的 link 錯誤,可以加上上面指令,根據這篇文章說法,可能跟編譯 pcl 順序有關?

03. 產生 VS 專案檔。

cmake . -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/src/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static

04. 編譯程式

msbuild pcl_visualizer.sln /p:Configuration=Release

我有試過將 A 台電腦(Windows 10 Pro)編譯出來的執行檔 pcl_visualizer.exe 拿到另一台電腦執行(Windows 10 Pro),確實是靜態編譯無誤。

但如果是用 GCP 新開一台 VM(Windows Server 2022 + Desktop Experiences),則會有找不到 opengl32sw.dll 的問題,但程式是可以執行起來無誤,只是相關 UI 元件無法渲染,故只有一個灰底的執行畫面以及 CMD 畫面。

QWindowsEGLStaticContext::create: Failed to load and resolve libEGL functions
Failed to load opengl32sw.dll (The specified module could not be found.)
Failed to load and resolve WGL/OpenGL functions 

如果我將 Windows 10 的 opengl32sw.dll 複製到 VM 中,則是會產生 init GLEW 失敗的相關訊息(GLEW could not be initialized: Missing GL version),我個人猜測跟顯卡驅動程式有關?又或許是 Windows Server 無法使用之類的?

另外拿一台新電腦重灌 Windows 10 並更新顯卡驅動程式後,這次就可以順利執行成功。

以上就是相關的注意事項,如果本身就是使用 C/C++ 的開發者,我想有關編譯的問題應該也難不倒這些高手XD 

2023年7月18日 星期二

vcpkg + CMake 快速入門指南

呆過公司的開發環境一向以 Windows 居多,遇到 C/C++ 的專案確實沒有那麼方便,雖然我們可以針對相依函式庫一個一個各別編譯,但要看的文件及耗費的心力還真不少,故在 Windows 下我強烈推薦使用 vcpkg,它可以幫忙解決很多相依性問題,底下就是一些快速入門的訣竅,記錄一下,避免忘記。

建議

C 槽空間至少要有 1 TB,我之前編譯完 llvm + halide,Windows 11 的 C 槽就用了 500 多 GB。

另一個 Windows 10 系統,編譯 pcl(vcpkg install pcl[core,qt,vtk]:x64-windows-static)就花了 200 GB 並且因為 C 槽空間不足,最後還差 10 來個函式庫還未編譯完畢(已用空間包含先前編譯過的 x64-windows 版本了)。 

vcpkg 相關

安裝函式庫的指令,xxx 表示函式庫名稱,yyy、zzz 則是表示相關的函式庫,後面分別是指定編譯版本以及是否要靜態編譯。

vcpkg install xxx[yyy, zzz]:x64-windows (x64-windows-static)

vcpkg 安裝完會有提醒事項,如果是使用 CMake 來規劃專案,就需要把 find_package 相關的提示記起來,一般來說函式庫定義名稱會等於安裝時的 xxx,只是改成大寫。


vcpkg integrate install 則是讓 vcpkg 跟 Visual Studio 做連結,使用 cmake 時只要簡單指定 -DCMAKE_TOOLCHAIN_FILE=C:/src/vcpkg/scripts/buildsystems/vcpkg.cmake 就可以找到相關函式庫的路徑。

如果函式庫有相關,最好是要一起編譯,不然先後順序不對可能就要重新編譯,以我最近遇到的 hailde 及 llvm 來說,如果沒有先編譯 halide,llvm 就有可能要重新編譯,以我最新的筆電 i7-13700H 來說,光 llvm 就要編譯 13 個小時以上。

如果之前安裝完函式庫未記住 CMake targets,可以去 C:\src\vcpkg\installed\x64-windows\share\xxx 資料夾,檢查是否有相關的 .cmake 檔案可以參考,一般來說檔名可能會是這種形式 <PackageName>Config.cmake,詳情可以參考這裡

cmake 相關

cmake 是透過 CMakeLists.txt 來建構專案,如果函式庫是用 vcpkg 安裝的方式,則我們的 CMakeLists.txt 可以很簡單來寫。

以此專案為例,原本作者應該是沒有使用 vcpkg,故 CMakeListx.txt 寫的就比較囉嗦。

在有 vcpkg 下,我們應該只需要 find_package 及 include_directories 即可(碰到的專案還不夠多,待驗證?),剛好這個專案有例外,故我們需要另外指定 VTK include 路徑。

cmake_minimum_required(VERSION 3.19)

project(3DReconstruct)

find_package(OpenCV CONFIG REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(PCL CONFIG REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})

# fix pcl include <pcl/visualization/cloud_viewer.h> issue
# this error is due to the unadaptable including format between PCL and vcpkg.
# so we must use absolute path, this solution depends on your installation version of VTK.
# see https://github.com/microsoft/vcpkg/issues/24439
include_directories(C:/src/vcpkg/installed/x64-windows/include/vtk-9.0)

# build executable
add_executable(Phase_Shift main.cpp CalPhase.h CameraCalib.h)
add_library(Camera_Calib_LIB CameraCalib.cpp CameraCalib.h)
add_library(CalPhase_LIB CalPhase.cpp CalPhase.h)
add_library(ProPoint_LIB Propointcloud.cpp Propointcloud.h)

target_link_libraries(Phase_Shift ${OpenCV_LIBS} ${PCL_LIBRARIES})
target_link_libraries(Phase_Shift Camera_Calib_LIB)
target_link_libraries(Phase_Shift CalPhase_LIB)
target_link_libraries(Phase_Shift ProPoint_LIB)