From dae2ef47f1e40762bbb8bb6dc2ff5f2409e2d68e Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 21 Nov 2013 01:08:53 +0000 Subject: [PATCH] [PECOFF] Move files with ".lib" extension to the end of the input file list. It's allowed to specify library files *before* object files in the command line. Object files seems to be processed first, and then their undefined symbols are resolved from the libraries. This patch implements the compatible behavior. llvm-svn: 195295 --- lld/lib/Driver/WinLinkDriver.cpp | 17 +++++++++++++++-- lld/unittests/DriverTests/WinLinkDriverTest.cpp | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 7f71a3c97b9f..7e9a55cfcbd7 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -13,6 +13,7 @@ /// //===----------------------------------------------------------------------===// +#include #include #include #include @@ -600,6 +601,8 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx, defaultLibs.push_back((*it)->getValue()); } + std::vector inputFiles; + // Process all the arguments and create Input Elements for (auto inputArg : *parsedArgs) { switch (inputArg->getOption().getID()) { @@ -850,8 +853,7 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx, break; case OPT_INPUT: - inputElements.push_back(std::unique_ptr( - new PECOFFFileNode(ctx, ctx.allocate(inputArg->getValue())))); + inputFiles.push_back(ctx.allocate(inputArg->getValue())); break; #define DEFINE_BOOLEAN_FLAG(name, setter) \ @@ -877,6 +879,17 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx, } } + // Move files with ".lib" extension at the end of the input file list. Say + // foo.obj depends on bar.lib. The linker needs to accept both "bar.lib + // foo.obj" and "foo.obj bar.lib". + auto compfn = [](StringRef a, StringRef b) { + return !a.endswith_lower(".lib") && b.endswith_lower(".lib"); + }; + std::stable_sort(inputFiles.begin(), inputFiles.end(), compfn); + for (StringRef path : inputFiles) + inputElements.push_back(std::unique_ptr( + new PECOFFFileNode(ctx, path))); + // Use the default entry name if /entry option is not given. if (ctx.entrySymbolName().empty()) ctx.setEntrySymbolName(getDefaultEntrySymbolName(ctx)); diff --git a/lld/unittests/DriverTests/WinLinkDriverTest.cpp b/lld/unittests/DriverTests/WinLinkDriverTest.cpp index 65f2a9c3161f..89a590fbd914 100644 --- a/lld/unittests/DriverTests/WinLinkDriverTest.cpp +++ b/lld/unittests/DriverTests/WinLinkDriverTest.cpp @@ -130,6 +130,21 @@ TEST_F(WinLinkParserTest, Libpath) { EXPECT_EQ("dir2", paths[1]); } +// +// Tests for input file order +// + +TEST_F(WinLinkParserTest, InputOrder) { + EXPECT_TRUE(parse("link.exe", "b.lib", "b.obj", "c.obj", "a.lib", "a.obj", + nullptr)); + EXPECT_EQ(5, inputFileCount()); + EXPECT_EQ("b.obj", inputFile(0)); + EXPECT_EQ("c.obj", inputFile(1)); + EXPECT_EQ("a.obj", inputFile(2)); + EXPECT_EQ("b.lib", inputFile(3)); + EXPECT_EQ("a.lib", inputFile(4)); +} + // // Tests for command line options that take values. //