@@ -175,6 +175,27 @@ public final class UserToolchain: Toolchain {
175175 return try getTool ( name, binDirectories: envSearchPaths, fileSystem: fileSystem)
176176 }
177177
178+ private static func getTargetInfo( swiftCompiler: AbsolutePath ) throws -> JSON {
179+ // Call the compiler to get the target info JSON.
180+ let compilerOutput : String
181+ do {
182+ let result = try AsyncProcess . popen ( args: swiftCompiler. pathString, " -print-target-info " )
183+ compilerOutput = try result. utf8Output ( ) . spm_chomp ( )
184+ } catch {
185+ throw InternalError (
186+ " Failed to load target info ( \( error. interpolationDescription) ) "
187+ )
188+ }
189+ // Parse the compiler's JSON output.
190+ do {
191+ return try JSON ( string: compilerOutput)
192+ } catch {
193+ throw InternalError (
194+ " Failed to parse target info ( \( error. interpolationDescription) ). \n Raw compiler output: \( compilerOutput) "
195+ )
196+ }
197+ }
198+
178199 private static func getTargetInfo( swiftCompiler: AbsolutePath ) async throws -> JSON {
179200 // Call the compiler to get the target info JSON.
180201 let compilerOutput : String
@@ -666,6 +687,218 @@ public final class UserToolchain: Toolchain {
666687 case custom( searchPaths: [ AbsolutePath ] , useXcrun: Bool = true )
667688 }
668689
690+ @available ( * , deprecated, message: " Use the async alternative " )
691+ public init (
692+ swiftSDK: SwiftSDK ,
693+ environment: Environment = . current,
694+ searchStrategy: SearchStrategy = . default,
695+ customTargetInfo: JSON ? = nil ,
696+ customLibrariesLocation: ToolchainConfiguration . SwiftPMLibrariesLocation ? = nil ,
697+ customInstalledSwiftPMConfiguration: InstalledSwiftPMConfiguration ? = nil ,
698+ fileSystem: any FileSystem = localFileSystem
699+ ) throws {
700+ self . swiftSDK = swiftSDK
701+ self . environment = environment
702+
703+ switch searchStrategy {
704+ case . default:
705+ // Get the search paths from PATH.
706+ self . envSearchPaths = getEnvSearchPaths (
707+ pathString: environment [ . path] ,
708+ currentWorkingDirectory: fileSystem. currentWorkingDirectory
709+ )
710+ self . useXcrun = !( fileSystem is InMemoryFileSystem )
711+ case . custom( let searchPaths, let useXcrun) :
712+ self . envSearchPaths = searchPaths
713+ self . useXcrun = useXcrun
714+ }
715+
716+ let swiftCompilers = try UserToolchain . determineSwiftCompilers (
717+ binDirectories: swiftSDK. toolset. rootPaths,
718+ useXcrun: self . useXcrun,
719+ environment: environment,
720+ searchPaths: self . envSearchPaths,
721+ fileSystem: fileSystem
722+ )
723+ self . swiftCompilerPath = swiftCompilers. compile
724+ self . architectures = swiftSDK. architectures
725+
726+ if let customInstalledSwiftPMConfiguration {
727+ self . installedSwiftPMConfiguration = customInstalledSwiftPMConfiguration
728+ } else {
729+ let path = swiftCompilerPath. parentDirectory. parentDirectory. appending ( components: [
730+ " share " , " pm " , " config.json " ,
731+ ] )
732+ self . installedSwiftPMConfiguration = try Self . loadJSONResource (
733+ config: path,
734+ type: InstalledSwiftPMConfiguration . self,
735+ default: InstalledSwiftPMConfiguration . default)
736+ }
737+
738+ var triple : Basics . Triple
739+ if let targetTriple = swiftSDK. targetTriple {
740+ self . targetInfo = nil
741+ triple = targetTriple
742+ } else {
743+ // targetInfo from the compiler
744+ let targetInfo : JSON
745+ if let customTargetInfo {
746+ targetInfo = customTargetInfo
747+ } else {
748+ targetInfo = try Self . getTargetInfo ( swiftCompiler: swiftCompilers. compile)
749+ }
750+ self . targetInfo = targetInfo
751+ triple = try swiftSDK. targetTriple ?? Self . getHostTriple ( targetInfo: targetInfo, versioned: false )
752+ }
753+
754+ // Change the triple to the specified arch if there's exactly one of them.
755+ // The Triple property is only looked at by the native build system currently.
756+ if let architectures = self . architectures, architectures. count == 1 {
757+ let components = triple. tripleString. drop ( while: { $0 != " - " } )
758+ triple = try Triple ( architectures [ 0 ] + components)
759+ }
760+
761+ self . targetTriple = triple
762+
763+ var swiftCompilerFlags : [ String ] = [ ]
764+ var extraLinkerFlags : [ String ] = [ ]
765+
766+ let swiftTestingPath : AbsolutePath ? = try Self . deriveSwiftTestingPath (
767+ derivedSwiftCompiler: swiftCompilers. compile,
768+ swiftSDK: self . swiftSDK,
769+ triple: triple,
770+ environment: environment,
771+ fileSystem: fileSystem
772+ )
773+
774+ if triple. isMacOSX, let swiftTestingPath {
775+ // Swift Testing is a framework (e.g. from CommandLineTools) so use -F.
776+ if swiftTestingPath. extension == " framework " {
777+ swiftCompilerFlags += [ " -F " , swiftTestingPath. pathString]
778+
779+ // Otherwise Swift Testing is assumed to be a swiftmodule + library, so use -I and -L.
780+ } else {
781+ swiftCompilerFlags += [
782+ " -I " , swiftTestingPath. pathString,
783+ " -L " , swiftTestingPath. pathString,
784+ ]
785+ }
786+ }
787+
788+ // Specify the plugin path for Swift Testing's macro plugin if such a
789+ // path exists in this toolchain.
790+ if let swiftTestingPluginPath = Self . deriveSwiftTestingPluginPath (
791+ derivedSwiftCompiler: swiftCompilers. compile,
792+ fileSystem: fileSystem
793+ ) {
794+ swiftCompilerFlags += [ " -plugin-path " , swiftTestingPluginPath. pathString]
795+ }
796+
797+ swiftCompilerFlags += try Self . deriveSwiftCFlags (
798+ triple: triple,
799+ swiftSDK: swiftSDK,
800+ environment: environment,
801+ fileSystem: fileSystem
802+ )
803+
804+ extraLinkerFlags += swiftSDK. toolset. knownTools [ . linker] ? . extraCLIOptions ?? [ ]
805+
806+ self . extraFlags = BuildFlags (
807+ cCompilerFlags: swiftSDK. toolset. knownTools [ . cCompiler] ? . extraCLIOptions ?? [ ] ,
808+ cxxCompilerFlags: swiftSDK. toolset. knownTools [ . cxxCompiler] ? . extraCLIOptions ?? [ ] ,
809+ swiftCompilerFlags: swiftCompilerFlags,
810+ linkerFlags: extraLinkerFlags,
811+ xcbuildFlags: swiftSDK. toolset. knownTools [ . xcbuild] ? . extraCLIOptions ?? [ ] )
812+
813+ self . includeSearchPaths = swiftSDK. pathsConfiguration. includeSearchPaths ?? [ ]
814+ self . librarySearchPaths = swiftSDK. pathsConfiguration. includeSearchPaths ?? [ ]
815+
816+ self . librarianPath = try swiftSDK. toolset. knownTools [ . librarian] ? . path ?? UserToolchain . determineLibrarian (
817+ triple: triple,
818+ binDirectories: swiftSDK. toolset. rootPaths,
819+ useXcrun: useXcrun,
820+ environment: environment,
821+ searchPaths: envSearchPaths,
822+ extraSwiftFlags: self . extraFlags. swiftCompilerFlags,
823+ fileSystem: fileSystem
824+ )
825+
826+ if let sdkDir = swiftSDK. pathsConfiguration. sdkRootPath {
827+ let sysrootFlags = [ triple. isDarwin ( ) ? " -isysroot " : " --sysroot " , sdkDir. pathString]
828+ self . extraFlags. cCompilerFlags. insert ( contentsOf: sysrootFlags, at: 0 )
829+ }
830+
831+ if triple. isWindows ( ) {
832+ if let root = environment. windowsSDKRoot {
833+ if let settings = WindowsSDKSettings (
834+ reading: root. appending ( " SDKSettings.plist " ) ,
835+ observabilityScope: nil ,
836+ filesystem: fileSystem
837+ ) {
838+ switch settings. defaults. runtime {
839+ case . multithreadedDebugDLL:
840+ // Defines _DEBUG, _MT, and _DLL
841+ // Linker uses MSVCRTD.lib
842+ self . extraFlags. cCompilerFlags += [
843+ " -D_DEBUG " ,
844+ " -D_MT " ,
845+ " -D_DLL " ,
846+ " -Xclang " ,
847+ " --dependent-lib=msvcrtd " ,
848+ ]
849+
850+ case . multithreadedDLL:
851+ // Defines _MT, and _DLL
852+ // Linker uses MSVCRT.lib
853+ self . extraFlags. cCompilerFlags += [ " -D_MT " , " -D_DLL " , " -Xclang " , " --dependent-lib=msvcrt " ]
854+
855+ case . multithreadedDebug:
856+ // Defines _DEBUG, and _MT
857+ // Linker uses LIBCMTD.lib
858+ self . extraFlags. cCompilerFlags += [ " -D_DEBUG " , " -D_MT " , " -Xclang " , " --dependent-lib=libcmtd " ]
859+
860+ case . multithreaded:
861+ // Defines _MT
862+ // Linker uses LIBCMT.lib
863+ self . extraFlags. cCompilerFlags += [ " -D_MT " , " -Xclang " , " --dependent-lib=libcmt " ]
864+ }
865+ }
866+ }
867+ }
868+
869+ let swiftPMLibrariesLocation = try customLibrariesLocation ?? Self . deriveSwiftPMLibrariesLocation (
870+ swiftCompilerPath: swiftCompilerPath,
871+ swiftSDK: swiftSDK,
872+ environment: environment,
873+ fileSystem: fileSystem
874+ )
875+
876+ let xctestPath : AbsolutePath ?
877+ if case . custom( _, let useXcrun) = searchStrategy, !useXcrun {
878+ xctestPath = nil
879+ } else {
880+ xctestPath = try Self . deriveXCTestPath (
881+ swiftSDK: self . swiftSDK,
882+ triple: triple,
883+ environment: environment,
884+ fileSystem: fileSystem
885+ )
886+ }
887+
888+ self . configuration = . init(
889+ librarianPath: librarianPath,
890+ swiftCompilerPath: swiftCompilers. manifest,
891+ swiftCompilerFlags: self . extraFlags. swiftCompilerFlags,
892+ swiftCompilerEnvironment: environment,
893+ swiftPMLibrariesLocation: swiftPMLibrariesLocation,
894+ sdkRootPath: self . swiftSDK. pathsConfiguration. sdkRootPath,
895+ xctestPath: xctestPath,
896+ swiftTestingPath: swiftTestingPath
897+ )
898+
899+ self . fileSystem = fileSystem
900+ }
901+
669902 public init (
670903 swiftSDK: SwiftSDK ,
671904 environment: Environment = . current,
0 commit comments