交叉编译wxWidgets程序在Win10运行时无标准输出及GUI异常
问题描述
环境与wxWidgets编译步骤
在Ubuntu 18.04环境下使用mingw-w64编译wxWidgets-3.1.3源码,编译命令如下:
./configure --prefix=build/win64 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-cxx=11 --with-msw --enable-stl --enable-debug make -j4 make install
测试程序配置
测试C++代码
#include <unistd.h> #include <iostream> int main() { std::cout<<"Debug start main()"<<std::endl; fprintf(stderr,"..."); sleep(3); }
CMake配置
find_package(wxWidgets REQUIRED COMPONENTS gl core base aui) add_executable(myapp main.cpp) target_link_libraries(myapp ${wxWidgets_LIBRARIES})
构建命令
cd build cmake -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/../cmake/mingw-w64.toolchain \ -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/bin \ -DCMAKE_BUILD_TYPE=Debug \ ..
CMake工具链文件内容
set(CMAKE_SYSTEM_NAME WindowsStore) set(CMAKE_SYSTEM_VERSION 10.0) set(CMAKE_SYSTEM_PROCESSOR x86_64) set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc-posix) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++-posix) set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong") set(CMAKE_C_FLAGS_INIT "") set(CMAKE_C_FLAGS_DEBUG "-O0 -g -pg -Wextra") set(CMAKE_C_FLAGS_RELEASE "-O2 -Wall -Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong -std=c++11") set(CMAKE_CXX_FLAGS_INIT "") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -pg") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -Wall") # where is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX} # mingw folder ${CMAKE_PREFIX_PATH} ) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
遇到的问题
- 控制台输出消失:将生成的exe复制到Windows 10运行后,无法看到控制台输出,但程序会执行sleep操作;即使使用Windows版MinGW的gdb调试也无printf输出。若移除wxWidgets库链接,则能正常显示控制台输出。
- 手动main启动GUI失败:使用
wxIMPLEMENT_APP(MyApp);且不定义int main()时,GUI能正常启动;但使用以下代码启动GUI则失败:
#include <wx/wx.h> int main(int argc, char *argv[]){ wxEntryStart(wxArgc, argv); if (!wxTheApp || !wxTheApp->CallOnInit()){ std::cout << "Failed!\n" << std::flush; return false; } }
问题分析与解决
1. 控制台输出消失的原因及解决
Windows系统中,PE程序分为GUI子系统和控制台子系统:GUI程序默认不会创建控制台窗口,stdout/stderr输出会被静默丢弃;控制台程序则会自动分配控制台窗口。
wxWidgets默认编译为GUI程序,链接其库时,链接器会自动将程序标记为GUI子系统,导致你看不到控制台输出。
解决方法(二选一):
- 编译wxWidgets时启用控制台支持:在
configure命令中添加--enable-console参数,重新编译安装wxWidgets。 - CMake中强制指定控制台子系统:在CMakeLists.txt中添加链接选项,强制程序使用控制台子系统:
target_link_options(myapp PRIVATE -mconsole)
2. 手动main启动GUI失败的原因及修正
你的手动main函数存在两个关键问题:
- 缺少事件循环与清理步骤:
wxEntryStart仅完成wxWidgets的初始化,还需要调用wxTheApp->OnRun()进入GUI事件循环,结束后要调用wxEntryCleanup()完成资源清理。 - 参数错误:代码中误用了
wxArgc,应该直接传入main函数的argc和argv。
修正后的代码:
#include <wx/wx.h> int main(int argc, char *argv[]) { // 初始化wxWidgets if (!wxEntryStart(argc, argv)) { std::cout << "Failed to initialize wxWidgets!\n" << std::flush; return 1; } // 启动应用初始化并进入事件循环 if (wxTheApp && wxTheApp->CallOnInit()) { wxTheApp->OnRun(); } // 清理wxWidgets资源 wxEntryCleanup(); return 0; }
额外注意:工具链文件的潜在问题
你的CMake工具链中设置了CMAKE_SYSTEM_NAME WindowsStore,这是针对UWP应用的配置,但wxWidgets主要针对传统桌面Windows程序,UWP环境可能存在兼容性问题,建议改为:
set(CMAKE_SYSTEM_NAME Windows)
内容的提问来源于stack exchange,提问作者ywiyogo
相关产品推荐
相关产品推荐

