aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-11-26 17:40:11 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-11-26 17:40:11 +0200
commit8fbc673998ed0946403b0c89397d68ab93a1c49c (patch)
tree3dd4df011bb55a12263425c2feddd29ff569bdf4
parent0e9bf64dadc029bdf3e97ffb982d297eee0499e4 (diff)
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).
-rw-r--r--libbuild2/cc/link-rule.cxx70
-rw-r--r--libbuild2/cc/msvc.cxx6
2 files changed, 44 insertions, 32 deletions
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<libi> (t));
-
- out2 = "/IMPLIB:";
- out2 += relative (imp.path ()).string ();
- args.push_back (out2.c_str ());
+ out2 += relative (find_adhoc_member<libi> (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<string> (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<libi> (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)