@@ -250,18 +250,23 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
250250
251251 MemoryBufferRef mbref = takeBuffer (std::move (mb));
252252
253+ auto maybePrintWarning = [&](StringRef type, StringRef message) {
254+ if (inCmdLineArchive)
255+ Warn (ctx) << type << " file provided between "
256+ << inCmdLineArchive->startLibArg << " /"
257+ << inCmdLineArchive->endLibArg << " " << message;
258+ };
259+
253260 // File type is detected by contents, not by file extension.
254261 switch (identify_magic (mbref.getBuffer ())) {
255262 case file_magic::windows_resource:
256- assert (!inCmdLineArchive &&
257- " Cannot specify a RES file inside a --start-lib/--end-lib group." );
263+ maybePrintWarning (" .res" , " will not be lazy" );
258264 resources.push_back (mbref);
259265 break ;
260266 case file_magic::archive:
261267 // FIXME: We could later support --start-lib/--end-lib groups, to allow for
262268 // "extending" an existing archive/LIB.
263- assert (!inCmdLineArchive &&
264- " Cannot specify a LIB file inside a --start-lib/--end-lib group." );
269+ maybePrintWarning (" .lib/.a" , " has no effect" );
265270 if (wholeArchive) {
266271 std::unique_ptr<Archive> file =
267272 CHECK (Archive::create (mbref), filename + " : failed to parse archive" );
@@ -283,8 +288,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
283288 addFile (ObjFile::create (ctx, mbref), inCmdLineArchive);
284289 break ;
285290 case file_magic::pdb:
286- assert (!inCmdLineArchive &&
287- " Cannot specify a PDB file inside a --start-lib/--end-lib group." );
291+ maybePrintWarning (" .pdb" , " will not be lazy" );
288292 addFile (make<PDBInputFile>(ctx, mbref));
289293 break ;
290294 case file_magic::coff_cl_gl_object:
@@ -293,9 +297,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
293297 break ;
294298 case file_magic::pecoff_executable:
295299 if (ctx.config .mingw ) {
296- assert (
297- !inCmdLineArchive &&
298- " Cannot specify a PE/EXE file inside a --start-lib/--end-lib group." );
300+ maybePrintWarning (" .dll" , " will not be lazy" );
299301 addFile (make<DLLFile>(ctx.symtab , mbref));
300302 break ;
301303 }
@@ -314,7 +316,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
314316
315317void LinkerDriver::enqueuePath (
316318 StringRef path, bool wholeArchive,
317- std::optional<std::shared_future <CmdLineArchive *>> inCmdLineArchive) {
319+ std::optional<std::shared_ptr <CmdLineArchive *>> inCmdLineArchive) {
318320 auto future = std::make_shared<std::future<MBErrPair>>(
319321 createFutureForFile (std::string (path)));
320322 std::string pathStr = std::string (path);
@@ -354,8 +356,7 @@ void LinkerDriver::enqueuePath(
354356 Err (ctx) << msg << " ; did you mean '" << nearest << " '" ;
355357 } else
356358 ctx.driver .addBuffer (std::move (mb), wholeArchive,
357- inCmdLineArchive ? inCmdLineArchive->get ()
358- : nullptr );
359+ inCmdLineArchive ? **inCmdLineArchive : nullptr );
359360 });
360361}
361362
@@ -2172,35 +2173,55 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
21722173 return false ;
21732174 };
21742175
2176+ // Store start_lib/end_lib arguments in order to render dignostics in the
2177+ // same way the flags are written on the command line.
2178+ llvm::opt::Arg *startLibArg = nullptr ;
2179+ llvm::opt::Arg *endLibArg = nullptr ;
2180+ auto endLibSpelling = [&]() {
2181+ return endLibArg ? endLibArg->getSpelling ()
2182+ : lld::args::getOptionSpellingLikeArg (
2183+ ctx.optTable , OPT_end_lib, startLibArg, ctx.saver );
2184+ };
2185+
21752186 // Create a list of input files. These can be given as OPT_INPUT options
21762187 // and OPT_wholearchive_file options, and we also need to track OPT_start_lib
21772188 // and OPT_end_lib.
21782189 {
21792190 llvm::TimeTraceScope timeScope2 (" Parse & queue inputs" );
2180- std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive;
2191+ std::optional<std::shared_ptr<CmdLineArchive *>> inCmdLineArchive;
2192+ auto close = [&]() {
2193+ enqueueTask ([=]() {
2194+ assert (inCmdLineArchive);
2195+ if (CmdLineArchive *a = **inCmdLineArchive)
2196+ a->maybeParse ();
2197+ });
2198+ };
2199+
21812200 for (auto *arg : args) {
21822201 switch (arg->getOption ().getID ()) {
21832202 case OPT_end_lib:
21842203 if (!inCmdLineArchive) {
21852204 Err (ctx) << " stray " << arg->getSpelling ();
21862205 } else {
2187- enqueueTask ([=]() { inCmdLineArchive->get ()->maybeParse (); });
2206+ endLibArg = arg;
2207+ close ();
21882208 inCmdLineArchive = std::nullopt ;
21892209 }
21902210 break ;
21912211 case OPT_start_lib:
21922212 if (inCmdLineArchive) {
21932213 Err (ctx) << " nested " << arg->getSpelling ();
21942214 } else {
2195- auto a = std::make_shared<std::promise<CmdLineArchive *>>() ;
2196- inCmdLineArchive = a-> get_future (). share ();
2197- enqueueTask ([&, a ]() {
2215+ startLibArg = arg ;
2216+ inCmdLineArchive = std::make_shared<CmdLineArchive *> ();
2217+ enqueueTask ([&, inCmdLineArchive, startLibArg, endLibArg ]() {
21982218 // In is important to create a fake archive here so that we
21992219 // remember its placement on the command-line. This will be
22002220 // later needed to resolve symbols in the archive order required
22012221 // by the MSVC specification.
2202- a->set_value (make<CmdLineArchive>(
2203- ctx.symtab , MemoryBufferRef ({}, " <cmdline-lib>" )));
2222+ **inCmdLineArchive = make<CmdLineArchive>(
2223+ ctx.symtab , MemoryBufferRef ({}, " <cmdline-lib>" ),
2224+ startLibArg->getSpelling (), endLibSpelling ());
22042225 });
22052226 }
22062227 break ;
@@ -2218,8 +2239,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
22182239 }
22192240 }
22202241 if (inCmdLineArchive) {
2221- Warn (ctx) << " --start-lib with no --end-lib" ;
2222- enqueueTask ([=]() { inCmdLineArchive->get ()->maybeParse (); });
2242+ StringRef startLib = startLibArg->getSpelling ();
2243+ Warn (ctx) << startLib << " without " << endLibSpelling ()
2244+ << " \n NOTE: all files provided after " << startLib
2245+ << " were lazy." ;
2246+ close ();
22232247 }
22242248 }
22252249
@@ -2740,7 +2764,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
27402764 // /manifestdependency: enables /manifest unless an explicit /manifest:no is
27412765 // also passed.
27422766 if (config->manifest == Configuration::Embed)
2743- addBuffer (createManifestRes (), false );
2767+ addBuffer (createManifestRes ());
27442768 else if (config->manifest == Configuration::SideBySide ||
27452769 (config->manifest == Configuration::Default &&
27462770 !config->manifestDependencies .empty ()))
0 commit comments