本文在《C++跨平台GUI框架wxWidgets:CMake源码编译与构建》在基础上,进一步拓展在CMake中使用wxWidgets的细节问题。wxWidgets教程完整目录
一、创建示例项目
本文使用的示例项目来自《C++跨平台GUI框架wxWidgets:CMake源码编译与构建》3.1节“find_package方式“。
(一)项目结构
创建工程目录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上为空。本质上是 " 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文件来获得更确切的结论。

1万+

被折叠的 条评论
为什么被折叠?



