[Autolink] Autolinking on COFF for Cygwin/MinGW

Cygwin and MinGW should use the autolink feature in the sameway of Linux
due to the linker's limit. Now swift-autolink-extract recognizes the
COFF format file for Cygwin/MinGW.
This commit is contained in:
Han Sangjin
2016-08-06 21:45:25 +09:00
parent 2ef0a8fdcb
commit 0747503b0f
9 changed files with 66 additions and 29 deletions

View File

@@ -273,7 +273,7 @@ code for the target that is not the build machine:
``armv7``, ``armv7k``, ``arm64``).
* ``%target-os``: the target operating system (``macosx``, ``darwin``,
``linux``, ``freebsd``).
``linux``, ``freebsd``, ``windows-cygnus``, ``windows-gnu``).
* ``%target-object-format``: the platform's object format (``elf``, ``macho``,
``coff``).

View File

@@ -1316,7 +1316,8 @@ void Driver::buildActions(const ToolChain &TC,
if (OI.shouldLink() && !AllLinkerInputs.empty()) {
auto *LinkAction = new LinkJobAction(AllLinkerInputs, OI.LinkAction);
if (TC.getTriple().getObjectFormat() == llvm::Triple::ELF) {
if (TC.getTriple().getObjectFormat() == llvm::Triple::ELF ||
TC.getTriple().isOSCygMing()) {
// 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.

View File

@@ -4,3 +4,4 @@
// REQUIRES: autolink-extract
// CHECK-elf: -lswiftCore
// CHECK-coff: -lswiftCore

View File

@@ -6,3 +6,4 @@
// REQUIRES: autolink-extract
// CHECK-elf: -lswiftCore
// CHECK-coff: -lswiftCore

View File

@@ -9,4 +9,7 @@
// CHECK-elf-DAG: -lswiftCore
// CHECK-elf-DAG: -lempty
// CHECK-coff-DAG: -lswiftCore
// CHECK-coff-DAG: -lempty
import empty

View File

@@ -10,4 +10,7 @@
// CHECK-elf-DAG: -lswiftCore
// CHECK-elf-DAG: -lempty
// CHECK-coff-DAG: -lswiftCore
// CHECK-coff-DAG: -lempty
import empty

View File

@@ -1,4 +1,6 @@
; RUN: llc -mtriple armv7--linux-gnueabihf -filetype obj -o - %s | %target-swift-autolink-extract -o - - | FileCheck %s
; RUN: llc -mtriple x86_64--windows-gnu -filetype obj -o - %s | %target-swift-autolink-extract -o - - | FileCheck %s
; RUN: llc -mtriple x86_64--windows-cygnus -filetype obj -o - %s | %target-swift-autolink-extract -o - - | FileCheck %s
; REQUIRES: autolink-extract
; Ensure that the options in the object file preserve ordering. The linker

View File

@@ -691,17 +691,30 @@ if run_vendor == 'apple':
"%s clang++ %s" %
(xcrun_prefix, config.target_cc_options))
elif run_os == 'linux-gnu' or run_os == 'linux-gnueabihf' or run_os == 'freebsd':
# Linux/FreeBSD
if run_os == 'freebsd':
elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'windows-gnu']:
# Linux/FreeBSD/Cygwin
if run_os == 'windows-cygnus':
lit_config.note("Testing Cygwin " + config.variant_triple)
config.target_object_format = "coff"
config.target_dylib_extension = "dll"
config.target_sdk_name = "cygwin"
elif run_os == 'windows-gnu':
lit_config.note("Testing MinGW " + config.variant_triple)
config.target_object_format = "coff"
config.target_dylib_extension = "dll"
config.target_sdk_name = "mingw"
elif run_os == 'freebsd':
lit_config.note("Testing FreeBSD " + config.variant_triple)
config.target_object_format = "elf"
config.target_dylib_extension = "so"
config.target_sdk_name = "freebsd"
else:
lit_config.note("Testing Linux " + config.variant_triple)
config.target_object_format = "elf"
config.target_dylib_extension = "so"
config.target_object_format = "elf"
config.target_dylib_extension = "so"
config.target_sdk_name = "linux"
config.target_runtime = "native"
config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract")
config.target_sdk_name = "freebsd" if run_os == "freebsd" else "linux"
config.target_build_swift = (
'%s -target %s %s %s %s %s'
% (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt,

View File

@@ -31,6 +31,7 @@
#include "llvm/Option/Option.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
using namespace swift;
@@ -106,32 +107,44 @@ public:
}
};
// Look inside the binary 'Bin' and append any linker flags found in its
// ".swift1_autolink_entries" section to 'LinkerFlags'. If 'Bin' is an archive,
// recursively look inside all children within the archive. Return 'true' if
// there was an error, and 'false' otherwise.
/// Look inside the object file 'ObjectFile' and append any linker flags found in
/// its ".swift1_autolink_entries" section to 'LinkerFlags'.
static void
extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
std::vector<std::string> &LinkerFlags) {
// Search for the section we hold autolink entries in
for (auto &Section : ObjectFile->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.push_back(Flag);
}
}
}
/// Look inside the binary 'Bin' and append any linker flags found in its
/// ".swift1_autolink_entries" section to 'LinkerFlags'. If 'Bin' is an archive,
/// recursively look inside all children within the archive. Return 'true' if
/// there was an error, and 'false' otherwise.
static bool extractLinkerFlags(const llvm::object::Binary *Bin,
CompilerInstance &Instance,
StringRef BinaryFileName,
std::vector<std::string> &LinkerFlags) {
if (auto *ObjectFile = llvm::dyn_cast<llvm::object::ELFObjectFileBase>(Bin)) {
// Search for the section we hold autolink entries in
for (auto &Section : ObjectFile->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.push_back(Flag);
}
}
extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags);
return false;
} else if (auto *ObjectFile =
llvm::dyn_cast<llvm::object::COFFObjectFile>(Bin)) {
extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags);
return false;
} else if (auto *Archive = llvm::dyn_cast<llvm::object::Archive>(Bin)) {
for (const auto &Child : Archive->children()) {