File: SwiftDriverExecutor.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (114 lines) | stat: -rw-r--r-- 4,449 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//===- SwiftDriverExecutor.swift - Builtin DriverExecutor implementation --===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftDriver
import class Foundation.FileHandle

import class TSCBasic.DiagnosticsEngine
import class TSCBasic.Process
import class TSCBasic.ProcessSet
import enum TSCBasic.ProcessEnv
import func TSCBasic.exec
import protocol TSCBasic.FileSystem
import struct TSCBasic.ProcessResult

public final class SwiftDriverExecutor: DriverExecutor {
  let diagnosticsEngine: DiagnosticsEngine
  let processSet: ProcessSet
  let fileSystem: FileSystem
  public let resolver: ArgsResolver
  let env: [String: String]

  public init(diagnosticsEngine: DiagnosticsEngine,
              processSet: ProcessSet,
              fileSystem: FileSystem,
              env: [String: String]) throws {
    self.diagnosticsEngine = diagnosticsEngine
    self.processSet = processSet
    self.fileSystem = fileSystem
    self.env = env
    self.resolver = try ArgsResolver(fileSystem: fileSystem)
  }

  public func execute(job: Job,
                      forceResponseFiles: Bool = false,
                      recordedInputModificationDates: [TypedVirtualPath: TimePoint] = [:]) throws -> ProcessResult {
    let useResponseFiles : ResponseFileHandling = forceResponseFiles ? .forced : .heuristic
    let arguments: [String] = try resolver.resolveArgumentList(for: job,
                                                               useResponseFiles: useResponseFiles)

    try job.verifyInputsNotModified(since: recordedInputModificationDates,
                                    fileSystem: fileSystem)

    if job.requiresInPlaceExecution {
      for (envVar, value) in job.extraEnvironment {
        try ProcessEnv.setVar(envVar, value: value)
      }

      try exec(path: arguments[0], args: arguments)
    } else {
      var childEnv = env
      childEnv.merge(job.extraEnvironment, uniquingKeysWith: { (_, new) in new })
      let process : ProcessProtocol
      if job.inputs.contains(TypedVirtualPath(file: .standardInput, type: .swift)) {
        process = try Process.launchProcessAndWriteInput(
          arguments: arguments, env: childEnv, inputFileHandle: FileHandle.standardInput
        )
      } else {
        process = try Process.launchProcess(arguments: arguments, env: childEnv)
      }
      return try process.waitUntilExit()
    }
  }

  public func execute(workload: DriverExecutorWorkload,
                      delegate: JobExecutionDelegate,
                      numParallelJobs: Int = 1,
                      forceResponseFiles: Bool = false,
                      recordedInputModificationDates: [TypedVirtualPath: TimePoint] = [:]
  ) throws {
    let llbuildExecutor = MultiJobExecutor(
      workload: workload,
      resolver: resolver,
      executorDelegate: delegate,
      diagnosticsEngine: diagnosticsEngine,
      numParallelJobs: numParallelJobs,
      processSet: processSet,
      forceResponseFiles: forceResponseFiles,
      recordedInputModificationDates: recordedInputModificationDates)
    try llbuildExecutor.execute(env: env, fileSystem: fileSystem)
  }

  @discardableResult
  public func checkNonZeroExit(args: String..., environment: [String: String] = ProcessEnv.vars) throws -> String {
    return try Process.checkNonZeroExit(arguments: args, environment: environment)
  }

  public func description(of job: Job, forceResponseFiles: Bool) throws -> String {
    let useResponseFiles : ResponseFileHandling = forceResponseFiles ? .forced : .heuristic
    let (args, usedResponseFile) = try resolver.resolveArgumentList(for: job, useResponseFiles: useResponseFiles)
    var result = args.map { $0.spm_shellEscaped() }.joined(separator: " ")

    if usedResponseFile {
      // Print the response file arguments as a comment.
      result += " # \(job.commandLine.joinedUnresolvedArguments)"
    }

    if !job.extraEnvironment.isEmpty {
      result += " #"
      for (envVar, val) in job.extraEnvironment {
        result += " \(envVar)=\(val)"
      }
    }
    return result
  }
}