Add switch '-Xcc <ccflag>'. Fix #2093. (#2104)

This commit is contained in:
Adrian Matoga 2017-05-16 20:23:02 +02:00 committed by kinke
parent 3d7e4c0036
commit aafd6541c7
4 changed files with 67 additions and 21 deletions

View file

@ -284,11 +284,13 @@ cl::list<std::string> transitions(
"Help with language change identified by <idents>, use ? for list"), "Help with language change identified by <idents>, use ? for list"),
cl::value_desc("idents"), cl::CommaSeparated); cl::value_desc("idents"), cl::CommaSeparated);
static StringsAdapter linkSwitchStore("L", global.params.linkswitches); cl::list<std::string> linkerSwitches("L",
static cl::list<std::string, StringsAdapter> cl::desc("Pass <linkerflag> to the linker"),
linkerSwitches("L", cl::desc("Pass <linkerflag> to the linker"), cl::value_desc("linkerflag"), cl::Prefix);
cl::value_desc("linkerflag"), cl::location(linkSwitchStore),
cl::Prefix); cl::list<std::string> ccSwitches("Xcc", cl::CommaSeparated,
cl::desc("Pass <ccflag> to GCC/Clang for linking"),
cl::value_desc("ccflag"));
cl::opt<std::string> cl::opt<std::string>
moduleDeps("deps", moduleDeps("deps",

View file

@ -66,6 +66,8 @@ extern cl::list<std::string> versions;
extern cl::list<std::string> transitions; extern cl::list<std::string> transitions;
extern cl::opt<std::string> moduleDeps; extern cl::opt<std::string> moduleDeps;
extern cl::opt<std::string> cacheDir; extern cl::opt<std::string> cacheDir;
extern cl::list<std::string> linkerSwitches;
extern cl::list<std::string> ccSwitches;
extern cl::opt<std::string> mArch; extern cl::opt<std::string> mArch;
extern cl::opt<bool> m32bits; extern cl::opt<bool> m32bits;

View file

@ -355,21 +355,38 @@ static int linkObjToBinaryGcc(bool sharedLib) {
if (opts::isUsingLTO()) if (opts::isUsingLTO())
addLTOLinkFlags(args); addLTOLinkFlags(args);
// additional linker switches // additional linker and cc switches (preserve order across both lists)
for (unsigned i = 0; i < global.params.linkswitches->dim; i++) { for (unsigned ilink = 0, icc = 0;;) {
const char *p = (*global.params.linkswitches)[i]; unsigned linkpos = ilink < opts::linkerSwitches.size()
// Don't push -l and -L switches using -Xlinker, but pass them indirectly ? opts::linkerSwitches.getPosition(ilink)
// via GCC. This makes sure user-defined paths take precedence over : std::numeric_limits<unsigned>::max();
// GCC's builtin LIBRARY_PATHs. unsigned ccpos = icc < opts::ccSwitches.size()
// Options starting with `-Wl,`, -shared or -static are not handled by ? opts::ccSwitches.getPosition(icc)
// the linker and must be passed to the driver. : std::numeric_limits<unsigned>::max();
auto str = llvm::StringRef(p); if (linkpos < ccpos) {
if (!(str.startswith("-l") || str.startswith("-L") || const std::string& p = opts::linkerSwitches[ilink++];
str.startswith("-Wl,") || // Don't push -l and -L switches using -Xlinker, but pass them indirectly
str.startswith("-shared") || str.startswith("-static"))) { // via GCC. This makes sure user-defined paths take precedence over
args.push_back("-Xlinker"); // GCC's builtin LIBRARY_PATHs.
// Options starting with `-Wl,`, -shared or -static are not handled by
// the linker and must be passed to the driver.
auto str = llvm::StringRef(p);
if (!(str.startswith("-l") || str.startswith("-L") ||
str.startswith("-Wl,") ||
str.startswith("-shared") || str.startswith("-static"))) {
args.push_back("-Xlinker");
}
args.push_back(p);
} else if (ccpos < linkpos) {
args.push_back(opts::ccSwitches[icc++]);
} else {
break;
} }
args.push_back(p); }
// libs added via pragma(lib, libname)
for (unsigned i = 0; i < global.params.linkswitches->dim; i++) {
args.push_back((*global.params.linkswitches)[i]);
} }
// default libs // default libs
@ -518,6 +535,11 @@ static void addMscrtLibs(std::vector<std::string> &args) {
static int linkObjToBinaryMSVC(bool sharedLib) { static int linkObjToBinaryMSVC(bool sharedLib) {
Logger::println("*** Linking executable ***"); Logger::println("*** Linking executable ***");
if (!opts::ccSwitches.empty()) {
error(Loc(), "-Xcc is not supported for MSVC");
fatal();
}
#ifdef _WIN32 #ifdef _WIN32
windows::setupMsvcEnvironment(); windows::setupMsvcEnvironment();
#endif #endif
@ -584,8 +606,7 @@ static int linkObjToBinaryMSVC(bool sharedLib) {
CreateDirectoryOnDisk(gExePath); CreateDirectoryOnDisk(gExePath);
// additional linker switches // additional linker switches
for (unsigned i = 0; i < global.params.linkswitches->dim; i++) { auto addSwitch = [&](std::string str) {
std::string str = global.params.linkswitches->data[i];
if (str.length() > 2) { if (str.length() > 2) {
// rewrite common -L and -l switches // rewrite common -L and -l switches
if (str[0] == '-' && str[1] == 'L') { if (str[0] == '-' && str[1] == 'L') {
@ -595,6 +616,14 @@ static int linkObjToBinaryMSVC(bool sharedLib) {
} }
} }
args.push_back(str); args.push_back(str);
};
for (const auto& str : opts::linkerSwitches) {
addSwitch(str);
}
for (unsigned i = 0; i < global.params.linkswitches->dim; i++) {
addSwitch(global.params.linkswitches->data[i]);
} }
// default libs // default libs

View file

@ -0,0 +1,13 @@
// Test if global order of flags passed with -Xcc, -L and pragma(lib) is preserved
// UNSUPPORTED: Windows
// RUN: /bin/sh -c '%ldc %s -of=%t -Xcc -DOPT1,-DOPT2 -L-L/usr/lib -L--defsym -Lfoo=5 -Xcc -DOPT3 -v 2>/dev/null || true' | FileCheck %s
// CHECK: -DOPT1 -DOPT2 -L/usr/lib -Xlinker --defsym -Xlinker foo=5 -DOPT3 {{.*}}-lpthread
pragma(lib, "pthread");
void main()
{
}