@@ -531,39 +531,33 @@ 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
+ cmd += [
555
+ " -L " , runtimePath. pathString, " -lPackageDescription " ,
556
+ " -Xlinker " , " -rpath " , " -Xlinker " , resources. libDir. parentDirectory. pathString,
557
+ ]
564
558
}
565
559
566
- cmd += interpreterFlags
560
+ cmd += compilerFlags
567
561
if let moduleCachePath = moduleCachePath {
568
562
cmd += [ " -module-cache-path " , moduleCachePath]
569
563
}
@@ -579,36 +573,52 @@ public final class ManifestLoader: ManifestLoaderProtocol {
579
573
580
574
cmd += [ manifestPath. pathString]
581
575
582
- // Create and open a temporary file to write json to.
583
- try withTemporaryFile { file in
576
+ try withTemporaryDirectory { directory in
577
+ let executablePath = directory. appending ( component: " manifest " )
578
+
579
+ // Set path to compiled manifest executable.
580
+ cmd += [ " -o " , executablePath. pathString]
581
+
582
+ try Process . popen ( arguments: cmd)
583
+
584
+ // Compile the manifest.
585
+ let compilerResult = try Process . popen ( arguments: cmd)
586
+ let compilerOutput = try ( compilerResult. utf8Output ( ) + compilerResult. utf8stderrOutput ( ) ) . spm_chuzzle ( )
587
+ manifestParseResult. compilerOutput = compilerOutput
588
+
589
+ // Return now if there was an error.
590
+ if compilerResult. exitStatus != . terminated( code: 0 ) {
591
+ return
592
+ }
593
+
584
594
// 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
595
+ cmd = [ executablePath. pathString, " -fileno " , " 1 " ]
596
+
594
597
#if os(macOS)
595
- env [ " SWIFT_FORCE_MODULE_LOADING " ] = " prefer-parseable "
598
+ // If enabled, use sandbox-exec on macOS. This provides some safety against
599
+ // arbitrary code execution when parsing manifest files. We only allow
600
+ // the permissions which are absolutely necessary for manifest parsing.
601
+ if isManifestSandboxEnabled {
602
+ let cacheDirectories = [
603
+ cacheDir,
604
+ moduleCachePath. map ( { AbsolutePath ( $0) } )
605
+ ] . compactMap ( { $0 } )
606
+ let profile = sandboxProfile ( toolsVersion: toolsVersion, cacheDirectories: cacheDirectories)
607
+ cmd += [ " sandbox-exec " , " -p " , profile]
608
+ }
596
609
#endif
597
610
598
611
// 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
612
+ let runResult = try Process . popen ( arguments: cmd)
613
+ let runOutput = try ( runResult. utf8Output ( ) + runResult. utf8stderrOutput ( ) ) . spm_chuzzle ( )
602
614
603
615
// Return now if there was an error.
604
- if result. exitStatus != . terminated( code: 0 ) {
616
+ if runResult. exitStatus != . terminated( code: 0 ) {
617
+ manifestParseResult. errorOutput = runOutput
605
618
return
606
619
}
607
620
608
- guard let json = try localFileSystem. readFileContents ( file. path) . validDescription else {
609
- throw StringError ( " the manifest has invalid encoding " )
610
- }
611
- manifestParseResult. parsedManifest = json
621
+ manifestParseResult. parsedManifest = runOutput
612
622
}
613
623
}
614
624
@@ -661,7 +671,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
661
671
private var _sdkRoot : AbsolutePath ? = nil
662
672
663
673
/// Returns the interpreter flags for a manifest.
664
- public func interpreterFlags (
674
+ public func compilerFlags (
665
675
for toolsVersion: ToolsVersion
666
676
) -> [ String ] {
667
677
var cmd = [ String] ( )
@@ -705,26 +715,31 @@ public final class ManifestLoader: ManifestLoaderProtocol {
705
715
}
706
716
707
717
/// Returns the sandbox profile to be used when parsing manifest on macOS.
708
- private func sandboxProfile( _ cacheDirs : [ AbsolutePath ] = [ ] ) -> String {
718
+ private func sandboxProfile( toolsVersion : ToolsVersion , cacheDirectories : [ AbsolutePath ] = [ ] ) -> String {
709
719
let stream = BufferedOutputByteStream ( )
710
720
stream <<< " (version 1) " <<< " \n "
711
721
// Deny everything by default.
712
722
stream <<< " (deny default) " <<< " \n "
713
723
// Import the system sandbox profile.
714
724
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 "
725
+
726
+ // The following accesses are only needed when interpreting the manifest (versus running a compiled version).
727
+ if toolsVersion < . vNext {
728
+ // Allow reading all files.
729
+ stream <<< " (allow file-read*) " <<< " \n "
730
+ // These are required by the Swift compiler.
731
+ stream <<< " (allow process*) " <<< " \n "
732
+ stream <<< " (allow sysctl*) " <<< " \n "
733
+ // Allow writing in temporary locations.
734
+ stream <<< " (allow file-write* " <<< " \n "
735
+ for directory in Platform . darwinCacheDirectories ( ) {
736
+ stream <<< " (regex # \" ^ \( directory. pathString) /org \\ .llvm \\ .clang.* \" ) " <<< " \n "
737
+ }
738
+ for directory in cacheDirectories {
739
+ stream <<< " (subpath \" \( directory. pathString) \" ) " <<< " \n "
740
+ }
727
741
}
742
+
728
743
stream <<< " ) " <<< " \n "
729
744
return stream. bytes. description
730
745
}
0 commit comments