[driver] Allow -force-single-frontend-invocation and -emit-objc-header[-path] to be used together.

Added support in Driver which allows -force-single-frontend-invocation and
-emit-objc-header[-path] to be used together in a single invocation.

Added support in tools::Swift to pass -emit-objc-header-path if an Objective-C
header was requested; this is only valid in OutputInfo::Mode::SingleCompile
mode, and an assertion enforces this.

Added a test which ensures that the same header is emitted in with
-force-single-frontend-invocation and without it.

Swift SVN r20185
This commit is contained in:
Connor Wakamo
2014-07-18 22:04:29 +00:00
parent ae0dfd4676
commit 497eeffa55
6 changed files with 32 additions and 17 deletions

View File

@@ -53,10 +53,6 @@ ERROR(error_command_failed,driver,none,
ERROR(error_cannot_specify__o_for_multiple_outputs,driver,none, ERROR(error_cannot_specify__o_for_multiple_outputs,driver,none,
"cannot specify -o when generating multiple output files", ()) "cannot specify -o when generating multiple output files", ())
ERROR(error_emit_objc_header_with_single_compile,driver,none,
"cannot emit an Objective-C header with "
"-force-single-frontend-invocation", ())
ERROR(error_unable_to_load_output_file_map,driver, none, ERROR(error_unable_to_load_output_file_map,driver, none,
"unable to load output file map", ()) "unable to load output file map", ())

View File

@@ -416,14 +416,6 @@ void Driver::buildOutputInfo(const DerivedArgList &Args,
assert(OI.CompilerOutputType != types::ID::TY_INVALID); assert(OI.CompilerOutputType != types::ID::TY_INVALID);
bool shouldEmitObjCHeader = Args.hasArg(options::OPT_emit_objc_header,
options::OPT_emit_objc_header_path);
if (shouldEmitObjCHeader &&
OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
Diags.diagnose(SourceLoc(),
diag::error_emit_objc_header_with_single_compile);
}
OI.ShouldGenerateDebugInfo = Args.hasArg(options::OPT_g); OI.ShouldGenerateDebugInfo = Args.hasArg(options::OPT_g);
if (Args.hasArg(options::OPT_emit_module, options::OPT_emit_module_path)) { if (Args.hasArg(options::OPT_emit_module, options::OPT_emit_module_path)) {
@@ -432,7 +424,8 @@ void Driver::buildOutputInfo(const DerivedArgList &Args,
OI.ShouldGenerateModule = true; OI.ShouldGenerateModule = true;
OI.ShouldTreatModuleAsTopLevelOutput = true; OI.ShouldTreatModuleAsTopLevelOutput = true;
} else if ((OI.ShouldGenerateDebugInfo && OI.shouldLink()) || } else if ((OI.ShouldGenerateDebugInfo && OI.shouldLink()) ||
shouldEmitObjCHeader) { Args.hasArg(options::OPT_emit_objc_header,
options::OPT_emit_objc_header_path)) {
// An option has been passed which requires a module, but the user hasn't // An option has been passed which requires a module, but the user hasn't
// requested one. Generate a module, but treat it as an intermediate output. // requested one. Generate a module, but treat it as an intermediate output.
OI.ShouldGenerateModule = true; OI.ShouldGenerateModule = true;
@@ -1096,7 +1089,9 @@ Job *Driver::buildJobsForAction(const Compilation &C, const Action *A,
} }
// Choose the Objective-C header output path. // Choose the Objective-C header output path.
if (isa<MergeModuleJobAction>(JA) && if ((isa<MergeModuleJobAction>(JA) ||
(isa<CompileJobAction>(JA) &&
OI.CompilerMode == OutputInfo::Mode::SingleCompile)) &&
C.getArgs().hasArg(options::OPT_emit_objc_header, C.getArgs().hasArg(options::OPT_emit_objc_header,
options::OPT_emit_objc_header_path)) { options::OPT_emit_objc_header_path)) {
StringRef ObjCHeaderPath; StringRef ObjCHeaderPath;

View File

@@ -368,6 +368,17 @@ Job *Swift::constructJob(const JobAction &JA, std::unique_ptr<JobList> Inputs,
Arguments.push_back(ModuleOutputPath.c_str()); Arguments.push_back(ModuleOutputPath.c_str());
} }
const std::string &ObjCHeaderOutputPath =
Output->getAdditionalOutputForType(types::ID::TY_ObjCHeader);
if (!ObjCHeaderOutputPath.empty()) {
assert(OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
"The Swift tool should only emit an Obj-C header in single compile"
"mode!");
Arguments.push_back("-emit-objc-header-path");
Arguments.push_back(ObjCHeaderOutputPath.c_str());
}
const std::string &SerializedDiagnosticsPath = const std::string &SerializedDiagnosticsPath =
Output->getAdditionalOutputForType(types::TY_SerializedDiagnostics); Output->getAdditionalOutputForType(types::TY_SerializedDiagnostics);
if (!SerializedDiagnosticsPath.empty()) { if (!SerializedDiagnosticsPath.empty()) {

View File

@@ -1,3 +1,3 @@
// Used by multiple_input.swift test. // Used by multiple_input.swift and emit-objc-header.swift tests.
func libraryFunction() {} func libraryFunction() {}

View File

@@ -1,5 +1,5 @@
// Used by multiple_input.swift test. This file should be inferred as the main // Used by multiple_input.swift and emit-objc-header.swift tests. This file
// source file from its name. // should be inferred as the main source file from its name.
var x = 4 + 5 var x = 4 + 5
println(x) println(x)

View File

@@ -0,0 +1,13 @@
// RUN: %swift_driver -Xfrontend %clang-importer-sdk -emit-module -o %t.1.swiftmodule -emit-objc-header -emit-objc-header-path %t.1.h -module-name ThisModule %s %S/Inputs/main.swift %S/Inputs/lib.swift
// RUN: %swift_driver -Xfrontend %clang-importer-sdk -emit-module -o %t.2.swiftmodule -emit-objc-header -emit-objc-header-path %t.2.h -module-name ThisModule %s %S/Inputs/main.swift %S/Inputs/lib.swift -force-single-frontend-invocation
// RUN: diff %t.1.h %t.2.h
import Foundation
public class A: NSObject {
func foo() {}
@objc func bar(x: Int, baz y: Int) -> Int { return 1 }
}
public class B: A {
func doSomething() {}
}