summaryrefslogtreecommitdiff
path: root/Meta
diff options
context:
space:
mode:
authorBen Wiederhake <BenWiederhake.GitHub@gmx.de>2021-01-21 21:41:48 +0100
committerLinus Groh <mail@linusgroh.de>2021-10-20 09:20:18 +0100
commit8de696bdd04b5d5b9e0bc6fbfe2d1e03371817e2 (patch)
tree899bb98fa6e2968e91feeb98cc08261677b50978 /Meta
parentdee26ca5cdfe62c28c6ec5c516187f335b58471e (diff)
downloadserenity-8de696bdd04b5d5b9e0bc6fbfe2d1e03371817e2.zip
HeaderCheck: It checks some of your headers
Diffstat (limited to 'Meta')
-rw-r--r--Meta/CMake/common_options.cmake1
-rw-r--r--Meta/HeaderCheck/.gitignore1
-rw-r--r--Meta/HeaderCheck/CMakeLists.txt4
-rwxr-xr-xMeta/HeaderCheck/generate_all.py70
4 files changed, 76 insertions, 0 deletions
diff --git a/Meta/CMake/common_options.cmake b/Meta/CMake/common_options.cmake
index d46fe3f734..15f2d2a4b6 100644
--- a/Meta/CMake/common_options.cmake
+++ b/Meta/CMake/common_options.cmake
@@ -7,6 +7,7 @@ serenity_option(ENABLE_UNDEFINED_SANITIZER OFF CACHE BOOL "Enable undefined beha
serenity_option(ENABLE_ALL_THE_DEBUG_MACROS OFF CACHE BOOL "Enable all debug macros to validate they still compile")
serenity_option(ENABLE_ALL_DEBUG_FACILITIES OFF CACHE BOOL "Enable all noisy debug symbols and options. Not recommended for normal developer use")
+serenity_option(ENABLE_COMPILETIME_HEADER_CHECK OFF CACHE BOOL "Enable compiletime check that each library header compiles stand-alone")
serenity_option(ENABLE_UNICODE_DATABASE_DOWNLOAD ON CACHE BOOL "Enable download of Unicode UCD and CLDR files at build time")
serenity_option(INCLUDE_WASM_SPEC_TESTS OFF CACHE BOOL "Download and include the WebAssembly spec testsuite")
diff --git a/Meta/HeaderCheck/.gitignore b/Meta/HeaderCheck/.gitignore
new file mode 100644
index 0000000000..a0f00082c8
--- /dev/null
+++ b/Meta/HeaderCheck/.gitignore
@@ -0,0 +1 @@
+CMakeLists.txt
diff --git a/Meta/HeaderCheck/CMakeLists.txt b/Meta/HeaderCheck/CMakeLists.txt
new file mode 100644
index 0000000000..86e0d165e1
--- /dev/null
+++ b/Meta/HeaderCheck/CMakeLists.txt
@@ -0,0 +1,4 @@
+execute_process(COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/generate_all.py" "${SERENITY_ARCH}" OUTPUT_VARIABLE SOURCES_STRING)
+string(REPLACE "\n" ";" SOURCES_LIST ${SOURCES_STRING})
+
+add_library(HeaderCheck OBJECT ${SOURCES_LIST})
diff --git a/Meta/HeaderCheck/generate_all.py b/Meta/HeaderCheck/generate_all.py
new file mode 100755
index 0000000000..df7c9e9142
--- /dev/null
+++ b/Meta/HeaderCheck/generate_all.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import subprocess
+
+TEST_FILE_TEMPLATE = '''\
+#include <{filename}>
+// Check idempotency:
+#include <{filename}>
+'''
+
+
+def get_headers_here():
+ result = subprocess.run(['git', 'ls-files', 'Userland/Libraries/*.h'], check=True, capture_output=True, text=True)
+ assert result.stderr == ''
+ output = result.stdout.split('\n')
+ assert output[-1] == '' # Trailing newline
+ assert len(output) > 500, 'There should be well over a thousand headers, not only {}?!'.format(len(output))
+ return output[:-1]
+
+
+def as_filename(header_path):
+ return header_path.replace('/', '__') + '__test.cpp'
+
+
+def verbosely_write(path, new_content):
+ print(path)
+ # FIXME: Ensure directory exists
+ if os.path.exists(path):
+ with open(path, 'r') as fp:
+ old_data = fp.read()
+ if old_data == new_content:
+ # Fast path! Don't trigger ninja
+ return
+ with open(path, 'w') as fp:
+ fp.write(new_content)
+
+
+def generate_part(header):
+ content = TEST_FILE_TEMPLATE.format(filename=header)
+ if header.startswith('Kernel/'):
+ content += '#define KERNEL\n'
+ verbosely_write(as_filename(header), content)
+
+
+def run(root_path, arch):
+ os.chdir(root_path)
+ headers_list = get_headers_here()
+
+ generated_files_path = os.path.join(root_path, 'Build', arch, 'Meta', 'HeaderCheck')
+ if not os.path.exists(generated_files_path):
+ os.mkdir(generated_files_path)
+ os.chdir(generated_files_path)
+ for header in headers_list:
+ generate_part(header)
+
+
+if __name__ == '__main__':
+ if 'SERENITY_SOURCE_DIR' not in os.environ:
+ print('Must set SERENITY_SOURCE_DIR first!', file=sys.stderr)
+ exit(1)
+ if len(sys.argv) == 2:
+ with open('/tmp/the_arg', 'w') as fp:
+ fp.write(sys.argv[1])
+ run(os.environ['SERENITY_SOURCE_DIR'], sys.argv[1])
+ else:
+ print('Usage: SERENITY_SOURCE_DIR=/path/to/serenity {} SERENITY_BUILD_ARCH'
+ .format(sys.argv[0]), file=sys.stderr)
+ exit(1)