mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Extract autolink information as a compile step.
Swift SVN r25510
This commit is contained in:
@@ -38,6 +38,7 @@ public:
|
||||
Input = 0,
|
||||
CompileJob,
|
||||
MergeModuleJob,
|
||||
AutolinkExtractJob,
|
||||
REPLJob,
|
||||
LinkJob,
|
||||
GenerateDSYMJob,
|
||||
@@ -176,6 +177,17 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AutolinkExtractJobAction : public JobAction {
|
||||
virtual void anchor();
|
||||
public:
|
||||
AutolinkExtractJobAction(ArrayRef<Action *> Inputs)
|
||||
: JobAction(Action::AutolinkExtractJob, Inputs, types::TY_AutolinkFile) {}
|
||||
|
||||
static bool classof(const Action *A) {
|
||||
return A->getKind() == Action::AutolinkExtractJob;
|
||||
}
|
||||
};
|
||||
|
||||
class GenerateDSYMJobAction : public JobAction {
|
||||
virtual void anchor();
|
||||
public:
|
||||
|
||||
@@ -110,9 +110,10 @@ public:
|
||||
/// DriverKind determines how later arguments are parsed, as well as the
|
||||
/// allowable OutputInfo::Mode values.
|
||||
enum class DriverKind {
|
||||
Interactive, // swift
|
||||
Batch, // swiftc
|
||||
UpdateCode, // swift-update
|
||||
Interactive, // swift
|
||||
Batch, // swiftc
|
||||
UpdateCode, // swift-update
|
||||
AutolinkExtract, // swift-autolink-extract
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -44,12 +44,14 @@ class ToolChain {
|
||||
mutable std::unique_ptr<Tool> LLDB;
|
||||
mutable std::unique_ptr<Tool> Linker;
|
||||
mutable std::unique_ptr<Tool> Dsymutil;
|
||||
mutable std::unique_ptr<Tool> AutolinkExtract;
|
||||
|
||||
Tool *getSwift() const;
|
||||
Tool *getMergeModule() const;
|
||||
Tool *getLLDB() const;
|
||||
Tool *getLinker() const;
|
||||
Tool *getDsymutil() const;
|
||||
Tool *getAutolinkExtract() const;
|
||||
|
||||
protected:
|
||||
ToolChain(const Driver &D, const llvm::Triple &T) : D(D), Triple(T) {}
|
||||
|
||||
@@ -44,6 +44,7 @@ TYPE("image", Image, "out", "")
|
||||
TYPE("object", Object, "o", "")
|
||||
TYPE("dSYM", dSYM, "dSYM", "")
|
||||
TYPE("dependencies", Dependencies, "d", "")
|
||||
TYPE("autolink", AutolinkFile, "autolink", "")
|
||||
TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
|
||||
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
|
||||
TYPE("assembly", Assembly, "s", "")
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace options {
|
||||
NoDriverOption = (1 << 5),
|
||||
NoInteractiveOption = (1 << 6),
|
||||
NoBatchOption = (1 << 7),
|
||||
DoesNotAffectIncrementalBuild = (1 << 8)
|
||||
DoesNotAffectIncrementalBuild = (1 << 8),
|
||||
AutolinkExtractOption = (1 << 9)
|
||||
};
|
||||
|
||||
enum ID {
|
||||
|
||||
@@ -23,6 +23,9 @@ include "llvm/Option/OptParser.td"
|
||||
// The option should be accepted by swift -frontend.
|
||||
def FrontendOption : OptionFlag;
|
||||
|
||||
// The option should be accepted by swift-autolink-extract
|
||||
def AutolinkExtractOption : OptionFlag;
|
||||
|
||||
// The option should not be accepted by the driver.
|
||||
def NoDriverOption : OptionFlag;
|
||||
|
||||
@@ -83,7 +86,8 @@ def driver_use_frontend_path : Separate<["-"], "driver-use-frontend-path">,
|
||||
def driver_mode : Joined<["--"], "driver-mode=">, Flags<[HelpHidden]>,
|
||||
HelpText<"Set the driver mode to either 'swift' or 'swiftc' or 'swift-update'">;
|
||||
|
||||
def help : Flag<["-", "--"], "help">, Flags<[FrontendOption]>,
|
||||
def help : Flag<["-", "--"], "help">,
|
||||
Flags<[FrontendOption, AutolinkExtractOption]>,
|
||||
HelpText<"Display available options">;
|
||||
def h : Flag<["-"], "h">, Alias<help>;
|
||||
def help_hidden : Flag<["-", "--"], "help-hidden">,
|
||||
@@ -104,7 +108,7 @@ def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
|
||||
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>;
|
||||
|
||||
def o : JoinedOrSeparate<["-"], "o">,
|
||||
Flags<[FrontendOption, NoInteractiveOption]>,
|
||||
Flags<[FrontendOption, AutolinkExtractOption, NoInteractiveOption]>,
|
||||
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
|
||||
|
||||
def j : JoinedOrSeparate<["-"], "j">, Flags<[DoesNotAffectIncrementalBuild]>,
|
||||
|
||||
@@ -29,6 +29,7 @@ const char *Action::getClassName(ActionClass AC) {
|
||||
case Input: return "input";
|
||||
case CompileJob: return "compile";
|
||||
case MergeModuleJob: return "merge-module";
|
||||
case AutolinkExtractJob: return "swift-autolink-extract";
|
||||
case REPLJob: return "repl";
|
||||
case LinkJob: return "link";
|
||||
case GenerateDSYMJob: return "generate-dSYM";
|
||||
@@ -45,6 +46,8 @@ void CompileJobAction::anchor() {}
|
||||
|
||||
void MergeModuleJobAction::anchor() {}
|
||||
|
||||
void AutolinkExtractJobAction::anchor() {}
|
||||
|
||||
void REPLJobAction::anchor() {}
|
||||
|
||||
void LinkJobAction::anchor() {}
|
||||
|
||||
@@ -93,6 +93,7 @@ void Driver::parseDriverKind(ArrayRef<const char *> Args) {
|
||||
.Case("swift", DriverKind::Interactive)
|
||||
.Case("swiftc", DriverKind::Batch)
|
||||
.Case("swift-update", DriverKind::UpdateCode)
|
||||
.Case("swift-autolink-extract", DriverKind::AutolinkExtract)
|
||||
.Default(None);
|
||||
|
||||
if (Kind.hasValue())
|
||||
@@ -1009,6 +1010,7 @@ void Driver::buildActions(const ToolChain &TC,
|
||||
if (OI.ShouldGenerateModule)
|
||||
break;
|
||||
SWIFT_FALLTHROUGH;
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_Object:
|
||||
// Object inputs are only okay if linking.
|
||||
if (OI.shouldLink())
|
||||
@@ -1092,6 +1094,18 @@ void Driver::buildActions(const ToolChain &TC,
|
||||
|
||||
if (OI.shouldLink()) {
|
||||
Action *LinkAction = new LinkJobAction(CompileActions, OI.LinkAction);
|
||||
|
||||
if (TC.getTriple().getObjectFormat() == llvm::Triple::ELF) {
|
||||
// On ELF platforms there's no built in autolinking mechanism, so we
|
||||
// pull the info we need from the .o files directly and pass them as an
|
||||
// argument input file to the linker.
|
||||
Action *AutolinkExtractAction = new AutolinkExtractJobAction(CompileActions);
|
||||
// Takes the same inputs as the linker, but doesn't own them.
|
||||
AutolinkExtractAction->setOwnsInputs(false);
|
||||
// And gives its output to the linker.
|
||||
LinkAction->addInput(AutolinkExtractAction);
|
||||
}
|
||||
|
||||
if (MergeModuleAction) {
|
||||
// We have a MergeModuleJobAction; this needs to be an input to the
|
||||
// LinkJobAction. It shares inputs with the LinkAction, so tell it that it
|
||||
@@ -1767,6 +1781,7 @@ void Driver::printHelp(bool ShowHidden) const {
|
||||
break;
|
||||
case DriverKind::Batch:
|
||||
case DriverKind::UpdateCode:
|
||||
case DriverKind::AutolinkExtract:
|
||||
ExcludedFlagsBitmask |= options::NoBatchOption;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ CACHE_TOOL(Swift)
|
||||
CACHE_TOOL(MergeModule)
|
||||
CACHE_TOOL(LLDB)
|
||||
CACHE_TOOL(Dsymutil)
|
||||
CACHE_TOOL(AutolinkExtract)
|
||||
|
||||
Tool *ToolChain::getLinker() const {
|
||||
if (!Linker)
|
||||
@@ -53,6 +54,8 @@ Tool *ToolChain::selectTool(const JobAction &JA) const {
|
||||
return getLinker();
|
||||
case Action::GenerateDSYMJob:
|
||||
return getDsymutil();
|
||||
case Action::AutolinkExtractJob:
|
||||
return getAutolinkExtract();
|
||||
case Action::REPLJob:
|
||||
switch (cast<REPLJobAction>(JA).getRequestedMode()) {
|
||||
case REPLJobAction::Mode::Integrated:
|
||||
|
||||
@@ -195,6 +195,7 @@ Job *Swift::constructJob(const JobAction &JA, std::unique_ptr<JobList> Inputs,
|
||||
break;
|
||||
case types::TY_Swift:
|
||||
case types::TY_dSYM:
|
||||
case types::TY_AutolinkFile:
|
||||
case types::TY_Dependencies:
|
||||
case types::TY_SwiftModuleDocFile:
|
||||
case types::TY_ClangModuleFile:
|
||||
@@ -477,6 +478,25 @@ Job *Dsymutil::constructJob(const JobAction &JA,
|
||||
Arguments);
|
||||
}
|
||||
|
||||
Job *AutolinkExtract::constructJob(const JobAction &JA,
|
||||
std::unique_ptr<JobList> Inputs,
|
||||
std::unique_ptr<CommandOutput> Output,
|
||||
const ActionList &InputActions,
|
||||
const ArgList &Args,
|
||||
const OutputInfo &OI) const {
|
||||
assert(Output->getPrimaryOutputType() == types::TY_AutolinkFile);
|
||||
|
||||
ArgStringList Arguments;
|
||||
addPrimaryInputsOfType(Arguments, *Inputs, types::TY_Object);
|
||||
addInputsOfType(Arguments, InputActions, types::TY_Object);
|
||||
|
||||
Arguments.push_back("-o");
|
||||
Arguments.push_back(Args.MakeArgString(Output->getPrimaryOutputFilename()));
|
||||
|
||||
return new Job(JA, *this, std::move(Inputs), std::move(Output), getPath(),
|
||||
Arguments);
|
||||
}
|
||||
|
||||
/// Darwin Tools
|
||||
|
||||
llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Arch) {
|
||||
@@ -718,8 +738,17 @@ Job *linux::Linker::constructJob(const JobAction &JA,
|
||||
Arguments.push_back("-Xlinker");
|
||||
Arguments.push_back(Args.MakeArgString(RuntimeLibPath));
|
||||
|
||||
// Always add the stdlib
|
||||
Arguments.push_back("-lswiftCore");
|
||||
|
||||
// Add any autolinking scripts to the arguments
|
||||
for (const Job *Cmd : *Inputs) {
|
||||
auto &OutputInfo = Cmd->getOutput();
|
||||
if (OutputInfo.getPrimaryOutputType() == types::TY_AutolinkFile)
|
||||
Arguments.push_back(Args.MakeArgString(
|
||||
Twine("@") + OutputInfo.getPrimaryOutputFilename()));
|
||||
}
|
||||
|
||||
// Add the linker script that coalesces protocol conformance sections.
|
||||
Arguments.push_back("-Xlinker");
|
||||
Arguments.push_back("-T");
|
||||
|
||||
@@ -105,6 +105,18 @@ public:
|
||||
const OutputInfo &OI) const;
|
||||
};
|
||||
|
||||
class LLVM_LIBRARY_VISIBILITY AutolinkExtract : public ToolchainTool {
|
||||
public:
|
||||
explicit AutolinkExtract(const ToolChain &TC)
|
||||
: ToolchainTool("swift-autolink-extract", TC) {}
|
||||
|
||||
virtual Job *constructJob(const JobAction &JA,
|
||||
std::unique_ptr<JobList> Inputs,
|
||||
std::unique_ptr<CommandOutput> Output,
|
||||
const ActionList &InputActions,
|
||||
const llvm::opt::ArgList &Args,
|
||||
const OutputInfo &OI) const;
|
||||
};
|
||||
|
||||
namespace darwin {
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ bool types::isTextual(ID Id) {
|
||||
case types::TY_RawSIL:
|
||||
case types::TY_LLVM_IR:
|
||||
case types::TY_ObjCHeader:
|
||||
case types::TY_AutolinkFile:
|
||||
return true;
|
||||
case types::TY_Image:
|
||||
case types::TY_Object:
|
||||
|
||||
6
test/AutolinkExtract/empty.swift
Normal file
6
test/AutolinkExtract/empty.swift
Normal file
@@ -0,0 +1,6 @@
|
||||
// RUN: %target-swiftc_driver -c %s -o %t
|
||||
// RUN: %target-swift-autolink-extract %t -o - | FileCheck --check-prefix CHECK-%target-object-format %s
|
||||
|
||||
// REQUIRES: autolink-extract
|
||||
|
||||
// CHECK-elf: -lswiftCore
|
||||
6
test/AutolinkExtract/error_no_inputs.swift
Normal file
6
test/AutolinkExtract/error_no_inputs.swift
Normal file
@@ -0,0 +1,6 @@
|
||||
// RUN: %target-swiftc_driver -c %s -o %t
|
||||
// RUN: not %target-swift-autolink-extract 2>&1 | FileCheck %s
|
||||
|
||||
// REQUIRES: autolink-extract
|
||||
|
||||
// CHECK: <unknown>:0: error: this mode requires at least one input file
|
||||
12
test/AutolinkExtract/import.swift
Normal file
12
test/AutolinkExtract/import.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir -p %t
|
||||
// RUN: %target-swiftc_driver -emit-library -emit-module -emit-module-path %t/empty.swiftmodule -module-name empty -module-link-name empty %S/empty.swift
|
||||
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental.o
|
||||
// RUN: %target-swift-autolink-extract %t/import_experimental.o -o - | FileCheck --check-prefix CHECK-%target-object-format %s
|
||||
|
||||
// REQUIRES: autolink-extract
|
||||
|
||||
// CHECK-elf-DAG: -lswiftCore
|
||||
// CHECK-elf-DAG: -lempty
|
||||
|
||||
import empty
|
||||
5
test/Driver/autolink_extract.swift
Normal file
5
test/Driver/autolink_extract.swift
Normal file
@@ -0,0 +1,5 @@
|
||||
// RUN: %target-swiftc_driver -### %s | FileCheck %s
|
||||
|
||||
// REQUIRES: autolink-extract
|
||||
|
||||
// CHECK: swift-autolink-extract {{.+}}.o -o {{.+}}.autolink
|
||||
@@ -1,9 +1,14 @@
|
||||
// RUN: %swift_driver_plain --driver-mode=swiftc -driver-print-actions %s 2>&1 | FileCheck -check-prefix=CHECK-SWIFTC %s
|
||||
// RUN: %swift_driver_plain --driver-mode=swiftc -driver-print-actions %s 2>&1 | FileCheck -check-prefix=CHECK-SWIFTC-%target-object-format %s
|
||||
// RUN: %swift_driver_plain -driver-print-actions %s --driver-mode=swiftc 2>&1 | FileCheck -check-prefix=CHECK-SWIFT %s
|
||||
|
||||
// CHECK-SWIFTC: 0: input, "{{.*}}driver_mode.swift", swift
|
||||
// CHECK-SWIFTC: 1: compile, {0}, object
|
||||
// CHECK-SWIFTC: 2: link, {1}, image
|
||||
// CHECK-SWIFTC-macho: 0: input, "{{.*}}driver_mode.swift", swift
|
||||
// CHECK-SWIFTC-macho: 1: compile, {0}, object
|
||||
// CHECK-SWIFTC-macho: 2: link, {1}, image
|
||||
|
||||
// CHECK-SWIFTC-elf: 0: input, "{{.*}}driver_mode.swift", swift
|
||||
// CHECK-SWIFTC-elf: 1: compile, {0}, object
|
||||
// CHECK-SWIFTC-elf: 2: swift-autolink-extract, {1}, autolink
|
||||
// CHECK-SWIFTC-elf: 3: link, {1, 2}, image
|
||||
|
||||
// CHECK-SWIFT: 0: input, "{{.*}}driver_mode.swift", swift
|
||||
// CHECK-SWIFT: 1: compile, {0}, none
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
// DEBUG: -o linker.dSYM
|
||||
|
||||
// DEBUG_LINUX: bin/swift
|
||||
// DEBUG_LINUX-NEXT: bin/swift-autolink-extract
|
||||
// DEBUG_LINUX-NEXT: bin/swift
|
||||
// DEBUG_LINUX-NEXT: bin/clang++{{"? }}
|
||||
// DEBUG_LINUX: -o linker
|
||||
|
||||
@@ -10,14 +10,18 @@
|
||||
// COMPILE: 0: input
|
||||
// COMPILE: 1: compile, {0}, object
|
||||
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty 2>&1 | FileCheck -check-prefix=LINK %s
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty.swiftmodule 2>&1 | FileCheck -check-prefix=LINK %s
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty.o 2>&1 | FileCheck -check-prefix=LINK %s
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty 2>&1 | FileCheck -check-prefix=LINK-%target-object-format %s
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty.swiftmodule 2>&1 | FileCheck -check-prefix=LINK-%target-object-format %s
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty.o 2>&1 | FileCheck -check-prefix=LINK-%target-object-format %s
|
||||
// RUN: not %swiftc_driver -driver-print-actions %t/empty.h 2>&1 | FileCheck -check-prefix=ERROR %s
|
||||
// RUN: %swiftc_driver -driver-print-actions %t/empty.swift 2>&1 | FileCheck -check-prefix=COMPILE %s
|
||||
|
||||
// LINK: 0: input
|
||||
// LINK: 1: link, {0}, image
|
||||
// LINK-macho: 0: input
|
||||
// LINK-macho: 1: link, {0}, image
|
||||
|
||||
// LINK-elf: 0: input
|
||||
// LINK-elf: 1: swift-autolink-extract, {0}, autolink
|
||||
// LINK-elf: 2: link, {0, 1}, image
|
||||
|
||||
// RUN: not %swiftc_driver -driver-print-actions -emit-module %t/empty 2>&1 | FileCheck -check-prefix=ERROR %s
|
||||
// RUN: %swiftc_driver -driver-print-actions -emit-module %t/empty.swiftmodule 2>&1 | FileCheck -check-prefix=MODULE %s
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_swift_executable(swift
|
||||
driver.cpp
|
||||
autolink_extract_main.cpp
|
||||
frontend_main.cpp
|
||||
update_main.cpp
|
||||
LINK_LIBRARIES
|
||||
@@ -25,6 +26,10 @@ add_custom_command(TARGET swift POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" "-E" "create_symlink" "swift" "swift-update"
|
||||
WORKING_DIRECTORY "${SWIFT_RUNTIME_OUTPUT_INTDIR}")
|
||||
|
||||
add_custom_command(TARGET swift POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" "-E" "create_symlink" "swift" "swift-autolink-extract"
|
||||
WORKING_DIRECTORY "${SWIFT_RUNTIME_OUTPUT_INTDIR}")
|
||||
|
||||
# If building as part of clang, make sure the headers are installed.
|
||||
if(NOT SWIFT_BUILT_STANDALONE)
|
||||
add_dependencies(swift clang-headers)
|
||||
@@ -56,3 +61,10 @@ swift_install_in_component(compiler
|
||||
swift_install_in_component(compiler
|
||||
FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-update"
|
||||
DESTINATION "bin")
|
||||
|
||||
if(SWIFT_HOST_VARIANT STREQUAL "LINUX")
|
||||
# No need for this on other platforms.
|
||||
swift_install_in_component(compiler
|
||||
FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-autolink-extract"
|
||||
DESTINATION "bin")
|
||||
endif()
|
||||
|
||||
182
tools/driver/autolink_extract_main.cpp
Normal file
182
tools/driver/autolink_extract_main.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
//===-- autolink_extract_main.cpp - autolink extraction utility -----------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Extracts autolink flags from object files so they can be passed to the
|
||||
// linker directly. Mostly useful for platforms where the linker doesn't
|
||||
// natively support autolinking (ie. ELF-based platforms).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||
#include "swift/Option/Options.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace llvm::opt;
|
||||
|
||||
class AutolinkExtractInvocation {
|
||||
private:
|
||||
std::string MainExecutablePath;
|
||||
std::string OutputFilename = "-";
|
||||
std::vector<std::string> InputFilenames;
|
||||
|
||||
public:
|
||||
void setMainExecutablePath(const std::string &Path) {
|
||||
MainExecutablePath = Path;
|
||||
}
|
||||
|
||||
const std::string &getOutputFilename() {
|
||||
return OutputFilename;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &getInputFilenames() {
|
||||
return InputFilenames;
|
||||
}
|
||||
|
||||
int parseArgs(ArrayRef<const char *> Args,
|
||||
DiagnosticEngine &Diags) {
|
||||
using namespace options;
|
||||
|
||||
// Parse frontend command line options using Swift's option table.
|
||||
std::unique_ptr<llvm::opt::InputArgList> ParsedArgs;
|
||||
std::unique_ptr<llvm::opt::OptTable> Table = createSwiftOptTable();
|
||||
unsigned MissingIndex;
|
||||
unsigned MissingCount;
|
||||
ParsedArgs.reset(
|
||||
Table->ParseArgs(Args.begin(), Args.end(), MissingIndex, MissingCount,
|
||||
AutolinkExtractOption));
|
||||
if (MissingCount) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_missing_arg_value,
|
||||
ParsedArgs->getArgString(MissingIndex), MissingCount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ParsedArgs->hasArg(OPT_UNKNOWN)) {
|
||||
for (const Arg *A : make_range(ParsedArgs->filtered_begin(OPT_UNKNOWN),
|
||||
ParsedArgs->filtered_end())) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_unknown_arg,
|
||||
A->getAsString(*ParsedArgs));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParsedArgs->getLastArg(OPT_help)) {
|
||||
std::string ExecutableName = llvm::sys::path::stem(MainExecutablePath);
|
||||
Table->PrintHelp(llvm::outs(), ExecutableName.c_str(),
|
||||
"Swift Autolink Extract", options::AutolinkExtractOption,
|
||||
0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (const Arg *A : make_range(ParsedArgs->filtered_begin(OPT_INPUT),
|
||||
ParsedArgs->filtered_end())) {
|
||||
InputFilenames.push_back(A->getValue());
|
||||
}
|
||||
|
||||
if (InputFilenames.empty()) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (const Arg *A = ParsedArgs->getLastArg(OPT_o)) {
|
||||
OutputFilename = A->getValue();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
|
||||
void *MainAddr) {
|
||||
CompilerInstance Instance;
|
||||
PrintingDiagnosticConsumer PDC;
|
||||
Instance.addDiagnosticConsumer(&PDC);
|
||||
|
||||
AutolinkExtractInvocation Invocation;
|
||||
std::string MainExecutablePath = llvm::sys::fs::getMainExecutable(Argv0,
|
||||
MainAddr);
|
||||
Invocation.setMainExecutablePath(MainExecutablePath);
|
||||
|
||||
// Parse arguments.
|
||||
if (Invocation.parseArgs(Args, Instance.getDiags()) != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Store each linker flag only once
|
||||
std::set<std::string> LinkerFlags;
|
||||
|
||||
for (const auto &ObjectFileName : Invocation.getInputFilenames()) {
|
||||
auto ObjectFileOwner =
|
||||
llvm::object::ObjectFile::createObjectFile(ObjectFileName);
|
||||
if (!ObjectFileOwner) {
|
||||
Instance.getDiags().diagnose(SourceLoc(), diag::error_open_input_file,
|
||||
ObjectFileName,
|
||||
ObjectFileOwner.getError().message());
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto ObjectFile = ObjectFileOwner->getBinary();
|
||||
if (llvm::isa<llvm::object::ELFObjectFileBase>(ObjectFile)) {
|
||||
// Search for the section we hold autolink entries in
|
||||
for (auto &Section : ObjectFileOwner->getBinary()->sections()) {
|
||||
llvm::StringRef SectionName;
|
||||
Section.getName(SectionName);
|
||||
if (SectionName == ".swift1_autolink_entries") {
|
||||
llvm::StringRef SectionData;
|
||||
Section.getContents(SectionData);
|
||||
|
||||
// entries are null-terminated, so extract them and push them into
|
||||
// the set.
|
||||
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
|
||||
SectionData.split(SplitFlags, llvm::StringRef("\0", 1),
|
||||
-1, /*KeepEmpty=*/false);
|
||||
for (const auto &Flag : SplitFlags) {
|
||||
LinkerFlags.insert(Flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Instance.getDiags().diagnose(SourceLoc(), diag::error_open_input_file,
|
||||
ObjectFileName,
|
||||
"Don't know how to extract from object file"
|
||||
"format");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::string OutputFilename = Invocation.getOutputFilename();
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream OutOS(OutputFilename, EC, llvm::sys::fs::F_None);
|
||||
if (OutOS.has_error() || EC) {
|
||||
Instance.getDiags().diagnose(SourceLoc(), diag::error_opening_output,
|
||||
OutputFilename, EC.message());
|
||||
OutOS.clear_error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (auto &Flag : LinkerFlags) {
|
||||
OutOS << Flag << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -51,6 +51,10 @@ extern int frontend_main(ArrayRef<const char *> Args, const char *Argv0,
|
||||
extern int update_main(ArrayRef<const char *> Args, const char *Argv0,
|
||||
void *MainAddr);
|
||||
|
||||
/// Run 'swift-autolink-extract'.
|
||||
extern int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
|
||||
void *MainAddr);
|
||||
|
||||
int main(int argc_, const char **argv_) {
|
||||
// Print a stack trace if we signal out.
|
||||
llvm::sys::PrintStackTraceOnErrorSignal();
|
||||
@@ -87,10 +91,17 @@ int main(int argc_, const char **argv_) {
|
||||
Diags.addConsumer(PDC);
|
||||
|
||||
Driver TheDriver(Path, llvm::sys::path::stem(argv[0]), argv, Diags);
|
||||
if (TheDriver.getDriverKind() == Driver::DriverKind::UpdateCode) {
|
||||
switch (TheDriver.getDriverKind()) {
|
||||
case Driver::DriverKind::UpdateCode:
|
||||
return update_main(TheDriver.getArgsWithoutProgramNameAndDriverMode(argv),
|
||||
argv[0],
|
||||
(void *)(intptr_t)getExecutablePath);
|
||||
case Driver::DriverKind::AutolinkExtract:
|
||||
return autolink_extract_main(
|
||||
TheDriver.getArgsWithoutProgramNameAndDriverMode(argv),
|
||||
argv[0], (void *)(intptr_t)getExecutablePath);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
llvm::InitializeAllTargets();
|
||||
|
||||
Reference in New Issue
Block a user