From 6521ee2c2f12b7f2553add1f5e3174aaafc780a3 Mon Sep 17 00:00:00 2001 From: Naomi Kirby Date: Mon, 30 Dec 2024 11:07:54 -0800 Subject: [PATCH] Xcode 16 build fixes (#10148) * Remove -Xlink=-force:multiple hack * Add framework search paths for IOSGlean * Turn off Xcode's ENABLE_DEBUG_DYLIB option This option breaks the Qt/iOS application setup. Qt tries to override the program entrypoint on iOS, and directs it to _qt_main_wrapper() instead using a linker argument, but these arguments get dropped when building as a dylib, causing Xcode to skip _qt_main_wrapper() and invokes main() directly. * Fix static assert in DeviceModel We encounter an assert in Xcode 16 because the sortCallback method used in the DeviceModel does not satisfy strict-weak ordering due to the special case added for the current device. To fix this we can simplify the callback so that it sorts by creation time and move the current device as a second step. * Bump conda golang to 1.22 * Update 3rdparty/wireguard-apple to fix Xcode16 compile fail --- .gitmodules | 2 +- 3rdparty/wireguard-apple | 2 +- env.yml | 2 +- ios/networkextension/CMakeLists.txt | 13 +++++++++++++ scripts/cmake/rustlang.cmake | 7 ------- src/cmake/ios.cmake | 5 ++++- src/models/devicemodel.cpp | 29 ++++++++++++++--------------- src/models/devicemodel.h | 1 + 8 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.gitmodules b/.gitmodules index dda559a180..0229d34922 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,7 +4,7 @@ shallow = true [submodule "3rdparty/wireguard-apple"] path = 3rdparty/wireguard-apple - url = https://github.com/WireGuard/wireguard-apple + url = https://github.com/mozilla/wireguard-apple.git shallow = true [submodule "3rdparty/openSSL"] path = 3rdparty/openSSL diff --git a/3rdparty/wireguard-apple b/3rdparty/wireguard-apple index 12b095470a..3ba0b4cc2e 160000 --- a/3rdparty/wireguard-apple +++ b/3rdparty/wireguard-apple @@ -1 +1 @@ -Subproject commit 12b095470ad29ecea7436088f6e5fa701e6445a6 +Subproject commit 3ba0b4cc2e187c15c0416378e71e93a5d6252167 diff --git a/env.yml b/env.yml index b3f6f436b5..277c5f271d 100644 --- a/env.yml +++ b/env.yml @@ -18,7 +18,7 @@ dependencies: - rust-std-x86_64-linux-android=1.75 - rust-std-i686-linux-android=1.75 - rust-std-aarch64-linux-android=1.75 - - go=1.18 + - go=1.22 - compiler-rt - cmake=3.26.3 - ninja=1.11.0 diff --git a/ios/networkextension/CMakeLists.txt b/ios/networkextension/CMakeLists.txt index eb6f9b91bd..9aa92a4ead 100644 --- a/ios/networkextension/CMakeLists.txt +++ b/ios/networkextension/CMakeLists.txt @@ -140,3 +140,16 @@ set_source_files_properties( target_sources(networkextension PRIVATE ${CMAKE_BINARY_DIR}/src/generated/VPNMetrics.swift ) + +# The IOSGlean framework is built under the src directory, so we'll need to +# explicitly add it to the framework search paths. However, this gets messy +# in Xcode because the actual path is somewhat somewhat buried in +# subdirectories. +if(XCODE) + # Xcode is a multi-config generator, so technically we need to do this for + # each supported config too. + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES}) + set_target_properties(networkextension PROPERTIES + "XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS[variant=${CONFIG}]" "${CMAKE_BINARY_DIR}/src/${CONFIG}$(EFFECTIVE_PLATFORM_NAME)") + endforeach() +endif() diff --git a/scripts/cmake/rustlang.cmake b/scripts/cmake/rustlang.cmake index 56f687702f..aa677e837f 100644 --- a/scripts/cmake/rustlang.cmake +++ b/scripts/cmake/rustlang.cmake @@ -381,11 +381,4 @@ function(add_rust_library TARGET_NAME) add_dependencies(${TARGET_NAME} ${TARGET_NAME}_builder) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS}) - - ## When including multiple rust staticlibs, we often wind up with duplicate - ## symbols from the rust runtime. Work around it by permitting duplicates - ## during linking. - set_property(TARGET ${TARGET_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS - $<$:-Xlink=-force:multiple> - ) endfunction() diff --git a/src/cmake/ios.cmake b/src/cmake/ios.cmake index a9c0075be3..f983ac14d9 100644 --- a/src/cmake/ios.cmake +++ b/src/cmake/ios.cmake @@ -29,7 +29,6 @@ target_sources(mozillavpn PRIVATE ${CMAKE_SOURCE_DIR}/src/platforms/ios/iosgleanbridge.h ) - ## Install the Network Extension into the bundle. add_dependencies(mozillavpn networkextension) @@ -74,6 +73,10 @@ set_target_properties(mozillavpn PROPERTIES # Do not strip debug symbols on copy XCODE_ATTRIBUTE_COPY_PHASE_STRIP "NO" XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT "NO" + # Do not build with debug dylibs - it breaks the Qt/ios entrypoint. + # This can be fixed by rolling out own entrypoint and invoking + # UIApplicationMain() ourselves. + XCODE_ATTRIBUTE_ENABLE_DEBUG_DYLIB "NO" ) target_include_directories(mozillavpn PRIVATE ${CMAKE_SOURCE_DIR}) diff --git a/src/models/devicemodel.cpp b/src/models/devicemodel.cpp index e5273a2a2e..3a98ec91e1 100644 --- a/src/models/devicemodel.cpp +++ b/src/models/devicemodel.cpp @@ -71,20 +71,21 @@ bool DeviceModel::fromSettings(const Keys* keys) { namespace { -bool sortCallback(const Device& a, const Device& b, const Keys* keys) { - if (a.isCurrentDevice(keys)) { - return true; - } - - if (b.isCurrentDevice(keys)) { - return false; - } - +bool sortCallback(const Device& a, const Device& b) { return a.createdAt() > b.createdAt(); } } // anonymous namespace +// Check if the current device exists, and if so move it to to the front. +void DeviceModel::moveCurrentDevice(const Keys* keys) { + for (qsizetype index = 0; index < m_devices.length(); index++) { + if (m_devices.at(index).isCurrentDevice(keys)) { + m_devices.move(index, 0); + } + } +} + bool DeviceModel::fromJsonInternal(const Keys* keys, const QByteArray& json) { beginResetModel(); @@ -132,9 +133,8 @@ bool DeviceModel::fromJsonInternal(const Keys* keys, const QByteArray& json) { } } - std::sort(m_devices.begin(), m_devices.end(), - std::bind(sortCallback, std::placeholders::_1, - std::placeholders::_2, keys)); + std::sort(m_devices.begin(), m_devices.end(), sortCallback); + moveCurrentDevice(keys); endResetModel(); emit changed(); @@ -207,9 +207,8 @@ void DeviceModel::stopDeviceRemovalFromPublicKey(const QString& publicKey, m_devices.append(*i); - std::sort(m_devices.begin(), m_devices.end(), - std::bind(sortCallback, std::placeholders::_1, - std::placeholders::_2, keys)); + std::sort(m_devices.begin(), m_devices.end(), sortCallback); + moveCurrentDevice(keys); m_removedDevices.erase(i); diff --git a/src/models/devicemodel.h b/src/models/devicemodel.h index 932362fd0f..8fe5c1e74d 100644 --- a/src/models/devicemodel.h +++ b/src/models/devicemodel.h @@ -74,6 +74,7 @@ class DeviceModel final : public QAbstractListModel, public LogSerializer { private: [[nodiscard]] bool fromJsonInternal(const Keys* keys, const QByteArray& json); + void moveCurrentDevice(const Keys* keys); bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;