Index: include/lld/LinkDriver/LinkDriver.h =================================================================== --- /dev/null +++ include/lld/LinkDriver/LinkDriver.h @@ -0,0 +1,26 @@ +//===- lld/LinkDriver/LinkDriver.h - link.exe-compatible driver -*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines an interface to a link.exe-compatible driver. +// Used by lld-link. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_LINKDRIVER_LINKDRIVER_H +#define LLD_LINKDRIVER_LINKDRIVER_H + +#include "llvm/ADT/ArrayRef.h" + +namespace lld { + +int linkDriverMain(llvm::ArrayRef ArgsArr); + +} + +#endif Index: lib/CMakeLists.txt =================================================================== --- lib/CMakeLists.txt +++ lib/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(Config) add_subdirectory(Core) add_subdirectory(Driver) +add_subdirectory(LinkDriver) add_subdirectory(ReaderWriter) Index: lib/LinkDriver/CMakeLists.txt =================================================================== --- /dev/null +++ lib/LinkDriver/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_TARGET_DEFINITIONS Options.td) +tablegen(LLVM Options.inc -gen-opt-parser-defs) +add_public_tablegen_target(LinkOptionsTableGen) + +add_llvm_library(LLDLinkDriver + LinkDriver.cpp + ) +add_dependencies(LLDLinkDriver LinkOptionsTableGen) Index: lib/LinkDriver/LinkDriver.cpp =================================================================== --- /dev/null +++ lib/LinkDriver/LinkDriver.cpp @@ -0,0 +1,85 @@ +//===- LinkDriver.cpp - link.exe-compatible driver ------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a link.exe-compatible driver +// Used by lld-link. +// +//===----------------------------------------------------------------------===// + +#include "lld/LinkDriver/LinkDriver.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/StringSaver.h" + +using namespace llvm; + +namespace { + +enum { + OPT_INVALID = 0, +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, +#include "Options.inc" +#undef OPTION +}; + +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#include "Options.inc" +#undef PREFIX + +static const llvm::opt::OptTable::Info infoTable[] = { +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ + { \ + X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ + OPT_##GROUP, OPT_##ALIAS, X6 \ + }, +#include "Options.inc" +#undef OPTION +}; + +class LinkOptTable : public llvm::opt::OptTable { +public: + LinkOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {} +}; + +} + +int lld::linkDriverMain(llvm::ArrayRef ArgsArr) { + SmallVector NewArgs(ArgsArr.begin(), ArgsArr.end()); + BumpPtrAllocator Alloc; + StringSaver Saver(Alloc); + cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgs); + ArgsArr = NewArgs; + + LinkOptTable Table; + unsigned MissingIndex; + unsigned MissingCount; + llvm::opt::InputArgList Args = + Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount); + if (MissingCount) { + llvm::errs() << "missing arg value for \"" + << Args.getArgString(MissingIndex) + << "\", expected " << MissingCount + << (MissingCount == 1 ? " argument.\n" : " arguments.\n"); + return 1; + } + for (auto *Arg : Args.filtered(OPT_UNKNOWN)) + llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; + + if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) { + llvm::errs() << "no input files.\n"; + return 1; + } + + return 0; +} Index: lib/LinkDriver/Options.td =================================================================== --- /dev/null +++ lib/LinkDriver/Options.td @@ -0,0 +1,12 @@ +include "llvm/Option/OptParser.td" + +// link.exe accepts options starting with either a dash or a slash. + +// Flag that takes no arguments. +class F : Flag<["/", "-", "-?"], name>; + +// Flag that takes one argument after ":". +class P : + Joined<["/", "-", "-?"], name#":">, HelpText; + +def out : P<"out", "Path to file to write output">; Index: tools/lld/CMakeLists.txt =================================================================== --- tools/lld/CMakeLists.txt +++ tools/lld/CMakeLists.txt @@ -11,16 +11,18 @@ install(TARGETS lld RUNTIME DESTINATION bin) -# Create the lld-link[.exe] symlink in the build directory. If symlink is not -# supported by the operating system, create a copy instead. if(UNIX) - set(command create_symlink) - # Make relative symlink - set(src "lld${CMAKE_EXECUTABLE_SUFFIX}") + set(LLD_LINK_OR_COPY create_symlink) + set(lld_binary "lld${CMAKE_EXECUTABLE_SUFFIX}") else() - set(command copy) - set(src "${LLVM_RUNTIME_OUTPUT_INTDIR}/lld${CMAKE_EXECUTABLE_SUFFIX}") + set(LLD_LINK_OR_COPY copy) + set(lld_binary "${LLVM_RUNTIME_OUTPUT_INTDIR}/lld${CMAKE_EXECUTABLE_SUFFIX}") endif() -set(dst "${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link${CMAKE_EXECUTABLE_SUFFIX}") -add_custom_command(TARGET lld POST_BUILD - COMMAND ${CMAKE_COMMAND} -E ${command} ${src} ${dst}) + +set(lld_link "${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link${CMAKE_EXECUTABLE_SUFFIX}") + +add_custom_command(OUTPUT ${lld_link} + COMMAND ${CMAKE_COMMAND} -E ${LLD_LINK_OR_COPY} "${lld_binary}" "${lld_link}" + DEPENDS lld) + +install(SCRIPT install_symlink.cmake -DCMAKE_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\") Index: tools/lld/install_symlink.cmake =================================================================== --- /dev/null +++ tools/lld/install_symlink.cmake @@ -0,0 +1,25 @@ +# We need to execute this script at installation time because the +# DESTDIR environment variable may be unset at configuration time. +# See PR8397. + +if(UNIX) + set(LINK_OR_COPY create_symlink) + set(DESTDIR $ENV{DESTDIR}) +else() + set(LINK_OR_COPY copy) +endif() + +# CMAKE_EXECUTABLE_SUFFIX is undefined on cmake scripts. See PR9286. +if( WIN32 ) + set(EXECUTABLE_SUFFIX ".exe") +else() + set(EXECUTABLE_SUFFIX "") +endif() + +set(bindir "${DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/") + +message("Creating lld-link") + +execute_process( + COMMAND "${CMAKE_COMMAND}" -E ${LINK_OR_COPY} "lld${EXECUTABLE_SUFFIX}" "lld-link${EXECUTABLE_SUFFIX}" + WORKING_DIRECTORY "${bindir}")