一、創建示例項目

(一)項目結構

創建工程目錄simple,及示例代碼如下:

【wxWidgets 教程】安裝、配置、HelloWorld篇(一)_Xiao_#wxWidgets

(二)源代碼

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上為空。本質上是

"wx-config --cxxflags"

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文件來獲得更確切的結論。