Skip to content

[5.10 🍒] Fine-grained autolinking control #69016

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
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
9 changes: 9 additions & 0 deletions include/swift/AST/IRGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,15 @@ class IRGenOptions {
/// 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;

Expand Down
9 changes: 9 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,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">;

Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2568,6 +2568,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);
Expand Down
42 changes: 27 additions & 15 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1459,21 +1459,33 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) {
// emit it into the IR of debugger expressions.
if (Context.LangOpts.DebuggerSupport)
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;
}

if (Context.LangOpts.hasFeature(Feature::Embedded))
return;

// '-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()) {
Expand Down
17 changes: 17 additions & 0 deletions test/ClangImporter/autolink-disable-all.swift
Original file line number Diff line number Diff line change
@@ -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 = !{}
27 changes: 27 additions & 0 deletions test/ClangImporter/autolink-disable-frameworks.swift
Original file line number Diff line number Diff line change
@@ -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"}
25 changes: 25 additions & 0 deletions test/ClangImporter/autolink-disable-library.swift
Original file line number Diff line number Diff line change
@@ -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"}}}