Skip to content

Commit 71a1f13

Browse files
committed
[llvm-libtool-darwin] Add support for -D and -U options
Add support for `-D` and `-U` options for llvm-libtool-darwin. `-D` allows for using zero for timestamps and UIDs/GIDs. `-U` allows for using actual timestamps and UIDs/GIDs. Reviewed by jhenderson, smeenai Differential Revision: https://reviews.llvm.org/D84209
1 parent d9a9192 commit 71a1f13

File tree

3 files changed

+101
-25
lines changed

3 files changed

+101
-25
lines changed

llvm/docs/CommandGuide/llvm-libtool-darwin.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ OPTIONS
3838

3939
Display the version of this program.
4040

41+
.. option:: -D
42+
43+
Use zero for timestamps and UIDs/GIDs. This is set by default.
44+
45+
.. option:: -U
46+
47+
Use actual timestamps and UIDs/GIDs.
48+
4149
.. option:: -o <filename>
4250

4351
Specify the output file name. Must be specified exactly once.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## This test checks that timestamps are set to 0 by default or when the -D
2+
## option is specified, and that they are preserved when the -U option is
3+
## specified.
4+
## We only test timestamps as a proxy for full deterministic writing; i.e. we
5+
## assume UID/GIDs are preserved if timestamps are preserved.
6+
7+
# RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o
8+
# RUN: touch -t 199505050555.55 %t-input1.o
9+
10+
## Test values are set to 0 (by default):
11+
# RUN: llvm-libtool-darwin -static -o %t.lib %t-input1.o
12+
# RUN: env TZ=GMT llvm-ar tv %t.lib | FileCheck %s --check-prefix=CHECK-DETERMINISTIC
13+
14+
## Test values are set to 0 (with -D):
15+
# RUN: llvm-libtool-darwin -static -o %t.lib -D %t-input1.o
16+
# RUN: env TZ=GMT llvm-ar tv %t.lib | FileCheck %s --check-prefix=CHECK-DETERMINISTIC
17+
18+
# CHECK-DETERMINISTIC: {{[[:space:]]1970[[:space:]]}}
19+
20+
## Test values are preserved (with -U):
21+
# RUN: llvm-libtool-darwin -static -o %t.lib -U %t-input1.o
22+
# RUN: env TZ=GMT llvm-ar tv %t.lib | FileCheck %s --check-prefix=CHECK-NONDETERMINISTIC
23+
24+
# CHECK-NONDETERMINISTIC: {{[[:space:]]1995[[:space:]]}}
25+
26+
## D Flag specified more than once:
27+
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-input1.o -D -D 2>&1 | \
28+
# RUN: FileCheck %s --check-prefix=CHECK-ERROR-D
29+
30+
# CHECK-ERROR-D: for the -D option: may only occur zero or one times!
31+
32+
## U Flag specified more than once:
33+
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-input1.o -U -U 2>&1 | \
34+
# RUN: FileCheck %s --check-prefix=CHECK-ERROR-U
35+
36+
# CHECK-ERROR-U: for the -U option: may only occur zero or one times!
37+
38+
## Both D and U flags specified:
39+
# RUN: not llvm-libtool-darwin -static -o %t.lib %t-input1.o -D -U 2>&1 | \
40+
# RUN: FileCheck %s --check-prefix=CHECK-ERROR-BOTH
41+
42+
# CHECK-ERROR-BOTH: error: cannot specify both -D and -U flags

llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,23 @@ static cl::opt<Operation> LibraryOperation(
4242
"Produce a statically linked library from the input files")),
4343
cl::Required, cl::cat(LibtoolCategory));
4444

45+
static cl::opt<bool> DeterministicOption(
46+
"D", cl::desc("Use zero for timestamps and UIDs/GIDs (Default)"),
47+
cl::init(false), cl::cat(LibtoolCategory));
48+
49+
static cl::opt<bool>
50+
NonDeterministicOption("U", cl::desc("Use actual timestamps and UIDs/GIDs"),
51+
cl::init(false), cl::cat(LibtoolCategory));
52+
4553
static cl::opt<std::string>
4654
FileList("filelist",
4755
cl::desc("Pass in file containing a list of filenames"),
4856
cl::value_desc("listfile[,dirname]"), cl::cat(LibtoolCategory));
4957

58+
struct Config {
59+
bool Deterministic = true; // Updated by 'D' and 'U' modifiers.
60+
};
61+
5062
static Error processFileList() {
5163
StringRef FileName, DirName;
5264
std::tie(FileName, DirName) = StringRef(FileList).rsplit(",");
@@ -99,9 +111,9 @@ static Error verifyMachOObject(const NewArchiveMember &Member) {
99111
}
100112

101113
static Error addChildMember(std::vector<NewArchiveMember> &Members,
102-
const object::Archive::Child &M) {
114+
const object::Archive::Child &M, const Config &C) {
103115
Expected<NewArchiveMember> NMOrErr =
104-
NewArchiveMember::getOldMember(M, /*Deterministic=*/true);
116+
NewArchiveMember::getOldMember(M, C.Deterministic);
105117
if (!NMOrErr)
106118
return NMOrErr.takeError();
107119

@@ -115,9 +127,10 @@ static Error addChildMember(std::vector<NewArchiveMember> &Members,
115127

116128
static Error
117129
addMember(std::vector<NewArchiveMember> &Members, StringRef FileName,
118-
std::vector<std::unique_ptr<MemoryBuffer>> &ArchiveBuffers) {
130+
std::vector<std::unique_ptr<MemoryBuffer>> &ArchiveBuffers,
131+
const Config &C) {
119132
Expected<NewArchiveMember> NMOrErr =
120-
NewArchiveMember::getFile(FileName, /*Deterministic=*/true);
133+
NewArchiveMember::getFile(FileName, C.Deterministic);
121134
if (!NMOrErr)
122135
return createFileError(FileName, NMOrErr.takeError());
123136

@@ -135,7 +148,7 @@ addMember(std::vector<NewArchiveMember> &Members, StringRef FileName,
135148

136149
Error Err = Error::success();
137150
for (const object::Archive::Child &Child : Lib.children(Err))
138-
if (Error E = addChildMember(Members, Child))
151+
if (Error E = addChildMember(Members, Child, C))
139152
return createFileError(FileName, std::move(E));
140153
if (Err)
141154
return createFileError(FileName, std::move(Err));
@@ -154,43 +167,56 @@ addMember(std::vector<NewArchiveMember> &Members, StringRef FileName,
154167
return Error::success();
155168
}
156169

157-
static Error createStaticLibrary() {
170+
static Error createStaticLibrary(const Config &C) {
158171
std::vector<NewArchiveMember> NewMembers;
159172
std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;
160173
for (StringRef Member : InputFiles)
161-
if (Error E = addMember(NewMembers, Member, ArchiveBuffers))
174+
if (Error E = addMember(NewMembers, Member, ArchiveBuffers, C))
162175
return E;
163176

164-
if (Error E = writeArchive(OutputFile, NewMembers,
165-
/*WriteSymtab=*/true,
166-
/*Kind=*/object::Archive::K_DARWIN,
167-
/*Deterministic=*/true,
168-
/*Thin=*/false))
177+
if (Error E =
178+
writeArchive(OutputFile, NewMembers,
179+
/*WriteSymtab=*/true,
180+
/*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
181+
/*Thin=*/false))
169182
return E;
170183
return Error::success();
171184
}
172185

186+
static Expected<Config> parseCommandLine(int Argc, char **Argv) {
187+
Config C;
188+
cl::ParseCommandLineOptions(Argc, Argv, "llvm-libtool-darwin\n");
189+
190+
if (DeterministicOption && NonDeterministicOption)
191+
return createStringError(std::errc::invalid_argument,
192+
"cannot specify both -D and -U flags");
193+
else if (NonDeterministicOption)
194+
C.Deterministic = false;
195+
196+
if (!FileList.empty())
197+
if (Error E = processFileList())
198+
return std::move(E);
199+
200+
if (InputFiles.empty())
201+
return createStringError(std::errc::invalid_argument,
202+
"no input files specified");
203+
204+
return C;
205+
}
206+
173207
int main(int Argc, char **Argv) {
174208
InitLLVM X(Argc, Argv);
175209
cl::HideUnrelatedOptions({&LibtoolCategory, &ColorCategory});
176-
cl::ParseCommandLineOptions(Argc, Argv, "llvm-libtool-darwin\n");
177-
if (!FileList.empty()) {
178-
if (Error E = processFileList()) {
179-
WithColor::defaultErrorHandler(std::move(E));
180-
return EXIT_FAILURE;
181-
}
182-
}
183-
184-
if (InputFiles.empty()) {
185-
Error E = createStringError(std::errc::invalid_argument,
186-
"no input files specified");
187-
WithColor::defaultErrorHandler(std::move(E));
210+
Expected<Config> ConfigOrErr = parseCommandLine(Argc, Argv);
211+
if (!ConfigOrErr) {
212+
WithColor::defaultErrorHandler(ConfigOrErr.takeError());
188213
return EXIT_FAILURE;
189214
}
190215

216+
Config C = *ConfigOrErr;
191217
switch (LibraryOperation) {
192218
case Operation::Static:
193-
if (Error E = createStaticLibrary()) {
219+
if (Error E = createStaticLibrary(C)) {
194220
WithColor::defaultErrorHandler(std::move(E));
195221
return EXIT_FAILURE;
196222
}

0 commit comments

Comments
 (0)