2024-08-06 02:45:00 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
Generates a clang module map for a given directory
|
|
|
|
"""
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import pathlib
|
|
|
|
import yaml
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
def write_file_if_not_same(file_path, content):
|
|
|
|
try:
|
|
|
|
with open(file_path, 'r') as f:
|
|
|
|
if f.read() == content:
|
|
|
|
return
|
|
|
|
except FileNotFoundError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
with open(file_path, 'w') as f:
|
|
|
|
f.write(content)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
epilog=__doc__,
|
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
|
|
parser.add_argument('directory', help='source directory to generate module map for')
|
2024-11-14 23:05:08 +00:00
|
|
|
parser.add_argument('--module-name', help='top-level module name')
|
|
|
|
parser.add_argument('--module-map', required=True, help='output module map file')
|
|
|
|
parser.add_argument('--vfs-map', required=True, help='output VFS map file')
|
|
|
|
parser.add_argument('--exclude-files', nargs='*', required=False, help='files to exclude in the module map')
|
|
|
|
parser.add_argument('--generated-files', nargs='*', help='extra files to include in the module map')
|
2024-08-06 02:45:00 +00:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
root = pathlib.Path(args.directory)
|
|
|
|
if not root.is_dir():
|
|
|
|
print(f"Error: {args.directory} is not a directory", file=sys.stderr)
|
|
|
|
return 1
|
|
|
|
pathlib.Path(args.module_map).parent.mkdir(parents=True, exist_ok=True)
|
2024-08-27 01:04:05 +00:00
|
|
|
pathlib.Path(args.vfs_map).parent.mkdir(parents=True, exist_ok=True)
|
2024-11-14 23:05:08 +00:00
|
|
|
exclude_files = set(args.exclude_files) if args.exclude_files else set()
|
2024-08-06 02:45:00 +00:00
|
|
|
|
2024-11-14 23:05:08 +00:00
|
|
|
header_files = [f for f in root.rglob('**/*.h') if f.is_file() and f.name not in exclude_files]
|
2024-08-27 01:04:05 +00:00
|
|
|
module_name = args.module_name if args.module_name else root.name
|
2024-08-06 02:45:00 +00:00
|
|
|
|
|
|
|
module_map = f"module {module_name} {{\n"
|
|
|
|
for header_file in header_files:
|
|
|
|
module_map += f" header \"{header_file.relative_to(root)}\"\n"
|
|
|
|
for generated_file in args.generated_files:
|
|
|
|
module_map += f" header \"{generated_file}\"\n"
|
|
|
|
module_map += " requires cplusplus\n"
|
|
|
|
module_map += " export *\n"
|
|
|
|
module_map += "}\n"
|
|
|
|
|
|
|
|
vfs_map = {
|
|
|
|
"version": 0,
|
|
|
|
"use-external-names": False,
|
|
|
|
"roots": [
|
|
|
|
{
|
|
|
|
"name": f"{root}/module.modulemap",
|
|
|
|
"type": "file",
|
|
|
|
"external-contents": f"{args.module_map}"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
write_file_if_not_same(args.module_map, module_map)
|
|
|
|
write_file_if_not_same(args.vfs_map, yaml.dump(vfs_map))
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
sys.exit(main())
|