forked from OSchip/llvm-project
[Driver] Fix symlinked universal driver behavior and add a test.
llvm-svn: 178798
This commit is contained in:
parent
c451e5766e
commit
dfe85483d5
|
@ -48,21 +48,11 @@ private:
|
|||
class UniversalDriver : public Driver {
|
||||
public:
|
||||
/// Determine flavor and pass control to Driver for that flavor.
|
||||
static bool link(int argc, const char *argv[]);
|
||||
static bool link(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
private:
|
||||
UniversalDriver() LLVM_DELETED_FUNCTION;
|
||||
|
||||
enum class Flavor {
|
||||
invalid,
|
||||
gnu_ld, // -flavor gnu
|
||||
win_link, // -flavor link
|
||||
darwin_ld, // -flavor darwin
|
||||
core // -flavor core OR -core
|
||||
};
|
||||
|
||||
static Flavor selectFlavor(std::vector<const char*> &args);
|
||||
static Flavor strToFlavor(StringRef str);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -14,96 +14,120 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/ReaderWriter/MachOTargetInfo.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/Option.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
|
||||
#include <memory>
|
||||
using namespace lld;
|
||||
|
||||
namespace {
|
||||
enum class Flavor {
|
||||
invalid,
|
||||
gnu_ld, // -flavor gnu
|
||||
win_link, // -flavor link
|
||||
darwin_ld, // -flavor darwin
|
||||
core // -flavor core OR -core
|
||||
};
|
||||
|
||||
Flavor strToFlavor(StringRef str) {
|
||||
return llvm::StringSwitch<Flavor>(str)
|
||||
.Case("gnu", Flavor::gnu_ld)
|
||||
.Case("link", Flavor::win_link)
|
||||
.Case("darwin", Flavor::darwin_ld)
|
||||
.Case("core", Flavor::core)
|
||||
.Case("ld", Flavor::gnu_ld) // deprecated
|
||||
.Default(Flavor::invalid);
|
||||
}
|
||||
|
||||
struct ProgramNameParts {
|
||||
StringRef _target;
|
||||
StringRef _flavor;
|
||||
};
|
||||
|
||||
ProgramNameParts parseProgramName(StringRef programName) {
|
||||
SmallVector<StringRef, 3> components;
|
||||
llvm::SplitString(programName, components, "-");
|
||||
ProgramNameParts ret;
|
||||
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
// Erase any lld components.
|
||||
components.erase(std::remove(components.begin(), components.end(), "lld"),
|
||||
components.end());
|
||||
|
||||
// Find the flavor component.
|
||||
auto flIter = std::find_if(components.begin(), components.end(),
|
||||
[](StringRef str)->bool {
|
||||
return strToFlavor(str) != Flavor::invalid;
|
||||
});
|
||||
|
||||
if (flIter != components.end()) {
|
||||
ret._flavor = *flIter;
|
||||
components.erase(flIter);
|
||||
}
|
||||
|
||||
// Any remaining component must be the target.
|
||||
if (components.size() == 1)
|
||||
ret._target = components[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Flavor selectFlavor(std::vector<const char *> &args, raw_ostream &diag) {
|
||||
// -core as first arg is shorthand for -flavor core.
|
||||
if (args.size() > 1 && StringRef(args[1]) == "-core") {
|
||||
args.erase(args.begin() + 1);
|
||||
return Flavor::core;
|
||||
}
|
||||
// Handle -flavor as first arg.
|
||||
if (args.size() > 2 && StringRef(args[1]) == "-flavor") {
|
||||
Flavor flavor = strToFlavor(args[2]);
|
||||
args.erase(args.begin() + 1);
|
||||
args.erase(args.begin() + 1);
|
||||
if (flavor == Flavor::invalid)
|
||||
diag << "error: '" << args[2] << "' invalid value for -flavor.\n";
|
||||
return flavor;
|
||||
}
|
||||
|
||||
Flavor flavor =
|
||||
strToFlavor(parseProgramName(llvm::sys::path::stem(args[0]))._flavor);
|
||||
|
||||
// If flavor still undetermined, then error out.
|
||||
if (flavor == Flavor::invalid)
|
||||
diag << "error: failed to determine driver flavor from program name"
|
||||
" '" << args[0] << "'.\n";
|
||||
return flavor;
|
||||
}
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
||||
bool UniversalDriver::link(int argc, const char *argv[]) {
|
||||
bool UniversalDriver::link(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics) {
|
||||
// Convert argv[] C-array to vector.
|
||||
std::vector<const char *> args;
|
||||
args.assign(&argv[0], &argv[argc]);
|
||||
|
||||
std::vector<const char *> args(argv, argv + argc);
|
||||
|
||||
// Determine flavor of link based on command name or -flavor argument.
|
||||
// Note: 'args' is modified to remove -flavor option.
|
||||
Flavor flavor = selectFlavor(args);
|
||||
|
||||
Flavor flavor = selectFlavor(args, diagnostics);
|
||||
|
||||
// Switch to appropriate driver.
|
||||
switch (flavor) {
|
||||
case Flavor::gnu_ld:
|
||||
return GnuLdDriver::linkELF(args.size(), &args[0]);
|
||||
return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
|
||||
case Flavor::darwin_ld:
|
||||
return DarwinLdDriver::linkMachO(args.size(), &args[0]);
|
||||
return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
|
||||
case Flavor::core:
|
||||
return CoreDriver::link(args.size(), &args[0]);
|
||||
return CoreDriver::link(args.size(), args.data(), diagnostics);
|
||||
case Flavor::win_link:
|
||||
llvm_unreachable("Unsupported flavor");
|
||||
case Flavor::invalid:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Pick the flavor of driver to use based on the command line and
|
||||
/// host environment.
|
||||
UniversalDriver::Flavor UniversalDriver::selectFlavor(
|
||||
std::vector<const char*> &args) {
|
||||
// -core as first arg is shorthand for -flavor core.
|
||||
if (args.size() >= 1 && StringRef(args[1]) == "-core") {
|
||||
args.erase(args.begin() + 1);
|
||||
return Flavor::core;
|
||||
}
|
||||
// Handle -flavor as first arg.
|
||||
if (args.size() >= 2 && StringRef(args[1]) == "-flavor") {
|
||||
Flavor flavor = strToFlavor(args[2]);
|
||||
args.erase(args.begin() + 1);
|
||||
args.erase(args.begin() + 1);
|
||||
if (flavor == Flavor::invalid)
|
||||
llvm::errs() << "error: '" << args[2] << "' invalid value for -flavor.\n";
|
||||
return flavor;
|
||||
}
|
||||
|
||||
// Check if flavor is at end of program name (e.g. "lld-gnu");
|
||||
SmallVector<StringRef, 3> components;
|
||||
llvm::SplitString(args[0], components, "-");
|
||||
Flavor flavor = strToFlavor(components.back());
|
||||
|
||||
// If flavor still undetermined, then error out.
|
||||
if (flavor == Flavor::invalid)
|
||||
llvm::errs() << "error: failed to determine driver flavor from program name"
|
||||
" '" << args[0] << "'.\n";
|
||||
return flavor;
|
||||
}
|
||||
|
||||
/// Maps flavor strings to Flavor enum values.
|
||||
UniversalDriver::Flavor UniversalDriver::strToFlavor(StringRef str) {
|
||||
return llvm::StringSwitch<Flavor>(str)
|
||||
.Case("gnu", Flavor::gnu_ld)
|
||||
.Case("darwin", Flavor::darwin_ld)
|
||||
.Case("link", Flavor::win_link)
|
||||
.Case("core", Flavor::core)
|
||||
.Case("ld", Flavor::gnu_ld) // deprecated
|
||||
.Default(Flavor::invalid);
|
||||
}
|
||||
|
||||
|
||||
} // namespace lld
|
||||
} // end namespace lld
|
||||
|
|
|
@ -7,12 +7,8 @@ set_target_properties(LLDUnitTests PROPERTIES FOLDER "lld tests")
|
|||
# Produces a binary named 'basename(test_dirname)'.
|
||||
function(add_lld_unittest test_dirname)
|
||||
add_unittest(LLDUnitTests ${test_dirname} ${ARGN})
|
||||
target_link_libraries(${test_dirname} ${LLVM_COMMON_LIBS})
|
||||
endfunction()
|
||||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
support
|
||||
)
|
||||
|
||||
add_lld_unittest(CoreTests
|
||||
RangeTest.cpp
|
||||
)
|
||||
add_subdirectory(CoreTests)
|
||||
add_subdirectory(DriverTests)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
add_lld_unittest(CoreTests
|
||||
RangeTest.cpp
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
add_lld_unittest(DriverTests
|
||||
UniversalDriverTest.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(DriverTests
|
||||
lldDriver
|
||||
)
|
|
@ -0,0 +1,35 @@
|
|||
//===- lld/unittest/UniversalDriverTest.cpp -------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// \brief Universal driver tests that depend on the value of argv[0].
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace lld;
|
||||
|
||||
TEST(UniversalDriver, flavor) {
|
||||
const char *args[] = { "ld" };
|
||||
|
||||
std::string diags;
|
||||
raw_string_ostream os(diags);
|
||||
UniversalDriver::link(array_lengthof(args), args, os);
|
||||
EXPECT_EQ(os.str().find("failed to determine driver flavor"),
|
||||
std::string::npos);
|
||||
EXPECT_NE(os.str().find("No input files"),
|
||||
std::string::npos);
|
||||
}
|
Loading…
Reference in New Issue