一、創建示例項目
(一)項目結構
創建工程目錄simple,及示例代碼如下:
(二)源代碼
1. 頭文件
#include<wx/wxprec.h>
#ifndef WX_PRECOMP
#include<wx/wx.h>
#endif
class MyApp : public wxAppConsole{
public:
virtual bool OnInit();
virtual int OnRun();
};
wxDECLARE_APP(MyApp);
2. 實現文件
#include<myapp.h>
#include<iostream>
wxIMPLEMENT_APP_CONSOLE(MyApp);
bool MyApp::OnInit(){
std::cout<<"OnInit()"<<std::endl;
return true;
}
int MyApp::OnRun(){
std::cout<<"on run \n";
return 0;
}
3. CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(wxtest )
include_directories(./inc)
aux_source_directory(./src SRC)
find_package(wxWidgets REQUIRED COMPONENTS net core base)
if(wxWidgets_USE_FILE) # not defined in CONFIG mode
include(${wxWidgets_USE_FILE})
endif()
add_executable(myapp ${SRC})
target_link_libraries(myapp ${wxWidgets_LIBRARIES})
4. 編譯並運行程序
cmake -B build
cmake --build build
二、CMakeLists.txt解析
在CMakeLists.txt中,有關wxWidgets的配置為:
find_package(wxWidgets REQUIRED COMPONENTS net core base)
if(wxWidgets_USE_FILE) # not defined in CONFIG mode
include(${wxWidgets_USE_FILE})
endif()
#add_executable(myapp ...)
target_link_libraries(myapp ${wxWidgets_LIBRARIES})
(一)find_package指令
find_package用於查找是否安裝了wxWidgets並選擇默認配置使用。wxWidgets是一個CMake模塊化庫。該指令的語法格式為:
find_package(wxWidgets COMPONENTS core base ... OPTIONAL_COMPONENTS net ...)
該指令將引入以下變量:
|
wxWidgets_FOUND
|
如果找到wxWidgets,則設置為TRUE
|
|
wxWidgets_INCLUDE_DIRS
|
WIN32的包含目錄,即,查找"wx/wx.h"和
"wx/setup.h"的位置;對於Unix可能為空。
|
|
wxWidgets_LIBRARIES
|
wxWidgets庫的路徑
|
|
wxWidgets_LIBRARY_DIRS
|
編譯時鏈接目錄,對於UNIX上的
rpath很有用。通常在WIN32環境中為空字符串。
|
|
wxWidgets_DEFINITIONS
|
包含編譯/鏈接WX所需的定義,例如:WXUSINGDLL |
|
wxWidgets_DEFINITIONS_DEBUG
|
包含編譯/鏈接WX調試版本所需的定義,例如:WXDEBUG |
|
wxWidgets_CXX_FLAGS
|
Unix的包含目錄和編譯器標誌;在WIN32上為空。本質上是
" |
|
wxWidgets_USE_FILE
|
方便的包含文件
|
wxWidgets支持庫(或可選庫)包括:gl,core,base,net,webview等。
對於單體wxWidgets編譯版,庫的值只能是:mono
特別需要注意的地方是,在MinGW中,庫的順序很重要,不能更改。正確的順序如下所示:
find_package(wxWidgets REQUIRED net gl core base)
include(${wxWidgets_USE_FILE})
target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
(二)包含配置文件
if(wxWidgets_FOUND) #或 if(wxWidgets_USE_FILE)
include(${wxWidgets_USE_FILE})
endif()
${wxWidgets_USE_FILE}指UsewxWidgets.cmake文件。該文件會存在安裝wxWidgets時部署在本機上。但found_package指令會首先檢查當前目錄是否存在同名文件,如存在,則加載該文件,否則,使用wxWidgets庫中默認的同名文件。
wxWidgets中默認的UsewxWidgets.cmake文件定義如下:
if (wxWidgets_FOUND)
if (wxWidgets_INCLUDE_DIRS)
if(wxWidgets_INCLUDE_DIRS_NO_SYSTEM)
include_directories(${wxWidgets_INCLUDE_DIRS})
else()
include_directories(SYSTEM ${wxWidgets_INCLUDE_DIRS})
endif()
endif()
if (wxWidgets_LIBRARY_DIRS)
link_directories(${wxWidgets_LIBRARY_DIRS})
endif()
if (wxWidgets_DEFINITIONS)
set_property(DIRECTORY APPEND
PROPERTY COMPILE_DEFINITIONS ${wxWidgets_DEFINITIONS})
endif()
if (wxWidgets_DEFINITIONS_DEBUG)
set_property(DIRECTORY APPEND
PROPERTY COMPILE_DEFINITIONS_DEBUG ${wxWidgets_DEFINITIONS_DEBUG})
endif()
if (wxWidgets_CXX_FLAGS)
# Flags are expected to be a string here, not a list.
string(REPLACE ";" " " wxWidgets_CXX_FLAGS_str "${wxWidgets_CXX_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS " ${wxWidgets_CXX_FLAGS_str}")
unset(wxWidgets_CXX_FLAGS_str)
endif()
else ()
message("wxWidgets requested but not found.")
endif()
該文件引入了wxWidgets頭文件目錄、庫文件目錄、相關宏定義、編譯標誌等信息。這些信息將會直接影響應用程序的編譯。
(三)依賴庫設置
對於每個可執行文件/庫目標,設置wxWidgets庫依賴:
# 對於每個依賴的可執行文件/庫目標:
target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
${wxWidgets_LIBRARIES}在UsewxWidgets.cmake中定義,庫所在目錄由UsewxWidgets.cmake指定。
三、總結
CMake 是一個跨平台的自動化構建系統,主要用於管理軟件的構建過程。它不直接構建軟件,而是生成標準的構建文件(如 Makefile、Visual Studio 項目文件等),然後由相應的原生構建工具(如 make、ninja、MSBuild)來執行實際的編譯和鏈接。
然而,對外部庫在CMake中的使用,通常沒有統一的標準。本文分析了wxWidgets在CMake中的配置方法,分析的主要依據是wxWidgets安裝過程中在本機部署的FindwxWidgets.cmake和UsewxWidgets.cmake文件。
筆者更想強調的時,當需要在CMake工程中集成一個新的C++庫時,一方面可以通過官方的教程來查看集成方式,另一方面則可分析庫的FindXXX.cmake文件來獲得更確切的結論。