From a8b89107a536c05b1564a633bf503c7ddf8f34f5 Mon Sep 17 00:00:00 2001 From: Tobias Hieta Date: Fri, 6 Sep 2024 14:29:16 +0200 Subject: [PATCH] [macOS] Refactor Platform and Compiler settings for Apple Platforms This commit introduces two new global settings classes. ApplePlatformSettings and ClangForAppleSettings. The goal is to make the compiler path and SDK path more configurable and able to be overriden from nuget packages that contain a custom compiler and sdk. This introduces a breaking change in the form of deprecating Options.Xcode.SDKRoot this has been split up per platform, meaning that if you want to change the SDK root you need to now set ApplePlatform.Settings.MacOSSDKPath ApplePlatform.Settings.IPhoneOSSDKPath etc. This also introduces the ClangForApple.Settings.IsAppleClang which can be used to check if the current compiler is the apple version of clang or a custom one. --- .../Apple/ApplePlatformSettings.cs | 102 ++++++++++++++++++ .../Apple/BaseApplePlatform.cs | 28 ++--- .../Apple/ClangForAppleSettings.cs | 90 ++++++++++++++++ .../Apple/MacCatalystPlatform.cs | 12 +-- .../Apple/MacOsPlatform.cs | 15 +-- .../Apple/iOsPlatform.cs | 12 +-- .../Apple/tvOsPlatform.cs | 12 +-- .../Apple/watchOsPlatform.cs | 12 +-- Sharpmake/Options.XCode.cs | 1 + 9 files changed, 212 insertions(+), 72 deletions(-) create mode 100644 Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ApplePlatformSettings.cs create mode 100644 Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ClangForAppleSettings.cs diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ApplePlatformSettings.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ApplePlatformSettings.cs new file mode 100644 index 000000000..9f1942146 --- /dev/null +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ApplePlatformSettings.cs @@ -0,0 +1,102 @@ +// Copyright (c) Ubisoft. All Rights Reserved. +// Licensed under the Apache 2.0 License. See LICENSE.md in the project root for license information. + +using System.IO; + +namespace Sharpmake +{ + public static class ApplePlatform + { + public static class Settings + { + private static string s_xcodeDevPath; + public static string XCodeDeveloperPath + { + get + { + if (s_xcodeDevPath == null && Util.GetExecutingPlatform() != Platform.mac) + throw new Error("ApplePlatform.Settings.XCodeDeveloperPath must be defined when not running on macOS"); + + return s_xcodeDevPath ?? (s_xcodeDevPath = "/Applications/Xcode.app/Contents/Developer"); + } + + set + { + s_xcodeDevPath = Util.PathMakeStandard(value); + } + } + + private static string s_macOSSDKPath; + public static string MacOSSDKPath + { + get + { + return s_macOSSDKPath ?? (s_macOSSDKPath = $"{XCodeDeveloperPath}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"); + } + + set + { + s_macOSSDKPath = Util.PathMakeStandard(value); + } + } + + private static string s_iphoneOSSDKPath; + public static string IPhoneOSSDkPath + { + get + { + return s_iphoneOSSDKPath ?? (s_iphoneOSSDKPath = $"{XCodeDeveloperPath}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"); + } + + set + { + s_iphoneOSSDKPath = Util.PathMakeStandard(value); + } + } + + + private static string s_macCatalystSDKPath; + public static string MacCatalystSDKPath + { + get + { + return s_macCatalystSDKPath ?? (s_macCatalystSDKPath = $"{XCodeDeveloperPath}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"); + } + + set + { + s_macCatalystSDKPath = Util.PathMakeStandard(value); + } + } + + private static string s_tvOSSDKPath; + public static string TVOSSDKPath + { + get + { + return s_tvOSSDKPath ?? (s_tvOSSDKPath = $"{XCodeDeveloperPath}/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk"); + } + + set + { + s_tvOSSDKPath = Util.PathMakeStandard(value); + } + } + + private static string s_watchOSSDKPath; + public static string WatchOSSDKPath + { + get + { + return s_watchOSSDKPath ?? (s_watchOSSDKPath = $"{XCodeDeveloperPath}/Platforms/watchOS.platform/Developer/SDKs/watchOS.sdk"); + } + + set + { + s_watchOSSDKPath = Util.PathMakeStandard(value); + } + } + + } + } +} diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs index 3c50e26f4..5a3e7464d 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/BaseApplePlatform.cs @@ -19,8 +19,6 @@ public abstract partial class BaseApplePlatform , IClangPlatformBff , IPlatformVcxproj // TODO: this is really sad, nuke it { - protected const string XCodeDeveloperFolder = "/Applications/Xcode.app/Contents/Developer"; - public abstract Platform SharpmakePlatform { get; } #region IPlatformDescriptor @@ -36,7 +34,8 @@ public bool IsLinkerInvokedViaCompiler { bool isLinkerInvokedViaCompiler = false; var fastBuildSettings = PlatformRegistry.Get(SharpmakePlatform); - fastBuildSettings.LinkerInvokedViaCompiler.TryGetValue(DevEnv.xcode, out isLinkerInvokedViaCompiler); + if (fastBuildSettings.LinkerInvokedViaCompiler.TryGetValue(DevEnv.xcode, out bool isLinkerInvokedViaCompilerOverride)) + isLinkerInvokedViaCompiler = isLinkerInvokedViaCompilerOverride; return isLinkerInvokedViaCompiler; } } @@ -232,7 +231,7 @@ private CompilerSettings GetMasterCompilerSettings(IDictionary(conf); - Options.XCode.Compiler.SDKRoot sdkRoot = Options.GetObject(conf); - if (sdkRoot != null) - options["SDKRoot"] = sdkRoot.Value; - context.SelectOption( Options.Option(Options.XCode.Compiler.SkipInstall.Disable, () => options["SkipInstall"] = "NO"), Options.Option(Options.XCode.Compiler.SkipInstall.Enable, () => options["SkipInstall"] = "YES") @@ -1199,8 +1190,7 @@ public void SelectCustomSysLibRoot(IGenerationContext context, string defaultSdk var conf = context.Configuration; var cmdLineOptions = context.CommandLineOptions; - Options.XCode.Compiler.SDKRoot customSdkRoot = Options.GetObject(conf); - cmdLineOptions["SysLibRoot"] = (IsLinkerInvokedViaCompiler ? "-isysroot " : "-syslibroot ") + (customSdkRoot?.Value ?? defaultSdkRoot); + cmdLineOptions["SysLibRoot"] = (IsLinkerInvokedViaCompiler ? "-isysroot " : "-syslibroot ") + defaultSdkRoot; } public virtual void SelectLinkerOptions(IGenerationContext context) diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ClangForAppleSettings.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ClangForAppleSettings.cs new file mode 100644 index 000000000..1035912bd --- /dev/null +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/ClangForAppleSettings.cs @@ -0,0 +1,90 @@ +// Copyright (c) Ubisoft. All Rights Reserved. +// Licensed under the Apache 2.0 License. See LICENSE.md in the project root for license information. + +using System.IO; + +namespace Sharpmake +{ + public static class ClangForApple + { + public static string GetClangExecutablePath() + { + return Path.Combine(Settings.LLVMInstallDir, "bin"); + } + + public static string GetClangIncludePath() + { + return Path.Combine(Settings.LLVMInstallDir, "lib", "clang", Settings.ClangVersion, "include"); + } + + public static string GetClangLibraryPath() + { + return Path.Combine(Settings.LLVMInstallDir, "lib", "clang", Settings.ClangVersion, "lib", "darwin"); + } + + public static class Settings + { + private static bool s_isAppleClang = true; + public static bool IsAppleClang + { + get + { + if (Util.GetExecutingPlatform() == Platform.win64) + return false; + return s_isAppleClang; + } + set + { + if (value && Util.GetExecutingPlatform() == Platform.win64) + throw new Error("Apple clang doesn't work on Windows"); + s_isAppleClang = value; + } + } + + private static string s_llvmInstallDir; + public static string LLVMInstallDir + { + get + { + if (!string.IsNullOrEmpty(s_llvmInstallDir)) + return s_llvmInstallDir; + + if (Util.GetExecutingPlatform() == Platform.win64) + return ClangForWindows.Settings.LLVMInstallDir; + + return $"{ApplePlatform.Settings.XCodeDeveloperPath}/Toolchains/XcodeDefault.xctoolchain/usr"; + } + + set + { + s_llvmInstallDir = Util.PathMakeStandard(value); + } + } + + private static string s_clangVersion; + public static string ClangVersion + { + get + { + if (s_clangVersion == null) + { + if (Util.DirectoryExists(LLVMInstallDir)) + s_clangVersion = Util.GetClangVersionFromLLVMInstallDir(LLVMInstallDir); + else + throw new Error($"ClangForApple.Settings.LLVMInstallDir is pointing to {LLVMInstallDir}, which doesn't exists."); + } + return s_clangVersion; + } + + set + { + s_clangVersion = value; + if (!Util.DirectoryExists(Path.Combine(LLVMInstallDir, "lib", "clang", s_clangVersion))) + throw new Error($"Cannot find required files for Clang {s_clangVersion} in {LLVMInstallDir}"); + } + } + } + } +} + + diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacCatalystPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacCatalystPlatform.cs index fc6512db6..12f702afa 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacCatalystPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacCatalystPlatform.cs @@ -55,14 +55,7 @@ public override void SelectCompilerOptions(IGenerationContext context) // Sysroot options["SDKRoot"] = "iphoneos"; - cmdLineOptions["SDKRoot"] = $"-isysroot {XCodeDeveloperFolder}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"; - Options.XCode.Compiler.SDKRoot customSdkRoot = Options.GetObject(conf); - if (customSdkRoot != null) - { - // Xcode doesn't accept the customized sdk path as SDKRoot - //options["SDKRoot"] = customSdkRoot.Value; - cmdLineOptions["SDKRoot"] = $"-isysroot {customSdkRoot.Value}"; - } + cmdLineOptions["SDKRoot"] = $"-isysroot {ApplePlatform.Settings.MacCatalystSDKPath}"; // Target options["MacOSDeploymentTarget"] = FileGeneratorUtilities.RemoveLineTag; @@ -265,8 +258,7 @@ public override void SelectLinkerOptions(IGenerationContext context) base.SelectLinkerOptions(context); // Sysroot - var defaultSdkRoot = $"{XCodeDeveloperFolder}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"; - SelectCustomSysLibRoot(context, defaultSdkRoot); + SelectCustomSysLibRoot(context, ApplePlatform.Settings.MacCatalystSDKPath); } } } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacOsPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacOsPlatform.cs index d96eabecc..8b67b202b 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacOsPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/MacOsPlatform.cs @@ -48,17 +48,7 @@ public override void SelectCompilerOptions(IGenerationContext context) // Sysroot options["SDKRoot"] = "macosx"; - cmdLineOptions["SDKRoot"] = $"-isysroot {XCodeDeveloperFolder}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"; - Options.XCode.Compiler.SDKRoot customSdkRoot = Options.GetObject(conf); - if (customSdkRoot != null) - { - // Xcode doesn't accept the customized sdk path as SDKRoot - //options["SDKRoot"] = customSdkRoot.Value; - if (!string.IsNullOrEmpty(customSdkRoot.Value)) - cmdLineOptions["SDKRoot"] = $"-isysroot {customSdkRoot.Value}"; - else - cmdLineOptions["SDKRoot"] = FileGeneratorUtilities.RemoveLineTag; - } + cmdLineOptions["SDKRoot"] = $"-isysroot {ApplePlatform.Settings.MacOSSDKPath}"; // Target options["IPhoneOSDeploymentTarget"] = FileGeneratorUtilities.RemoveLineTag; @@ -126,8 +116,7 @@ public override void SelectLinkerOptions(IGenerationContext context) base.SelectLinkerOptions(context); // Sysroot - var defaultSdkRoot = $"{XCodeDeveloperFolder}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"; - SelectCustomSysLibRoot(context, defaultSdkRoot); + SelectCustomSysLibRoot(context, ApplePlatform.Settings.MacOSSDKPath); } } } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/iOsPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/iOsPlatform.cs index 39d61cd69..3cabf5035 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/iOsPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/iOsPlatform.cs @@ -54,14 +54,7 @@ public override void SelectCompilerOptions(IGenerationContext context) // Sysroot options["SDKRoot"] = "iphoneos"; - cmdLineOptions["SDKRoot"] = $"-isysroot {XCodeDeveloperFolder}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"; - Options.XCode.Compiler.SDKRoot customSdkRoot = Options.GetObject(conf); - if (customSdkRoot != null) - { - // Xcode doesn't accept the customized sdk path as SDKRoot - //options["SDKRoot"] = customSdkRoot.Value; - cmdLineOptions["SDKRoot"] = $"-isysroot {customSdkRoot.Value}"; - } + cmdLineOptions["SDKRoot"] = $"-isysroot {ApplePlatform.Settings.IPhoneOSSDkPath}"; // Target options["MacOSDeploymentTarget"] = FileGeneratorUtilities.RemoveLineTag; @@ -237,8 +230,7 @@ public override void SelectLinkerOptions(IGenerationContext context) base.SelectLinkerOptions(context); // Sysroot - var defaultSdkRoot = $"{XCodeDeveloperFolder}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"; - SelectCustomSysLibRoot(context, defaultSdkRoot); + SelectCustomSysLibRoot(context, ApplePlatform.Settings.IPhoneOSSDkPath); } } } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/tvOsPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/tvOsPlatform.cs index 5af56f453..7a72a83e5 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/tvOsPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/tvOsPlatform.cs @@ -55,14 +55,7 @@ public override void SelectCompilerOptions(IGenerationContext context) // Sysroot options["SDKRoot"] = "appletvos"; - cmdLineOptions["SDKRoot"] = $"-isysroot {XCodeDeveloperFolder}/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk"; - Options.XCode.Compiler.SDKRoot customSdkRoot = Options.GetObject(conf); - if (customSdkRoot != null) - { - // Xcode doesn't accept the customized sdk path as SDKRoot - //options["SDKRoot"] = customSdkRoot.Value; - cmdLineOptions["SDKRoot"] = $"-isysroot {customSdkRoot.Value}"; - } + cmdLineOptions["SDKRoot"] = $"-isysroot {ApplePlatform.Settings.TVOSSDKPath}"; // Target options["MacOSDeploymentTarget"] = FileGeneratorUtilities.RemoveLineTag; @@ -98,8 +91,7 @@ public override void SelectLinkerOptions(IGenerationContext context) base.SelectLinkerOptions(context); // Sysroot - var defaultSdkRoot = $"{XCodeDeveloperFolder}/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk"; - SelectCustomSysLibRoot(context, defaultSdkRoot); + SelectCustomSysLibRoot(context, ApplePlatform.Settings.TVOSSDKPath); } } } diff --git a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/watchOsPlatform.cs b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/watchOsPlatform.cs index ab62c723d..1e77596b9 100644 --- a/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/watchOsPlatform.cs +++ b/Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/watchOsPlatform.cs @@ -54,14 +54,7 @@ public override void SelectCompilerOptions(IGenerationContext context) // Sysroot options["SDKRoot"] = "watchos"; - cmdLineOptions["SDKRoot"] = $"-isysroot {XCodeDeveloperFolder}/Platforms/watchOS.platform/Developer/SDKs/watchOS.sdk"; - Options.XCode.Compiler.SDKRoot customSdkRoot = Options.GetObject(conf); - if (customSdkRoot != null) - { - // Xcode doesn't accept the customized sdk path as SDKRoot - //options["SDKRoot"] = customSdkRoot.Value; - cmdLineOptions["SDKRoot"] = $"-isysroot {customSdkRoot.Value}"; - } + cmdLineOptions["SDKRoot"] = $"-isysroot {ApplePlatform.Settings.WatchOSSDKPath}"; // Target options["MacOSDeploymentTarget"] = FileGeneratorUtilities.RemoveLineTag; @@ -89,8 +82,7 @@ public override void SelectLinkerOptions(IGenerationContext context) base.SelectLinkerOptions(context); // Sysroot - var defaultSdkRoot = $"{XCodeDeveloperFolder}/Platforms/watchOS.platform/Developer/SDKs/watchOS.sdk"; - SelectCustomSysLibRoot(context, defaultSdkRoot); + SelectCustomSysLibRoot(context, ApplePlatform.Settings.WatchOSSDKPath); } } } diff --git a/Sharpmake/Options.XCode.cs b/Sharpmake/Options.XCode.cs index 4a591a684..7dee64334 100644 --- a/Sharpmake/Options.XCode.cs +++ b/Sharpmake/Options.XCode.cs @@ -450,6 +450,7 @@ public enum RTTI Enable } + [Obsolete("Deprecated and Ignored. Use `ApplePlatform.Settings.MacOSSDKPath` instead.", error: true)] public class SDKRoot { public string Value;