From d72500bc70e0b7f1b36c56c737ca71ee3ee4e47f Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 6 Nov 2024 19:34:46 +0100 Subject: [PATCH] Fix CMake integration of NMODL generation. The code for the code-generator NMODL is itself generated from Jinja templates. This requires CMake integration to ensure it happens automatically. The following has been changed about the integration: * The CMake code needs a list of the generated files. This list is stored in a CMake file and included. This file must exist before running `code_generator.py` to generate the NMODL code, because the command to generate the files needs to know which file it will be generating. Therefore, we split the script into two phases: one to generate the list of generated files, and another to generate the files. * The list of generated files depends on the build flags. Therefore, this file (`code_generator.cmake`) can't be checked into the Git repo. The `code_generator.cmake` is created during the configure phase, and now lives in the build directory. * CMake code was lifted from `src/language/CMakeLists.txt` to the top-level `CMakeLists.txt` to avoid any scoping issues for the lists of generated files. * Removed pattern of yielding tasks while creating a list tasks in favour of returning the list of tasks directly. --- CMakeLists.txt | 71 ++++++- src/CMakeLists.txt | 3 +- src/language/CMakeLists.txt | 35 ---- src/language/code_generator.cmake | 212 -------------------- src/language/code_generator.py | 31 ++- src/language/code_generator_opts.in | 1 + src/language/templates/code_generator.cmake | 3 +- src/language/templates/visitors/visitor.hpp | 8 +- 8 files changed, 102 insertions(+), 262 deletions(-) delete mode 100644 src/language/code_generator.cmake create mode 100644 src/language/code_generator_opts.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 47b0484443..f8f631bb7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,10 +230,75 @@ if(NOT NMODL_AS_SUBPROJECT AND NMODL_ENABLE_TESTS) endif() # ============================================================================= -# list of autogenerated files -# ============================================================================= -include(${PROJECT_SOURCE_DIR}/src/language/code_generator.cmake) +# Generate NMODL code, e.g. ast & visitor base classes. +# ----------------------------------------------------------------------------- +# clang-format is handled by the HPC coding conventions scripts, which also handle generating the +# .clang-format configuration file. It's important that we only try to format code if formatting was +# enabled and NMODL's .clang-format exists, otherwise clang-format will search too far up the +# directory tree and find the wrong configuration file. This can break compilation. +if(NMODL_CLANG_FORMAT OR NMODL_FORMATTING) + set(CODE_GENERATOR_OPTS -v --clang-format=${ClangFormat_EXECUTABLE}) + foreach(clang_format_opt ${NMODL_ClangFormat_OPTIONS} --style=file) + list(APPEND CODE_GENERATOR_OPTS --clang-format-opts=${clang_format_opt}) + endforeach() +endif() +if(NOT NMODL_ENABLE_PYTHON_BINDINGS) + list(APPEND CODE_GENERATOR_OPTS "--disable-pybind") +endif() + +# ----------------------------------------------------------------------------- +# Part I: generate the list of generated files +# ----------------------------------------------------------------------------- +execute_process( + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/language/code_generator.py + ${CODE_GENERATOR_OPTS} --generate-cmake --base-dir ${PROJECT_BINARY_DIR}/src + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/language) + +# Ensure that the above runs again, if its dependencies update. +set_property( + DIRECTORY + APPEND + PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/language/code_generator.py") + +set_property( + DIRECTORY + APPEND + PROPERTY CMAKE_CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/src/language/templates/code_generator.cmake) + +# The list should be up-to-date now. +include(${PROJECT_BINARY_DIR}/src/code_generator.cmake) + +# ----------------------------------------------------------------------------- +# Part II: generate AST/Visitor classes from language definition +# ----------------------------------------------------------------------------- +set_source_files_properties(${NMODL_GENERATED_SOURCES} PROPERTIES GENERATED TRUE) + +# Make the codegen options available as a dependency by storing them in a file. +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/language/code_generator_opts.in + ${CMAKE_CURRENT_BINARY_DIR}/src/language/code_generator_opts) + +add_custom_command( + OUTPUT ${NMODL_GENERATED_SOURCES} + COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/src/language/code_generator.py + ${CODE_GENERATOR_OPTS} --base-dir ${PROJECT_BINARY_DIR}/src + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/language + DEPENDS ${CODE_GENERATOR_PY_FILES} + DEPENDS ${CODE_GENERATOR_YAML_FILES} + DEPENDS ${CODE_GENERATOR_JINJA_FILES} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/src/language/code_generator_opts + COMMENT "-- NMODL : GENERATING AST CLASSES WITH PYTHON GENERATOR! --") +unset(CODE_GENERATOR_OPTS) + +# ----------------------------------------------------------------------------- +# Target to propagate dependencies properly to lexer +# ----------------------------------------------------------------------------- +add_custom_target(pyastgen DEPENDS ${PROJECT_BINARY_DIR}/src/ast/ast.cpp) + +# ============================================================================= +# Deal with the hand-written code +# ============================================================================= add_subdirectory(src) # ============================================================================= diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 14051dba96..1c44ad028a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,8 +4,9 @@ add_compile_options(${NMODL_EXTRA_CXX_FLAGS}) add_link_options(${NMODL_EXTRA_CXX_FLAGS}) -add_subdirectory(codegen) add_subdirectory(language) + +add_subdirectory(codegen) add_subdirectory(lexer) add_subdirectory(parser) add_subdirectory(printer) diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index 92a8ce46b4..8b13789179 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -1,36 +1 @@ -# ============================================================================= -# Command to generate AST/Visitor classes from language definition -# ============================================================================= -set_source_files_properties(${NMODL_GENERATED_SOURCES} PROPERTIES GENERATED TRUE) -# clang-format is handled by the HPC coding conventions scripts, which also handle generating the -# .clang-format configuration file. It's important that we only try to format code if formatting was -# enabled and NMODL's .clang-format exists, otherwise clang-format will search too far up the -# directory tree and find the wrong configuration file. This can break compilation. -if(NMODL_CLANG_FORMAT OR NMODL_FORMATTING) - set(CODE_GENERATOR_OPTS -v --clang-format=${ClangFormat_EXECUTABLE}) - foreach(clang_format_opt ${NMODL_ClangFormat_OPTIONS} --style=file) - list(APPEND CODE_GENERATOR_OPTS --clang-format-opts=${clang_format_opt}) - endforeach() -endif() - -if(NOT NMODL_ENABLE_PYTHON_BINDINGS) - list(APPEND CODE_GENERATOR_OPTS "--disable-pybind") -endif() - -add_custom_command( - OUTPUT ${NMODL_GENERATED_SOURCES} - COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/code_generator.py - ${CODE_GENERATOR_OPTS} --base-dir ${PROJECT_BINARY_DIR}/src - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${CODE_GENERATOR_PY_FILES} - DEPENDS ${CODE_GENERATOR_YAML_FILES} - DEPENDS ${CODE_GENERATOR_JINJA_FILES} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/templates/code_generator.cmake - COMMENT "-- NMODL : GENERATING AST CLASSES WITH PYTHON GENERATOR! --") -unset(CODE_GENERATOR_OPTS) - -# ============================================================================= -# Target to propagate dependencies properly to lexer -# ============================================================================= -add_custom_target(pyastgen DEPENDS ${PROJECT_BINARY_DIR}/src/ast/ast.cpp) diff --git a/src/language/code_generator.cmake b/src/language/code_generator.cmake deleted file mode 100644 index 2bec777654..0000000000 --- a/src/language/code_generator.cmake +++ /dev/null @@ -1,212 +0,0 @@ -# -# THIS FILE IS GENERATED AND SHALL NOT BE EDITED. -# - -# cmake-format: off -set(CODE_GENERATOR_JINJA_FILES - ${PROJECT_SOURCE_DIR}/src/language/templates/ast/all.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/ast/ast.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/ast/ast.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/ast/ast_decl.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/ast/node.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/ast/node_class.template - ${PROJECT_SOURCE_DIR}/src/language/templates/pybind/pyast.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/pybind/pyast.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/pybind/pynode.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/pybind/pysymtab.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/pybind/pyvisitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/pybind/pyvisitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/ast_visitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/ast_visitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/checkparent_visitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/checkparent_visitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/json_visitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/json_visitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/lookup_visitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/lookup_visitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/nmodl_visitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/nmodl_visitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/symtab_visitor.cpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/symtab_visitor.hpp - ${PROJECT_SOURCE_DIR}/src/language/templates/visitors/visitor.hpp -) - -set(CODE_GENERATOR_PY_FILES - ${PROJECT_SOURCE_DIR}/src/language/argument.py - ${PROJECT_SOURCE_DIR}/src/language/code_generator.py - ${PROJECT_SOURCE_DIR}/src/language/language_parser.py - ${PROJECT_SOURCE_DIR}/src/language/node_info.py - ${PROJECT_SOURCE_DIR}/src/language/nodes.py - ${PROJECT_SOURCE_DIR}/src/language/utils.py -) - -set(CODE_GENERATOR_YAML_FILES - ${PROJECT_SOURCE_DIR}/src/language/codegen.yaml - ${PROJECT_SOURCE_DIR}/src/language/nmodl.yaml -) - -set(AST_GENERATED_SOURCES - ${PROJECT_BINARY_DIR}/src/ast/after_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/all.hpp - ${PROJECT_BINARY_DIR}/src/ast/argument.hpp - ${PROJECT_BINARY_DIR}/src/ast/assigned_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/assigned_definition.hpp - ${PROJECT_BINARY_DIR}/src/ast/ast.cpp - ${PROJECT_BINARY_DIR}/src/ast/ast.hpp - ${PROJECT_BINARY_DIR}/src/ast/ast_decl.hpp - ${PROJECT_BINARY_DIR}/src/ast/ba_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/ba_block_type.hpp - ${PROJECT_BINARY_DIR}/src/ast/bbcore_pointer.hpp - ${PROJECT_BINARY_DIR}/src/ast/bbcore_pointer_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/before_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/binary_expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/binary_operator.hpp - ${PROJECT_BINARY_DIR}/src/ast/block.hpp - ${PROJECT_BINARY_DIR}/src/ast/block_comment.hpp - ${PROJECT_BINARY_DIR}/src/ast/boolean.hpp - ${PROJECT_BINARY_DIR}/src/ast/breakpoint_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/compartment.hpp - ${PROJECT_BINARY_DIR}/src/ast/conductance_hint.hpp - ${PROJECT_BINARY_DIR}/src/ast/conserve.hpp - ${PROJECT_BINARY_DIR}/src/ast/constant_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/constant_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/constant_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/constructor_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/cvode_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/define.hpp - ${PROJECT_BINARY_DIR}/src/ast/derivative_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/derivimplicit_callback.hpp - ${PROJECT_BINARY_DIR}/src/ast/destructor_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/diff_eq_expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/discrete_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/double.hpp - ${PROJECT_BINARY_DIR}/src/ast/double_unit.hpp - ${PROJECT_BINARY_DIR}/src/ast/eigen_linear_solver_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/eigen_newton_solver_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/electrode_cur_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/electrode_current.hpp - ${PROJECT_BINARY_DIR}/src/ast/else_if_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/else_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/expression_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/extern_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/external.hpp - ${PROJECT_BINARY_DIR}/src/ast/factor_def.hpp - ${PROJECT_BINARY_DIR}/src/ast/float.hpp - ${PROJECT_BINARY_DIR}/src/ast/for_netcon.hpp - ${PROJECT_BINARY_DIR}/src/ast/from_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/function_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/function_call.hpp - ${PROJECT_BINARY_DIR}/src/ast/function_table_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/global.hpp - ${PROJECT_BINARY_DIR}/src/ast/global_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/identifier.hpp - ${PROJECT_BINARY_DIR}/src/ast/if_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/include.hpp - ${PROJECT_BINARY_DIR}/src/ast/independent_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/indexed_name.hpp - ${PROJECT_BINARY_DIR}/src/ast/initial_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/integer.hpp - ${PROJECT_BINARY_DIR}/src/ast/kinetic_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/lag_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/limits.hpp - ${PROJECT_BINARY_DIR}/src/ast/lin_equation.hpp - ${PROJECT_BINARY_DIR}/src/ast/line_comment.hpp - ${PROJECT_BINARY_DIR}/src/ast/linear_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/local_list_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/local_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/lon_diffuse.hpp - ${PROJECT_BINARY_DIR}/src/ast/longitudinal_diffusion_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/model.hpp - ${PROJECT_BINARY_DIR}/src/ast/mutex_lock.hpp - ${PROJECT_BINARY_DIR}/src/ast/mutex_unlock.hpp - ${PROJECT_BINARY_DIR}/src/ast/name.hpp - ${PROJECT_BINARY_DIR}/src/ast/net_receive_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/neuron_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/node.hpp - ${PROJECT_BINARY_DIR}/src/ast/non_lin_equation.hpp - ${PROJECT_BINARY_DIR}/src/ast/non_linear_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/nonspecific.hpp - ${PROJECT_BINARY_DIR}/src/ast/nonspecific_cur_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/nrn_state_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/number.hpp - ${PROJECT_BINARY_DIR}/src/ast/number_range.hpp - ${PROJECT_BINARY_DIR}/src/ast/ontology_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/param_assign.hpp - ${PROJECT_BINARY_DIR}/src/ast/param_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/paren_expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/pointer.hpp - ${PROJECT_BINARY_DIR}/src/ast/pointer_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/prime_name.hpp - ${PROJECT_BINARY_DIR}/src/ast/procedure_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/program.hpp - ${PROJECT_BINARY_DIR}/src/ast/protect_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/random_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/random_var_list.hpp - ${PROJECT_BINARY_DIR}/src/ast/range.hpp - ${PROJECT_BINARY_DIR}/src/ast/range_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/react_var_name.hpp - ${PROJECT_BINARY_DIR}/src/ast/reaction_operator.hpp - ${PROJECT_BINARY_DIR}/src/ast/reaction_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/read_ion_var.hpp - ${PROJECT_BINARY_DIR}/src/ast/solution_expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/solve_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/state_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/statement_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/string.hpp - ${PROJECT_BINARY_DIR}/src/ast/suffix.hpp - ${PROJECT_BINARY_DIR}/src/ast/table_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/thread_safe.hpp - ${PROJECT_BINARY_DIR}/src/ast/unary_expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/unary_operator.hpp - ${PROJECT_BINARY_DIR}/src/ast/unit.hpp - ${PROJECT_BINARY_DIR}/src/ast/unit_block.hpp - ${PROJECT_BINARY_DIR}/src/ast/unit_def.hpp - ${PROJECT_BINARY_DIR}/src/ast/unit_state.hpp - ${PROJECT_BINARY_DIR}/src/ast/update_dt.hpp - ${PROJECT_BINARY_DIR}/src/ast/useion.hpp - ${PROJECT_BINARY_DIR}/src/ast/valence.hpp - ${PROJECT_BINARY_DIR}/src/ast/var_name.hpp - ${PROJECT_BINARY_DIR}/src/ast/verbatim.hpp - ${PROJECT_BINARY_DIR}/src/ast/watch.hpp - ${PROJECT_BINARY_DIR}/src/ast/watch_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/while_statement.hpp - ${PROJECT_BINARY_DIR}/src/ast/wrapped_expression.hpp - ${PROJECT_BINARY_DIR}/src/ast/write_ion_var.hpp -) - -if(NMODL_ENABLE_PYTHON_BINDINGS) -set(PYBIND_GENERATED_SOURCES - ${PROJECT_BINARY_DIR}/src/pybind/pyast.cpp - ${PROJECT_BINARY_DIR}/src/pybind/pyast.hpp - ${PROJECT_BINARY_DIR}/src/pybind/pynode_0.cpp - ${PROJECT_BINARY_DIR}/src/pybind/pynode_1.cpp - ${PROJECT_BINARY_DIR}/src/pybind/pysymtab.cpp - ${PROJECT_BINARY_DIR}/src/pybind/pyvisitor.cpp - ${PROJECT_BINARY_DIR}/src/pybind/pyvisitor.hpp -) -endif() - -set(VISITORS_GENERATED_SOURCES - ${PROJECT_BINARY_DIR}/src/visitors/ast_visitor.cpp - ${PROJECT_BINARY_DIR}/src/visitors/ast_visitor.hpp - ${PROJECT_BINARY_DIR}/src/visitors/checkparent_visitor.cpp - ${PROJECT_BINARY_DIR}/src/visitors/checkparent_visitor.hpp - ${PROJECT_BINARY_DIR}/src/visitors/json_visitor.cpp - ${PROJECT_BINARY_DIR}/src/visitors/json_visitor.hpp - ${PROJECT_BINARY_DIR}/src/visitors/lookup_visitor.cpp - ${PROJECT_BINARY_DIR}/src/visitors/lookup_visitor.hpp - ${PROJECT_BINARY_DIR}/src/visitors/nmodl_visitor.cpp - ${PROJECT_BINARY_DIR}/src/visitors/nmodl_visitor.hpp - ${PROJECT_BINARY_DIR}/src/visitors/symtab_visitor.cpp - ${PROJECT_BINARY_DIR}/src/visitors/symtab_visitor.hpp - ${PROJECT_BINARY_DIR}/src/visitors/visitor.hpp -) - -set(NMODL_GENERATED_SOURCES - ${AST_GENERATED_SOURCES} - ${PYBIND_GENERATED_SOURCES} - ${VISITORS_GENERATED_SOURCES} -) -# cmake-format: on diff --git a/src/language/code_generator.py b/src/language/code_generator.py index 23bf8ed1dc..73ff2caba3 100644 --- a/src/language/code_generator.py +++ b/src/language/code_generator.py @@ -34,6 +34,7 @@ class CodeGenerator( "base_dir", "clang_format", "disable_pybind", + "generate_cmake", "jinja_env", "jinja_templates_dir", "modification_date", @@ -51,6 +52,7 @@ class CodeGenerator( base_dir: output root directory where Jinja templates are rendered clang_format: clang-format command line if C++ files have to be formatted, `None` otherwise disable_pybind: disable python bindings related code generation + generate_cmake: generate the CMake include and none of the rest py_files: list of Path objects to the Python files used by this program yaml_files: list of Path object to YAML files describing the NMODL language modification_date: most recent modification date of the Python and YAML files in this directory @@ -60,7 +62,13 @@ class CodeGenerator( temp_dir: path to the directory where to create temporary files """ - def __new__(cls, base_dir, clang_format=None, disable_pybind=False): + def __new__( + cls, + base_dir, + clang_format=None, + disable_pybind=False, + generate_cmake=False, + ): this_dir = Path(__file__).parent.resolve() jinja_templates_dir = this_dir / "templates" py_files = [Path(p).relative_to(this_dir) for p in this_dir.glob("*.py")] @@ -70,6 +78,7 @@ def __new__(cls, base_dir, clang_format=None, disable_pybind=False): base_dir=base_dir, clang_format=clang_format, disable_pybind=disable_pybind, + generate_cmake=generate_cmake, this_dir=this_dir, jinja_templates_dir=jinja_templates_dir, jinja_env=jinja2.Environment( @@ -123,7 +132,7 @@ def _cmake_deps_task(self, tasks): An instance of JinjaTask """ input = self.jinja_templates_dir / "code_generator.cmake" - output = self.this_dir / input.name + output = self.base_dir / input.name inputs = set() outputs = dict() for task in tasks: @@ -176,6 +185,9 @@ def workload(self): tasks = [] for path in self.jinja_templates_dir.iterdir(): + if not path.is_dir(): + continue + sub_dir = PurePath(path).name # skip pybind directory as it's needed for python bindings only @@ -197,7 +209,6 @@ def workload(self): extradeps=extradeps[filepath], ) tasks.append(task) - yield task elif filepath == pynode_cpp_tpl: chunk_length = math.ceil(len(self.nodes) / num_pybind_files) for chunk_k in range(num_pybind_files): @@ -220,7 +231,6 @@ def workload(self): extradeps=extradeps[filepath], ) tasks.append(task) - yield task else: task = JinjaTask( app=self, @@ -234,8 +244,11 @@ def workload(self): extradeps=extradeps[filepath], ) tasks.append(task) - yield task - yield self._cmake_deps_task(tasks) + + if self.generate_cmake: + return [self._cmake_deps_task(tasks)] + else: + return tasks class JinjaTask( @@ -371,6 +384,11 @@ def parse_args(args=None): action="store_true", help="Do not generate code related to python bindigs", ) + parser.add_argument( + "--generate-cmake", + action="store_true", + help="Generate the CMake includes instead of the rest.", + ) args = parser.parse_args(args=args) @@ -411,6 +429,7 @@ def main(args=None): clang_format=args.clang_format, base_dir=args.base_dir, disable_pybind=args.disable_pybind, + generate_cmake=args.generate_cmake, ) num_tasks = 0 tasks_performed = [] diff --git a/src/language/code_generator_opts.in b/src/language/code_generator_opts.in new file mode 100644 index 0000000000..b0da71b0e2 --- /dev/null +++ b/src/language/code_generator_opts.in @@ -0,0 +1 @@ +${CODE_GENERATOR_OPTS} diff --git a/src/language/templates/code_generator.cmake b/src/language/templates/code_generator.cmake index 45d150bc19..8b9462cff4 100644 --- a/src/language/templates/code_generator.cmake +++ b/src/language/templates/code_generator.cmake @@ -1,5 +1,5 @@ # -# THIS FILE IS GENERATED AND SHALL NOT BE EDITED. +# THIS FILE IS GENERATED. # # cmake-format: off @@ -34,4 +34,5 @@ set(NMODL_GENERATED_SOURCES ${{ '{' }}{{ dir | upper }}_GENERATED_SOURCES} {% endfor %} ) + # cmake-format: on diff --git a/src/language/templates/visitors/visitor.hpp b/src/language/templates/visitors/visitor.hpp index 7efa4e1572..c7d15b007c 100644 --- a/src/language/templates/visitors/visitor.hpp +++ b/src/language/templates/visitors/visitor.hpp @@ -41,8 +41,8 @@ class Visitor { virtual ~Visitor() = default; {% for node in nodes %} - /// visit node of type ast::{{ node.class_name }} - virtual void visit_{{ node.class_name|snake_case }}(ast::{{ node.class_name }}& node) = 0; + /// visit node of type ast::{{ node.class_name }} + virtual void visit_{{ node.class_name|snake_case }}(ast::{{ node.class_name }}& node) = 0; {% endfor %} }; @@ -60,8 +60,8 @@ class ConstVisitor { virtual ~ConstVisitor() = default; {% for node in nodes %} - /// visit node of type ast::{{ node.class_name }} - virtual void visit_{{ node.class_name|snake_case }}(const ast::{{ node.class_name }}& node) = 0; + /// visit node of type ast::{{ node.class_name }} + virtual void visit_{{ node.class_name|snake_case }}(const ast::{{ node.class_name }}& node) = 0; {% endfor %} };