Skip to content

Frontend: allow specifying a different target triple for internal clang instance to use #37774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 6, 2021
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
10 changes: 10 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ namespace swift {
/// performed.
llvm::Optional<llvm::Triple> TargetVariant;

/// The target triple to instantiate the internal clang instance.
/// When not specified, the compiler will use the value of -target to
/// instantiate the clang instance.
/// This is mainly used to avoid lowering the target triple to use for clang when
/// importing a .swiftinterface whose -target value may be different from
/// the loading module.
/// The lowering triple may result in multiple versions of the same Clang
/// modules being built.
llvm::Optional<llvm::Triple> ClangTarget;

/// The SDK version, if known.
Optional<llvm::VersionTuple> SDKVersion;

Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,10 @@ def target_variant : Separate<["-"], "target-variant">,
HelpText<"Generate 'zippered' code for macCatalyst that can run on the specified"
" variant target triple in addition to the main -target triple">;

def clang_target : Separate<["-"], "clang-target">,
Flags<[FrontendOption, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Separately set the target we should use for internal Clang instance">;

def profile_generate : Flag<["-"], "profile-generate">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Generate instrumented code to collect execution counts">;
Expand Down
6 changes: 5 additions & 1 deletion lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,11 @@ importer::addCommonInvocationArguments(
std::vector<std::string> &invocationArgStrs,
ASTContext &ctx) {
using ImporterImpl = ClangImporter::Implementation;
const llvm::Triple &triple = ctx.LangOpts.Target;
llvm::Triple triple = ctx.LangOpts.Target;
// Use clang specific target triple if given.
if (ctx.LangOpts.ClangTarget.hasValue()) {
triple = ctx.LangOpts.ClangTarget.getValue();
}
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
const ClangImporterOptions &importerOpts = ctx.ClangImporterOpts;

Expand Down
14 changes: 14 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,20 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.TargetVariant = llvm::Triple(A->getValue());
}

// Collect -clang-target value if specified in the front-end invocation.
// Usually, the driver will pass down a clang target with the
// exactly same value as the main target, so we could dignose the usage of
// unavailable APIs.
// The reason we cannot infer clang target from -target is that not all
// front-end invocation will include a -target to start with. For instance,
// when compiling a Swift module from a textual interface, -target isn't
// necessary because the textual interface hardcoded the proper target triple
// to use. Inferring -clang-target there will always give us the default
// target triple.
if (const Arg *A = Args.getLastArg(OPT_clang_target)) {
Opts.ClangTarget = llvm::Triple(A->getValue());
}

Opts.EnableCXXInterop |= Args.hasArg(OPT_enable_cxx_interop);
Opts.EnableObjCInterop =
Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
Expand Down
11 changes: 11 additions & 0 deletions lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,17 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
GenericArgs.push_back(triple);
}

if (LangOpts.ClangTarget.hasValue()) {
genericSubInvocation.getLangOptions().ClangTarget = LangOpts.ClangTarget;
auto triple = ArgSaver.save(genericSubInvocation.getLangOptions()
.ClangTarget->getTriple());
assert(!triple.empty());
// In explicit module build, all PCMs will be built using the given clang target.
// So the Swift interface should know that as well to load these PCMs properly.
GenericArgs.push_back("-clang-target");
GenericArgs.push_back(triple);
}

// Inherit the Swift language version
genericSubInvocation.getLangOptions().EffectiveLanguageVersion =
LangOpts.EffectiveLanguageVersion;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// swift-interface-format-version: 1.0
// swift-module-flags: -module-name XWithTarget -target x86_64-apple-macosx10.9
import Swift
@_exported import X
public func overlayFuncX() { }
21 changes: 21 additions & 0 deletions test/ScanDependencies/clang-target.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// REQUIRES: VENDOR=apple
// RUN: %empty-directory(%t.module-cache)
// RUN: %target-swift-frontend -emit-module -o %t.foo.swiftmodule -module-cache-path %t.module-cache -I %S/Inputs/CHeaders -I %S/Inputs/Swift %s -target x86_64-apple-macosx10.14

// Without -clang-target, we build two X.pcm
// RUN: find %t.module-cache -name "X-*.pcm" | count 2

// RUN: %empty-directory(%t.module-cache)
// RUN: %target-swift-frontend -emit-module -o %t.foo.swiftmodule -module-cache-path %t.module-cache -I %S/Inputs/CHeaders -I %S/Inputs/Swift %s -target x86_64-apple-macosx10.14 -clang-target x86_64-apple-macosx10.14

// With -clang-target, we build one X.pcm
// RUN: find %t.module-cache -name "X-*.pcm" | count 1

// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t.module-cache %s -o %t.deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -target x86_64-apple-macosx10.14 -clang-target x86_64-apple-macosx10.14
// RUN: %FileCheck %s < %t.deps.json

// CHECK: "-clang-target"
// CHECK-NEXT: "x86_64-apple-macosx10.14"

import X
import XWithTarget