Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Sources/SwiftDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
# Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -57,6 +57,7 @@ add_library(SwiftDriver
Jobs/APIDigesterJobs.swift
Jobs/AutolinkExtractJob.swift
Jobs/BackendJob.swift
Jobs/CheckScriptJob.swift
Jobs/CommandLineArguments.swift
Jobs/CompileJob.swift
Jobs/DarwinToolchain+LinkerSupport.swift
Expand All @@ -75,6 +76,7 @@ add_library(SwiftDriver
Jobs/Planning.swift
Jobs/PrintTargetInfoJob.swift
Jobs/ReplJob.swift
Jobs/RunScriptJob.swift
Jobs/Toolchain+InterpreterSupport.swift
Jobs/Toolchain+LinkerSupport.swift
Jobs/VerifyDebugInfoJob.swift
Expand Down
55 changes: 55 additions & 0 deletions Sources/SwiftDriver/Jobs/CheckScriptJob.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//===-------- CheckScriptJob.swift - Swift Script Prechecking Job --------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021 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 TSCBasic

public enum ScriptingError: Error, DiagnosticData {
case tooManyInputFiles
case noSwiftScript

public var description: String {
switch self {
case .tooManyInputFiles:
return "Scripting mode expect exactly 1 input file"

case .noSwiftScript:
return "'swift-script' tool not found"
}
}
}

extension Driver {
/// Check if the script requires scripting mode.
func checkScriptJob(inputs: [TypedVirtualPath]) throws -> Job {
var commandLine: [Job.ArgTemplate] = []
commandLine.appendFlags("-frontend", "-print-package-declarations")

// Check and add the input file.
guard inputs.count == 1 else {
throw ScriptingError.tooManyInputFiles
}
for input in inputs {
commandLine.append(.path(input.file))
}

return Job(
moduleName: moduleOutputInfo.name,
kind: .checkScript,
tool: .absolute(try toolchain.getToolPath(.swiftCompiler)),
commandLine: commandLine,
inputs: inputs,
primaryInputs: [],
outputs: [],
requiresInPlaceExecution: false,
supportsResponseFiles: true
)
}
}
54 changes: 32 additions & 22 deletions Sources/SwiftDriver/Jobs/Job.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Copyright (c) 2014 - 2021 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
Expand Down Expand Up @@ -41,6 +41,9 @@ public struct Job: Codable, Equatable, Hashable {
case generateABIBaseline = "generate-abi-baseline"
case compareAPIBaseline = "compare-api-baseline"
case compareABIBaseline = "compare-abi-baseline"

case checkScript = "check-script"
case runScript = "run-script"
}

public enum ArgTemplate: Equatable, Hashable {
Expand Down Expand Up @@ -166,52 +169,52 @@ extension Job : CustomStringConvertible {
public var description: String {
switch kind {
case .compile:
return "Compiling \(moduleName) \(displayInputs.first?.file.basename ?? "")"
return "Compiling \(moduleName) \(displayInputs.first?.file.basename ?? "")"

case .mergeModule:
return "Merging module \(moduleName)"
return "Merging module \(moduleName)"

case .link:
return "Linking \(moduleName)"
return "Linking \(moduleName)"

case .generateDSYM:
return "Generating dSYM for module \(moduleName)"
return "Generating dSYM for module \(moduleName)"

case .autolinkExtract:
return "Extracting autolink information for module \(moduleName)"
return "Extracting autolink information for module \(moduleName)"

case .emitModule:
return "Emitting module for \(moduleName)"
return "Emitting module for \(moduleName)"

case .generatePCH:
return "Compiling bridging header \(displayInputs.first?.file.basename ?? "")"
return "Compiling bridging header \(displayInputs.first?.file.basename ?? "")"

case .moduleWrap:
return "Wrapping Swift module \(moduleName)"

case .generatePCM:
return "Compiling Clang module \(moduleName)"
return "Compiling Clang module \(moduleName)"

case .dumpPCM:
return "Dump information about Clang module \(displayInputs.first?.file.name ?? "")"
return "Dump information about Clang module \(displayInputs.first?.file.name ?? "")"

case .interpret:
return "Interpreting \(displayInputs.first?.file.name ?? "")"
return "Interpreting \(displayInputs.first?.file.name ?? "")"

case .repl:
return "Executing Swift REPL"
return "Executing Swift REPL"

case .verifyDebugInfo:
return "Verifying debug information for module \(moduleName)"
return "Verifying debug information for module \(moduleName)"

case .printTargetInfo:
return "Gathering target information for module \(moduleName)"
return "Gathering target information for module \(moduleName)"

case .versionRequest:
return "Getting Swift version information"
return "Getting Swift version information"

case .help:
return "Swift help"
return "Swift help"

case .backend:
return "Embedding bitcode for \(moduleName) \(displayInputs.first?.file.basename ?? "")"
Expand All @@ -236,6 +239,12 @@ extension Job : CustomStringConvertible {

case .compareABIBaseline:
return "Comparing ABI of \(moduleName) to baseline"

case .checkScript:
return "Checking if \(displayInputs.first?.file.basename ?? "") requires scripting mode"

case .runScript:
return "Running a script with SwiftPM"
}
}

Expand All @@ -254,13 +263,14 @@ extension Job.Kind {
public var isSwiftFrontend: Bool {
switch self {
case .backend, .compile, .mergeModule, .emitModule, .generatePCH,
.generatePCM, .dumpPCM, .interpret, .repl, .printTargetInfo,
.versionRequest, .emitSupportedFeatures, .scanDependencies, .verifyModuleInterface:
return true
.generatePCM, .dumpPCM, .interpret, .repl, .printTargetInfo, .checkScript,
.versionRequest, .emitSupportedFeatures, .scanDependencies, .verifyModuleInterface:
return true

case .autolinkExtract, .generateDSYM, .help, .link, .verifyDebugInfo, .moduleWrap,
.generateAPIBaseline, .generateABIBaseline, .compareAPIBaseline, .compareABIBaseline:
return false
.generateAPIBaseline, .generateABIBaseline, .compareAPIBaseline, .compareABIBaseline,
.runScript:
return false
}
}

Expand All @@ -275,7 +285,7 @@ extension Job.Kind {
.help, .link, .verifyDebugInfo, .scanDependencies,
.emitSupportedFeatures, .moduleWrap, .verifyModuleInterface,
.generateAPIBaseline, .generateABIBaseline, .compareAPIBaseline,
.compareABIBaseline:
.compareABIBaseline, .checkScript, .runScript:
return false
}
}
Expand Down
14 changes: 12 additions & 2 deletions Sources/SwiftDriver/Jobs/Planning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Copyright (c) 2014 - 2021 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
Expand Down Expand Up @@ -687,7 +687,17 @@ extension Driver {
case .immediate:
var jobs: [Job] = []
try addPrecompileModuleDependenciesJobs(addJob: { jobs.append($0) })
jobs.append(try interpretJob(inputs: inputFiles))
// Check if the script requires scripting mode.
let result = try executor.execute(job: checkScriptJob(inputs: inputFiles),
forceResponseFiles: true,
recordedInputModificationDates: recordedInputModificationDates)
// Only use scripting mode when package dependencies are known.
if result.exitStatus == .terminated(code: 0),
try !result.utf8Output().hasPrefix("[]") {
jobs.append(try runScriptJob(inputs: inputFiles))
} else {
jobs.append(try interpretJob(inputs: inputFiles))
}
return (jobs, nil)

case .standardCompile, .batchCompile, .singleCompile:
Expand Down
68 changes: 68 additions & 0 deletions Sources/SwiftDriver/Jobs/RunScriptJob.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===--------------- RunScriptJob.swift - Swift Scripting Mode ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021 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 TSCBasic

extension Driver {
/// Run a script with the `swift-script` tool.
mutating func runScriptJob(inputs allInputs: [TypedVirtualPath]) throws -> Job {
// Find and use `swift-script run`.
let swiftScriptTool = try toolchain.getToolPath(.swiftCompiler).parentDirectory.appending(component: "swift-script")
guard fileSystem.isExecutableFile(swiftScriptTool) else {
throw ScriptingError.noSwiftScript
}
var commandLine: [Job.ArgTemplate] = [.flag("run")]

// Add the inputs.
var inputs: [TypedVirtualPath] = []
for input in allInputs {
commandLine.append(.path(input.file))
inputs.append(input)
}

// Add frontend arguments.
var frontendArgs: [Job.ArgTemplate] = swiftCompilerPrefixArgs.map { Job.ArgTemplate.flag($0) }
try frontendArgs.appendAll(.l, .framework, from: &parsedOptions)
frontendArgs.forEach {
commandLine.appendFlag("-Xfrontend")
commandLine.append($0)
}

// Appending extra arguments
// FIXME: Is there a more elegant solution?
try commandLine.appendLast(.DASHDASH, from: &parsedOptions)
if let idx = commandLine.firstIndex(of: .flag("--")) {
commandLine.remove(at: idx)
}

// Explicitly handle -v flag
// FIXME: Is there a more elegant solution?
if let idx = commandLine.firstIndex(of: .flag("-v")) {
commandLine.remove(at: idx)
stderrStream <<< "\(swiftScriptTool.pathString) \(commandLine.joinedUnresolvedArguments)\n"
stderrStream.flush()
} else {
commandLine.insert(.flag("--quiet"), at: 1)
}

return Job(
moduleName: moduleOutputInfo.name,
kind: .runScript,
tool: .absolute(swiftScriptTool),
commandLine: commandLine,
inputs: inputs,
primaryInputs: [],
outputs: [],
requiresInPlaceExecution: true,
supportsResponseFiles: true
)
}
}