Skip to content

Commit fadfb6c

Browse files
authored
Merge pull request swiftlang#31874 from benlangmuir/driver-tmp-sad
[driver/sourcekit] Avoid creating temporary output files in TMPDIR
2 parents 0e892a9 + 251dbb9 commit fadfb6c

File tree

8 files changed

+135
-27
lines changed

8 files changed

+135
-27
lines changed

include/swift/Driver/FrontendUtil.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,18 @@ namespace driver {
3333
/// \param Action Called with the list of frontend arguments if there were no
3434
/// errors in processing \p ArgList. This is a callback rather than a return
3535
/// value to avoid copying the arguments more than necessary.
36+
/// \param ForceNoOutputs If true, override the output mode to "-typecheck" and
37+
/// produce no outputs. For example, this disables "-emit-module" and "-c" and
38+
/// prevents the creation of temporary files.
3639
///
3740
/// \returns True on error, or if \p Action returns true.
3841
///
3942
/// \note This function is not intended to create invocations which are
4043
/// suitable for use in REPL or immediate modes.
4144
bool getSingleFrontendInvocationFromDriverArguments(
4245
ArrayRef<const char *> ArgList, DiagnosticEngine &Diags,
43-
llvm::function_ref<bool(ArrayRef<const char *> FrontendArgs)> Action);
46+
llvm::function_ref<bool(ArrayRef<const char *> FrontendArgs)> Action,
47+
bool ForceNoOutputs = false);
4448

4549
} // end namespace driver
4650
} // end namespace swift

include/swift/Option/Options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace options {
3636
SwiftIndentOption = (1 << 11),
3737
ArgumentIsPath = (1 << 12),
3838
ModuleInterfaceOption = (1 << 13),
39+
SupplementaryOutput = (1 << 14),
3940
};
4041

4142
enum ID {

include/swift/Option/Options.td

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ def ArgumentIsPath : OptionFlag;
5151
// and read/parsed from there when reconstituting a .swiftmodule from it.
5252
def ModuleInterfaceOption : OptionFlag;
5353

54+
// The option causes the output of a supplementary output, or is the path option
55+
// for a supplementary output. E.g., `-emit-module` and `-emit-module-path`.
56+
def SupplementaryOutput : OptionFlag;
57+
5458
/////////
5559
// Options
5660

@@ -314,49 +318,57 @@ def profile_stats_entities: Flag<["-"], "profile-stats-entities">,
314318
HelpText<"Profile changes to stats in -stats-output-dir, subdivided by source entity">;
315319

316320
def emit_dependencies : Flag<["-"], "emit-dependencies">,
317-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
321+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
322+
SupplementaryOutput]>,
318323
HelpText<"Emit basic Make-compatible dependencies files">;
319324
def track_system_dependencies : Flag<["-"], "track-system-dependencies">,
320325
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
321326
HelpText<"Track system dependencies while emitting Make-style dependencies">;
322327

323328
def emit_loaded_module_trace : Flag<["-"], "emit-loaded-module-trace">,
324-
Flags<[FrontendOption, NoInteractiveOption]>,
329+
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>,
325330
HelpText<"Emit a JSON file containing information about what modules were loaded">;
326331
def emit_loaded_module_trace_path : Separate<["-"], "emit-loaded-module-trace-path">,
327-
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
332+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
333+
SupplementaryOutput]>,
328334
HelpText<"Emit the loaded module trace JSON to <path>">,
329335
MetaVarName<"<path>">;
330336
def emit_loaded_module_trace_path_EQ : Joined<["-"], "emit-loaded-module-trace-path=">,
331-
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
337+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
338+
SupplementaryOutput]>,
332339
Alias<emit_loaded_module_trace_path>;
333340
def emit_cross_import_remarks : Flag<["-"], "Rcross-import">,
334341
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
335342
HelpText<"Emit a remark if a cross-import of a module is triggered.">;
336343

337344
def emit_tbd : Flag<["-"], "emit-tbd">,
338345
HelpText<"Emit a TBD file">,
339-
Flags<[FrontendOption, NoInteractiveOption]>;
346+
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>;
340347
def emit_tbd_path : Separate<["-"], "emit-tbd-path">,
341-
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
348+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
349+
SupplementaryOutput]>,
342350
HelpText<"Emit the TBD file to <path>">,
343351
MetaVarName<"<path>">;
344352
def emit_tbd_path_EQ : Joined<["-"], "emit-tbd-path=">,
345-
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
353+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
354+
SupplementaryOutput]>,
346355
Alias<emit_tbd_path>;
347356
def embed_tbd_for_module : Separate<["-"], "embed-tbd-for-module">,
348357
Flags<[FrontendOption]>,
349358
HelpText<"Embed symbols from the module in the emitted tbd file">;
350359

351360
def serialize_diagnostics : Flag<["-"], "serialize-diagnostics">,
352-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
361+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
362+
SupplementaryOutput]>,
353363
HelpText<"Serialize diagnostics in a binary format">;
354364
def serialize_diagnostics_path : Separate<["-"], "serialize-diagnostics-path">,
355-
Flags<[FrontendOption, NoBatchOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
365+
Flags<[FrontendOption, NoBatchOption, DoesNotAffectIncrementalBuild,
366+
ArgumentIsPath, SupplementaryOutput]>,
356367
HelpText<"Emit a serialized diagnostics file to <path>">,
357368
MetaVarName<"<path>">;
358369
def serialize_diagnostics_path_EQ: Joined<["-"], "serialize-diagnostics-path=">,
359-
Flags<[FrontendOption, NoBatchOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
370+
Flags<[FrontendOption, NoBatchOption, DoesNotAffectIncrementalBuild,
371+
ArgumentIsPath, SupplementaryOutput]>,
360372
Alias<serialize_diagnostics_path>;
361373
def color_diagnostics : Flag<["-"], "color-diagnostics">,
362374
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
@@ -410,32 +422,34 @@ def autolink_force_load : Flag<["-"], "autolink-force-load">,
410422
HelpText<"Force ld to link against this module even if no symbols are used">;
411423

412424
def emit_module : Flag<["-"], "emit-module">,
413-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
425+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
426+
SupplementaryOutput]>,
414427
HelpText<"Emit an importable module">;
415428
def emit_module_path : Separate<["-"], "emit-module-path">,
416429
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
417-
ArgumentIsPath]>,
430+
ArgumentIsPath, SupplementaryOutput]>,
418431
HelpText<"Emit an importable module to <path>">,
419432
MetaVarName<"<path>">;
420433
def emit_module_path_EQ : Joined<["-"], "emit-module-path=">,
421434
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
422-
ArgumentIsPath]>,
435+
ArgumentIsPath, SupplementaryOutput]>,
423436
Alias<emit_module_path>;
424437

425438
def emit_module_interface :
426439
Flag<["-"], "emit-module-interface">,
427-
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
440+
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild,
441+
SupplementaryOutput]>,
428442
HelpText<"Output module interface file">;
429443
def emit_module_interface_path :
430444
Separate<["-"], "emit-module-interface-path">,
431445
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
432-
ArgumentIsPath]>,
446+
ArgumentIsPath, SupplementaryOutput]>,
433447
MetaVarName<"<path>">, HelpText<"Output module interface file to <path>">;
434448

435449
def emit_private_module_interface_path :
436450
Separate<["-"], "emit-private-module-interface-path">,
437451
Flags<[FrontendOption, NoInteractiveOption, HelpHidden,
438-
DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
452+
DoesNotAffectIncrementalBuild, ArgumentIsPath, SupplementaryOutput]>,
439453
MetaVarName<"<path>">, HelpText<"Output private module interface file to <path>">;
440454

441455
def avoid_emit_module_source_info :
@@ -446,25 +460,27 @@ def avoid_emit_module_source_info :
446460
def emit_module_source_info_path :
447461
Separate<["-"], "emit-module-source-info-path">,
448462
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
449-
ArgumentIsPath]>,
463+
ArgumentIsPath, SupplementaryOutput]>,
450464
MetaVarName<"<path>">, HelpText<"Output module source info file to <path>">;
451465

452466
def emit_parseable_module_interface :
453467
Flag<["-"], "emit-parseable-module-interface">,
454468
Alias<emit_module_interface>,
455-
Flags<[NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild]>;
469+
Flags<[NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild,
470+
SupplementaryOutput]>;
456471
def emit_parseable_module_interface_path :
457472
Separate<["-"], "emit-parseable-module-interface-path">,
458473
Alias<emit_module_interface_path>,
459474
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
460-
HelpHidden, ArgumentIsPath]>;
475+
HelpHidden, ArgumentIsPath, SupplementaryOutput]>;
461476

462477
def emit_objc_header : Flag<["-"], "emit-objc-header">,
463-
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
478+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
479+
SupplementaryOutput]>,
464480
HelpText<"Emit an Objective-C header file">;
465481
def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
466482
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
467-
ArgumentIsPath]>,
483+
ArgumentIsPath, SupplementaryOutput]>,
468484
MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;
469485

470486
def static : Flag<["-"], "static">,

lib/Driver/FrontendUtil.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ using namespace swift::driver;
2525

2626
bool swift::driver::getSingleFrontendInvocationFromDriverArguments(
2727
ArrayRef<const char *> Argv, DiagnosticEngine &Diags,
28-
llvm::function_ref<bool(ArrayRef<const char *> FrontendArgs)> Action) {
28+
llvm::function_ref<bool(ArrayRef<const char *> FrontendArgs)> Action,
29+
bool ForceNoOutputs) {
2930
SmallVector<const char *, 16> Args;
3031
Args.push_back("<swiftc>"); // FIXME: Remove dummy argument.
3132
Args.insert(Args.end(), Argv.begin(), Argv.end());
@@ -57,6 +58,20 @@ bool swift::driver::getSingleFrontendInvocationFromDriverArguments(
5758
if (Diags.hadAnyError())
5859
return true;
5960

61+
if (ForceNoOutputs) {
62+
// Clear existing output modes and supplementary outputs.
63+
ArgList->eraseArg(options::OPT_modes_Group);
64+
ArgList->eraseArgIf([](const llvm::opt::Arg *A) {
65+
return A && A->getOption().hasFlag(options::SupplementaryOutput);
66+
});
67+
68+
unsigned index = ArgList->MakeIndex("-typecheck");
69+
// Takes ownership of the Arg.
70+
ArgList->append(new llvm::opt::Arg(
71+
TheDriver.getOpts().getOption(options::OPT_typecheck),
72+
ArgList->getArgString(index), index));
73+
}
74+
6075
std::unique_ptr<ToolChain> TC = TheDriver.buildToolChain(*ArgList);
6176
if (Diags.hadAnyError())
6277
return true;

test/Driver/createCompilerInvocation.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,36 @@
77

88
// CHECK-FAIL: error: unable to create a CompilerInvocation
99
// CHECK-NOWARN-NOT: warning
10+
11+
// RUN: %swift-ide-test_plain -test-createCompilerInvocation \
12+
// RUN: -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path %t/foo.tbd -emit-dependencies -serialize-diagnostics %s \
13+
// RUN: 2>&1 | %FileCheck %s --check-prefix=NORMAL_ARGS --implicit-check-not="error: "
14+
// NORMAL_ARGS: Frontend Arguments BEGIN
15+
// NORMAL_ARGS-DAG: -o{{$}}
16+
// NORMAL_ARGS-DAG: foo-{{[a-z0-9]+}}.o
17+
// NORMAL_ARGS-DAG: -c{{$}}
18+
// NORMAL_ARGS-DAG: -module-name
19+
// NORMAL_ARGS-DAG: -emit-module-path
20+
// NORMAL_ARGS-DAG: -emit-module-doc-path
21+
// NORMAL_ARGS-DAG: -emit-module-source-info-path
22+
// NORMAL_ARGS-DAG: -emit-module-interface-path
23+
// NORMAL_ARGS-DAG: -emit-objc-header-path
24+
// NORMAL_ARGS-DAG: -emit-tbd-path
25+
// NORMAL_ARGS-DAG: -serialize-diagnostics-path
26+
// NORMAL_ARGS: Frontend Arguments END
27+
28+
// RUN: %swift-ide-test_plain -test-createCompilerInvocation -force-no-outputs \
29+
// RUN: -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path %t/foo.tbd -emit-dependencies -serialize-diagnostics %s \
30+
// RUN: 2>&1 > %t.nooutput_args
31+
// RUN: %FileCheck %s --check-prefix=NOOUTPUT_ARGS --implicit-check-not="error: " < %t.nooutput_args
32+
// RUN: %FileCheck %s --check-prefix=NOOUTPUT_ARGS_NEG --implicit-check-not="error: " < %t.nooutput_args
33+
// NOOUTPUT_ARGS_NEG-NOT: -o{{$}}
34+
// NOOUTPUT_ARGS_NEG-NOT: foo-{{[a-z0-9]+}}.o
35+
// NOOUTPUT_ARGS_NEG-NOT: -o{{$}}
36+
// NOOUTPUT_ARGS_NEG-NOT: -emit
37+
// NOOUTPUT_ARGS_NEG-NOT: -serialize-diagnostics
38+
39+
// NOOUTPUT_ARGS: Frontend Arguments BEGIN
40+
// NOOUTPUT_ARGS-DAG: -typecheck
41+
// NOOUTPUT_ARGS-DAG: -module-name
42+
// NOOUTPUT_ARGS: Frontend Arguments END
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// REQUIRES: shell
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=syntax-map %s
5+
// RUN: ls %t/ | count 0
6+
7+
// RUN: %empty-directory(%t)
8+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=syntax-map %s -- %s
9+
// RUN: ls %t/ | count 0
10+
11+
// RUN: %empty-directory(%t)
12+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=syntax-map %s -- %s -c -o %t/foo.o
13+
// RUN: ls %t/ | count 0
14+
15+
// RUN: %empty-directory(%t)
16+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s
17+
// RUN: ls %t/ | count 0
18+
19+
// RUN: %empty-directory(%t)
20+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s -c -o %t/foo.o
21+
// RUN: ls %t/ | count 0
22+
23+
// RUN: %empty-directory(%t)
24+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s -emit-module -module-name main -emit-module-path %t/main.swiftmodule -emit-module-interface -enable-library-evolution -emit-module-interface-path %t/main.swiftinterface -emit-objc-header -emit-objc-header-path %t/main.h -c -o %t/foo.o
25+
// RUN: ls %t/ | count 0
26+
27+
// RUN: %empty-directory(%t)
28+
// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s -emit-module -module-name main -emit-module-path %t/main.swiftmodule -emit-executable -o %t/foo
29+
// RUN: ls %t/ | count 0

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ bool SwiftASTManager::initCompilerInvocation(
507507
bool HadError = driver::getSingleFrontendInvocationFromDriverArguments(
508508
Args, Diags, [&](ArrayRef<const char *> FrontendArgs) {
509509
return Invocation.parseArgs(FrontendArgs, Diags);
510-
});
510+
}, /*ForceNoOutputs=*/true);
511511

512512
// Remove the StreamDiagConsumer as it's no longer needed.
513513
Diags.removeConsumer(DiagConsumer);

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,7 +3224,7 @@ static int doPrintUSRs(const CompilerInvocation &InitInvok,
32243224
return 0;
32253225
}
32263226

3227-
static int doTestCreateCompilerInvocation(ArrayRef<const char *> Args) {
3227+
static int doTestCreateCompilerInvocation(ArrayRef<const char *> Args, bool ForceNoOutputs) {
32283228
PrintingDiagnosticConsumer PDC;
32293229
SourceManager SM;
32303230
DiagnosticEngine Diags(SM);
@@ -3233,8 +3233,13 @@ static int doTestCreateCompilerInvocation(ArrayRef<const char *> Args) {
32333233
CompilerInvocation CI;
32343234
bool HadError = driver::getSingleFrontendInvocationFromDriverArguments(
32353235
Args, Diags, [&](ArrayRef<const char *> FrontendArgs) {
3236+
llvm::outs() << "Frontend Arguments BEGIN\n";
3237+
for (const char *arg : FrontendArgs) {
3238+
llvm::outs() << arg << "\n";
3239+
}
3240+
llvm::outs() << "Frontend Arguments END\n";
32363241
return CI.parseArgs(FrontendArgs, Diags);
3237-
});
3242+
}, ForceNoOutputs);
32383243

32393244
if (HadError) {
32403245
llvm::errs() << "error: unable to create a CompilerInvocation\n";
@@ -3272,8 +3277,13 @@ int main(int argc, char *argv[]) {
32723277
// llvm::cl::ParseCommandLineOptions.
32733278
StringRef FirstArg(argv[1]);
32743279
if (FirstArg == "-test-createCompilerInvocation") {
3280+
bool ForceNoOutputs = false;
32753281
ArrayRef<const char *> Args(argv + 2, argc - 2);
3276-
return doTestCreateCompilerInvocation(Args);
3282+
if (argc > 2 && StringRef(argv[2]) == "-force-no-outputs") {
3283+
ForceNoOutputs = true;
3284+
Args = Args.drop_front();
3285+
}
3286+
return doTestCreateCompilerInvocation(Args, ForceNoOutputs);
32773287
}
32783288
}
32793289

0 commit comments

Comments
 (0)