From 13662afc688fe681b5a05cae78fcb2b27cf4c72a Mon Sep 17 00:00:00 2001 From: Roberto Nibali Date: Wed, 8 Jul 2026 09:51:34 +0200 Subject: [PATCH 1/2] configure: support Homebrew Qt with the selected macOS SDK Use the selected SDK sysroot for Darwin compile probes, prefer its libc++ headers over unrelated Homebrew GCC headers, and treat a custom Homebrew Qt path as a framework installation. Detect Homebrew Qt tools and plugins under share/qt so the generated kBuild paths also produce a complete app bundle. Signed-off-by: Roberto Nibali --- configure.py | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/configure.py b/configure.py index bd5e2feda4b..1bc408a8774 100755 --- a/configure.py +++ b/configure.py @@ -725,6 +725,9 @@ def compileAndRun(sName, asIncPaths, asLibPaths, asIncFiles, asLibFiles, \ asCmd.extend( [ sFileSource ] ); asCmd.extend( [ '/Fe:' + sFileImage ] ); else: # Non-Windows + if enmBuildTarget == BuildTarget.DARWIN \ + and g_oEnv['VBOX_PATH_MACOSX_SDK']: + asCmd.extend([ '-isysroot', g_oEnv['VBOX_PATH_MACOSX_SDK'] ]); if asIncPaths: for sIncPath in asIncPaths: asCmd.extend( [ f'-I{sIncPath}' ] ); @@ -1414,8 +1417,8 @@ def getIncSearchPaths(self): # macOS (Darwin) # elif self.enmBuildTarget == BuildTarget.DARWIN: - asPaths.extend([ '/opt/homebrew/include', - os.path.join(g_oEnv['VBOX_PATH_MACOSX_SDK'], 'usr', 'include', 'c++', 'v1') ]); + asPaths.extend([ os.path.join(g_oEnv['VBOX_PATH_MACOSX_SDK'], 'usr', 'include', 'c++', 'v1'), + '/opt/homebrew/include' ]); # # Linux @@ -1764,8 +1767,12 @@ def checkCallback_qt(self): sPathBin = None; sPathLibExec = None; - # Check if we have our own pre-compiled Qt in tools first. - sPathBase = self.getToolPath(); + # Check if we have our own pre-compiled Qt in tools first. A custom + # Darwin path may point at a normal framework installation instead. + if self.enmBuildTarget == BuildTarget.DARWIN and self.sRootPath: + sPathBase = None; + else: + sPathBase = self.getToolPath(); if sPathBase: self.asLibFiles = [ 'libQt6CoreVBox' ]; g_oEnv.set('VBOX_WITH_ORACLE_QT', '1'); @@ -1803,10 +1810,11 @@ def checkCallback_qt(self): # Search for the library file. # Note: Ordered by precedence. Do not change! - asPath = [ sPathBase, - getPackagePath('qt@6')[1], - '/System/Library', - '/Library' ]; + asPath = [ self.sRootPath, + sPathBase, + getPackagePath('qt@6')[1], + '/System/Library', + '/Library' ]; sPathFramework = None; for sPathBase in asPath: if not sPathBase: # No custom path? Skip. @@ -1825,23 +1833,33 @@ def checkCallback_qt(self): break; if sPathFramework: + sPathFrameworkParent = os.path.dirname(sPathFramework); # We need to clear the library defined the the LibraryCheck definition # -- macOS uses the framework concept instead. self.asLibFiles = []; - self.asLibPaths.insert(0, sPathFramework); + self.asLibPaths.insert(0, sPathFrameworkParent); # Include the framework headers. - self.asIncPaths.insert(0, f'{sPathBase}/lib/QtCore.framework/Headers'); + self.asIncPaths.insert(0, os.path.join(sPathFramework, 'Headers')); # More stuff needed in order to get it linked. - self.asLinkerArgs.extend([ '-std=c++17', '-framework', 'QtCore', '-F', f'{sPathBase}/lib', '-g', '-O', '-Wall' ]); + self.asCompilerArgs.extend([ '-F', sPathFrameworkParent ]); + self.asLinkerArgs.extend([ '-std=c++17', '-framework', 'QtCore', '-F', sPathFrameworkParent, '-g', '-O', '-Wall' ]); sPkgName = 'Qt6Core'; ## @todo Make the code generic once we have similar SDKs. if sPathBase: g_oEnv.set( 'VBOX_PATH_QT', sPathBase); - g_oEnv.set(f'PATH_SDK_{self.sSdkName}', sPathBase); + sPathSdk = sPathBase; sPathBin = os.path.join(sPathBase, 'bin'); sPathInc = os.path.join(sPathBase, 'include'); sPathLib = os.path.join(sPathBase, 'lib'); sPathLibExec = os.path.join(sPathBase, 'libexec'); + if self.enmBuildTarget == BuildTarget.DARWIN: + sPathQtData = os.path.join(sPathBase, 'share', 'qt'); + if isDir(os.path.join(sPathQtData, 'plugins')): + sPathSdk = sPathQtData; + sPathQtLibExec = os.path.join(sPathQtData, 'libexec'); + if isDir(sPathQtLibExec): + sPathLibExec = sPathQtLibExec; + g_oEnv.set(f'PATH_SDK_{self.sSdkName}', sPathSdk); if self.enmBuildTarget != BuildTarget.WINDOWS: # Tell g++ that we need C++17 -- otherwise Qt6 won't compile. From 44488285002172baabc520a290a668438cf91b94 Mon Sep 17 00:00:00 2001 From: Roberto Nibali Date: Thu, 16 Jul 2026 16:41:36 +0200 Subject: [PATCH 2/2] Darwin: fix current SDK source build blockers Signed-off-by: Roberto Nibali --- .../settings/editors/UIHostComboEditor.cpp | 8 ++++---- .../darwin/HostDnsServiceDarwin.cpp | 3 ++- .../src-server/darwin/HostPowerDarwin.cpp | 3 +-- .../target-armv8/NEMR3Native-darwin-armv8.cpp | 20 +++++++++++++------ 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/VBox/Frontends/VirtualBox/src/settings/editors/UIHostComboEditor.cpp b/src/VBox/Frontends/VirtualBox/src/settings/editors/UIHostComboEditor.cpp index 6fe67766ab1..9b680d9643a 100644 --- a/src/VBox/Frontends/VirtualBox/src/settings/editors/UIHostComboEditor.cpp +++ b/src/VBox/Frontends/VirtualBox/src/settings/editors/UIHostComboEditor.cpp @@ -147,19 +147,19 @@ QString UINativeHotKey::toString(int iKeyCode) { case shiftKey: case rightShiftKey: - strKeyName = strKeyName.arg(QChar(kShiftUnicode)); + strKeyName = strKeyName.arg(QChar(static_cast(kShiftUnicode))); break; case optionKey: case rightOptionKey: - strKeyName = strKeyName.arg(QChar(kOptionUnicode)); + strKeyName = strKeyName.arg(QChar(static_cast(kOptionUnicode))); break; case controlKey: case rightControlKey: - strKeyName = strKeyName.arg(QChar(kControlUnicode)); + strKeyName = strKeyName.arg(QChar(static_cast(kControlUnicode))); break; case cmdKey: case kEventKeyModifierRightCmdKeyMask: - strKeyName = strKeyName.arg(QChar(kCommandUnicode)); + strKeyName = strKeyName.arg(QChar(static_cast(kCommandUnicode))); break; } diff --git a/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp b/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp index 2b32987cec6..c16e988d566 100644 --- a/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp +++ b/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp @@ -241,6 +241,7 @@ int HostDnsServiceDarwin::updateInfo(void) { CFStringRef const serverAddressRef = (CFStringRef)CFArrayGetValueAtIndex(serverArrayRef, i); if (serverAddressRef) + { if (!queryCFStringAsUtf8Str(serverAddressRef, strTmp, _16K)) { LogRel(("HostDnsServiceDarwin: idx: %u: Failed to convert address.\n", i)); @@ -273,6 +274,7 @@ int HostDnsServiceDarwin::updateInfo(void) } else LogRel(("HostDnsServiceDarwin: line %u: bad nameserver address %s\n", i, strTmp.c_str())); + } } } @@ -313,4 +315,3 @@ void HostDnsServiceDarwin::Data::performShutdownCallback(void *pInfo) AssertPtrReturnVoid(pThis->m); ASMAtomicXchgBool(&pThis->m->m_fStop, true); } - diff --git a/src/VBox/Main/src-server/darwin/HostPowerDarwin.cpp b/src/VBox/Main/src-server/darwin/HostPowerDarwin.cpp index 2c1c7c65d8b..9b483478797 100644 --- a/src/VBox/Main/src-server/darwin/HostPowerDarwin.cpp +++ b/src/VBox/Main/src-server/darwin/HostPowerDarwin.cpp @@ -229,7 +229,7 @@ void HostPowerServiceDarwin::checkBatteryCriticalLevel(bool *pfCriticalChanged) result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue); - critical = remCapacity < criticalValue; + critical = remCapacity < (float)criticalValue; /* We have to take action only if we are on battery, the * previous state wasn't critical, the state has changed & the @@ -249,4 +249,3 @@ void HostPowerServiceDarwin::checkBatteryCriticalLevel(bool *pfCriticalChanged) CFRelease(pBlob); CFRelease(pSources); } - diff --git a/src/VBox/VMM/VMMR3/target-armv8/NEMR3Native-darwin-armv8.cpp b/src/VBox/VMM/VMMR3/target-armv8/NEMR3Native-darwin-armv8.cpp index 1f644c8fc8f..60631a2b2dc 100644 --- a/src/VBox/VMM/VMMR3/target-armv8/NEMR3Native-darwin-armv8.cpp +++ b/src/VBox/VMM/VMMR3/target-armv8/NEMR3Native-darwin-armv8.cpp @@ -73,7 +73,7 @@ * Structures and Typedefs * *********************************************************************************************************************************/ -#if MAC_OS_X_VERSION_MIN_REQUIRED < 150000 +#if !__has_include() /* Since 15.0+ */ typedef enum hv_gic_distributor_reg_t : uint16_t @@ -138,12 +138,17 @@ typedef enum hv_gic_intid_t : uint16_t HV_GIC_INT_PERFORMANCE_MONITOR = 30 } hv_gic_intid_t; -# define HV_SYS_REG_ACTLR_EL1 (hv_sys_reg_t)0xc081 - #else # define HV_GIC_ICC_REG_INVALID (hv_gic_icc_reg_t)UINT16_MAX #endif +#define VBOX_HV_SYS_REG_ACTLR_EL1 (hv_sys_reg_t)0xc081 + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 150000 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + typedef hv_vm_config_t FN_HV_VM_CONFIG_CREATE(void); typedef hv_return_t FN_HV_VM_CONFIG_GET_EL2_SUPPORTED(bool *el2_supported); typedef hv_return_t FN_HV_VM_CONFIG_GET_EL2_ENABLED(hv_vm_config_t config, bool *el2_enabled); @@ -193,6 +198,10 @@ typedef hv_return_t FN_HV_GIC_SET_REDISTRIBUTOR_REG(hv_vcpu_t vcpu, hv_gic_r typedef hv_return_t FN_HV_GIC_GET_INTID(hv_gic_intid_t interrupt, uint32_t *intid); +#if MAC_OS_X_VERSION_MIN_REQUIRED < 150000 +# pragma clang diagnostic pop +#endif + /** * ARM PSCI Affinity info arguments. @@ -559,7 +568,7 @@ static const struct uint32_t offCpumCtx; } s_aCpumSysRegsSequioa[] = { - { HV_SYS_REG_ACTLR_EL1, CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Actlr.u64) } + { VBOX_HV_SYS_REG_ACTLR_EL1, CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Actlr.u64) } }; /** EL2 support system registers. */ static const struct @@ -1045,7 +1054,7 @@ static int nemR3DarwinCopyStateFromHv(PVMCC pVM, PVMCPUCC pVCpu, uint64_t fWhat) * https://github.com/AsahiLinux/docs/blob/main/docs/hw/cpu/system-registers.md#actlr_el1-arm-standard-not-standard * But the ones being set are not documented. Maybe they are always set by the Hypervisor... */ - if (s_aCpumSysRegsSequioa[i].enmHvReg == HV_SYS_REG_ACTLR_EL1) + if (s_aCpumSysRegsSequioa[i].enmHvReg == VBOX_HV_SYS_REG_ACTLR_EL1) *pu64 &= RT_BIT_64(1); } } @@ -3476,4 +3485,3 @@ VMM_INT_DECL(uint32_t) NEMHCGetFeatures(PVMCC pVM) * * @todo Add notes as the implementation progresses... */ -