This guide explains how to set up a CMake project with wxWidgets on macOS to create properly bundled applications that work on both Apple Silicon and Intel Macs.
- Uninstall any existing wxWidgets installation:
brew uninstall wxwidgets
- Build wxWidgets from source as a universal binary:
# Download wxWidgets source
mkdir build-universal && cd build-universal
# Configure for universal binary
cmake -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
-DCMAKE_BUILD_TYPE=Release \
..
# Build and install
make
sudo make install
- Verify the built libraries are universal:
lipo -info /usr/local/lib/libwx_*
You should see both x86_64
and arm64
architectures listed.
Your root CMakeLists.txt should include:
# Set deployment target for all targets
if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
# Ensure all subprojects use the same deployment target
set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET})
endif()
# Find wxWidgets with required components
find_package(wxWidgets REQUIRED gl core base adv html webview net media)
include(${wxWidgets_USE_FILE})
In your app's CMakeLists.txt, add this configuration for proper library bundling:
if(APPLE)
# Set the rpath to look for libraries relative to the executable
set_target_properties(${PROJECT_NAME} PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "@executable_path/../Frameworks"
)
# Get code signing identity
execute_process(
COMMAND security find-identity -v -p codesigning
OUTPUT_VARIABLE CODESIGN_IDENTITIES
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX MATCH "([A-F0-9]+) \"Apple Development" SIGNING_IDENTITY "${CODESIGN_IDENTITIES}")
set(CODESIGN_IDENTITY "${CMAKE_MATCH_1}")
# Create script to copy and sign libraries
file(WRITE "${CMAKE_BINARY_DIR}/copy_wx_libs.sh"
"#!/bin/sh\n"
"for lib in \\\n"
" /usr/local/lib/libwx_baseu*-3.2*.dylib \\\n"
" /usr/local/lib/libwx_osx_cocoau_gl*-3.2*.dylib \\\n"
" /usr/local/lib/libwx_osx_cocoau_core*-3.2*.dylib \\\n"
" /usr/local/lib/libwx_osx_cocoau_adv*-3.2*.dylib \\\n"
" /usr/local/lib/libwx_osx_cocoau_html*-3.2*.dylib \\\n"
" /usr/local/lib/libwx_osx_cocoau_webview*-3.2*.dylib \\\n"
" /usr/local/lib/libwx_osx_cocoau_media*-3.2*.dylib; do\n"
" cp -P \"$lib\" \"$1\" \n"
" codesign --force --sign \"$2\" \"$1/$(basename $lib)\" \n"
"done\n"
)
# Make the script executable
execute_process(COMMAND chmod +x "${CMAKE_BINARY_DIR}/copy_wx_libs.sh")
# Add post-build commands
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:${PROJECT_NAME}>/../Frameworks"
COMMAND "${CMAKE_BINARY_DIR}/copy_wx_libs.sh"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/../Frameworks"
"${CODESIGN_IDENTITY}"
)
endif()
-
Universal Binary Support: The application and all wxWidgets libraries will support both Apple Silicon and Intel Macs.
-
Library Bundling: Required wxWidgets libraries are copied into your app bundle's Frameworks directory, making the app self-contained.
-
Code Signing: All bundled libraries are properly signed with your development certificate.
-
RPATH Configuration: The app is configured to look for libraries in its own bundle first.
The script copies these wxWidgets components by default:
- Base libraries (libwx_baseu*)
- GL libraries
- Core libraries
- Advanced libraries
- HTML libraries
- WebView libraries
- Media libraries
To modify which libraries are bundled, edit the list in the shell script section of the CMake configuration.
- Check that your app bundle contains the required libraries:
ls YourApp.app/Contents/Frameworks/libwx_*
- Verify the architectures of your app and bundled libraries:
lipo -info YourApp.app/Contents/MacOS/YourApp
lipo -info YourApp.app/Contents/Frameworks/libwx_*
- Test the app on both Apple Silicon and Intel Macs.
- If the app crashes with "Library not loaded" errors, check that all required libraries are in the Frameworks directory.
- If you get code signing errors, verify your signing identity is correct.
- Use
otool -L YourApp.app/Contents/MacOS/YourApp
to verify library paths are correct.