From 34c308ebdb219c8c3e5cdc5a1192db8a51ef0c44 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 17 Jun 2026 11:46:23 -0400 Subject: macOS 27 build fixes + transition to UTType for file pickers (#5937) * Get the viewer building on macOS 27 * Strip -mmacosx-version-min when we're below an SDK supported version. Substitutes an actual SDK supported minimum version. * Move kIOMainPortDefault behind an SDK compatibility check. * Update llwindowmacosx_iokit.h * Update llwindowmacosx_iokit.h --- indra/cmake/00-Common.cmake | 11 ++++++ indra/cmake/Linking.cmake | 2 ++ indra/cmake/Variables.cmake | 33 +++++++++++++++++- indra/llwindow/CMakeLists.txt | 1 + indra/llwindow/llwindowmacosx.cpp | 4 +-- indra/llwindow/llwindowmacosx_iokit.h | 35 +++++++++++++++++++ indra/newview/llappviewermacosx.cpp | 3 +- indra/newview/llfilepicker_mac.mm | 63 +++++++++++++++++++++++++++++------ indra/newview/llmachineid.cpp | 4 +-- 9 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 indra/llwindow/llwindowmacosx_iokit.h diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 99ea22ab4b..72347446b9 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -18,6 +18,17 @@ include(Variables) # We go to some trouble to set LL_BUILD to the set of relevant compiler flags. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LL_BUILD}") + +if (DARWIN) + # LL_BUILD carries a literal -mmacosx-version-min= from + # viewer-build-variables. We derive the macOS deployment target in + # Variables.cmake (clamping up to the SDK's supported minimum when needed) + # and let CMAKE_OSX_DEPLOYMENT_TARGET emit the flag to both compiler and + # linker. Strip the verbatim flag here so it can't conflict with the + # clamped deployment target. + string(REGEX REPLACE "-mmacosx-version-min=[0-9.]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +endif (DARWIN) + # Given that, all the flags you see added below are flags NOT present in # https://bitbucket.org/lindenlab/viewer-build-variables/src/tip/variables. # Before adding new ones here, it's important to ask: can this flag really be diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 900a64e2dd..5d4e8d8634 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -77,6 +77,7 @@ else() find_library(COREAUDIO_LIBRARY CoreAudio) find_library(COREGRAPHICS_LIBRARY CoreGraphics) find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox) + find_library(UNIFORMTYPEIDENTIFIERS_LIBRARY UniformTypeIdentifiers) target_link_libraries( ll::oslibraries INTERFACE ${COCOA_LIBRARY} @@ -87,6 +88,7 @@ else() ${COREAUDIO_LIBRARY} ${AUDIOTOOLBOX_LIBRARY} ${COREGRAPHICS_LIBRARY} + ${UNIFORMTYPEIDENTIFIERS_LIBRARY} ) endif() diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 22c2156bb8..baa93bd128 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -144,7 +144,38 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(DARWIN 1) string(REGEX MATCH "-mmacosx-version-min=([^ ]+)" scratch "$ENV{LL_BUILD}") - set(CMAKE_OSX_DEPLOYMENT_TARGET "${CMAKE_MATCH_1}" CACHE STRING "macOS Deploy Target" FORCE) + set(LL_REQUESTED_DEPLOYMENT_TARGET "${CMAKE_MATCH_1}") + + # Determine the lowest deployment target the active macOS SDK still supports. + # We aim for 11.0 in our public builds, but newer Xcode/SDK releases + # periodically raise this floor (e.g. Xcode 26 -> 13.3, Xcode 27 -> 14), and + # linking against a deployment target below the SDK's minimum fails. Read the + # supported minimum from the SDK and clamp our requested target up to it when + # necessary, so the build tracks whatever the SDK allows automatically. + set(LL_SDK_MINIMUM_DEPLOYMENT_TARGET "") + execute_process( + COMMAND xcrun --sdk macosx --show-sdk-path + OUTPUT_VARIABLE LL_MACOS_SDK_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + if (LL_MACOS_SDK_PATH AND EXISTS "${LL_MACOS_SDK_PATH}/SDKSettings.plist") + execute_process( + COMMAND /usr/libexec/PlistBuddy -c + "Print :SupportedTargets:macosx:MinimumDeploymentTarget" + "${LL_MACOS_SDK_PATH}/SDKSettings.plist" + OUTPUT_VARIABLE LL_SDK_MINIMUM_DEPLOYMENT_TARGET + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + endif () + + set(LL_EFFECTIVE_DEPLOYMENT_TARGET "${LL_REQUESTED_DEPLOYMENT_TARGET}") + if (LL_SDK_MINIMUM_DEPLOYMENT_TARGET AND + LL_REQUESTED_DEPLOYMENT_TARGET VERSION_LESS LL_SDK_MINIMUM_DEPLOYMENT_TARGET) + message(STATUS "Requested macOS deploy target ${LL_REQUESTED_DEPLOYMENT_TARGET} is below the SDK minimum ${LL_SDK_MINIMUM_DEPLOYMENT_TARGET}; clamping to ${LL_SDK_MINIMUM_DEPLOYMENT_TARGET}") + set(LL_EFFECTIVE_DEPLOYMENT_TARGET "${LL_SDK_MINIMUM_DEPLOYMENT_TARGET}") + endif () + + set(CMAKE_OSX_DEPLOYMENT_TARGET "${LL_EFFECTIVE_DEPLOYMENT_TARGET}" CACHE STRING "macOS Deploy Target" FORCE) message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET = '${CMAKE_OSX_DEPLOYMENT_TARGET}'") # Use dwarf symbols for most libraries for compilation speed diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 13a7592e8f..3dae2d1067 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -60,6 +60,7 @@ set(macosx_HEADER_FILES llkeyboardmacosx.h llwindowmacosx.h llwindowmacosx-objc.h + llwindowmacosx_iokit.h llopenglview-objc.h llappdelegate-objc.h ) diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index f8920318d3..1dd795cd3a 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include "llwindowmacosx_iokit.h" #include #include #include @@ -2379,7 +2379,7 @@ bool LLWindowMacOSX::getInputDevices(U32 device_type_filter, io_iterator_t io_iter = 0; // create an IO object iterator - result = IOServiceGetMatchingServices( kIOMasterPortDefault, device_dict_ref, &io_iter ); + result = IOServiceGetMatchingServices( kLLIOMainPort, device_dict_ref, &io_iter ); if ( kIOReturnSuccess != result ) { LL_WARNS("Joystick") << "IOServiceGetMatchingServices failed" << LL_ENDL; diff --git a/indra/llwindow/llwindowmacosx_iokit.h b/indra/llwindow/llwindowmacosx_iokit.h new file mode 100644 index 0000000000..a6be2c86ef --- /dev/null +++ b/indra/llwindow/llwindowmacosx_iokit.h @@ -0,0 +1,35 @@ +/** + * @file llwindowmacosx_iokit.h + * @brief IOKit compatibility for macOS deployment target differences + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2025, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#pragma once +#include + +// kIOMainPortDefault is the macOS 12+ rename of kIOMasterPortDefault. +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000 +static const mach_port_t kLLIOMainPort = kIOMainPortDefault; +#else +static const mach_port_t kLLIOMainPort = kIOMasterPortDefault; +#endif diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 1c01d06852..c188bb459f 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -49,6 +49,7 @@ #include "llerrorcontrol.h" #include "llvoavatarself.h" // for gAgentAvatarp->getFullname() #include +#include "llwindowmacosx_iokit.h" #ifdef LL_CARBON_CRASH_HANDLER #include #endif @@ -441,7 +442,7 @@ std::string LLAppViewerMacOSX::generateSerialNumber() // JC: Sample code from http://developer.apple.com/technotes/tn/tn1103.html CFStringRef serialNumber = NULL; - io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, + io_service_t platformExpert = IOServiceGetMatchingService(kLLIOMainPort, IOServiceMatching("IOPlatformExpertDevice")); if (platformExpert) { diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm index 99e93bafbf..3a0bc4005e 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -26,15 +26,28 @@ #ifdef LL_DARWIN #import +#import #include #include "llfilepicker_mac.h" +// Convert a file extension or UTI string into a UTType for use with +// NSOpenPanel/NSSavePanel's allowedContentTypes. +static UTType *contentTypeForString(NSString *typeString) +{ + UTType *type = [UTType typeWithFilenameExtension:typeString]; + if (!type) + { + type = [UTType typeWithIdentifier:typeString]; + } + return type; +} + NSOpenPanel *init_panel(const std::vector* allowed_types, unsigned int flags) { int i; NSOpenPanel *panel = [NSOpenPanel openPanel]; - NSMutableArray *fileTypes = nil; + NSMutableArray *fileTypes = nil; if ( allowed_types && !allowed_types->empty()) @@ -43,9 +56,13 @@ NSOpenPanel *init_panel(const std::vector* allowed_types, unsigned for (i=0;isize();++i) { - [fileTypes addObject: - [NSString stringWithCString:(*allowed_types)[i].c_str() - encoding:[NSString defaultCStringEncoding]]]; + NSString *typeString = [NSString stringWithCString:(*allowed_types)[i].c_str() + encoding:[NSString defaultCStringEncoding]]; + UTType *type = contentTypeForString(typeString); + if (type) + { + [fileTypes addObject:type]; + } } } @@ -57,9 +74,9 @@ NSOpenPanel *init_panel(const std::vector* allowed_types, unsigned [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )]; [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; - if (fileTypes) + if (fileTypes && fileTypes.count > 0) { - [panel setAllowedFileTypes:fileTypes]; + [panel setAllowedContentTypes:fileTypes]; } else { @@ -196,12 +213,25 @@ std::unique_ptr doSaveDialog(const std::string* file, NSSavePanel *panel = [NSSavePanel savePanel]; NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]]; - NSArray *fileType = [extensionns componentsSeparatedByString:@","]; + NSArray *extensions = [extensionns componentsSeparatedByString:@","]; + + NSMutableArray *fileType = [[NSMutableArray alloc] init]; + for (NSString *ext in extensions) + { + UTType *type = contentTypeForString(ext); + if (type) + { + [fileType addObject:type]; + } + } //[panel setMessage:@"Save Image File"]; [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; [panel setCanSelectHiddenExtension:true]; - [panel setAllowedFileTypes:fileType]; + if (fileType.count > 0) + { + [panel setAllowedContentTypes:fileType]; + } NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; NSURL* url = [NSURL fileURLWithPath:fileName]; @@ -231,12 +261,25 @@ void doSaveDialogModeless(const std::string* file, NSSavePanel *panel = [NSSavePanel savePanel]; NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]]; - NSArray *fileType = [extensionns componentsSeparatedByString:@","]; + NSArray *extensions = [extensionns componentsSeparatedByString:@","]; + + NSMutableArray *fileType = [[NSMutableArray alloc] init]; + for (NSString *ext in extensions) + { + UTType *type = contentTypeForString(ext); + if (type) + { + [fileType addObject:type]; + } + } //[panel setMessage:@"Save Image File"]; [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; [panel setCanSelectHiddenExtension:true]; - [panel setAllowedFileTypes:fileType]; + if (fileType.count > 0) + { + [panel setAllowedContentTypes:fileType]; + } NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; NSURL* url = [NSURL fileURLWithPath:fileName]; diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp index 0a90cf0699..0373b25143 100644 --- a/indra/newview/llmachineid.cpp +++ b/indra/newview/llmachineid.cpp @@ -34,7 +34,7 @@ #include #elif LL_DARWIN #include -#include +#include "llwindowmacosx_iokit.h" #endif unsigned char static_unique_id[] = {0,0,0,0,0,0}; unsigned char static_legacy_id[] = {0,0,0,0,0,0}; @@ -350,7 +350,7 @@ bool LLWMIMethods::getGenericSerialNumber(const BSTR &select, const LPCWSTR &var bool getSerialNumber(unsigned char *unique_id, size_t len) { CFStringRef serial_cf_str = NULL; - io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, + io_service_t platformExpert = IOServiceGetMatchingService(kLLIOMainPort, IOServiceMatching("IOPlatformExpertDevice")); if (platformExpert) { -- cgit v1.3