Skip to content
Merged
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
12 changes: 11 additions & 1 deletion Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,12 @@ public struct Driver {
/// The debug information to produce.
@_spi(Testing) public let debugInfo: DebugInfo

// The information about the module to produce.
/// The information about the module to produce.
@_spi(Testing) public let moduleOutputInfo: ModuleOutputInfo

/// Name of the package containing a target module or file.
@_spi(Testing) public let packageName: String?

/// Info needed to write and maybe read the build record.
/// Only present when the driver will be writing the record.
/// Only used for reading when compiling incrementally.
Expand Down Expand Up @@ -637,6 +640,13 @@ public struct Driver {
// Compute debug information output.
self.debugInfo = Self.computeDebugInfo(&parsedOptions, diagnosticsEngine: diagnosticEngine)

// Validate package name; if package name is nil, it will be checked
// in the frontend during type check on `package` symbols
self.packageName = parsedOptions.getLastArgument(.packageName)?.asSingle
if let packageName = packageName, !packageName.sd_isSwiftIdentifier {
diagnosticsEngine.emit(.error_bad_package_name(packageName))
}

// Determine the module we're building and whether/how the module file itself will be emitted.
self.moduleOutputInfo = try Self.computeModuleInfo(
&parsedOptions, compilerOutputType: compilerOutputType, compilerMode: compilerMode, linkerOutputType: linkerOutputType,
Expand Down
4 changes: 4 additions & 0 deletions Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ extension Driver {
commandLine.appendFlags("-module-name", moduleOutputInfo.name)
}

if let packageName = packageName {
commandLine.appendFlags("-package-name", packageName)
}

// Enable frontend Parseable-output, if needed.
if parsedOptions.contains(.useFrontendParseableOutput) {
commandLine.appendFlag("-frontend-parseable-output")
Expand Down
7 changes: 7 additions & 0 deletions Sources/SwiftDriver/Utilities/Diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ extension Diagnostic.Message {
return .error("bad module alias \"\(arg)\"")
}

static func error_bad_package_name(_ packageName: String) -> Diagnostic.Message {
if packageName.isEmpty {
return .error("package name is empty; pass a non-empty string or remove \'-package-name\'")
}
return .error("package name \"\(packageName)\" is not a valid identifier")
}

static var error_hermetic_seal_cannot_have_library_evolution: Diagnostic.Message {
.error("Cannot use -experimental-hermetic-seal-at-link with -enable-library-evolution")
}
Expand Down
10 changes: 10 additions & 0 deletions Sources/SwiftOptions/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ extension Option {
public static let disableCrossImportOverlays: Option = Option("-disable-cross-import-overlays", .flag, attributes: [.frontend, .noDriver], helpText: "Do not automatically import declared cross-import overlays.")
public static let disableDebuggerShadowCopies: Option = Option("-disable-debugger-shadow-copies", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable debugger shadow copies of local variables.This option is only useful for testing the compiler.")
public static let disableDeserializationRecovery: Option = Option("-disable-deserialization-recovery", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't attempt to recover from missing xrefs (etc) in swiftmodules")
public static let disableDeserializationSafety: Option = Option("-disable-deserialization-safety", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't avoid reading potentially unsafe decls in swiftmodules")
public static let disableDiagnosticPasses: Option = Option("-disable-diagnostic-passes", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Don't run diagnostic passes")
public static let disableEmitGenericClassRoTList: Option = Option("-disable-emit-generic-class-ro_t-list", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of a section with references to class_ro_t of generic class patterns")
public static let disableExperimentalClangImporterDiagnostics: Option = Option("-disable-experimental-clang-importer-diagnostics", .flag, attributes: [.helpHidden, .frontend, .noDriver, .moduleInterface], helpText: "Disable experimental diagnostics when importing C, C++, and Objective-C libraries")
Expand Down Expand Up @@ -174,6 +175,7 @@ extension Option {
public static let disableReadonlyStaticObjects: Option = Option("-disable-readonly-static-objects", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Avoid allocating static objects in a read-only data section")
public static let disableReflectionMetadata: Option = Option("-disable-reflection-metadata", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of reflection metadata for nominal types")
public static let disableReflectionNames: Option = Option("-disable-reflection-names", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of names of stored properties and enum cases inreflection metadata")
public static let disableRelativeProtocolWitnessTables: Option = Option("-disable-relative-protocol-witness-tables", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable relative protocol witness tables")
public static let disableRemoveDeprecatedCheck: Option = Option("-disable-remove-deprecated-check", .flag, attributes: [.noDriver], helpText: "Skip diagnosing removal of deprecated symbols")
public static let disableRemoveDeprecatedCheck_: Option = Option("--disable-remove-deprecated-check", .flag, alias: Option.disableRemoveDeprecatedCheck, attributes: [.noDriver], helpText: "Skip diagnosing removal of deprecated symbols")
public static let disableRequirementMachineConcreteContraction: Option = Option("-disable-requirement-machine-concrete-contraction", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable preprocessing pass to eliminate conformance requirements on generic parameters which are made concrete")
Expand Down Expand Up @@ -322,6 +324,7 @@ extension Option {
public static let enableCrossImportOverlays: Option = Option("-enable-cross-import-overlays", .flag, attributes: [.frontend, .noDriver], helpText: "Automatically import declared cross-import overlays.")
public static let EnbaleDefaultCMO: Option = Option("-enable-default-cmo", .flag, attributes: [.helpHidden, .frontend], helpText: "Perform conservative cross-module optimization")
public static let enableDeserializationRecovery: Option = Option("-enable-deserialization-recovery", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Attempt to recover from missing xrefs (etc) in swiftmodules")
public static let enableDeserializationSafety: Option = Option("-enable-deserialization-safety", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Avoid reading potentially unsafe decls in swiftmodules")
public static let enableDestroyHoisting: Option = Option("-enable-destroy-hoisting=", .joined, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "true|false", helpText: "Whether to enable destroy hoisting")
public static let enableDynamicReplacementChaining: Option = Option("-enable-dynamic-replacement-chaining", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable chaining of dynamic replacements")
public static let enableEmitGenericClassRoTList: Option = Option("-enable-emit-generic-class-ro_t-list", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable emission of a section with references to class_ro_t of generic class patterns")
Expand Down Expand Up @@ -367,6 +370,7 @@ extension Option {
public static let enableOperatorDesignatedTypes: Option = Option("-enable-operator-designated-types", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable operator designated types")
public static let enableOssaModules: Option = Option("-enable-ossa-modules", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Always serialize SIL in ossa form. If this flag is not passed in, when optimizing ownership will be lowered before serializing SIL")
public static let enablePrivateImports: Option = Option("-enable-private-imports", .flag, attributes: [.helpHidden, .frontend, .noInteractive], helpText: "Allows this module's internal and private API to be accessed")
public static let enableRelativeProtocolWitnessTables: Option = Option("-enable-relative-protocol-witness-tables", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable relative protocol witness tables")
public static let enableRequirementMachineOpaqueArchetypes: Option = Option("-enable-requirement-machine-opaque-archetypes", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable more correct opaque archetype support, which is off by default because it might fail to produce a convergent rewrite system")
public static let enableResilience: Option = Option("-enable-resilience", .flag, attributes: [.helpHidden, .frontend, .noDriver, .moduleInterface], helpText: "Deprecated, use -enable-library-evolution instead")
public static let enableRoundTripDebugTypes: Option = Option("-enable-round-trip-debug-types", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enables verification of debug info mangling")
Expand Down Expand Up @@ -541,6 +545,7 @@ extension Option {
public static let O: Option = Option("-O", .flag, attributes: [.frontend, .moduleInterface], helpText: "Compile with optimizations", group: .O)
public static let o: Option = Option("-o", .joinedOrSeparate, attributes: [.frontend, .noInteractive, .autolinkExtract, .moduleWrap, .indent, .argumentIsPath], metaVar: "<file>", helpText: "Write output to <file>")
public static let packageDescriptionVersion: Option = Option("-package-description-version", .separate, attributes: [.helpHidden, .frontend, .moduleInterface], metaVar: "<vers>", helpText: "The version number to be applied on the input for the PackageDescription availability kind")
public static let packageName: Option = Option("-package-name", .separate, attributes: [.frontend], helpText: "Name of the package the module belongs to")
public static let parseAsLibrary: Option = Option("-parse-as-library", .flag, attributes: [.frontend, .noInteractive], helpText: "Parse the input file(s) as libraries, not scripts")
public static let parseSil: Option = Option("-parse-sil", .flag, attributes: [.frontend, .noInteractive], helpText: "Parse the input file as SIL code, not Swift source")
public static let parseStdlib: Option = Option("-parse-stdlib", .flag, attributes: [.helpHidden, .frontend, .moduleInterface], helpText: "Parse the input file(s) as the Swift standard library")
Expand Down Expand Up @@ -868,6 +873,7 @@ extension Option {
Option.disableCrossImportOverlays,
Option.disableDebuggerShadowCopies,
Option.disableDeserializationRecovery,
Option.disableDeserializationSafety,
Option.disableDiagnosticPasses,
Option.disableEmitGenericClassRoTList,
Option.disableExperimentalClangImporterDiagnostics,
Expand Down Expand Up @@ -908,6 +914,7 @@ extension Option {
Option.disableReadonlyStaticObjects,
Option.disableReflectionMetadata,
Option.disableReflectionNames,
Option.disableRelativeProtocolWitnessTables,
Option.disableRemoveDeprecatedCheck,
Option.disableRemoveDeprecatedCheck_,
Option.disableRequirementMachineConcreteContraction,
Expand Down Expand Up @@ -1056,6 +1063,7 @@ extension Option {
Option.enableCrossImportOverlays,
Option.EnbaleDefaultCMO,
Option.enableDeserializationRecovery,
Option.enableDeserializationSafety,
Option.enableDestroyHoisting,
Option.enableDynamicReplacementChaining,
Option.enableEmitGenericClassRoTList,
Expand Down Expand Up @@ -1101,6 +1109,7 @@ extension Option {
Option.enableOperatorDesignatedTypes,
Option.enableOssaModules,
Option.enablePrivateImports,
Option.enableRelativeProtocolWitnessTables,
Option.enableRequirementMachineOpaqueArchetypes,
Option.enableResilience,
Option.enableRoundTripDebugTypes,
Expand Down Expand Up @@ -1275,6 +1284,7 @@ extension Option {
Option.O,
Option.o,
Option.packageDescriptionVersion,
Option.packageName,
Option.parseAsLibrary,
Option.parseSil,
Option.parseStdlib,
Expand Down
23 changes: 23 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,29 @@ final class SwiftDriverTests: XCTestCase {
try assertNoDriverDiagnostics(args: "swiftc", "foo-bar.swift")
}

func testPackageNameFlag() throws {
// -package-name mypkg (valid string)
try assertNoDriverDiagnostics(args: "swiftc", "file.swift", "bar.swift", "-module-name", "MyModule", "-package-name", "mypkg", "-emit-module", "-emit-module-path", "../../path/to/MyModule.swiftmodule") { driver in
XCTAssertEqual(driver.packageName, "mypkg")
XCTAssertEqual(driver.moduleOutputInfo.output, .topLevel(try VirtualPath.intern(path: "../../path/to/MyModule.swiftmodule")))
}

// -package-name is not passed
try assertNoDriverDiagnostics(args: "swiftc", "file.swift") { driver in
XCTAssertNil(driver.packageName)
XCTAssertEqual(driver.moduleOutputInfo.name, "file")
}
}

func testPackageNameDiags() throws {
try assertDriverDiagnostics(args: ["swiftc", "file.swift", "-package-name", ""]) {
$1.expect(.error("package name is empty; pass a non-empty string or remove \'-package-name\'"))
}
try assertDriverDiagnostics(args: ["swiftc", "file.swift", "-module-name", "Foo", "-package-name", "123a!@#$"]) {
$1.expect(.error("package name \"123a!@#$\" is not a valid identifier"))
}
}

func testStandardCompileJobs() throws {
var driver1 = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "-module-name", "Test"])
let plannedJobs = try driver1.planBuild().removingAutolinkExtractJobs()
Expand Down
14 changes: 11 additions & 3 deletions Tests/SwiftOptionsTests/OptionParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ final class SwiftDriverTests: XCTestCase {
// Parse each kind of option
let results = try options.parse([
"input1", "-color-diagnostics", "-Ifoo", "-I", "bar spaces",
"-I=wibble", "input2", "-module-name", "main",
"-I=wibble", "input2", "-module-name", "main", "-package-name", "mypkg",
"-sanitize=a,b,c", "--", "-foo", "-bar"], for: .batch)
#if os(Windows)
XCTAssertEqual(results.description,
#"input1 -color-diagnostics -I foo -I "bar spaces" -I=wibble input2 -module-name main -sanitize=a,b,c -- -foo -bar"#)
#"input1 -color-diagnostics -I foo -I "bar spaces" -I=wibble input2 -module-name main -package-name mypkg -sanitize=a,b,c -- -foo -bar"#)
#else
XCTAssertEqual(results.description,
"input1 -color-diagnostics -I foo -I 'bar spaces' -I=wibble input2 -module-name main -sanitize=a,b,c -- -foo -bar")
"input1 -color-diagnostics -I foo -I 'bar spaces' -I=wibble input2 -module-name main -package-name mypkg -sanitize=a,b,c -- -foo -bar")
#endif
}

Expand Down Expand Up @@ -64,6 +64,14 @@ final class SwiftDriverTests: XCTestCase {
XCTAssertEqual(error as? OptionParseError, .missingArgument(index: 0, argument: "-module-name"))
}

XCTAssertThrowsError(try options.parse(["-package-name"], for: .batch)) { error in
XCTAssertEqual(error as? OptionParseError, .missingArgument(index: 0, argument: "-package-name"))
}

XCTAssertThrowsError(try options.parse(["-package-name"], for: .interactive)) { error in
XCTAssertEqual(error as? OptionParseError, .missingArgument(index: 0, argument: "-package-name"))
}

XCTAssertThrowsError(try options.parse(["-o"], for: .interactive)) { error in
XCTAssertEqual(error as? OptionParseError, .unsupportedOption(index: 0, argument: "-o", option: .o, currentDriverKind: .interactive))
}
Expand Down