Skip to content

Commit

Permalink
Only set rpath when linking against shared default libs
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke committed Apr 21, 2018
1 parent 611d324 commit 891234b
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 39 deletions.
6 changes: 0 additions & 6 deletions driver/cl_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,6 @@ cl::opt<std::string>
"'-deps' alone prints module dependencies "
"(imports/file/version/debug/lib)"));

cl::opt<cl::boolOrDefault>
staticFlag("static", llvm::cl::ZeroOrMore,
llvm::cl::desc("Create a statically linked binary, including "
"all system dependencies"),
cl::cat(linkingCategory));

cl::opt<bool> m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore);

cl::opt<bool> m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore);
Expand Down
1 change: 0 additions & 1 deletion driver/cl_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ extern cl::opt<std::string> moduleDeps;
extern cl::opt<std::string> cacheDir;
extern cl::list<std::string> linkerSwitches;
extern cl::list<std::string> ccSwitches;
extern cl::opt<cl::boolOrDefault> staticFlag;

extern cl::opt<bool> m32bits;
extern cl::opt<bool> m64bits;
Expand Down
2 changes: 2 additions & 0 deletions driver/configfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ static llvm::cl::opt<std::string>
clConf("conf", llvm::cl::desc("Use configuration file <filename>"),
llvm::cl::value_desc("filename"), llvm::cl::ZeroOrMore);

ConfigFile ConfigFile::instance;

#if _WIN32
std::string getUserHomeDirectory() {
char buff[MAX_PATH];
Expand Down
23 changes: 23 additions & 0 deletions driver/configfile.d
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ ArraySetting findArraySetting(GroupSetting section, string name)
return null;
}

ScalarSetting findScalarSetting(GroupSetting section, string name)
{
if (!section) return null;
foreach (c; section.children)
{
if (c.type == Setting.Type.scalar && c.name == name)
return cast(ScalarSetting) c;
}
return null;
}

string replace(string str, string pattern, string replacement)
{
Expand Down Expand Up @@ -95,6 +105,7 @@ private:
const(char)* pathcstr;
Array!(const(char)*) switches;
Array!(const(char)*) postSwitches;
const(char)* rpathcstr;

bool readConfig(const(char)* cfPath, const(char)* sectionName, const(char)* binDir)
{
Expand Down Expand Up @@ -159,6 +170,18 @@ private:
applyArray(this.switches, switches);
applyArray(this.postSwitches, postSwitches);

ScalarSetting findScalar(string name)
{
auto r = findScalarSetting(section, name);
if (!r)
r = findScalarSetting(defaultSection, name);
return r;
}

auto rpath = findScalar("rpath");
if (rpath)
this.rpathcstr = (rpath.val.replace("%%ldcbinarypath%%", dBinDir) ~ '\0').ptr;

return true;
}
catch (Exception ex)
Expand Down
6 changes: 5 additions & 1 deletion driver/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@

class ConfigFile {
public:
static ConfigFile instance;

bool read(const char *explicitConfFile, const char *section);

std::string path() { return std::string(pathcstr); }
std::string path() { return pathcstr; }

void extendCommandLine(llvm::SmallVectorImpl<const char *> &args);
std::string rpath() { return rpathcstr; }

private:
bool locate(std::string &pathstr);
Expand All @@ -36,6 +39,7 @@ class ConfigFile {
const char *pathcstr = nullptr;
Array<const char *> switches;
Array<const char *> postSwitches;
const char *rpathcstr = nullptr;
};

#endif // LDC_DRIVER_CONFIGFILE_H
11 changes: 10 additions & 1 deletion driver/linker-gcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
#include "driver/cl_options.h"
#include "driver/cl_options_instrumentation.h"
#include "driver/cl_options_sanitizers.h"
#include "driver/configfile.h"
#include "driver/exe_path.h"
#include "driver/ldc-version.h"
#include "driver/linker.h"
#include "driver/tool.h"
#include "gen/irstate.h"
#include "gen/logger.h"
Expand Down Expand Up @@ -476,11 +478,18 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
addLinker();
addUserSwitches();

// libs added via pragma(lib, libname)
// default libs and libs added via pragma(lib, libname)
for (auto ls : global.params.linkswitches) {
args.push_back(ls);
}

// -rpath if linking against shared default libs
if (willLinkAgainstSharedDefaultLibs()) {
const std::string rpath = ConfigFile::instance.rpath();
if (!rpath.empty())
addLdFlag("-rpath", rpath);
}

if (global.params.targetTriple->getOS() == llvm::Triple::Linux) {
// Make sure we don't do --gc-sections when generating a profile-
// instrumented binary. The runtime relies on magic sections, which
Expand Down
38 changes: 30 additions & 8 deletions driver/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,38 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/SourceMgr.h"

namespace cl = llvm::cl;

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

#if LDC_WITH_LLD
static llvm::cl::opt<bool>
useInternalLinker("link-internally", llvm::cl::ZeroOrMore,
llvm::cl::desc("Use internal LLD for linking"),
llvm::cl::cat(opts::linkingCategory));
static cl::opt<bool> useInternalLinker("link-internally", cl::ZeroOrMore,
cl::desc("Use internal LLD for linking"),
cl::cat(opts::linkingCategory));
#else
constexpr bool useInternalLinker = false;
#endif

static cl::opt<cl::boolOrDefault>
staticFlag("static", cl::ZeroOrMore,
cl::desc("Create a statically linked binary, including "
"all system dependencies"),
cl::cat(opts::linkingCategory));

static cl::opt<cl::boolOrDefault> linkDefaultLibShared(
"link-defaultlib-shared", cl::ZeroOrMore,
cl::desc("Link with shared versions of default libraries"),
cl::cat(opts::linkingCategory));

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

// linker-gcc.cpp
int linkObjToBinaryGcc(llvm::StringRef outputPath, bool useInternalLinker,
llvm::cl::boolOrDefault fullyStaticFlag);
cl::boolOrDefault fullyStaticFlag);

// linker-msvc.cpp
int linkObjToBinaryMSVC(llvm::StringRef outputPath, bool useInternalLinker,
llvm::cl::boolOrDefault fullyStaticFlag);
cl::boolOrDefault fullyStaticFlag);

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

Expand Down Expand Up @@ -87,6 +99,16 @@ static std::string getOutputName() {

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

bool willLinkAgainstSharedDefaultLibs() {
// -static enforces static default libs.
// Default to shared default libs for DLLs.
return staticFlag != cl::BOU_TRUE &&
(linkDefaultLibShared == cl::BOU_TRUE ||
(linkDefaultLibShared == cl::BOU_UNSET && global.params.dll));
}

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

/// Insert an LLVM bitcode file into the module
static void insertBitcodeIntoModule(const char *bcFile, llvm::Module &M,
llvm::LLVMContext &Context) {
Expand Down Expand Up @@ -130,10 +152,10 @@ int linkObjToBinary() {
createDirectoryForFileOrFail(gExePath);

if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
return linkObjToBinaryMSVC(gExePath, useInternalLinker, opts::staticFlag);
return linkObjToBinaryMSVC(gExePath, useInternalLinker, staticFlag);
}

return linkObjToBinaryGcc(gExePath, useInternalLinker, opts::staticFlag);
return linkObjToBinaryGcc(gExePath, useInternalLinker, staticFlag);
}

//////////////////////////////////////////////////////////////////////////////
Expand Down
6 changes: 6 additions & 0 deletions driver/linker.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class LLVMContext;

template <typename TYPE> struct Array;

/**
* Indicates whether the command-line options select shared druntime/Phobos for
* linking.
*/
bool willLinkAgainstSharedDefaultLibs();

/**
* Inserts bitcode files passed on the commandline into a module.
*/
Expand Down
15 changes: 2 additions & 13 deletions driver/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,6 @@ static cl::alias _linkDebugLib("link-debuglib", cl::Hidden,
cl::desc("Alias for -link-defaultlib-debug"),
cl::cat(linkingCategory));

static cl::opt<bool> linkDefaultLibShared(
"link-defaultlib-shared", cl::ZeroOrMore,
cl::desc("Link with shared versions of default libraries"),
cl::cat(linkingCategory));

// This function exits the program.
void printVersion(llvm::raw_ostream &OS) {
OS << "LDC - the LLVM D compiler (" << global.ldc_version << "):\n";
Expand Down Expand Up @@ -325,7 +320,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
expandResponseFiles(allocator, allArguments);

// read config file
ConfigFile cfg_file;
ConfigFile &cfg_file = ConfigFile::instance;
const char *explicitConfFile = tryGetExplicitConfFile(allArguments);
const std::string cfg_triple = tryGetExplicitTriple(allArguments).getTriple();
// just ignore errors for now, they are still printed
Expand Down Expand Up @@ -502,13 +497,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
} else if (!global.params.betterC) {
const bool addDebugSuffix =
(linkDefaultLibDebug && debugLib.getNumOccurrences() == 0);

// -static enforces static default libs.
// Default to shared default libs for DLLs.
const bool addSharedSuffix =
staticFlag != cl::BOU_TRUE &&
(linkDefaultLibShared ||
(linkDefaultLibShared.getNumOccurrences() == 0 && global.params.dll));
const bool addSharedSuffix = willLinkAgainstSharedDefaultLibs();

// Parse comma-separated default library list.
std::stringstream libNames(
Expand Down
4 changes: 3 additions & 1 deletion ldc2.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ default:
// default switches injected before all explicit command-line switches
switches = [
"-I@RUNTIME_DIR@/src",
"-I@JITRT_DIR@/d",@SHARED_LIBS_RPATH@
"-I@JITRT_DIR@/d",
"-defaultlib=druntime-ldc"@ADDITIONAL_DEFAULT_LDC_SWITCHES@
];
// default switches appended after all explicit command-line switches
post-switches = [
"-L-L@CMAKE_BINARY_DIR@/lib@LIB_SUFFIX@",@MULTILIB_ADDITIONAL_PATH@
];
// default rpath when linking against the shared default libs
rpath = "@SHARED_LIBS_RPATH@";
};
4 changes: 3 additions & 1 deletion ldc2_install.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ default:
// default switches injected before all explicit command-line switches
switches = [
"-I@INCLUDE_INSTALL_DIR@/ldc",
"-I@INCLUDE_INSTALL_DIR@",@SHARED_LIBS_INSTALL_RPATH@
"-I@INCLUDE_INSTALL_DIR@",
"-defaultlib=phobos2-ldc,druntime-ldc"@ADDITIONAL_DEFAULT_LDC_SWITCHES@
];
// default switches appended after all explicit command-line switches
post-switches = [
"-L-L@CMAKE_INSTALL_LIBDIR@",@MULTILIB_ADDITIONAL_INSTALL_PATH@
];
// default rpath when linking against the shared default libs
rpath = "@SHARED_LIBS_INSTALL_RPATH@";
};
4 changes: 3 additions & 1 deletion ldc2_phobos.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ default:
switches = [
"-I@RUNTIME_DIR@/src",
"-I@JITRT_DIR@/d",
"-I@PHOBOS2_DIR@",@SHARED_LIBS_RPATH@
"-I@PHOBOS2_DIR@",
"-defaultlib=phobos2-ldc,druntime-ldc"@ADDITIONAL_DEFAULT_LDC_SWITCHES@
];
// default switches appended after all explicit command-line switches
post-switches = [
"-L-L@CMAKE_BINARY_DIR@/lib@LIB_SUFFIX@",@MULTILIB_ADDITIONAL_PATH@
];
// default rpath when linking against the shared default libs
rpath = "@SHARED_LIBS_RPATH@";
};
12 changes: 6 additions & 6 deletions runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,14 @@ if(MULTILIB AND NOT "${TARGET_SYSTEM}" MATCHES "APPLE")
set(MULTILIB_ADDITIONAL_INSTALL_PATH "\n \"-L-L${CMAKE_INSTALL_PREFIX}/lib${MULTILIB_SUFFIX}\",\n \"-L--no-warn-search-mismatch\",")
endif()

# Set the -rpath linker option when shared runtime libraries are built.
if(NOT ${BUILD_SHARED_LIBS} STREQUAL "OFF")
# Default -rpath linker option when linking against shared libraries.
if(SHARED_LIBS_SUPPORTED)
if(MULTILIB AND NOT "${TARGET_SYSTEM}" MATCHES "APPLE")
set(SHARED_LIBS_RPATH "\n \"-L-rpath\", \"-L${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}:${CMAKE_BINARY_DIR}/lib${MULTILIB_SUFFIX}\",")
set(SHARED_LIBS_INSTALL_RPATH "\n \"-L-rpath\", \"-L${CMAKE_INSTALL_LIBDIR}:${CMAKE_INSTALL_PREFIX}/lib${MULTILIB_SUFFIX}\",")
set(SHARED_LIBS_RPATH "${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}:${CMAKE_BINARY_DIR}/lib${MULTILIB_SUFFIX}")
set(SHARED_LIBS_INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}:${CMAKE_INSTALL_PREFIX}/lib${MULTILIB_SUFFIX}")
else()
set(SHARED_LIBS_RPATH "\n \"-L-rpath\", \"-L${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}\",")
set(SHARED_LIBS_INSTALL_RPATH "\n \"-L-rpath\", \"-L${CMAKE_INSTALL_LIBDIR}\",")
set(SHARED_LIBS_RPATH "${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}")
set(SHARED_LIBS_INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}")
endif()
endif()

Expand Down

3 comments on commit 891234b

@mleise
Copy link
Contributor

@mleise mleise commented on 891234b Apr 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just about to add support for MULTILIB ldc2 on Gentoo and wondering what I should put in ldc2.conf for the rpath. Now I'll wait for the 1.9.0 release since it looks, like this commit is probably required for a smooth out of the box experience. Nice coincidence.

@kinke
Copy link
Member Author

@kinke kinke commented on 891234b Apr 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

smooth out of the box experience

That's certainly the goal, so if you have any suggestions, be sure to let me know (I've never had to fiddle with rpath myself, so I'm actually not really qualified for tackling this issue).

@mleise
Copy link
Contributor

@mleise mleise commented on 891234b Apr 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not qualified either. Didn't even know you could set multiple rpaths (which is good since then you can provide one for 32-bit and one for 64-bit). It comes in handy when you install to a non default location or as I do, treat every installation of ldc2 as a separate API with its own set of installed libraries much like how Python libraries are typically compiled and installed for Python 2.7 and 3.5.
In such a situation when you have e.g. a program using GtkD, it needs to have the correct rpath to /opt/ldc2-1.9/lib64/libgtkd-3.so.0 so it doesn't pick up the one compiled with 1.7 which might be ABI incompatible. Unless .... we eventually come to a point where API stability becomes a major thing for Dlang and we stop inferring attributes at library boundaries and I'll just install gtkd to /usr/lib64, but that's another story. 😀

Please sign in to comment.