Skip to content

Commit

Permalink
Merge pull request #2142 from kinke/archiver
Browse files Browse the repository at this point in the history
Integrate LLD for MSVC targets; prepare for other targets
  • Loading branch information
kinke committed Jun 4, 2017
2 parents e659db6 + 383c2d3 commit 2008400
Show file tree
Hide file tree
Showing 21 changed files with 892 additions and 738 deletions.
37 changes: 32 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")

include(FindDCompiler)
include(CheckIncludeFile)
include(CheckIncludeFileCXX)
include(CheckLibraryExists)
include(CheckCXXCompilerFlag)
include(CheckDSourceCompiles)
Expand Down Expand Up @@ -80,7 +81,7 @@ set(CONF_INST_DIR ${SYSCONF_INSTALL_DIR} CACHE PATH "Directory ldc.conf is insta
# Note: LIB_SUFFIX should perhaps be renamed to LDC_LIBDIR_SUFFIX.
set(LIB_SUFFIX "" CACHE STRING "Appended to the library installation directory. Set to '64' to install libraries into ${PREFIX}/lib64.")

# The following flags are currently not well tested, expect the build to fail.
# The following flag is currently not well tested, expect the build to fail.
option(GENERATE_OFFTI "generate complete ClassInfo.offTi arrays")
mark_as_advanced(GENERATE_OFFTI)

Expand Down Expand Up @@ -342,6 +343,8 @@ set(DRV_SRC
driver/tool.cpp
driver/archiver.cpp
driver/linker.cpp
driver/linker-gcc.cpp
driver/linker-msvc.cpp
driver/main.cpp
${CMAKE_BINARY_DIR}/driver/ldc-version.cpp
)
Expand Down Expand Up @@ -426,8 +429,6 @@ include_directories( SYSTEM
)
append("-I${PROJECT_SOURCE_DIR}" DDMD_DFLAGS)
append("-I${PROJECT_BINARY_DIR}" DDMD_DFLAGS)


if(MSVC)
include_directories(${PROJECT_SOURCE_DIR}/vcbuild)
endif()
Expand All @@ -446,12 +447,31 @@ if(GENERATE_OFFTI)
append("-DGENERATE_OFFTI" LDC_CXXFLAGS)
endif()

option(RISCV_LLVM_DEV, "full RISC-V support with riscv-llvm")
mark_as_advanced(RISCV_LLVM_DEV)
#
# LLD integration (requires LLVM >= 3.9 with LLD headers & libs)
#
set(LDC_WITH_LLD OFF)
if(LDC_LLVM_VER GREATER 308)
# check for LLD header
unset(LDC_WITH_LLD)
if(NOT MSVC)
set(CMAKE_REQUIRED_FLAGS -std=c++11)
endif()
set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIRS})
CHECK_INCLUDE_FILE_CXX(lld/Driver/Driver.h LDC_WITH_LLD)
unset(CMAKE_REQUIRED_FLAGS)
unset(CMAKE_REQUIRED_INCLUDES)
if(LDC_WITH_LLD)
message(STATUS "Building LDC with LLD support")
append("-DLDC_WITH_LLD" LDC_CXXFLAGS)
endif()
endif()

#
# Enable building with riscv-llvm, for full RISC-V support.
#
option(RISCV_LLVM_DEV, "full RISC-V support with riscv-llvm")
mark_as_advanced(RISCV_LLVM_DEV)
if(RISCV_LLVM_DEV)
append("-DRISCV_LLVM_DEV" LDC_CXXFLAGS)
endif()
Expand Down Expand Up @@ -546,6 +566,13 @@ add_custom_target(${LDMD_EXE} ALL DEPENDS ${LDMD_EXE_FULL})
# Figure out how to link the main LDC executable, for which we need to take the
# LLVM flags into account.
set(LDC_LINKERFLAG_LIST "${SANITIZE_LDFLAGS};${LLVM_LIBRARIES};${LLVM_LDFLAGS}")
if(LDC_WITH_LLD)
if(MSVC)
list(APPEND LDC_LINKERFLAG_LIST lldCOFF.lib lldCore.lib lldDriver.lib)
else()
set(LDC_LINKERFLAG_LIST "-llldCOFF;-llldCore;-llldDriver;${LDC_LINKERFLAG_LIST}")
endif()
endif()

set(LDC_LINK_MANUALLY OFF)
if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")))
Expand Down
3 changes: 2 additions & 1 deletion ddmd/mars.d
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,10 @@ version(IN_LLVM)
// in driver/main.cpp
void addDefaultVersionIdentifiers();
void codegenModules(ref Modules modules);
// in driver/archiver.cpp
int createStaticLibrary();
// in driver/linker.cpp
int linkObjToBinary();
int createStaticLibrary();
void deleteExeFile();
int runProgram();
}
Expand Down
140 changes: 122 additions & 18 deletions driver/archiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@
// License. See LLVM LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Builds up (relatively) standard unix archive files (.a) containing LLVM
// bitcode or other files.
//
//===----------------------------------------------------------------------===//

#if LDC_LLVM_VER >= 309
#include "errors.h"
#include "globals.h"
#include "driver/cl_options.h"
#include "driver/tool.h"
#include "gen/logger.h"
#include "llvm/ADT/Triple.h"

#include "driver/archiver.h"
#if LDC_LLVM_VER >= 309

#include "llvm/ADT/Triple.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/MachO.h"
Expand All @@ -42,7 +41,7 @@ using namespace llvm;
* support for `llvm-ar rcs <archive name> <member> ...`.
* It also makes sure the process isn't simply exited whenever a problem arises.
*/
namespace {
namespace llvm_ar {

StringRef ArchiveName;
std::vector<const char *> Members;
Expand Down Expand Up @@ -237,13 +236,13 @@ int performWriteOperation() {
return performWriteOperation(nullptr, nullptr);
}

} // anonymous namespace
} // namespace llvm_ar

////////////////////////////////////////////////////////////////////////////////

namespace ldc {
namespace {

int ar(ArrayRef<const char *> args) {
int internalAr(ArrayRef<const char *> args) {
if (args.size() < 4 || strcmp(args[0], "llvm-ar") != 0 ||
strcmp(args[1], "rcs") != 0) {
llvm_unreachable(
Expand All @@ -252,16 +251,17 @@ int ar(ArrayRef<const char *> args) {
return -1;
}

ArchiveName = args[2];
llvm_ar::ArchiveName = args[2];

auto membersSlice = args.slice(3);
Members.clear();
Members.insert(Members.end(), membersSlice.begin(), membersSlice.end());
llvm_ar::Members.clear();
llvm_ar::Members.insert(llvm_ar::Members.end(), membersSlice.begin(),
membersSlice.end());

return performWriteOperation();
return llvm_ar::performWriteOperation();
}

int lib(ArrayRef<const char *> args) {
int internalLib(ArrayRef<const char *> args) {
if (args.size() < 1 || strcmp(args[0], "llvm-lib.exe") != 0) {
llvm_unreachable("Expected archiver command line: llvm-lib.exe ...");
return -1;
Expand All @@ -270,6 +270,110 @@ int lib(ArrayRef<const char *> args) {
return libDriverMain(args);
}

} // namespace ldc
} // anonymous namespace

#endif // LDC_LLVM_VER >= 309

////////////////////////////////////////////////////////////////////////////////

static llvm::cl::opt<std::string> ar("ar", llvm::cl::desc("Archiver"),
llvm::cl::Hidden, llvm::cl::ZeroOrMore);

int createStaticLibrary() {
Logger::println("*** Creating static library ***");

const bool isTargetMSVC =
global.params.targetTriple->isWindowsMSVCEnvironment();

#if LDC_LLVM_VER >= 309
const bool useInternalArchiver = ar.empty();
#else
const bool useInternalArchiver = false;
#endif

// find archiver
std::string tool;
if (useInternalArchiver) {
tool = isTargetMSVC ? "llvm-lib.exe" : "llvm-ar";
} else {
#ifdef _WIN32
if (isTargetMSVC)
windows::setupMsvcEnvironment();
#endif

tool = getProgram(isTargetMSVC ? "lib.exe" : "ar", &ar);
}

// build arguments
std::vector<std::string> args;

// ask ar to create a new library
if (!isTargetMSVC) {
args.push_back("rcs");
}

// ask lib.exe to be quiet
if (isTargetMSVC) {
args.push_back("/NOLOGO");
}

// output filename
std::string libName;
if (global.params.libname) { // explicit
// DMD adds the default extension if there is none
libName = opts::invokedByLDMD
? FileName::defaultExt(global.params.libname, global.lib_ext)
: global.params.libname;
} else { // infer from first object file
libName = global.params.objfiles->dim
? FileName::removeExt((*global.params.objfiles)[0])
: "a.out";
libName += '.';
libName += global.lib_ext;
}

// DMD creates static libraries in the objects directory (unless using an
// absolute output path via `-of`).
if (opts::invokedByLDMD && global.params.objdir &&
!FileName::absolute(libName.c_str())) {
libName = FileName::combine(global.params.objdir, libName.c_str());
}

if (isTargetMSVC) {
args.push_back("/OUT:" + libName);
} else {
args.push_back(libName);
}

// object files
for (auto objfile : *global.params.objfiles) {
args.push_back(objfile);
}

// .res/.def files for lib.exe
if (isTargetMSVC) {
if (global.params.resfile)
args.push_back(global.params.resfile);
if (global.params.deffile)
args.push_back(std::string("/DEF:") + global.params.deffile);
}

// create path to the library
createDirectoryForFileOrFail(libName);

#if LDC_LLVM_VER >= 309
if (useInternalArchiver) {
const auto fullArgs = getFullArgs(tool, args, global.params.verbose);

const int exitCode =
isTargetMSVC ? internalLib(fullArgs) : internalAr(fullArgs);
if (exitCode)
error(Loc(), "%s failed with status: %d", tool.c_str(), exitCode);

return exitCode;
}
#endif

// invoke external archiver
return executeToolAndWait(tool, args, global.params.verbose);
}
20 changes: 6 additions & 14 deletions driver/archiver.h
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
//===-- driver/archiver.h - Creating static libs via LLVM--------*- C++ -*-===//
//===-- driver/archiver.h - Creating static libraries -----------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Provides an interface to LLVM built-in static lib generation via llvm-lib
// (MSVC targets) or llvm-ar (all other targets).
//
//===----------------------------------------------------------------------===//

#ifndef LDC_DRIVER_ARCHIVER_H
#define LDC_DRIVER_ARCHIVER_H

#if LDC_LLVM_VER >= 309
#include "llvm/ADT/ArrayRef.h"

namespace ldc {
int ar(llvm::ArrayRef<const char *> args);
int lib(llvm::ArrayRef<const char *> args);
}
#endif // LDC_LLVM_VER >= 309
/**
* Create a static library from object files.
* @return 0 on success.
*/
int createStaticLibrary();

#endif // !LDC_DRIVER_ARCHIVER_H
Loading

0 comments on commit 2008400

Please sign in to comment.