From 0747503b0f2e7207d494dba44504fa373f3615e3 Mon Sep 17 00:00:00 2001 From: Han Sangjin Date: Sat, 6 Aug 2016 21:45:25 +0900 Subject: [PATCH] [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. --- docs/Testing.rst | 2 +- lib/Driver/Driver.cpp | 3 +- test/AutolinkExtract/empty.swift | 1 + test/AutolinkExtract/empty_archive.swift | 1 + test/AutolinkExtract/import.swift | 3 ++ test/AutolinkExtract/import_archive.swift | 3 ++ test/AutolinkExtract/linker-order.ll | 2 + test/lit.cfg | 25 ++++++++--- tools/driver/autolink_extract_main.cpp | 55 ++++++++++++++--------- 9 files changed, 66 insertions(+), 29 deletions(-) diff --git a/docs/Testing.rst b/docs/Testing.rst index aadea8e0c7abb..75f347465620d 100644 --- a/docs/Testing.rst +++ b/docs/Testing.rst @@ -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``). diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1019f9ef044ee..f054e79a9189a 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -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. diff --git a/test/AutolinkExtract/empty.swift b/test/AutolinkExtract/empty.swift index 8dd98ea73bccc..2e3254611ea07 100644 --- a/test/AutolinkExtract/empty.swift +++ b/test/AutolinkExtract/empty.swift @@ -4,3 +4,4 @@ // REQUIRES: autolink-extract // CHECK-elf: -lswiftCore +// CHECK-coff: -lswiftCore diff --git a/test/AutolinkExtract/empty_archive.swift b/test/AutolinkExtract/empty_archive.swift index 54ebecee01c03..030ef6371f7b5 100644 --- a/test/AutolinkExtract/empty_archive.swift +++ b/test/AutolinkExtract/empty_archive.swift @@ -6,3 +6,4 @@ // REQUIRES: autolink-extract // CHECK-elf: -lswiftCore +// CHECK-coff: -lswiftCore diff --git a/test/AutolinkExtract/import.swift b/test/AutolinkExtract/import.swift index 225dfffb14e2b..c87a7bcf33fd2 100644 --- a/test/AutolinkExtract/import.swift +++ b/test/AutolinkExtract/import.swift @@ -9,4 +9,7 @@ // CHECK-elf-DAG: -lswiftCore // CHECK-elf-DAG: -lempty +// CHECK-coff-DAG: -lswiftCore +// CHECK-coff-DAG: -lempty + import empty diff --git a/test/AutolinkExtract/import_archive.swift b/test/AutolinkExtract/import_archive.swift index 0cba4a193991c..d3fa6a6f716b1 100644 --- a/test/AutolinkExtract/import_archive.swift +++ b/test/AutolinkExtract/import_archive.swift @@ -10,4 +10,7 @@ // CHECK-elf-DAG: -lswiftCore // CHECK-elf-DAG: -lempty +// CHECK-coff-DAG: -lswiftCore +// CHECK-coff-DAG: -lempty + import empty diff --git a/test/AutolinkExtract/linker-order.ll b/test/AutolinkExtract/linker-order.ll index 8f84a202531d5..7da7d6036aa0f 100644 --- a/test/AutolinkExtract/linker-order.ll +++ b/test/AutolinkExtract/linker-order.ll @@ -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 diff --git a/test/lit.cfg b/test/lit.cfg index a6a34af9352de..2e1ed5f30e8a5 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -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, diff --git a/tools/driver/autolink_extract_main.cpp b/tools/driver/autolink_extract_main.cpp index 949aca3408731..64cca89e7bf47 100644 --- a/tools/driver/autolink_extract_main.cpp +++ b/tools/driver/autolink_extract_main.cpp @@ -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 @@ class AutolinkExtractInvocation { } }; -// 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 &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 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 &LinkerFlags) { if (auto *ObjectFile = llvm::dyn_cast(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 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(Bin)) { + extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags); return false; } else if (auto *Archive = llvm::dyn_cast(Bin)) { for (const auto &Child : Archive->children()) {