ldc/driver/linker.cpp
Martin Kinkelin 1572c91fc0
Add -link-defaultlib-shared and rename -link-debuglib (#2443)
... to -link-defaultlib-debug (with alias for backwards compatibility).

-link-defaultlib-shared is to be used for switching between static and
shared default libs to be linked with.

It defaults to true when generating shared libraries (if shared
druntime/Phobos are supported for the target, i.e., not for Windows).
This is a benign breaking change!
2018-01-12 18:26:19 +01:00

164 lines
5.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- linker.cpp --------------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#include "errors.h"
#include "driver/cl_options.h"
#include "driver/linker.h"
#include "driver/tool.h"
#include "gen/llvm.h"
#include "gen/logger.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/SourceMgr.h"
//////////////////////////////////////////////////////////////////////////////
#if LDC_WITH_LLD
static llvm::cl::opt<bool>
useInternalLinker("link-internally", llvm::cl::ZeroOrMore, llvm::cl::Hidden,
llvm::cl::desc("Use internal LLD for linking"));
#else
constexpr bool useInternalLinker = false;
#endif
//////////////////////////////////////////////////////////////////////////////
// linker-gcc.cpp
int linkObjToBinaryGcc(llvm::StringRef outputPath, bool useInternalLinker,
llvm::cl::boolOrDefault fullyStaticFlag);
// linker-msvc.cpp
int linkObjToBinaryMSVC(llvm::StringRef outputPath, bool useInternalLinker,
llvm::cl::boolOrDefault fullyStaticFlag);
//////////////////////////////////////////////////////////////////////////////
static std::string getOutputName() {
const auto &triple = *global.params.targetTriple;
const bool sharedLib = global.params.dll;
const char *extension = nullptr;
if (sharedLib) {
extension = global.dll_ext;
} else if (triple.isOSWindows()) {
extension = "exe";
}
if (global.params.exefile) {
// DMD adds the default extension if there is none
return opts::invokedByLDMD && extension
? FileName::defaultExt(global.params.exefile, extension)
: global.params.exefile;
}
// Infer output name from first object file.
std::string result = global.params.objfiles->dim
? FileName::removeExt((*global.params.objfiles)[0])
: "a.out";
if (sharedLib && !triple.isWindowsMSVCEnvironment())
result = "lib" + result;
if (global.params.run) {
// If `-run` is passed, the executable is temporary and is removed
// after execution. Make sure the name does not collide with other files
// from other processes by creating a unique filename.
llvm::SmallString<128> tempFilename;
auto EC = llvm::sys::fs::createTemporaryFile(FileName::name(result.c_str()),
extension ? extension : "",
tempFilename);
if (!EC)
result = tempFilename.str();
} else if (extension) {
result += '.';
result += extension;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////
/// Insert an LLVM bitcode file into the module
static void insertBitcodeIntoModule(const char *bcFile, llvm::Module &M,
llvm::LLVMContext &Context) {
Logger::println("*** Linking-in bitcode file %s ***", bcFile);
llvm::SMDiagnostic Err;
std::unique_ptr<llvm::Module> loadedModule(
getLazyIRFileModule(bcFile, Err, Context));
if (!loadedModule) {
error(Loc(), "Error when loading LLVM bitcode file: %s", bcFile);
fatal();
}
#if LDC_LLVM_VER >= 308
llvm::Linker(M).linkInModule(std::move(loadedModule));
#else
llvm::Linker(&M).linkInModule(loadedModule.release());
#endif
}
/// Insert LLVM bitcode files into the module
void insertBitcodeFiles(llvm::Module &M, llvm::LLVMContext &Ctx,
Array<const char *> &bitcodeFiles) {
for (const char *fname : bitcodeFiles) {
insertBitcodeIntoModule(fname, M, Ctx);
}
}
//////////////////////////////////////////////////////////////////////////////
// path to the produced executable/shared library
static std::string gExePath;
//////////////////////////////////////////////////////////////////////////////
int linkObjToBinary() {
Logger::println("*** Linking executable ***");
// remember output path for later
gExePath = getOutputName();
createDirectoryForFileOrFail(gExePath);
if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
return linkObjToBinaryMSVC(gExePath, useInternalLinker, opts::staticFlag);
}
return linkObjToBinaryGcc(gExePath, useInternalLinker, opts::staticFlag);
}
//////////////////////////////////////////////////////////////////////////////
void deleteExeFile() {
if (!gExePath.empty() && !llvm::sys::fs::is_directory(gExePath)) {
llvm::sys::fs::remove(gExePath);
}
}
//////////////////////////////////////////////////////////////////////////////
int runProgram() {
assert(!gExePath.empty());
// Run executable
int status =
executeToolAndWait(gExePath, opts::runargs, global.params.verbose);
if (status < 0) {
#if defined(_MSC_VER) || defined(__MINGW32__)
error(Loc(), "program received signal %d", -status);
#else
error(Loc(), "program received signal %d (%s)", -status,
strsignal(-status));
#endif
return -status;
}
return status;
}