Fine-grained autolinking control

This change adds the following options to allow for greater control over the compiler's autolinking directive use:
- '-disable-autolink-library': equivalent to an existing '-disable-autolink-framework', this option takes a library name as input and ensures the compiler does not produce an autolink directive '-l<library-name>'.
- '-disable-autolink-frameworks': a boolean disable flag which turns off insertion of autolinking directives for all imported frameworks (of the type '-framework <framework-name>')
- '-disable-all-autolinking': a boolean disable flag which turns off insertion of *any* autolinking directives.

Resolves rdar://100859983
This commit is contained in:
Artem Chikin
2023-10-05 15:12:48 -07:00
parent 90506909d3
commit 57e4f244d1
7 changed files with 116 additions and 15 deletions

View File

@@ -325,6 +325,15 @@ public:
/// Frameworks that we should not autolink against.
SmallVector<std::string, 1> DisableAutolinkFrameworks;
/// Non-framework libraries that we should not autolink against.
SmallVector<std::string, 1> DisableAutolinkLibraries;
/// Whether we should disable inserting autolink directives for any frameworks.
unsigned DisableFrameworkAutolinking : 1;
/// Whether we should disable inserting autolink directives altogether.
unsigned DisableAllAutolinking : 1;
/// Print the LLVM inline tree at the end of the LLVM pass pipeline.
unsigned PrintInlineTree : 1;

View File

@@ -524,6 +524,15 @@ def code_complete_call_pattern_heuristics : Flag<["-"], "code-complete-call-patt
def disable_autolink_framework : Separate<["-"],"disable-autolink-framework">,
HelpText<"Disable autolinking against the provided framework">;
def disable_autolink_library : Separate<["-"],"disable-autolink-library">,
HelpText<"Disable autolinking against the provided library">;
def disable_autolink_frameworks : Flag<["-"],"disable-autolink-frameworks">,
HelpText<"Disable autolinking against all frameworks">;
def disable_all_autolinking : Flag<["-"],"disable-all-autolinking">,
HelpText<"Disable all Swift autolink directives">;
def disable_diagnostic_passes : Flag<["-"], "disable-diagnostic-passes">,
HelpText<"Don't run diagnostic passes">;

View File

@@ -2601,6 +2601,11 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
for (const Arg *A : Args.filtered(OPT_disable_autolink_framework)) {
Opts.DisableAutolinkFrameworks.push_back(A->getValue());
}
for (const Arg *A : Args.filtered(OPT_disable_autolink_library)) {
Opts.DisableAutolinkLibraries.push_back(A->getValue());
}
Opts.DisableFrameworkAutolinking = Args.hasArg(OPT_disable_autolink_frameworks);
Opts.DisableAllAutolinking = Args.hasArg(OPT_disable_all_autolinking);
Opts.GenerateProfile |= Args.hasArg(OPT_profile_generate);
const Arg *ProfileUse = Args.getLastArg(OPT_profile_use);

View File

@@ -1466,21 +1466,30 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) {
if (Context.LangOpts.hasFeature(Feature::Embedded))
return;
switch (linkLib.getKind()) {
case LibraryKind::Library: {
AutolinkEntries.emplace_back(linkLib);
break;
}
case LibraryKind::Framework: {
// If we're supposed to disable autolinking of this framework, bail out.
auto &frameworks = IRGen.Opts.DisableAutolinkFrameworks;
if (std::find(frameworks.begin(), frameworks.end(), linkLib.getName())
!= frameworks.end())
return;
AutolinkEntries.emplace_back(linkLib);
break;
}
// '-disable-autolinking' means we will not auto-link
// any loaded library at all.
if (!IRGen.Opts.DisableAllAutolinking) {
switch (linkLib.getKind()) {
case LibraryKind::Library: {
auto &libraries = IRGen.Opts.DisableAutolinkLibraries;
if (llvm::find(libraries, linkLib.getName()) != libraries.end())
return;
AutolinkEntries.emplace_back(linkLib);
break;
}
case LibraryKind::Framework: {
// 'disable-autolink-frameworks' means we will not auto-link
// any loaded framework.
if (!IRGen.Opts.DisableFrameworkAutolinking) {
auto &frameworks = IRGen.Opts.DisableAutolinkFrameworks;
if (llvm::find(frameworks, linkLib.getName()) != frameworks.end())
return;
AutolinkEntries.emplace_back(linkLib);
}
break;
}
}
}
if (linkLib.shouldForceLoad()) {

View File

@@ -0,0 +1,17 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -sdk %S/Inputs -Fsystem %S/Inputs/System/Library/Frameworks -enable-objc-interop -I %S/Inputs/custom-modules -disable-all-autolinking -module-name AutolinkDisableFrameworks -emit-ir -o %t/test.ll
// RUN: cat %t/test.ll | %FileCheck %s
// Linux uses a different autolinking mechanism, based on
// swift-autolink-extract. This file tests the Darwin mechanism.
// UNSUPPORTED: autolink-extract
import LinkMusket
import LinkFramework
import ClangModuleUser
import IndirectFrameworkImporter
import UsesSubmodule
// No linker options produced
// CHECK: !llvm.linker.options = !{}

View File

@@ -0,0 +1,27 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -sdk %S/Inputs -Fsystem %S/Inputs/System/Library/Frameworks -enable-objc-interop -I %S/Inputs/custom-modules -disable-autolink-frameworks -module-name AutolinkDisableFrameworks -emit-ir -o %t/test.ll
// RUN: cat %t/test.ll | %FileCheck %s
// Linux uses a different autolinking mechanism, based on
// swift-autolink-extract. This file tests the Darwin mechanism.
// UNSUPPORTED: autolink-extract
import LinkMusket
import LinkFramework
import ClangModuleUser
import IndirectFrameworkImporter
import UsesSubmodule
// CHECK: !llvm.linker.options = !{
// CHECK-DAG: !{{[0-9]+}} = !{!{{"-lLock"|"/DEFAULTLIB:Lock.lib"}}}
// CHECK-DAG: !{{[0-9]+}} = !{!{{"-lStock"|"/DEFAULTLIB:Stock.lib"}}}
// CHECK-DAG: !{{[0-9]+}} = !{!{{"-lUnderlyingClangLibrary"|"/DEFAULTLIB:UnderlyingClangLibrary.lib"}}}
// CHECK-NOT: !{!"-framework", !"Barrel"}
// CHECK-NOT: !{!"-framework", !"LinkFramework"}
// CHECK-NOT: !{!"-framework", !"Indirect"}
// CHECK-NOT: !{!"-framework", !"HasSubmodule"}
// CHECK-NOT: !{!"-framework", !"Barrel"}
// CHECK-NOT: !{!"-framework", !"Indirect"}

View File

@@ -0,0 +1,25 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -sdk %S/Inputs -Fsystem %S/Inputs/System/Library/Frameworks -enable-objc-interop -I %S/Inputs/custom-modules -disable-autolink-library Stock -disable-autolink-library UnderlyingClangLibrary -module-name AutolinkDisableFrameworks -emit-ir -o %t/test.ll
// RUN: cat %t/test.ll | %FileCheck %s
// Linux uses a different autolinking mechanism, based on
// swift-autolink-extract. This file tests the Darwin mechanism.
// UNSUPPORTED: autolink-extract
import LinkMusket
import LinkFramework
import ClangModuleUser
import IndirectFrameworkImporter
import UsesSubmodule
// CHECK: !llvm.linker.options = !{
// CHECK-DAG: !{{[0-9]+}} = !{!{{"-lLock"|"/DEFAULTLIB:Lock.lib"}}}
// CHECK-DAG: !{{[0-9]+}} = !{!"-framework", !"Barrel"}
// CHECK-DAG: !{{[0-9]+}} = !{!"-framework", !"LinkFramework"}
// CHECK-DAG: !{{[0-9]+}} = !{!"-framework", !"Indirect"}
// CHECK-DAG: !{{[0-9]+}} = !{!"-framework", !"HasSubmodule"}
// CHECK-NOT: !{!{{"-lStock"|"/DEFAULTLIB:Stock.lib"}}}
// CHECK-NOT: !{!{{"-lUnderlyingClangLibrary"|"/DEFAULTLIB:UnderlyingClangLibrary.lib"}}}