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