From 8fbc673998ed0946403b0c89397d68ab93a1c49c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 26 Nov 2019 17:40:11 +0200 Subject: Rename executable's .lib/.exp to avoid clashes with libraries Failed that we cannot have an executable and a library with the same name and in the same directory (their .lib's will clash). --- libbuild2/cc/link-rule.cxx | 70 +++++++++++++++++++++++++++------------------- libbuild2/cc/msvc.cxx | 6 ++-- 2 files changed, 44 insertions(+), 32 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index 62988c9..4fbdeda 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -2671,6 +2671,30 @@ namespace build2 args.push_back (in.c_str ()); } + // VC link.exe creates an import library and .exp file for an + // executable if any of its object files export any symbols (think a + // unit test linking libus{}). And, no, there is no way to suppress + // it (but we can change their names with /IMPLIB). Well, there is a + // way: create a .def file with an empty EXPORTS section, pass it to + // lib.exe to create a dummy .exp (and .lib), and then pass this + // empty .exp to link.exe. Wanna go this way? Didn't think so. + // + // Having no way to disable this, the next simplest thing seems to + // be just cleaning this mess up. Note, however, that we better + // change the default name since otherwise it will be impossible to + // have a library and an executable with the same name in the same + // directory (their .lib's will clash). + // + // Note also that if at some point we decide to support such "shared + // executables" (-rdynamic, etc), then it will probably have to be a + // different target type (exes{}?) since it will need a different set + // of object files (-fPIC so probably objs{}), etc. + // + // Also, while we are at it, this means there could be a DLL without + // an import library (which we currently don't handle very well). + // + out2 = "/IMPLIB:"; + if (ot == otype::s) { // On Windows libs{} is the DLL and an ad hoc group member is the @@ -2680,13 +2704,16 @@ namespace build2 // derived from the import library by changing the extension. // Lucky for us -- there is no option to name it. // - const file& imp (*find_adhoc_member (t)); - - out2 = "/IMPLIB:"; - out2 += relative (imp.path ()).string (); - args.push_back (out2.c_str ()); + out2 += relative (find_adhoc_member (t)->path ()).string (); + } + else + { + out2 += relt.string (); + out2 += ".lib"; } + args.push_back (out2.c_str ()); + // If we have /DEBUG then name the .pdb file. It is an ad hoc group // member. // @@ -2700,13 +2727,6 @@ namespace build2 args.push_back (out1.c_str ()); } - // @@ An executable can have an import library and VS seems to - // always name it. I wonder what would trigger its generation? - // Could it be the presence of export symbols? Yes, link.exe will - // generate the import library iff there are exported symbols. - // Which means there could be a DLL without an import library - // (which we currently don't handle very well). - // out = "/OUT:" + relt.string (); args.push_back (out.c_str ()); } @@ -3054,7 +3074,12 @@ namespace build2 // something like this) we are going to redirect stdout to stderr. // For sane compilers this should be harmless. // - bool filter (tsys == "win32-msvc" && !lt.static_library ()); + // Note that we don't need this for LLD's link.exe replacement which + // is quiet. + // + bool filter (tsys == "win32-msvc" && + !lt.static_library () && + cast (rs["bin.ld.id"]) != "msvc-lld"); process pr (*ld, args.data (), @@ -3108,25 +3133,12 @@ namespace build2 throw failed (); } - // VC link.exe creates an import library and .exp file for an - // executable if any of its object files export any symbols (think a - // unit test linking libus{}). And, no, there is no way to suppress - // it. Well, there is a way: create a .def file with an empty EXPORTS - // section, pass it to lib.exe to create a dummy .exp (and .lib), and - // then pass this empty .exp to link.exe. Wanna go this way? Didn't - // think so. Having no way to disable this, the next simplest thing - // seems to be just cleaning the mess up. - // - // Note also that if at some point we decide to support such "shared - // executables" (-rdynamic, etc), then it will probably have to be a - // different target type (exes{}?) since it will need a different set - // of object files (-fPIC so probably objs{}), etc. + // Clean up executable's import library (see above for details). // if (lt.executable () && tsys == "win32-msvc") { - path b (relt.base ()); - try_rmfile (b + ".lib", true /* ignore_errors */); - try_rmfile (b + ".exp", true /* ignore_errors */); + try_rmfile (relt + ".lib", true /* ignore_errors */); + try_rmfile (relt + ".exp", true /* ignore_errors */); } } diff --git a/libbuild2/cc/msvc.cxx b/libbuild2/cc/msvc.cxx index a85e7a0..c7022fc 100644 --- a/libbuild2/cc/msvc.cxx +++ b/libbuild2/cc/msvc.cxx @@ -192,13 +192,13 @@ namespace build2 if (l.compare (0, 3, " ") == 0) { // Use the actual import library name if this is a library (since we - // override this name) and the executable name otherwise (by default - // .lib/.exp are named by replacing the .exe extension). + // override this name) and the executable name otherwise (we pass + // /IMPLIB with .lib appended to the .exe extension). // path i ( lt == otype::s ? find_adhoc_member (t)->path ().leaf () - : t.path ().leaf ().base () + ".lib"); + : t.path ().leaf () + ".lib"); if (l.find (i.string ()) != string::npos && l.find (i.base ().string () + ".exp") != string::npos) -- cgit v1.1