Makefile targets for automatically generated files

Run `make generated_files` to generate the automatically generated
C source files and build scripts.

Run `make neat` to remove all automatically generated files, even C
source files and build scripts.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/Makefile b/Makefile
index 6a8b230..a0c4386 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,6 @@
 DESTDIR=/usr/local
 PREFIX=mbedtls_
+PERL ?= perl
 
 .SILENT:
 
@@ -22,6 +23,32 @@
 mbedtls_test:
 	$(MAKE) -C tests mbedtls_test
 
+library/%:
+	$(MAKE) -C library $*
+programs/%:
+	$(MAKE) -C programs $*
+tests/%:
+	$(MAKE) -C tests $*
+
+.PHONY: generated_files
+generated_files: library/generated_files
+generated_files: programs/generated_files
+generated_files: tests/generated_files
+generated_files: visualc_files
+
+.PHONY: visualc_files
+VISUALC_FILES = visualc/VS2010/mbedTLS.sln visualc/VS2010/mbedTLS.vcxproj
+# TODO: $(app).vcxproj for each $(app) in programs/
+visualc_files: $(VISUALC_FILES)
+$(VISUALC_FILES): scripts/generate_visualc_files.pl
+$(VISUALC_FILES): scripts/data_files/vs2010-app-template.vcxproj
+$(VISUALC_FILES): scripts/data_files/vs2010-main-template.vcxproj
+$(VISUALC_FILES): scripts/data_files/vs2010-sln-template.sln
+# TODO: also the list of .c and .h source files, but not their content
+$(VISUALC_FILES):
+	echo "  Gen   $@ ..."
+	$(PERL) scripts/generate_visualc_files.pl
+
 ifndef WINDOWS
 install: no_test
 	mkdir -p $(DESTDIR)/include/mbedtls
@@ -86,14 +113,27 @@
 	    echo '$(NULL_ENTROPY_WARNING)'
 endif
 
-clean:
+clean: clean_more_on_top
 	$(MAKE) -C library clean
 	$(MAKE) -C programs clean
 	$(MAKE) -C tests clean
+
+clean_more_on_top:
 ifndef WINDOWS
 	find . \( -name \*.gcno -o -name \*.gcda -o -name \*.info \) -exec rm {} +
 endif
 
+neat: clean_more_on_top
+	$(MAKE) -C library neat
+	$(MAKE) -C programs neat
+	$(MAKE) -C tests neat
+ifndef WINDOWS
+	rm -f visualc/VS2010/*.vcxproj visualc/VS2010/mbedTLS.sln
+else
+	if exist visualc\VS2010\*.vcxproj del /Q /F visualc\VS2010\*.vcxproj
+	if exist visualc\VS2010\mbedTLS.sln del /Q /F visualc\VS2010\mbedTLS.sln
+endif
+
 check: lib tests
 	$(MAKE) -C tests check
 
diff --git a/library/Makefile b/library/Makefile
index 17e42c2..155e926 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -22,6 +22,8 @@
 # To compile on Plan9:
 # CFLAGS += -D_BSD_EXTENSION
 
+PERL ?= perl
+
 # if were running on Windows build for Windows
 ifdef WINDOWS
 WINDOWS_BUILD=1
@@ -270,6 +272,24 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
 
+.PHONY: generated_files
+GENERATED_FILES = error.c version_features.c
+generated_files: $(GENERATED_FILES)
+
+error.c: ../scripts/generate_errors.pl
+error.c: ../scripts/data_files/error.fmt
+error.c: $(wildcard ../include/mbedtls/*.h)
+error.c:
+	echo "  Gen   $@"
+	$(PERL) ../scripts/generate_errors.pl
+
+version_features.c: ../scripts/generate_features.pl
+version_features.c: ../scripts/data_files/version_features.fmt
+version_features.c: ../include/mbedtls/config.h
+version_features.c:
+	echo "  Gen   $@"
+	$(PERL) ../scripts/generate_features.pl
+
 clean:
 ifndef WINDOWS
 	rm -f *.o libmbed*
@@ -279,3 +299,10 @@
 	if exist libmbed* del /Q /F libmbed*
 	del /Q /F del_errors_out_if_the_file_list_is_empty_but_not_if_a_file_does_not_exist $(subst /,\,$(THIRDPARTY_CRYPTO_OBJECTS))
 endif
+
+neat: clean
+ifndef WINDOWS
+	rm -f $(GENERATED_FILES)
+else
+	for %f in ($(subst /,\,$(GENERATED_FILES))) if exist %f del /Q /F %f
+endif
diff --git a/programs/Makefile b/programs/Makefile
index b194c69..7b2ec51 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -43,10 +43,12 @@
 ifdef SHARED
 SHARED_SUFFIX=.$(DLEXT)
 endif
+PYTHON ?= python
 else
 DLEXT ?= so
 EXEXT=
 SHARED_SUFFIX=
+PYTHON ?= $(shell if type python3 >/dev/null 2>/dev/null; then echo python3; else echo python; fi)
 endif
 
 APPS = \
@@ -132,6 +134,26 @@
 ${MBEDTLS_TEST_OBJS}:
 	$(MAKE) -C ../tests mbedtls_test
 
+.PHONY: generated_files
+GENERATED_FILES = psa/psa_constant_names_generated.c test/query_config.c
+generated_files: $(GENERATED_FILES)
+
+psa/psa_constant_names_generated.c: ../scripts/generate_psa_constants.py
+psa/psa_constant_names_generated.c: ../include/psa/crypto_values.h
+psa/psa_constant_names_generated.c: ../include/psa/crypto_extra.h
+psa/psa_constant_names_generated.c: ../tests/suites/test_suite_psa_crypto_metadata.data
+psa/psa_constant_names_generated.c:
+	echo "  Gen   $@"
+	$(PYTHON) ../scripts/generate_psa_constants.py
+
+test/query_config.c: ../scripts/generate_query_config.pl
+test/query_config.c: ../include/mbedtls/config.h
+test/query_config.c: ../scripts/data_files/query_config.fmt
+test/query_config.c:
+	echo "  Gen   $@"
+	$(PERL) ../scripts/generate_query_config.pl
+
+
 aes/aescrypt2$(EXEXT): aes/aescrypt2.c $(DEP)
 	echo "  CC    aes/aescrypt2.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) aes/aescrypt2.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -370,5 +392,12 @@
 endif
 	$(MAKE) -C fuzz clean
 
+neat: clean
+ifndef WINDOWS
+	rm -f $(GENERATED_FILES)
+else
+	for %f in ($(subst /,\,$(GENERATED_FILES))) if exist %f del /Q /F %f
+endif
+
 list:
 	echo $(APPS)
diff --git a/tests/Makefile b/tests/Makefile
index 7afd0f5..ef57169 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -5,6 +5,8 @@
 WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
 LDFLAGS ?=
 
+default: all
+
 # Include public header files from ../include, test-specific header files
 # from ./include, and private header files (used by some invasive tests)
 # from ../library.
@@ -56,10 +58,28 @@
 PYTHON ?= $(shell if type python3 >/dev/null 2>/dev/null; then echo python3; else echo python; fi)
 endif
 
+.PHONY: generated_files
+GENERATED_DATA_FILES := $(patsubst tests/%,%,$(shell $(PYTHON) scripts/generate_psa_tests.py --list))
+GENERATED_FILES := $(GENERATED_DATA_FILES)
+generated_files: $(GENERATED_FILES)
+
+$(GENERATED_DATA_FILES): scripts/generate_psa_tests.py
+$(GENERATED_DATA_FILES): ../include/psa/crypto_config.h
+$(GENERATED_DATA_FILES): ../include/psa/crypto_values.h
+$(GENERATED_DATA_FILES): ../include/psa/crypto_extra.h
+$(GENERATED_DATA_FILES): suites/test_suite_psa_crypto_metadata.data
+$(GENERATED_DATA_FILES):
+	echo "  Gen   $@ ..."
+	$(PYTHON) scripts/generate_psa_tests.py
+
 # A test application is built for each suites/test_suite_*.data file.
 # Application name is same as .data file's base name and can be
 # constructed by stripping path 'suites/' and extension .data.
-APPS = $(basename $(subst suites/,,$(wildcard suites/test_suite_*.data)))
+DATA_FILES := $(wildcard suites/test_suite_*.data)
+# Make sure that generated data files are included even if they don't
+# exist yet when the makefile is parsed.
+DATA_FILES += $(filter-out $(DATA_FILES),$(GENERATED_DATA_FILES))
+APPS = $(basename $(subst suites/,,$(DATA_FILES)))
 
 # Construct executable name by adding OS specific suffix $(EXEXT).
 BINARIES := $(addsuffix $(EXEXT),$(APPS))
@@ -144,6 +164,13 @@
 endif
 endif
 
+neat: clean
+ifndef WINDOWS
+	rm -f $(GENERATED_FILES)
+else
+	for %f in ($(subst /,\,$(GENERATED_FILES))) if exist %f del /Q /F %f
+endif
+
 # Test suites caught by SKIP_TEST_SUITES are built but not executed.
 check: $(BINARIES)
 	perl scripts/run-test-suites.pl --skip=$(SKIP_TEST_SUITES)