diff options
author | crupest <crupest@outlook.com> | 2018-11-13 01:01:27 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-11-13 01:01:27 +0800 |
commit | e158fcb47ea6a7bd9172d0751e38265b61d6c88c (patch) | |
tree | 1e142ae77ad824eeb87b634554d3f7159de442c9 /tools | |
parent | 828a48aa387796ce89706ade69d0a6a3bf1e35a9 (diff) | |
download | cru-e158fcb47ea6a7bd9172d0751e38265b61d6c88c.tar.gz cru-e158fcb47ea6a7bd9172d0751e38265b61d6c88c.tar.bz2 cru-e158fcb47ea6a7bd9172d0751e38265b61d6c88c.zip |
Dev code gen.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/cppmerge/.gitignore | 147 | ||||
-rw-r--r-- | tools/cppmerge/.vscode/launch.json | 20 | ||||
-rw-r--r-- | tools/cppmerge/main.py | 115 |
3 files changed, 269 insertions, 13 deletions
diff --git a/tools/cppmerge/.gitignore b/tools/cppmerge/.gitignore new file mode 100644 index 00000000..0b6b38d0 --- /dev/null +++ b/tools/cppmerge/.gitignore @@ -0,0 +1,147 @@ + +# Created by https://www.gitignore.io/api/python,visualstudiocode +# Edit at https://www.gitignore.io/?templates=python,visualstudiocode + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### Python Patch ### +.venv/ + +### Python.VirtualEnv Stack ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +pip-selfcheck.json + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/python,visualstudiocode diff --git a/tools/cppmerge/.vscode/launch.json b/tools/cppmerge/.vscode/launch.json new file mode 100644 index 00000000..dcbc3389 --- /dev/null +++ b/tools/cppmerge/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/main.py", + "args": [ + "--output", + "cru_ui", + "../../src" + ], + "console": "integratedTerminal" + } + ] +}
\ No newline at end of file diff --git a/tools/cppmerge/main.py b/tools/cppmerge/main.py index ed06a2f7..76966a47 100644 --- a/tools/cppmerge/main.py +++ b/tools/cppmerge/main.py @@ -5,7 +5,7 @@ import re import sys parser = argparse.ArgumentParser() -parser.add_argument("-o", "--output", required=True, help="The name of output header and source files excluding extension.") +parser.add_argument("-o", "--output", required=True, help="The path of output header and source files excluding extension.") parser.add_argument("input", nargs="+", help="The input source files or folders to scan.") parser.add_argument("-e", "--exclude", nargs="+", help="Filenames that exludes from merging.") args = parser.parse_args() @@ -23,25 +23,23 @@ def add_header_file(path): print("find header file: {}".format(path)) header_file_list.append(path) -cpp_header_file_regex = re.compile(r".*\.(h|hpp)") -cpp_source_file_regex = re.compile(r".*\.(cpp|cc|cxx)") +cpp_header_file_regex = re.compile(r"^.*\.(h|hpp)$") +cpp_source_file_regex = re.compile(r"^.*\.(cpp|cc|cxx)$") +def is_exclude(file_name): + return args.exclude and file_name in args.exclude for path in args.input: if os.path.isdir(path): input_dirs.append(path) elif os.path.isfile(path): file_name = os.path.basename(path) + if is_exclude(file_name): + sys.exit("{} is specified excluding.") if cpp_source_file_regex.match(file_name): - if file_name in args.exclude: - sys.exit("{} is specified excluding.") - else: - add_source_file(path) - elif cpp_header_file_regex.match(file_name): - if file_name in args.exclude: - sys.exit("{} is specified excluding.") - else: - add_header_file(path) + add_source_file(path) + elif cpp_header_file_regex.match(file_name): + add_header_file(path) else: sys.exit("{} is a file but it is neither c++ source nor header.".format(path)) else: @@ -52,7 +50,7 @@ actual_exclude_count = 0 for input_dir in input_dirs: for root, subdirs, files in os.walk(input_dir): for f in files: - if f in args.exclude: + if is_exclude(f): actual_exclude_count += 1 else: if cpp_source_file_regex.match(f): @@ -68,3 +66,94 @@ print("total find {} source file(s)".format(len(source_file_list))) print("total actual exclude {} file(s)".format(actual_exclude_count)) print() +norm_source_file_list = [os.path.normpath(path) for path in source_file_list] +norm_header_file_list = [os.path.normpath(path) for path in header_file_list] + +output_header_file_path = args.output + '.hpp' +output_source_file_path = args.output + '.cpp' + + +output_header_file = open(output_header_file_path, 'w') +output_source_file = open(output_source_file_path, 'w') + + +processed_headers = [] + +header_pragma_once_regex = re.compile(r'#\s*pragma\s*once') +header_include_command_regex = re.compile(r'#\s*include\s*"([\w.\-_/\\]+)"') + +def process_line(line): + match_result = header_include_command_regex.match(line) + if match_result: + return match_result.group(1) + else: + return None + +def find_header_path(base_path, header_path): + path = os.path.join(base_path, header_path) + if os.path.isfile(path): + return path + else: + for d in input_dirs: + path = os.path.join(d, header_path) + if os.path.isfile(path): + return path + raise RuntimeError("Header not found.\nBase path: {}\nHeader path: {}".format(base_path, header_path)) + +def process_header_file(base_path, header_path): + path = find_header_path(base_path, header_path) + path = os.path.normpath(path) + if path in processed_headers: + return + processed_headers.append(path) + + output_header_file.write("//--------------------------------------------------------\n") + output_header_file.write("//-------begin of file: {}\n".format(path)) + output_header_file.write("//--------------------------------------------------------\n") + header_f = open(path, 'r') + found_pragma_once = False + for line in header_f: + if (not found_pragma_once): + if header_pragma_once_regex.match(line): + found_pragma_once = True + continue + new_header_name = process_line(line) + if not new_header_name is None: + process_header_file(os.path.dirname(path), new_header_name) + else: + output_header_file.write(line) + output_header_file.write("//--------------------------------------------------------\n") + output_header_file.write("//-------end of file: {}\n".format(path)) + output_header_file.write("//--------------------------------------------------------\n") + + +output_header_file.write("#pragma once\n") + +output_source_file.write('#include "{}"\n'.format(os.path.basename(output_header_file_path))) + + +for source_path in source_file_list: + output_source_file.write("//--------------------------------------------------------\n") + output_source_file.write("//-------begin of file: {}\n".format(source_path)) + output_source_file.write("//--------------------------------------------------------\n") + source_f = open(source_path, 'r') + for line in source_f: + new_header_name = process_line(line) + if not new_header_name is None: + process_header_file(os.path.dirname(source_path), new_header_name) + else: + output_source_file.write(line) + output_source_file.write("//--------------------------------------------------------\n") + output_source_file.write("//-------end of file: {}\n".format(source_path)) + output_source_file.write("//--------------------------------------------------------\n") + +rest_header_count = len(norm_header_file_list) - len(processed_headers) + +if rest_header_count > 0: + print("{} header files are not included in any sources. Add them to header now.".format(rest_header_count)) + print() + for header_path in norm_header_file_list: + if header_path not in processed_headers: + process_header_file('.', header_path) + +print("Done!") |