Index: lld/COFF/Config.h =================================================================== --- lld/COFF/Config.h +++ lld/COFF/Config.h @@ -175,6 +175,7 @@ bool AppContainer = false; bool MinGW = false; bool WarnLocallyDefinedImported = true; + bool KeepUnchangedImplib = false; }; extern Configuration *Config; Index: lld/COFF/Driver.cpp =================================================================== --- lld/COFF/Driver.cpp +++ lld/COFF/Driver.cpp @@ -533,10 +533,42 @@ Exports.push_back(E2); } - auto E = writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports, - Config->Machine, false); - handleAllErrors(std::move(E), - [&](ErrorInfoBase &EIB) { error(EIB.message()); }); + auto HandleError = [](Error &&E) { + handleAllErrors(std::move(E), + [](ErrorInfoBase &EIB) { error(EIB.message()); }); + }; + auto LibName = getImportName(AsLib); + auto Path = getImplibPath(); + + // If Config->KeepUnchangedImplib is true and the import library already + // exists, replace it only if the contents have changed. + if (Config->KeepUnchangedImplib) { + auto OldBuf = MemoryBuffer::getFile(Path); + if (OldBuf) { + SmallString<128> TmpName; + auto EC = sys::fs::createUniqueFile(Path + ".tmp-%%%%%%%%.lib", TmpName); + if (EC) + fatal("Cannot create temporary file for import library " + Path + ": " + + EC.message()); + Error E = + writeImportLibrary(LibName, TmpName, Exports, Config->Machine, false); + if (!E) { + auto NewBuf = check(MemoryBuffer::getFile(TmpName)); + if ((*OldBuf)->getBuffer() != NewBuf->getBuffer()) { + OldBuf->reset(); + auto EC = sys::fs::rename(TmpName, Path); + if (EC) + HandleError(errorCodeToError(EC)); + } + } else { + HandleError(std::move(E)); + } + return; + } + } + + Error E = writeImportLibrary(LibName, Path, Exports, Config->Machine, false); + HandleError(std::move(E)); } static void parseModuleDefs(StringRef Path) { @@ -1031,6 +1063,8 @@ Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true); Config->AllowIsolation = Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true); + Config->KeepUnchangedImplib = Args.hasFlag( + OPT_keep_unchanged_implib, OPT_keep_unchanged_implib_no, false); Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); Config->TerminalServerAware = Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf); Index: lld/COFF/Options.td =================================================================== --- lld/COFF/Options.td +++ lld/COFF/Options.td @@ -121,6 +121,9 @@ def debug_ghash : F<"debug:ghash">; def debug_dwarf : F<"debug:dwarf">; def export_all_symbols : F<"export-all-symbols">; +defm keep_unchanged_implib : B<"keep-unchanged-implib", + "Keep original import library if contents haven't changed", + "Replace import library file even if contents are unchanged (default)">; def lldmingw : F<"lldmingw">; def msvclto : F<"msvclto">; def output_def : Joined<["/", "-"], "output-def:">; Index: lld/test/COFF/unchanged-importlib.test =================================================================== --- /dev/null +++ lld/test/COFF/unchanged-importlib.test @@ -0,0 +1,14 @@ +# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj +# RUN: lld-link -out:%t.dll -dll %t.obj +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll %t.obj +# RUN: ls -l %t.lib | FileCheck --check-prefix=NOKEEP %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -keep-unchanged-implib %t.obj +# RUN: ls -l %t.lib | FileCheck --check-prefix=KEEP %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -keep-unchanged-implib:no %t.obj +# RUN: ls -l %t.lib | FileCheck --check-prefix=NOKEEP %s + +# KEEP: Feb 1 1980 +# NOKEEP-NOT: Feb 1 1980