@@ -531,39 +531,39 @@ public final class ManifestLoader: ManifestLoaderProtocol {
531
531
532
532
// Compute the path to runtime we need to load.
533
533
let runtimePath = self . runtimePath ( for: toolsVersion)
534
- let interpreterFlags = self . interpreterFlags ( for: toolsVersion)
534
+ let compilerFlags = self . compilerFlags ( for: toolsVersion)
535
535
536
536
// FIXME: Workaround for the module cache bug that's been haunting Swift CI
537
537
// <rdar://problem/48443680>
538
538
let moduleCachePath = ProcessEnv . vars [ " SWIFTPM_MODULECACHE_OVERRIDE " ] ?? ProcessEnv . vars [ " SWIFTPM_TESTS_MODULECACHE " ]
539
539
540
- var cmd = [ String] ( )
541
- #if os(macOS)
542
- // If enabled, use sandbox-exec on macOS. This provides some safety against
543
- // arbitrary code execution when parsing manifest files. We only allow
544
- // the permissions which are absolutely necessary for manifest parsing.
545
- if isManifestSandboxEnabled {
546
- let cacheDirs = [
547
- cacheDir,
548
- moduleCachePath. map { AbsolutePath ( $0) }
549
- ] . compactMap { $0}
550
- cmd += [ " sandbox-exec " , " -p " , sandboxProfile ( cacheDirs) ]
551
- }
552
- #endif
540
+ var cmd : [ String ] = [ ]
553
541
cmd += [ resources. swiftCompiler. pathString]
554
- cmd += [ " --driver-mode=swift " ]
555
542
cmd += verbosity. ccArgs
556
543
557
544
// If we got the binDir that means we could be developing SwiftPM in Xcode
558
545
// which produces a framework for dynamic package products.
559
- let runtimeFrameworkPath = runtimePath. appending ( component: " PackageFrameworks " )
560
- if resources. binDir != nil , localFileSystem. exists ( runtimeFrameworkPath) {
561
- cmd += [ " -F " , runtimeFrameworkPath. pathString, " -framework " , " PackageDescription " ]
546
+ let packageFrameworkPath = runtimePath. appending ( component: " PackageFrameworks " )
547
+ if resources. binDir != nil , localFileSystem. exists ( packageFrameworkPath) {
548
+ cmd += [
549
+ " -F " , packageFrameworkPath. pathString,
550
+ " -framework " , " PackageDescription " ,
551
+ " -Xlinker " , " -rpath " , " -Xlinker " , packageFrameworkPath. pathString,
552
+ ]
562
553
} else {
563
- cmd += [ " -L " , runtimePath. pathString, " -lPackageDescription " ]
554
+ #if os(macOS)
555
+ let rpath = resources. libDir. parentDirectory
556
+ #else
557
+ let rpath = runtimePath
558
+ #endif
559
+ cmd += [
560
+ " -L " , runtimePath. pathString,
561
+ " -lPackageDescription " ,
562
+ " -Xlinker " , " -rpath " , " -Xlinker " , rpath. pathString
563
+ ]
564
564
}
565
565
566
- cmd += interpreterFlags
566
+ cmd += compilerFlags
567
567
if let moduleCachePath = moduleCachePath {
568
568
cmd += [ " -module-cache-path " , moduleCachePath]
569
569
}
@@ -579,36 +579,50 @@ public final class ManifestLoader: ManifestLoaderProtocol {
579
579
580
580
cmd += [ manifestPath. pathString]
581
581
582
- // Create and open a temporary file to write json to.
583
582
try withTemporaryFile { file in
583
+ // Set path to compiled manifest executable.
584
+ cmd += [ " -o " , file. path. pathString]
585
+
586
+ try Process . popen ( arguments: cmd)
587
+
588
+ // Compile the manifest.
589
+ let compilerResult = try Process . popen ( arguments: cmd)
590
+ let compilerOutput = try ( compilerResult. utf8Output ( ) + compilerResult. utf8stderrOutput ( ) ) . spm_chuzzle ( )
591
+ manifestParseResult. compilerOutput = compilerOutput
592
+
593
+ // Return now if there was an error.
594
+ if compilerResult. exitStatus != . terminated( code: 0 ) {
595
+ return
596
+ }
597
+
584
598
// Pass the fd in arguments.
585
- cmd += [ " -fileno " , " \( file. fileHandle. fileDescriptor) " ]
586
-
587
- // Prefer swiftinterface if both swiftmodule and swiftinterface files are present.
588
- //
589
- // This will avoid failures during incremental builds when the
590
- // slate swiftmodule file is still present from the previous
591
- // install. We should be able to remove this after some
592
- // transition period.
593
- var env = ProcessEnv . vars
599
+ cmd = [ file. path. pathString, " -fileno " , " 1 " ]
600
+
594
601
#if os(macOS)
595
- env [ " SWIFT_FORCE_MODULE_LOADING " ] = " prefer-parseable "
602
+ // If enabled, use sandbox-exec on macOS. This provides some safety against
603
+ // arbitrary code execution when parsing manifest files. We only allow
604
+ // the permissions which are absolutely necessary for manifest parsing.
605
+ if isManifestSandboxEnabled {
606
+ let cacheDirectories = [
607
+ cacheDir,
608
+ moduleCachePath. map ( { AbsolutePath ( $0) } )
609
+ ] . compactMap ( { $0 } )
610
+ let profile = sandboxProfile ( toolsVersion: toolsVersion, cacheDirectories: cacheDirectories)
611
+ cmd += [ " sandbox-exec " , " -p " , profile]
612
+ }
596
613
#endif
597
614
598
615
// Run the command.
599
- let result = try Process . popen ( arguments: cmd, environment: env)
600
- let output = try ( result. utf8Output ( ) + result. utf8stderrOutput ( ) ) . spm_chuzzle ( )
601
- manifestParseResult. compilerOutput = output
616
+ let runResult = try Process . popen ( arguments: cmd)
617
+ let runOutput = try ( runResult. utf8Output ( ) + runResult. utf8stderrOutput ( ) ) . spm_chuzzle ( )
602
618
603
619
// Return now if there was an error.
604
- if result. exitStatus != . terminated( code: 0 ) {
620
+ if runResult. exitStatus != . terminated( code: 0 ) {
621
+ manifestParseResult. errorOutput = runOutput
605
622
return
606
623
}
607
624
608
- guard let json = try localFileSystem. readFileContents ( file. path) . validDescription else {
609
- throw StringError ( " the manifest has invalid encoding " )
610
- }
611
- manifestParseResult. parsedManifest = json
625
+ manifestParseResult. parsedManifest = runOutput
612
626
}
613
627
}
614
628
@@ -661,7 +675,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
661
675
private var _sdkRoot : AbsolutePath ? = nil
662
676
663
677
/// Returns the interpreter flags for a manifest.
664
- public func interpreterFlags (
678
+ public func compilerFlags (
665
679
for toolsVersion: ToolsVersion
666
680
) -> [ String ] {
667
681
var cmd = [ String] ( )
@@ -705,26 +719,31 @@ public final class ManifestLoader: ManifestLoaderProtocol {
705
719
}
706
720
707
721
/// Returns the sandbox profile to be used when parsing manifest on macOS.
708
- private func sandboxProfile( _ cacheDirs : [ AbsolutePath ] = [ ] ) -> String {
722
+ private func sandboxProfile( toolsVersion : ToolsVersion , cacheDirectories : [ AbsolutePath ] = [ ] ) -> String {
709
723
let stream = BufferedOutputByteStream ( )
710
724
stream <<< " (version 1) " <<< " \n "
711
725
// Deny everything by default.
712
726
stream <<< " (deny default) " <<< " \n "
713
727
// Import the system sandbox profile.
714
728
stream <<< " (import \" system.sb \" ) " <<< " \n "
715
- // Allow reading all files.
716
- stream <<< " (allow file-read*) " <<< " \n "
717
- // These are required by the Swift compiler.
718
- stream <<< " (allow process*) " <<< " \n "
719
- stream <<< " (allow sysctl*) " <<< " \n "
720
- // Allow writing in temporary locations.
721
- stream <<< " (allow file-write* " <<< " \n "
722
- for directory in Platform . darwinCacheDirectories ( ) {
723
- stream <<< " (regex # \" ^ \( directory. pathString) /org \\ .llvm \\ .clang.* \" ) " <<< " \n "
724
- }
725
- for cacheDir in cacheDirs {
726
- stream <<< " (subpath \" \( cacheDir. pathString) \" ) " <<< " \n "
729
+
730
+ // The following accesses are only needed when interpreting the manifest (versus running a compiled version).
731
+ if toolsVersion < . vNext {
732
+ // Allow reading all files.
733
+ stream <<< " (allow file-read*) " <<< " \n "
734
+ // These are required by the Swift compiler.
735
+ stream <<< " (allow process*) " <<< " \n "
736
+ stream <<< " (allow sysctl*) " <<< " \n "
737
+ // Allow writing in temporary locations.
738
+ stream <<< " (allow file-write* " <<< " \n "
739
+ for directory in Platform . darwinCacheDirectories ( ) {
740
+ stream <<< " (regex # \" ^ \( directory. pathString) /org \\ .llvm \\ .clang.* \" ) " <<< " \n "
741
+ }
742
+ for directory in cacheDirectories {
743
+ stream <<< " (subpath \" \( directory. pathString) \" ) " <<< " \n "
744
+ }
727
745
}
746
+
728
747
stream <<< " ) " <<< " \n "
729
748
return stream. bytes. description
730
749
}
0 commit comments