build: make the static-file build repeatable

Two things kept the same source from producing the same image.

fileadder walked the input directory with readdir(), which returns entries
in whatever order the filesystem hands them over. The same tree therefore
embedded the files in a different order on a different filesystem, and the
image differed byte for byte. scandir() with alphasort() fixes the order.

version.h was listed in .PHONY, which makes it permanently out of date and
propagates that to everything including it, so a plain build recompiled the
four largest translation units even when nothing had changed. Dropping it
from .PHONY alone would go too far the other way: with no prerequisites the
recipe would never run again and the version string would freeze at its
first value. A FORCE prerequisite keeps the recipe running every time, and
the generated header is only moved into place when its content actually
differs, so the timestamp survives an unchanged rebuild.

Measured on this tree: with FORCE the version follows GIT_VERSION and an
unchanged rebuild leaves version.h untouched; without it the header keeps
the value from the first build.
This commit is contained in:
d00f authored and DrDoof committed 2026-09-29 05:27:07 +02:00
1 parent de705380c9
commit 5ffeb3d16a
2 files changed
+14 -7

No files matched your search

+6 -3
View File
@@ -112,11 +112,14 @@ html_min: $(HTML)
html_data.c html_data.h &: $(HTML) | tools html_min html_data.c html_data.h &: $(HTML) | tools html_min
tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data tools/output/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
$(VERSION_HEADER): $(VERSION_HEADER): FORCE
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \ @printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \ "#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
"#define BUILD_DATE \"$(BUILD_DATE)\"" \ "#define BUILD_DATE \"$(BUILD_DATE)\"" \
"#endif" > $(VERSION_HEADER) "#endif" > $(VERSION_HEADER).tmp
@cmp -s $(VERSION_HEADER).tmp $(VERSION_HEADER) \
&& rm -f $(VERSION_HEADER).tmp \
|| mv $(VERSION_HEADER).tmp $(VERSION_HEADER)
httpd: html_data.h httpd: html_data.h
@@ -166,7 +169,7 @@ $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.i
tools/output/crc_calculator -u $@ tools/output/crc_calculator -u $@
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) $(VERSION_HEADER) create_build_dir .PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir
.PHONY: .PHONY:
machine_check: machine_check:
+8 -4
View File
@@ -338,15 +338,16 @@ int main(int argc, char **argv)
if (stat(arguments.data_file, &s) == 0 && s.st_mode & S_IFDIR) { if (stat(arguments.data_file, &s) == 0 && s.st_mode & S_IFDIR) {
printf("Adding entries in directory %s\n", arguments.data_file); printf("Adding entries in directory %s\n", arguments.data_file);
addsDir = true; addsDir = true;
DIR *dirptr = opendir(arguments.data_file); struct dirent **entries;
if (!dirptr) { int n_entries = scandir(arguments.data_file, &entries, NULL, alphasort);
if (n_entries < 0) {
fprintf(stderr, "%s: ", arguments.data_file); fprintf(stderr, "%s: ", arguments.data_file);
perror("Error opening directory"); perror("Error opening directory");
return 5; return 5;
} }
struct dirent *in_file;
int addr = arguments.address; int addr = arguments.address;
while ( (in_file = readdir(dirptr)) ) { for (int e = 0; e < n_entries; e++) {
struct dirent *in_file = entries[e];
snprintf(pathbuffer, PATH_SIZE, "%s/%s", arguments.data_file, in_file->d_name); snprintf(pathbuffer, PATH_SIZE, "%s/%s", arguments.data_file, in_file->d_name);
if (stat(pathbuffer, &s) < 0) { if (stat(pathbuffer, &s) < 0) {
fprintf(stderr, "%s: ", pathbuffer); fprintf(stderr, "%s: ", pathbuffer);
@@ -377,6 +378,9 @@ int main(int argc, char **argv)
addidx(in_file->d_name, addr, data_read); addidx(in_file->d_name, addr, data_read);
addr += data_read; addr += data_read;
} }
for (int e = 0; e < n_entries; e++)
free(entries[e]);
free(entries);
} else { } else {
size_t data_read = addfile(arguments.data_file, arguments.address); size_t data_read = addfile(arguments.data_file, arguments.address);