forked from OSchip/llvm-project
[llvm-ar] Add --output to specify output directory
From binutils 2.34 onwards, ar supports --output to specify a directory where archive members should be extracted to. Port this feature. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D128626
This commit is contained in:
parent
d515211a0c
commit
bf223e43fe
|
@ -274,6 +274,11 @@ Other
|
||||||
This option allows for MRI scripts to be read through the standard input
|
This option allows for MRI scripts to be read through the standard input
|
||||||
stream. No other options are compatible with this option.
|
stream. No other options are compatible with this option.
|
||||||
|
|
||||||
|
.. option:: --output=<dir>
|
||||||
|
|
||||||
|
Specify a directory where archive members should be extracted to. By default the
|
||||||
|
current working directory is used.
|
||||||
|
|
||||||
.. option:: --rsp-quoting=<type>
|
.. option:: --rsp-quoting=<type>
|
||||||
This option selects the quoting style ``<type>`` for response files, either
|
This option selects the quoting style ``<type>`` for response files, either
|
||||||
``posix`` or ``windows``. The default when on Windows is ``windows``, otherwise the
|
``posix`` or ``windows``. The default when on Windows is ``windows``, otherwise the
|
||||||
|
|
|
@ -26,3 +26,7 @@ RUN: rm -f a.o b.o
|
||||||
RUN: llvm-ar x %S/Inputs/absolute-paths.lib
|
RUN: llvm-ar x %S/Inputs/absolute-paths.lib
|
||||||
RUN: llvm-nm a.o | FileCheck %s --check-prefix=CHECK-A
|
RUN: llvm-nm a.o | FileCheck %s --check-prefix=CHECK-A
|
||||||
RUN: llvm-nm b.o | FileCheck %s --check-prefix=CHECK-B
|
RUN: llvm-nm b.o | FileCheck %s --check-prefix=CHECK-B
|
||||||
|
|
||||||
|
RUN: mkdir dir
|
||||||
|
RUN: llvm-ar x %S/Inputs/absolute-paths.lib --output=dir/
|
||||||
|
RUN: cmp a.o dir/a.o
|
||||||
|
|
|
@ -34,3 +34,21 @@
|
||||||
# RUN: llvm-ar x %t/archive.a 2>&1 | count 0
|
# RUN: llvm-ar x %t/archive.a 2>&1 | count 0
|
||||||
# RUN: diff %t/a.txt %t/extracted/a.txt
|
# RUN: diff %t/a.txt %t/extracted/a.txt
|
||||||
# RUN: diff %t/b.txt %t/extracted/b.txt
|
# RUN: diff %t/b.txt %t/extracted/b.txt
|
||||||
|
|
||||||
|
## --output specifies the directory to extract archive members to. `1/2` is created by llvm-ar.
|
||||||
|
# RUN: llvm-ar --output=1/2 x %t/archive.a
|
||||||
|
# RUN: diff %t/a.txt %t/extracted/1/2/a.txt
|
||||||
|
# RUN: diff %t/b.txt %t/extracted/1/2/b.txt
|
||||||
|
|
||||||
|
## --output can be used with an absolute path and can be specified elsewhere on the command line.
|
||||||
|
# RUN: rm 1/2/a.txt
|
||||||
|
# RUN: llvm-ar xv %t/archive.a a.txt --output %t/extracted/1/2/../2 | FileCheck %s --check-prefix=OUTPUT-A
|
||||||
|
# RUN: diff %t/a.txt %t/extracted/1/2/a.txt
|
||||||
|
# OUTPUT-A: x - {{.*}}extracted{{.*}}a.txt
|
||||||
|
|
||||||
|
# RUN: not llvm-ar x --output=%t/a.txt %t/archive.a 2>&1 | FileCheck %s --check-prefix=OUTPUT-NOTDIR
|
||||||
|
# RUN: not llvm-ar x --output=%t/b.txt/a.txt %t/archive.a 2>&1 | FileCheck %s --check-prefix=OUTPUT-NOTDIR
|
||||||
|
# OUTPUT-NOTDIR: error: '{{.*}}a.txt' is not a directory
|
||||||
|
|
||||||
|
# RUN: not llvm-ar rc --output=1/2 %t/archive.a %t/a.txt 2>&1 | FileCheck %s --check-prefix=OUTPUT-ERR
|
||||||
|
# OUTPUT-ERR: error: --output is only applicable to the 'x' operation
|
||||||
|
|
|
@ -85,6 +85,7 @@ static void printArHelp(StringRef ToolName) {
|
||||||
=aix - aix (big archive)
|
=aix - aix (big archive)
|
||||||
--plugin=<string> - ignored for compatibility
|
--plugin=<string> - ignored for compatibility
|
||||||
-h --help - display this help and exit
|
-h --help - display this help and exit
|
||||||
|
--output - the directory to extract archive members to
|
||||||
--rsp-quoting - quoting style for response files
|
--rsp-quoting - quoting style for response files
|
||||||
=posix - posix
|
=posix - posix
|
||||||
=windows - windows
|
=windows - windows
|
||||||
|
@ -237,6 +238,9 @@ static int CountParam = 0;
|
||||||
// command line.
|
// command line.
|
||||||
static std::string ArchiveName;
|
static std::string ArchiveName;
|
||||||
|
|
||||||
|
// Output directory specified by --output.
|
||||||
|
static std::string OutputDir;
|
||||||
|
|
||||||
static std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
|
static std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
|
||||||
static std::vector<std::unique_ptr<object::Archive>> Archives;
|
static std::vector<std::unique_ptr<object::Archive>> Archives;
|
||||||
|
|
||||||
|
@ -454,6 +458,19 @@ static ArchiveOperation parseCommandLine() {
|
||||||
if (AddLibrary && Operation != QuickAppend)
|
if (AddLibrary && Operation != QuickAppend)
|
||||||
badUsage("the 'L' modifier is only applicable to the 'q' operation");
|
badUsage("the 'L' modifier is only applicable to the 'q' operation");
|
||||||
|
|
||||||
|
if (!OutputDir.empty()) {
|
||||||
|
if (Operation != Extract)
|
||||||
|
badUsage("--output is only applicable to the 'x' operation");
|
||||||
|
bool IsDir = false;
|
||||||
|
// If OutputDir is not a directory, create_directories may still succeed if
|
||||||
|
// all components of the path prefix are directories. Test is_directory as
|
||||||
|
// well.
|
||||||
|
if (!sys::fs::create_directories(OutputDir))
|
||||||
|
sys::fs::is_directory(OutputDir, IsDir);
|
||||||
|
if (!IsDir)
|
||||||
|
fail("'" + OutputDir + "' is not a directory");
|
||||||
|
}
|
||||||
|
|
||||||
// Return the parsed operation to the caller
|
// Return the parsed operation to the caller
|
||||||
return Operation;
|
return Operation;
|
||||||
}
|
}
|
||||||
|
@ -554,7 +571,15 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
|
||||||
failIfError(ModeOrErr.takeError());
|
failIfError(ModeOrErr.takeError());
|
||||||
sys::fs::perms Mode = ModeOrErr.get();
|
sys::fs::perms Mode = ModeOrErr.get();
|
||||||
|
|
||||||
llvm::StringRef outputFilePath = sys::path::filename(Name);
|
StringRef outputFilePath;
|
||||||
|
SmallString<128> path;
|
||||||
|
if (OutputDir.empty()) {
|
||||||
|
outputFilePath = sys::path::filename(Name);
|
||||||
|
} else {
|
||||||
|
sys::path::append(path, OutputDir, sys::path::filename(Name));
|
||||||
|
outputFilePath = path.str();
|
||||||
|
}
|
||||||
|
|
||||||
if (Verbose)
|
if (Verbose)
|
||||||
outs() << "x - " << outputFilePath << '\n';
|
outs() << "x - " << outputFilePath << '\n';
|
||||||
|
|
||||||
|
@ -1224,6 +1249,11 @@ static int ar_main(int argc, char **argv) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((Match = matchFlagWithArg("output", ArgIt, Argv))) {
|
||||||
|
OutputDir = Match;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (matchFlagWithArg("plugin", ArgIt, Argv) ||
|
if (matchFlagWithArg("plugin", ArgIt, Argv) ||
|
||||||
matchFlagWithArg("rsp-quoting", ArgIt, Argv))
|
matchFlagWithArg("rsp-quoting", ArgIt, Argv))
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue