Skip to content

Commit

Permalink
[macOS] Refactor Platform and Compiler settings for Apple Platforms
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tru authored and sylvain-audi committed Sep 17, 2024
1 parent 25d80ec commit a8b8910
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,7 +34,8 @@ public bool IsLinkerInvokedViaCompiler
{
bool isLinkerInvokedViaCompiler = false;
var fastBuildSettings = PlatformRegistry.Get<IFastBuildCompilerSettings>(SharpmakePlatform);
fastBuildSettings.LinkerInvokedViaCompiler.TryGetValue(DevEnv.xcode, out isLinkerInvokedViaCompiler);
if (fastBuildSettings.LinkerInvokedViaCompiler.TryGetValue(DevEnv.xcode, out bool isLinkerInvokedViaCompilerOverride))
isLinkerInvokedViaCompiler = isLinkerInvokedViaCompilerOverride;
return isLinkerInvokedViaCompiler;
}
}
Expand Down Expand Up @@ -232,7 +231,7 @@ private CompilerSettings GetMasterCompilerSettings(IDictionary<string, CompilerS

string binPath;
if (!fastBuildSettings.BinPath.TryGetValue(devEnv, out binPath))
binPath = $"{XCodeDeveloperFolder}/Toolchains/XcodeDefault.xctoolchain/usr/bin";
binPath = ClangForApple.GetClangExecutablePath();

string pathToCompiler = Util.GetCapitalizedPath(Util.PathGetAbsolute(projectRootPath, binPath));

Expand Down Expand Up @@ -271,23 +270,19 @@ private void SetConfiguration(CompilerSettings compilerSettings, string compiler
if (!fastBuildSettings.LinkerPath.TryGetValue(devEnv, out linkerPath))
linkerPath = binPath;

string exeExtension = (Util.GetExecutingPlatform() == Platform.win64) ? ".exe" : "";
string linkerExe;
if (!fastBuildSettings.LinkerExe.TryGetValue(devEnv, out linkerExe))
{
if (Util.GetExecutingPlatform() == Platform.win64)
linkerExe = IsLinkerInvokedViaCompiler ? "clang++.exe" : "ld64.lld.exe";
if (IsLinkerInvokedViaCompiler)
linkerExe = "clang++" + exeExtension;
else
linkerExe = IsLinkerInvokedViaCompiler ? "clang++" : "ld";
linkerExe = ClangForApple.Settings.IsAppleClang ? "ld" : "ld64.lld" + exeExtension;
}

string librarianExe;
if (!fastBuildSettings.LibrarianExe.TryGetValue(devEnv, out librarianExe))
{
if (Util.GetExecutingPlatform() == Platform.win64)
librarianExe = "llvm-ar.exe";
else
librarianExe = "ar";
}
librarianExe = ClangForApple.Settings.IsAppleClang ? "ar" : "llvm-ar" + exeExtension;

configurations.Add(configName,
new CompilerSettings.Configuration(
Expand Down Expand Up @@ -876,10 +871,6 @@ public virtual void SelectCompilerOptions(IGenerationContext context)

options["ProvisioningProfile"] = Options.StringOption.Get<Options.XCode.Compiler.ProvisioningProfile>(conf);

Options.XCode.Compiler.SDKRoot sdkRoot = Options.GetObject<Options.XCode.Compiler.SDKRoot>(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")
Expand Down Expand Up @@ -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<Options.XCode.Compiler.SDKRoot>(conf);
cmdLineOptions["SysLibRoot"] = (IsLinkerInvokedViaCompiler ? "-isysroot " : "-syslibroot ") + (customSdkRoot?.Value ?? defaultSdkRoot);
cmdLineOptions["SysLibRoot"] = (IsLinkerInvokedViaCompiler ? "-isysroot " : "-syslibroot ") + defaultSdkRoot;
}

public virtual void SelectLinkerOptions(IGenerationContext context)
Expand Down
Original file line number Diff line number Diff line change
@@ -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}");
}
}
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -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<Options.XCode.Compiler.SDKRoot>(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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Options.XCode.Compiler.SDKRoot>(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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
12 changes: 2 additions & 10 deletions Sharpmake.Platforms/Sharpmake.CommonPlatforms/Apple/iOsPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Options.XCode.Compiler.SDKRoot>(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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Options.XCode.Compiler.SDKRoot>(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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
Loading

0 comments on commit a8b8910

Please sign in to comment.