the .a archive format header requires a timestamp. This has led to countless headaches when I rebuild a static library, mainly because I can't exactly reproduce the original binary.
For example (this is on my Mac, but the same thing happens in x64 linux):
$ cat foo.h
int foo();
$ cat foo.c
#include "foo.h"
int foo() { return 3; }
$ gcc -fno-pic -m64 -arch x86_64 -I/usr/local/include -O3 -c foo.c -o foo.o -fpic
$ ar rcs libfoo.a foo.o
$ md5 libfoo.a
MD5 (libfoo.a) = 0d0e6606185de4e994c47f4a0e54c1c4
$ mv libfoo.a libfoo.a1
$ ar rcs libfoo.a foo.o
$ md5 libfoo.a
MD5 (libfoo.a) = 22a69d42e1325ae8f978c2a18a4886da
To prove to myself that the only difference was time, I took a diff based on hexdump:
$ diff <(hexdump libfoo.a) <(hexdump libfoo.a1)
2,3c2,3
< 0000010 20 20 20 20 20 20 20 20 31 33 31 31 30 34 33 30
< 0000020 38 36 20 20 35 30 31 20 20 20 32 30 20 20 20 20
---
> 0000010 20 20 20 20 20 20 20 20 31 33 31 31 30 34 32 38
> 0000020 37 31 20 20 35 30 31 20 20 20 32 30 20 20 20 20
which, if you backsolve using the header format, corresponds to the time field.
Manpage gives no indication of whether or not it is possible to override the timestamp from the header. Any thoughts?
Edit: yes, it is possible to go back and physically hack the file to use an arbitrary timestamp. yes, it is possible to change the program's behavior. Given the circumstances surrounding the situation, not all of which are strictly technical in nature, a tool to manually change the timestamp is not acceptable, nor is a modified version of ar
, nor is messing with the actual system time.
Edit: In this circumstance, I have to prove that, without any unacceptable deviation from the build path, the binaries can be produced from source. In some industries (e.g. finance) this is apparently a standard practice. A handrolled tool to change the timestamps is unacceptable (because a special tool, which was not in the original build path, was used). A handrolled version of ar
is unacceptable (similar problem). The problem with changing system clock is that the build would have to be perfectly coordinated (it is an hour-long build with a lot of libraries and binaries). Acceptable solutions include:
Static libraries are simply a collection of ordinary object files; conventionally, static libraries end with the ``. a'' suffix. This collection is created using the ar (archiver) program.
Thin archive <thin>. A thin archive only contains a symbol table and references to the file. The file format is essentially a System V format archive where every file is stored without the data sections.
ar -rcs is the most likely command you would use when using a Makefile to compile a library. r means that if the library already exists, replace the old files within the library with your new files. c means create the library if it did not exist.
In computer science, a static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable.
Use "deterministic mode" in ar. See option "D" for ar in manual.
me@mybox:~$ rm libfoo.a; touch foo.o; ar rcsD libfoo.a foo.o; md5sum libfoo.a
3ecae045133ff919d1e42f6050ef56be libfoo.a
me@mybox:~$ rm libfoo.a; touch foo.o; ar rcsD libfoo.a foo.o; md5sum libfoo.a
3ecae045133ff919d1e42f6050ef56be libfoo.a
If you use ranlib
afterwards, make sure you're using ranlib -D
; otherwise ranlib
will put the timestamp back.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With