From 5ec448516d7316d603a8c7bc28b9ab91fba2312a Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Wed, 31 Jan 2018 23:44:00 +0000 Subject: [PATCH] [COFF] make /incremental control overwriting unchanged import libraries Summary: r323164 made lld-link not overwrite import libraries when their contents haven't changed. MSVC's link.exe does this only when performing incremental linking. This change makes lld-link's import library overwriting similarly dependent on whether or not incremental linking is being performed. This is controlled by the /incremental or /incremental:no options. In addition, /opt:icf, /opt:ref, and /order turn off /incremental and issue a warning if /incremental was specified on the command line. Reviewers: rnk, ruiu, zturner Reviewed By: ruiu Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D42716 llvm-svn: 323930 --- lld/COFF/Config.h | 1 + lld/COFF/Driver.cpp | 27 +++++++++++ lld/COFF/Options.td | 5 +- lld/test/COFF/incremental.test | 66 ++++++++++++++++++++++++++ lld/test/COFF/unchanged-importlib.test | 7 --- 5 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 lld/test/COFF/incremental.test delete mode 100644 lld/test/COFF/unchanged-importlib.test diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index f98ed3fee3ed..10bc5728ddcc 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -179,6 +179,7 @@ struct Configuration { bool AppContainer = false; bool MinGW = false; bool WarnLocallyDefinedImported = true; + bool Incremental = true; }; extern Configuration *Config; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 0b426b321611..79a9d66ef2bc 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -547,6 +547,12 @@ static void createImportLibrary(bool AsLib) { std::string LibName = getImportName(AsLib); std::string Path = getImplibPath(); + if (!Config->Incremental) { + HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine, + false, Config->MinGW)); + return; + } + // If the import library already exists, replace it only if the contents // have changed. ErrorOr> OldBuf = MemoryBuffer::getFile(Path); @@ -907,6 +913,7 @@ void LinkerDriver::link(ArrayRef ArgsArr) { // Handle /debug if (Args.hasArg(OPT_debug, OPT_debug_dwarf, OPT_debug_ghash)) { Config->Debug = true; + Config->Incremental = true; if (auto *Arg = Args.getLastArg(OPT_debugtype)) Config->DebugTypes = parseDebugType(Arg->getValue()); else @@ -1113,6 +1120,9 @@ void LinkerDriver::link(ArrayRef ArgsArr) { Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true); Config->AllowIsolation = Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true); + Config->Incremental = + Args.hasFlag(OPT_incremental, OPT_incremental_no, + !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order)); 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); @@ -1120,6 +1130,23 @@ void LinkerDriver::link(ArrayRef ArgsArr) { Config->MapFile = getMapFile(Args); + if (Config->Incremental && Config->DoGC) { + warn("ignoring '/INCREMENTAL' because REF is enabled; use '/OPT:NOREF' to " + "disable"); + Config->Incremental = false; + } + + if (Config->Incremental && Config->DoICF) { + warn("ignoring '/INCREMENTAL' because ICF is enabled; use '/OPT:NOICF' to " + "disable"); + Config->Incremental = false; + } + + if (Config->Incremental && Args.hasArg(OPT_order)) { + warn("ignoring '/INCREMENTAL' due to '/ORDER' specification"); + Config->Incremental = false; + } + if (errorCount()) return; diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 50436da87fab..2b68af9f9ec8 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -103,6 +103,9 @@ defm fixed : B<"fixed", "Disable base relocations", defm highentropyva : B<"highentropyva", "Enable 64-bit ASLR (default on 64-bit)", "Disable 64-bit ASLR">; +defm incremental : B<"incremental", + "Keep original import library if contents are unchanged", + "Replace import library file even if contents are unchanged">; defm largeaddressaware : B<"largeaddressaware", "Enable large addresses (default on 64-bit)", "Disable large addresses (default on 32-bit)">; @@ -148,8 +151,6 @@ multiclass QB { def functionpadmin : F<"functionpadmin">; def ignoreidl : F<"ignoreidl">; -def incremental : F<"incremental">; -def no_incremental : F<"incremental:no">; def nologo : F<"nologo">; def throwingnew : F<"throwingnew">; def editandcontinue : F<"editandcontinue">; diff --git a/lld/test/COFF/incremental.test b/lld/test/COFF/incremental.test new file mode 100644 index 000000000000..d5a5ba87ebb4 --- /dev/null +++ b/lld/test/COFF/incremental.test @@ -0,0 +1,66 @@ +# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj +# RUN: lld-link -out:%t.dll -dll %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# 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: lld-link -out:%t.dll -dll -incremental %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=WARN-REF %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -incremental %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -debug %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -debug %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=KEEP %s + +# RUN: lld-link -out:%t.dll -dll -debug -incremental:no %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -debug -incremental:no %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -opt:icf %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -opt:icf %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,icf %t.obj 2>&1 \ +# RUN: | FileCheck -check-prefix=WARN-ICF %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -incremental -opt:noref,icf %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -debug -opt:icf %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -debug -opt:icf %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -opt:ref %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -opt:ref %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -incremental -opt:ref %t.obj 2>&1 \ +# RUN: | FileCheck -check-prefix=WARN-REF %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -incremental -opt:ref %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# RUN: lld-link -out:%t.dll -dll -debug -opt:ref %t.obj 2>&1 \ +# RUN: | FileCheck -allow-empty -check-prefix=NOWARN %s +# RUN: touch -t 198002011200.00 %t.lib +# RUN: lld-link -out:%t.dll -dll -debug -opt:ref %t.obj +# RUN: ls -l %t.lib | FileCheck -check-prefix=NOKEEP %s + +# NOWARN-NOT: ignoring '/INCREMENTAL' +# WARN-ICF: ignoring '/INCREMENTAL' because ICF is enabled; use '/OPT:NOICF' to disable +# WARN-REF: ignoring '/INCREMENTAL' because REF is enabled; use '/OPT:NOREF' to disable +# KEEP: {{Feb 1 1980|1980-02-01}} +# NOKEEP-NOT: {{Feb 1 1980|1980-02-01}} diff --git a/lld/test/COFF/unchanged-importlib.test b/lld/test/COFF/unchanged-importlib.test deleted file mode 100644 index cc5d61b917ad..000000000000 --- a/lld/test/COFF/unchanged-importlib.test +++ /dev/null @@ -1,7 +0,0 @@ -# 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=CHECK %s - -# CHECK: {{Feb 1 1980|1980-02-01}}