Merge pull request #469 from dpaulat/feature/macos

Add macOS support
This commit is contained in:
Dan Paulat 2025-06-19 00:51:07 -05:00 committed by GitHub
commit a81d6f340d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 535 additions and 81 deletions

1
.clang-format-ignore Normal file
View file

@ -0,0 +1 @@
CMakePresets.json

View file

@ -26,6 +26,8 @@ jobs:
env_cc: ''
env_cxx: ''
compiler: msvc
cppflags: ''
ldflags: ''
msvc_arch: x64
msvc_version: 2022
qt_version: 6.8.3
@ -43,6 +45,8 @@ jobs:
env_cc: gcc-11
env_cxx: g++-11
compiler: gcc
cppflags: ''
ldflags: ''
qt_version: 6.8.3
qt_arch_aqt: linux_gcc_64
qt_arch_dir: gcc_64
@ -59,6 +63,8 @@ jobs:
env_cc: clang-17
env_cxx: clang++-17
compiler: clang
cppflags: ''
ldflags: ''
qt_version: 6.8.3
qt_arch_aqt: linux_gcc_64
qt_arch_dir: gcc_64
@ -75,6 +81,8 @@ jobs:
env_cc: gcc-11
env_cxx: g++-11
compiler: gcc
cppflags: ''
ldflags: ''
qt_version: 6.8.3
qt_arch_aqt: linux_gcc_arm64
qt_arch_dir: gcc_arm64
@ -85,6 +93,36 @@ jobs:
appimage_arch: aarch64
artifact_suffix: linux-arm64
compiler_packages: g++-11
- name: macos_clang18_x64
os: macos-13
build_type: Release
env_cc: clang
env_cxx: clang++
compiler: clang
qt_version: 6.8.3
qt_arch_aqt: clang_64
qt_arch_dir: macos
qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport
qt_tools: ''
conan_package_manager: ''
conan_profile: scwx-macos_clang-18
appimage_arch: ''
artifact_suffix: macos-x64
- name: macos_clang18_arm64
os: macos-15
build_type: Release
env_cc: clang
env_cxx: clang++
compiler: clang
qt_version: 6.8.3
qt_arch_aqt: clang_64
qt_arch_dir: macos
qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport
qt_tools: ''
conan_package_manager: ''
conan_profile: scwx-macos_clang-18_armv8
appimage_arch: ''
artifact_suffix: macos-arm64
name: ${{ matrix.name }}
env:
CC: ${{ matrix.env_cc }}
@ -133,6 +171,17 @@ jobs:
flatpak-builder \
${{ matrix.compiler_packages }}
- name: Setup macOS Environment
if: ${{ startsWith(matrix.os, 'macos') }}
shell: bash
run: |
brew install llvm@18
LLVM_PATH=$(brew --prefix llvm@18)
echo "CC=${LLVM_PATH}/bin/clang" >> $GITHUB_ENV
echo "CXX=${LLVM_PATH}/bin/clang++" >> $GITHUB_ENV
echo "CPPFLAGS=-I${LLVM_PATH}/include" >> $GITHUB_ENV
echo "LDFLAGS=-L${LLVM_PATH}/lib -L${LLVM_PATH}/lib/c++" >> $GITHUB_ENV
- name: Setup Python Environment
shell: pwsh
run: |
@ -325,12 +374,26 @@ jobs:
name: supercell-wx-flatpak-${{ matrix.artifact_suffix }}
path: ${{ github.workspace }}/supercell-wx.flatpak
- name: Build Disk Image (macOS)
if: ${{ startsWith(matrix.os, 'macos') }}
shell: pwsh
run: |
cd build
cpack
- name: Upload Disk Image (macOS)
if: ${{ startsWith(matrix.os, 'macos') }}
uses: actions/upload-artifact@v4
with:
name: supercell-wx-${{ matrix.artifact_suffix }}
path: ${{ github.workspace }}/build/supercell-wx-*.dmg*
- name: Test Supercell Wx
working-directory: ${{ github.workspace }}/build
env:
MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }}
MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }}
run: ctest -C ${{ matrix.build_type }} --exclude-regex test_mln.*
run: ctest -C ${{ matrix.build_type }} --exclude-regex "test_mln.*|UpdateManager.*"
- name: Upload Test Logs
if: ${{ !cancelled() }}

View file

@ -3,6 +3,8 @@ set(PROJECT_NAME supercell-wx)
include(tools/scwx_config.cmake)
set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0)
scwx_python_setup()
project(${PROJECT_NAME}

View file

@ -210,6 +210,88 @@
"CC": "gcc-11",
"CXX": "g++-11"
}
},
{
"name": "macos-base",
"inherits": "base",
"hidden": true,
"cacheVariables": {
"CMAKE_PREFIX_PATH": "$env{HOME}/Qt/6.8.3/macos"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
},
{
"name": "macos-clang18-base",
"inherits": "macos-base",
"hidden": true
},
{
"name": "macos-clang18-x64-base",
"inherits": "macos-clang18-base",
"hidden": true,
"cacheVariables": {
"CONAN_HOST_PROFILE": "scwx-macos_clang-18",
"CONAN_BUILD_PROFILE": "scwx-macos_clang-18"
},
"environment": {
"CC": "/usr/local/opt/llvm@18/bin/clang",
"CXX": "/usr/local/opt/llvm@18/bin/clang++",
"PATH": "/usr/local/opt/llvm@18/bin:$penv{PATH}",
"CPPFLAGS": "-I/usr/local/opt/llvm@18/include",
"LDFLAGS": "-L/usr/local/opt/llvm@18/lib -L/usr/local/opt/llvm@18/lib/c++"
}
},
{
"name": "macos-clang18-arm64-base",
"inherits": "macos-clang18-base",
"hidden": true,
"cacheVariables": {
"CONAN_HOST_PROFILE": "scwx-macos_clang-18_armv8",
"CONAN_BUILD_PROFILE": "scwx-macos_clang-18_armv8"
},
"environment": {
"CC": "/opt/homebrew/opt/llvm@18/bin/clang",
"CXX": "/opt/homebrew/opt/llvm@18/bin/clang++",
"PATH": "/opt/homebrew/opt/llvm@18/bin:$penv{PATH}",
"CPPFLAGS": "-I/opt/homebrew/opt/llvm@18/include",
"LDFLAGS": "-L/opt/homebrew/opt/llvm@18/lib -L/opt/homebrew/opt/llvm@18/lib/c++"
}
},
{
"name": "macos-clang18-x64-debug",
"inherits": "macos-clang18-x64-base",
"displayName": "macOS Clang 18 x64 Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "macos-clang18-x64-release",
"inherits": "macos-clang18-x64-base",
"displayName": "macOS Clang 18 x64 Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "macos-clang18-arm64-debug",
"inherits": "macos-clang18-arm64-base",
"displayName": "macOS Clang 18 Arm64 Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "macos-clang18-arm64-release",
"inherits": "macos-clang18-arm64-base",
"displayName": "macOS Clang 18 Arm64 Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
@ -236,6 +318,30 @@
"configurePreset": "linux-gcc-release",
"displayName": "Linux GCC Release",
"configuration": "Release"
},
{
"name": "macos-clang18-x64-debug",
"configurePreset": "macos-clang18-x64-debug",
"displayName": "macOS Clang 18 x64 Debug",
"configuration": "Debug"
},
{
"name": "macos-clang18-x64-release",
"configurePreset": "macos-clang18-x64-release",
"displayName": "macOS Clang 18 x64 Release",
"configuration": "Release"
},
{
"name": "macos-clang18-arm64-debug",
"configurePreset": "macos-clang18-arm64-debug",
"displayName": "macOS Clang 18 Arm64 Debug",
"configuration": "Debug"
},
{
"name": "macos-clang18-arm64-release",
"configurePreset": "macos-clang18-arm64-release",
"displayName": "macOS Clang 18 Arm64 Release",
"configuration": "Release"
}
],
"testPresets": [

View file

@ -28,12 +28,13 @@ Supercell Wx supports the following 64-bit operating systems:
- Ubuntu 22.04+
- NixOS 25.05+
- Most distributions supporting the GCC Standard C++ Library 11+
- macOS 12 (Monterey) or later
## Linux Dependencies
Supercell Wx requires the following Linux dependencies:
- Linux/X11 (Wayland works too) with support for GCC 11 and OpenGL 3.3
- Linux/X11 (Wayland works too) with support for GCC 11, OpenGL 3.3 and OpenGL ES 3.0
- X11/XCB libraries including xcb-cursor
## FAQ

View file

@ -35,10 +35,16 @@ class SupercellWxConan(ConanFile):
self.options["openssl"].shared = True
self.options["libcurl"].ca_bundle = "none"
self.options["libcurl"].ca_path = "none"
elif self.settings.os == "Macos":
self.options["openssl"].shared = True
self.options["libcurl"].ca_bundle = "none"
self.options["libcurl"].ca_path = "none"
def requirements(self):
if self.settings.os == "Linux":
self.requires("onetbb/2022.0.0")
elif self.settings.os == "Macos":
self.requires("onetbb/2022.0.0")
def generate(self):
build_folder = os.path.join(self.build_folder,

@ -1 +1 @@
Subproject commit 554e6e9ac46b6eaf5970a219c88e3df11f1cee30
Subproject commit 3654f5fa9f06534d7fd2d95b810049a82e5953ef

View file

@ -35,6 +35,12 @@ else()
target_compile_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:-g>")
endif()
if (APPLE)
# Enable GL check error debug
target_compile_definitions(mbgl-core PRIVATE MLN_GL_CHECK_ERRORS=1)
target_compile_definitions(MLNQtCore PRIVATE MLN_GL_CHECK_ERRORS=1)
endif()
set(MLN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native/include
${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native-qt/src/core/include
${CMAKE_CURRENT_BINARY_DIR}/maplibre-native-qt/src/core/include PARENT_SCOPE)

BIN
scwx-qt/res/icons/scwx.icns Normal file

Binary file not shown.

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>LSMinimumSystemVersion</key>
<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
</dict>
</plist>

View file

@ -626,6 +626,26 @@ if (WIN32)
if (SCWX_DISABLE_CONSOLE)
set_target_properties(supercell-wx PROPERTIES WIN32_EXECUTABLE $<IF:$<CONFIG:Release>,TRUE,FALSE>)
endif()
elseif (APPLE)
set(SCWX_ICON "${scwx-qt_SOURCE_DIR}/res/icons/scwx.icns")
set_source_files_properties(${SCWX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES} ${SCWX_ICON})
string(TIMESTAMP CURRENT_YEAR "%Y")
set_target_properties(supercell-wx PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST "${scwx-qt_SOURCE_DIR}/res/scwx-qt.plist.in"
MACOSX_BUNDLE_GUI_IDENTIFIER "net.supercellwx.app"
MACOSX_BUNDLE_BUNDLE_NAME "Supercell Wx"
MACOSX_BUNDLE_BUNDLE_VERSION "${SCWX_VERSION}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${SCWX_VERSION}"
MACOSX_BUNDLE_COPYRIGHT "Copyright ${CURRENT_YEAR} Dan Paulat"
MACOSX_BUNDLE_ICON_FILE "scwx.icns"
MACOSX_BUNDLE_INFO_STRING "Free and open source advanced weather radar"
RESOURCE ${SCWX_ICON})
else()
qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES})
endif()
@ -635,7 +655,7 @@ if (WIN32)
target_compile_definitions(supercell-wx PUBLIC WIN32_LEAN_AND_MEAN)
endif()
if (NOT MSVC)
if (LINUX)
# Qt emit keyword is incompatible with TBB
target_compile_definitions(scwx-qt PRIVATE QT_NO_EMIT)
target_compile_definitions(supercell-wx PRIVATE QT_NO_EMIT)
@ -694,7 +714,9 @@ if (MSVC)
else()
target_compile_options(scwx-qt PRIVATE "$<$<CONFIG:Release>:-g>")
target_compile_options(supercell-wx PRIVATE "$<$<CONFIG:Release>:-g>")
endif()
if (LINUX)
# Add wayland client packages
find_package(QT NAMES Qt6
COMPONENTS WaylandClient
@ -733,9 +755,11 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
target_link_libraries(supercell-wx PRIVATE scwx-qt
wxdata)
# Set DT_RUNPATH for Linux targets
set_target_properties(MLNQtCore PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core
set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib")
if (LINUX)
# Set DT_RUNPATH for Linux targets
set_target_properties(MLNQtCore PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core
set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib")
endif()
install(TARGETS supercell-wx
MLNQtCore # QMapLibre::Core
@ -745,7 +769,15 @@ install(TARGETS supercell-wx
"^(/usr)?/lib/.*\\.so(\\..*)?"
RUNTIME
COMPONENT supercell-wx
BUNDLE
DESTINATION .
COMPONENT supercell-wx
OPTIONAL
LIBRARY
COMPONENT supercell-wx
OPTIONAL
FRAMEWORK
DESTINATION Frameworks
COMPONENT supercell-wx
OPTIONAL)
@ -767,14 +799,64 @@ install(SCRIPT ${deploy_script_qmaplibre_core}
install(SCRIPT ${deploy_script_scwx}
COMPONENT supercell-wx)
if (APPLE)
# Install additional script to fix up the bundle
install(CODE [[
include (BundleUtilities)
# Define the bundle path
set(BUNDLE_PATH "${CMAKE_INSTALL_PREFIX}/supercell-wx.app")
file(GLOB_RECURSE PLUGIN_DYLIBS "${BUNDLE_PATH}/Contents/PlugIns/**/*.dylib")
# Add the correct rpath for plugins to find bundled frameworks
foreach(PLUGIN_DYLIB ${PLUGIN_DYLIBS})
execute_process(
COMMAND install_name_tool -add_rpath "@loader_path/../../Frameworks"
${PLUGIN_DYLIB}
)
endforeach()
# Fix up the bundle with all dependencies
fixup_bundle(
"${BUNDLE_PATH}"
""
"${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/Frameworks"
)
# Re-sign the bundle
execute_process(
COMMAND codesign --force --deep --sign - "${BUNDLE_PATH}"
)
# Verify the bundle
verify_app("${BUNDLE_PATH}")
# Rename to "Supercell Wx.app"
file(REMOVE_RECURSE
"${CMAKE_INSTALL_PREFIX}/Supercell Wx.app")
file(RENAME
"${BUNDLE_PATH}"
"${CMAKE_INSTALL_PREFIX}/Supercell Wx.app")
# Remove extra directories
file(REMOVE_RECURSE
"${CMAKE_INSTALL_PREFIX}/Frameworks")
file(REMOVE_RECURSE
"${CMAKE_INSTALL_PREFIX}/lib")
]]
COMPONENT supercell-wx)
endif()
set(CPACK_PACKAGE_NAME "Supercell Wx")
set(CPACK_PACKAGE_VENDOR "Dan Paulat")
set(CPACK_PACKAGE_CHECKSUM SHA256)
set(CPACK_RESOURCE_FILE_LICENSE "${SCWX_DIR}/LICENSE.txt")
if (MSVC)
set(CPACK_PACKAGE_NAME "Supercell Wx")
set(CPACK_PACKAGE_VENDOR "Dan Paulat")
set(CPACK_PACKAGE_FILE_NAME "supercell-wx-v${SCWX_VERSION}-windows-x64")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Supercell Wx")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/res/icons/scwx-256.ico")
set(CPACK_PACKAGE_CHECKSUM SHA256)
set(CPACK_RESOURCE_FILE_LICENSE "${SCWX_DIR}/LICENSE.txt")
set(CPACK_GENERATOR WIX)
set(CPACK_PACKAGE_EXECUTABLES "supercell-wx;Supercell Wx")
set(CPACK_WIX_UPGRADE_GUID 36AD0F51-4D4F-4B5D-AB61-94C6B4E4FE1C)
@ -786,5 +868,15 @@ if (MSVC)
set(CPACK_INSTALL_CMAKE_PROJECTS
"${CMAKE_CURRENT_BINARY_DIR};${CMAKE_PROJECT_NAME};supercell-wx;/")
include(CPack)
elseif(APPLE)
set(CPACK_PACKAGE_FILE_NAME "supercell-wx-v${SCWX_VERSION}-macos")
set(CPACK_PACKAGE_ICON "${SCWX_ICON}")
set(CPACK_PACKAGE_VERSION "${SCWX_VERSION}")
set(CPACK_GENERATOR DragNDrop)
set(CPACK_COMPONENTS_ALL supercell-wx)
include(CPack)
endif()

View file

@ -740,7 +740,7 @@ bool Icons::RunMousePicking(
// For each pickable icon
auto it = std::find_if( //
std::execution::par_unseq,
std::execution::par,
p->currentHoverIcons_.crbegin(),
p->currentHoverIcons_.crend(),
[&mouseLocalCoords](const auto& icon)

View file

@ -4,10 +4,15 @@
#include <mutex>
#include <GL/glu.h>
#include <boost/container/stable_vector.hpp>
#if defined(_WIN32)
#if !defined(__APPLE__)
# include <GL/glu.h>
#else
# include <OpenGL/glu.h>
#endif
#if defined(_WIN32) || defined(__APPLE__)
typedef void (*_GLUfuncptr)(void);
#endif

View file

@ -12,6 +12,7 @@ namespace gl
{
static const std::string logPrefix_ = "scwx::qt::gl::gl_context";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
class GlContext::Impl
{
@ -84,6 +85,13 @@ void GlContext::Impl::InitializeGL()
gl_->initializeOpenGLFunctions();
gl30_->initializeOpenGLFunctions();
logger_->info("OpenGL Version: {}",
reinterpret_cast<const char*>(gl_->glGetString(GL_VERSION)));
logger_->info("OpenGL Vendor: {}",
reinterpret_cast<const char*>(gl_->glGetString(GL_VENDOR)));
logger_->info("OpenGL Renderer: {}",
reinterpret_cast<const char*>(gl_->glGetString(GL_RENDERER)));
gl_->glGenTextures(1, &textureAtlas_);
glInitialized_ = true;

View file

@ -28,6 +28,7 @@
#include <QApplication>
#include <QStandardPaths>
#include <QStyleHints>
#include <QSurfaceFormat>
#include <QTranslator>
#include <QPalette>
#include <QStyle>
@ -62,6 +63,16 @@ int main(int argc, char* argv[])
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
#if defined(__APPLE__)
// For macOS, we must choose between OpenGL 4.1 Core and OpenGL 2.1
// Compatibility. OpenGL 2.1 does not meet requirements for shaders used by
// Supercell Wx.
QSurfaceFormat surfaceFormat = QSurfaceFormat::defaultFormat();
surfaceFormat.setVersion(4, 1);
surfaceFormat.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
QSurfaceFormat::setDefaultFormat(surfaceFormat);
#endif
QApplication a(argc, argv);
QCoreApplication::setApplicationName("Supercell Wx");

View file

@ -175,7 +175,7 @@ public:
level2ChunksProviderManager_->Disable();
std::shared_lock lock(level3ProviderManagerMutex_);
std::for_each(std::execution::par_unseq,
std::for_each(std::execution::par,
level3ProviderManagerMap_.begin(),
level3ProviderManagerMap_.end(),
[](auto& p)
@ -693,7 +693,7 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group,
auto availableProducts =
providerManager->provider_->GetAvailableProducts();
if (std::find(std::execution::par_unseq,
if (std::find(std::execution::par,
availableProducts.cbegin(),
availableProducts.cend(),
product) != availableProducts.cend())
@ -920,13 +920,13 @@ RadarProductManager::GetActiveVolumeTimes(
// For each provider (in parallel)
std::for_each(
std::execution::par_unseq,
std::execution::par,
providers.begin(),
providers.end(),
[&](const std::shared_ptr<provider::NexradDataProvider>& provider)
{
// For yesterday, today and tomorrow (in parallel)
std::for_each(std::execution::par_unseq,
std::for_each(std::execution::par,
dates.begin(),
dates.end(),
[&](const auto& date)
@ -1246,7 +1246,7 @@ void RadarProductManagerImpl::PopulateProductTimes(
std::mutex volumeTimesMutex {};
// For yesterday, today and tomorrow (in parallel)
std::for_each(std::execution::par_unseq,
std::for_each(std::execution::par,
dates.begin(),
dates.end(),
[&](const auto& date)

View file

@ -62,7 +62,7 @@ LoadImageResources(const std::vector<std::string>& urlStrings)
std::mutex m {};
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>> images {};
std::for_each(std::execution::par_unseq,
std::for_each(std::execution::par,
urlStrings.begin(),
urlStrings.end(),
[&](auto& urlString)

View file

@ -17,7 +17,6 @@
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/range/irange.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/single.hpp>
@ -488,7 +487,7 @@ void TextEventManager::Impl::LoadArchives(
std::vector<scwx::types::iem::AfosEntry> loadListEntries {};
for (auto date : boost::irange(startDate, endDate))
for (auto date = startDate; date < endDate; date += std::chrono::days {1})
{
auto mapIt = unloadedProductMap_.find(date);
if (mapIt == unloadedProductMap_.cend())

View file

@ -11,6 +11,7 @@
#include <mutex>
#include <ranges>
#include <set>
#include <shared_mutex>
#include <unordered_map>
#include <unordered_set>

View file

@ -124,6 +124,9 @@ void AudioCodecPage::Impl::SetInstructionsLabelText()
self_,
[](const QString& link)
{ QDesktopServices::openUrl(QUrl {link}); });
#elif defined(__APPLE__)
instructionsLabel_->setText(tr(
"Please see the instructions for your Mac for installing media codecs."));
#else
instructionsLabel_->setText(
tr("Please see the instructions for your Linux distribution for "

View file

@ -13,8 +13,6 @@ namespace util
namespace color
{
static const std::string logPrefix_ = "scwx::qt::util::color";
std::string ToArgbString(const boost::gil::rgba8_pixel_t& color)
{
return fmt::format(

View file

@ -12,8 +12,6 @@ namespace qt
namespace util
{
static const std::string logPrefix_ = "scwx::qt::util::file";
std::unique_ptr<std::istream> OpenFile(const std::string& filename,
std::ios_base::openmode mode)
{

View file

@ -390,11 +390,10 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath, double scale)
QUrl url = QUrl::fromUserInput(qImagePath);
if (url.isLocalFile())
{
QString suffix = QFileInfo(qImagePath).suffix().toLower();
QString qLocalImagePath = url.toString(QUrl::PreferLocalFile);
const QString suffix = QFileInfo(qImagePath).suffix().toLower();
const QString qLocalImagePath = url.toString(QUrl::PreferLocalFile);
if (suffix == "svg")
{
@ -448,18 +447,18 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath, double scale)
// If no alpha channel, replace black with transparent
if (numChannels == 3)
{
std::for_each(
std::execution::par_unseq,
view.begin(),
view.end(),
[](boost::gil::rgba8_pixel_t& pixel)
{
static const boost::gil::rgba8_pixel_t kBlack {0, 0, 0, 255};
if (pixel == kBlack)
{
pixel[3] = 0;
}
});
std::for_each(std::execution::par,
view.begin(),
view.end(),
[](boost::gil::rgba8_pixel_t& pixel)
{
static const boost::gil::rgba8_pixel_t kBlack {
0, 0, 0, 255};
if (pixel == kBlack)
{
pixel[3] = 0;
}
});
}
stbi_image_free(pixelData);

View file

@ -0,0 +1,9 @@
[settings]
arch=x86_64
build_type=Release
compiler=clang
compiler.cppstd=20
compiler.libcxx=libc++
compiler.version=18
os=Macos
os.version=12.0

View file

@ -0,0 +1,9 @@
[settings]
arch=armv8
build_type=Release
compiler=clang
compiler.cppstd=20
compiler.libcxx=libc++
compiler.version=18
os=Macos
os.version=12.0

View file

@ -1,8 +1,19 @@
#!/bin/bash
script_dir="$(dirname "$(readlink -f "$0")")"
script_source="${BASH_SOURCE[0]:-$0}"
script_dir="$(cd "$(dirname "${script_source}")" && pwd)"
# Assign user-specified Python Virtual Environment
[ "${1:-}" = "none" ] && unset venv_path || export venv_path="$(readlink -f "${1:-${script_dir}/../.venv}")"
if [ "${1:-}" = "none" ]; then
unset venv_path
else
venv_arg="${1:-${script_dir}/../.venv}"
# Portable way to get absolute path without requiring the directory to exist
case "${venv_arg}" in
/*) venv_path="${venv_arg}" ;;
*) venv_path="$(cd "$(dirname "${venv_arg}")" && pwd)/$(basename "${venv_arg}")" ;;
esac
export venv_path
fi
# Load custom build settings
if [ -f "${script_dir}/lib/user-setup.sh" ]; then
@ -11,12 +22,12 @@ fi
# Activate Python Virtual Environment
if [ -n "${venv_path:-}" ]; then
python -m venv "${venv_path}"
python3 -m venv "${venv_path}"
source "${venv_path}/bin/activate"
fi
# Detect if a Python Virtual Environment was specified above, or elsewhere
IN_VENV=$(python -c 'import sys; print(sys.prefix != getattr(sys, "base_prefix", sys.prefix))')
IN_VENV=$(python3 -c 'import sys; print(sys.prefix != getattr(sys, "base_prefix", sys.prefix))')
if [ "${IN_VENV}" = "True" ]; then
# In a virtual environment, don't use --user
@ -27,27 +38,36 @@ else
fi
# Install Python packages
python -m pip install ${PIP_FLAGS} --upgrade pip
pip install ${PIP_FLAGS} -r "${script_dir}/../requirements.txt"
python3 -m pip install ${PIP_FLAGS} --upgrade pip
python3 -m pip install ${PIP_FLAGS} -r "${script_dir}/../requirements.txt"
# Configure default Conan profile
conan profile detect -e
# Conan profiles
conan_profiles=(
"scwx-linux_clang-17"
"scwx-linux_clang-17_armv8"
"scwx-linux_clang-18"
"scwx-linux_clang-18_armv8"
"scwx-linux_gcc-11"
"scwx-linux_gcc-11_armv8"
"scwx-linux_gcc-12"
"scwx-linux_gcc-12_armv8"
"scwx-linux_gcc-13"
"scwx-linux_gcc-13_armv8"
"scwx-linux_gcc-14"
"scwx-linux_gcc-14_armv8"
if [[ "$(uname)" == "Darwin" ]]; then
# macOS profiles
conan_profiles=(
"scwx-macos_clang-18"
"scwx-macos_clang-18_armv8"
)
else
# Linux profiles
conan_profiles=(
"scwx-linux_clang-17"
"scwx-linux_clang-17_armv8"
"scwx-linux_clang-18"
"scwx-linux_clang-18_armv8"
"scwx-linux_gcc-11"
"scwx-linux_gcc-11_armv8"
"scwx-linux_gcc-12"
"scwx-linux_gcc-12_armv8"
"scwx-linux_gcc-13"
"scwx-linux_gcc-13_armv8"
"scwx-linux_gcc-14"
"scwx-linux_gcc-14_armv8"
)
fi
# Install Conan profiles
for profile_name in "${conan_profiles[@]}"; do

View file

@ -1,5 +1,6 @@
#!/bin/bash
script_dir="$(dirname "$(readlink -f "$0")")"
script_source="${BASH_SOURCE[0]:-$0}"
script_dir="$(cd "$(dirname "${script_source}")" && pwd)"
cmake_args=(
-B "${build_dir}"

View file

@ -1,5 +1,6 @@
#!/bin/bash
script_dir="$(dirname "$(readlink -f "$0")")"
script_source="${BASH_SOURCE[0]:-$0}"
script_dir="$(cd "$(dirname "${script_source}")" && pwd)"
# Import common paths
source "${script_dir}/common-paths.sh"
@ -9,14 +10,14 @@ if [ -f "${script_dir}/user-setup.sh" ]; then
source "${script_dir}/user-setup.sh"
fi
# Activate Python Virtual Environment
# Activate python3 Virtual Environment
if [ -n "${venv_path:-}" ]; then
python -m venv "${venv_path}"
python3 -m venv "${venv_path}"
source "${venv_path}/bin/activate"
fi
# Detect if a Python Virtual Environment was specified above, or elsewhere
IN_VENV=$(python -c 'import sys; print(sys.prefix != getattr(sys, "base_prefix", sys.prefix))')
# Detect if a python3 Virtual Environment was specified above, or elsewhere
IN_VENV=$(python3 -c 'import sys; print(sys.prefix != getattr(sys, "base_prefix", sys.prefix))')
if [ "${IN_VENV}" = "True" ]; then
# In a virtual environment, don't use --user
@ -26,9 +27,9 @@ else
PIP_FLAGS="--upgrade --user"
fi
# Install Python packages
python -m pip install ${PIP_FLAGS} pip
pip install ${PIP_FLAGS} -r "${script_dir}/../../requirements.txt"
# Install python3 packages
python3 -m pip install ${PIP_FLAGS} pip
python3 -m pip install ${PIP_FLAGS} -r "${script_dir}/../../requirements.txt"
if [[ -n "${build_type}" ]]; then
# Install Conan profile and packages
@ -49,7 +50,7 @@ fi
# Run CMake Configure
"${script_dir}/run-cmake-configure.sh"
# Deactivate Python Virtual Environment
# Deactivate python3 Virtual Environment
if [ -n "${venv_path:-}" ]; then
deactivate
fi

View file

@ -1,5 +1,6 @@
#!/bin/bash
script_dir="$(dirname "$(readlink -f "$0")")"
script_source="${BASH_SOURCE[0]:-$0}"
script_dir="$(cd "$(dirname "${script_source}")" && pwd)"
# Configure default Conan profile
conan profile detect -e

View file

@ -31,6 +31,9 @@ macro(scwx_python_setup)
set(Python3_EXECUTABLE "$ENV{VIRTUAL_ENV}/bin/python")
endif()
# Add virtual environment to program search paths
set(CMAKE_PROGRAM_PATH "$ENV{VIRTUAL_ENV}/bin" ${CMAKE_PROGRAM_PATH})
message(STATUS "Using virtual environment: $ENV{VIRTUAL_ENV}")
else()
message(STATUS "Python virtual environment undefined")

30
tools/setup-macos-debug.sh Executable file
View file

@ -0,0 +1,30 @@
#!/bin/bash
script_source="${BASH_SOURCE[0]:-$0}"
script_dir="$(cd "$(dirname "${script_source}")" && pwd)"
export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-debug}")"
export build_type=Debug
export conan_profile=${2:-scwx-macos_clang-18_armv8}
export generator=Ninja
export qt_base="/Users/${USER}/Qt"
export qt_arch=macos
export address_sanitizer=${4:-disabled}
# Set explicit compiler paths
export CC=$(brew --prefix llvm@18)/bin/clang
export CXX=$(brew --prefix llvm@18)/bin/clang++
export PATH="$(brew --prefix llvm@18)/bin:$PATH"
export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++"
export CPPFLAGS="-I$(brew --prefix llvm@18)/include"
# Assign user-specified Python Virtual Environment
if [ "${3:-}" = "none" ]; then
unset venv_path
else
# macOS does not have 'readlink -f', use python for realpath
export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")"
fi
# Perform common setup
"${script_dir}/lib/setup-common.sh"

30
tools/setup-macos-release.sh Executable file
View file

@ -0,0 +1,30 @@
#!/bin/bash
script_source="${BASH_SOURCE[0]:-$0}"
script_dir="$(cd "$(dirname "${script_source}")" && pwd)"
export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-release}")"
export build_type=Release
export conan_profile=${2:-scwx-macos_clang-18_armv8}
export generator=Ninja
export qt_base="/Users/${USER}/Qt"
export qt_arch=macos
export address_sanitizer=${4:-disabled}
# Set explicit compiler paths
export CC=$(brew --prefix llvm@18)/bin/clang
export CXX=$(brew --prefix llvm@18)/bin/clang++
export PATH="$(brew --prefix llvm@18)/bin:$PATH"
export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++"
export CPPFLAGS="-I$(brew --prefix llvm@18)/include"
# Assign user-specified Python Virtual Environment
if [ "${3:-}" = "none" ]; then
unset venv_path
else
# macOS does not have 'readlink -f', use python for realpath
export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")"
fi
# Perform common setup
"${script_dir}/lib/setup-common.sh"

View file

@ -7,8 +7,6 @@ namespace network
namespace cpr
{
static const std::string logPrefix_ = "scwx::network::cpr";
static ::cpr::Header header_ {};
::cpr::Header GetHeader()

View file

@ -2,6 +2,7 @@
#include <scwx/util/logger.hpp>
#include <istream>
#include <numeric>
#include <string>
namespace scwx

View file

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.24)
project(scwx-data)
include(CheckCXXSymbolExists)
find_package(Boost)
find_package(cpr)
find_package(LibXml2)
@ -10,7 +12,9 @@ find_package(range-v3)
find_package(re2)
find_package(spdlog)
if (NOT MSVC)
check_cxx_symbol_exists(_LIBCPP_VERSION version LIBCPP)
if (LINUX)
find_package(TBB)
endif()
@ -327,10 +331,16 @@ if (NOT CHRONO_HAS_TIMEZONES_AND_CALENDERS)
target_link_libraries(wxdata PUBLIC date::date-tz)
endif()
if (NOT MSVC)
if (LINUX)
target_link_libraries(wxdata PUBLIC TBB::tbb)
endif()
if (LIBCPP)
# Enable support for parallel algorithms
target_compile_options(wxdata PUBLIC -fexperimental-library)
target_link_libraries(wxdata INTERFACE c++experimental)
endif()
set_target_properties(wxdata PROPERTIES CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF)