diff --git a/docs/source/usage/project_integration.md b/docs/source/usage/project_integration.md index 631a4123ba3e43c339ca46dec751e85926ed6893..491402cab0544f501ee77447e939b89c606c4987 100644 --- a/docs/source/usage/project_integration.md +++ b/docs/source/usage/project_integration.md @@ -122,6 +122,7 @@ pystencilssfg_generate_target_sources( <target> [FILE_EXTENSIONS <header-extension> <impl-extension>] [OUTPUT_MODE <standalone|inline|header-only>] [CONFIG_MODULE <path-to-config-module.py>] + [OUTPUT_DIRECTORY <output-directory>] ) ``` @@ -138,8 +139,11 @@ The function takes the following options: - `CONFIG_MODULE`: Set the configuration module for all scripts registered with this call. If set, this overrides the value of `PystencilsSfg_CONFIG_MODULE` in the current scope (see [](#cmake_set_config_module)) + - `OUTPUT_DIRECTORY`: Custom output directory for generated files. If `OUTPUT_DIRECTORY` is a relative path, + it will be interpreted relative to the current build directory. -Any C++ header files generated by the above call can be included in any files belonging to `target` via: +If `OUTPUT_DIRECTORY` is *not* specified, any C++ header files generated by the above call +can be included in any files belonging to `target` via: ```C++ #include "gen/<file1.hpp>" @@ -147,12 +151,12 @@ Any C++ header files generated by the above call can be included in any files be /* ... */ ``` -### Changing the Output Directory +:::{attention} +If you change the code generator output directory using the `OUTPUT_DIRECTORY` argument, +you are yourself responsible for placing that directory--or any of its parents--on the +include path of your target. +::: -The CMake function listed above will create a subdirectory `_gen/<target>` at the current point in -the build tree (i.e. [`CMAKE_CURRENT_BINARY_DIR`](https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_BINARY_DIR.html)). -This directory is placed on the include path of `<target>`, and the generated files will be written to `_gen/<target>/gen/` -such that they can be included with the `gen` prefix. (cmake_set_config_module)= ### Set a Configuration Module diff --git a/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake b/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake index 7f3b2da624c0e233ce815071b58d64b8024e6af2..17a7846e6a32761ae0490490acc645e65d376959 100644 --- a/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake +++ b/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake @@ -19,17 +19,13 @@ if(NOT DEFINED CACHE{_Pystencils_Include_Dir}) set(_Pystencils_Include_Dir ${_pystencils_includepath_result} CACHE PATH "") endif() -function(_pssfg_add_gen_source target script) +function(_pssfg_add_gen_source target script outputDirectory) set(options) set(oneValueArgs) set(multiValueArgs GENERATOR_ARGS USER_ARGS DEPENDS) cmake_parse_arguments(_pssfg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - set(generatedSourcesIncludeDir ${CMAKE_CURRENT_BINARY_DIR}/_gen/${target}) - set(generatedSourcesDir ${generatedSourcesIncludeDir}/gen) - file(MAKE_DIRECTORY ${generatedSourcesDir}) - get_filename_component(basename ${script} NAME_WLE) cmake_path(ABSOLUTE_PATH script OUTPUT_VARIABLE scriptAbsolute) @@ -43,24 +39,23 @@ function(_pssfg_add_gen_source target script) set(generatedSourcesAbsolute) foreach (filename ${generatedSources}) - list(APPEND generatedSourcesAbsolute "${generatedSourcesDir}/${filename}") + list(APPEND generatedSourcesAbsolute "${outputDirectory}/${filename}") endforeach () - file(MAKE_DIRECTORY "${generatedSourcesDir}") + file(MAKE_DIRECTORY ${outputDirectory}) add_custom_command(OUTPUT ${generatedSourcesAbsolute} DEPENDS ${scriptAbsolute} ${_pssfg_DEPENDS} COMMAND ${PystencilsSfg_PYTHON_INTERPRETER} ${scriptAbsolute} ${_pssfg_GENERATOR_ARGS} ${_pssfg_USER_ARGS} - WORKING_DIRECTORY "${generatedSourcesDir}") + WORKING_DIRECTORY "${outputDirectory}") target_sources(${target} PRIVATE ${generatedSourcesAbsolute}) - target_include_directories(${target} PRIVATE ${generatedSourcesIncludeDir} ${_Pystencils_Include_Dir}) endfunction() function(pystencilssfg_generate_target_sources TARGET) set(options) - set(oneValueArgs OUTPUT_MODE CONFIG_MODULE) + set(oneValueArgs OUTPUT_MODE CONFIG_MODULE OUTPUT_DIRECTORY) set(multiValueArgs SCRIPTS DEPENDS FILE_EXTENSIONS ARGS) cmake_parse_arguments(_pssfg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -93,6 +88,19 @@ function(pystencilssfg_generate_target_sources TARGET) endif() endif() + if(DEFINED _pssfg_OUTPUT_DIRECTORY) + cmake_path(IS_RELATIVE _pssfg_OUTPUT_DIRECTORY _pssfg_output_dir_is_relative) + if(_pssfg_output_dir_is_relative) + set(outputDirectory ${CMAKE_CURRENT_BINARY_DIR}/${_pssfg_OUTPUT_DIRECTORY}) + else() + set(outputDirectory ${_pssfg_OUTPUT_DIRECTORY}) + endif() + else() + set(generatedSourcesIncludeDir ${CMAKE_CURRENT_BINARY_DIR}/_gen/${TARGET}) + set(outputDirectory ${generatedSourcesIncludeDir}/gen) + target_include_directories(${TARGET} PRIVATE ${generatedSourcesIncludeDir}) + endif() + if(DEFINED _pssfg_FILE_EXTENSIONS) string(JOIN "," extensionsString ${_pssfg_FILE_EXTENSIONS}) @@ -106,11 +114,13 @@ function(pystencilssfg_generate_target_sources TARGET) foreach(codegenScript ${_pssfg_SCRIPTS}) _pssfg_add_gen_source( - ${TARGET} ${codegenScript} + ${TARGET} ${codegenScript} ${outputDirectory} GENERATOR_ARGS ${generatorArgs} USER_ARGS ${userArgs} DEPENDS ${_pssfg_DEPENDS} ) endforeach() + + target_include_directories(${TARGET} PRIVATE ${_Pystencils_Include_Dir}) endfunction() diff --git a/tests/integration/cmake_project/CMakeLists.txt b/tests/integration/cmake_project/CMakeLists.txt index e4470c9e0cab8604dcbbdcff9f424d81655583fa..4c15d570dfa287e861ac710b59a66dc6ae28da88 100644 --- a/tests/integration/cmake_project/CMakeLists.txt +++ b/tests/integration/cmake_project/CMakeLists.txt @@ -37,3 +37,10 @@ pystencilssfg_generate_target_sources( ARGS apples bananas unicorns OUTPUT_MODE header-only ) + +pystencilssfg_generate_target_sources( + TestApp + SCRIPTS CustomDirTest.py + OUTPUT_DIRECTORY my-output + OUTPUT_MODE header-only +) diff --git a/tests/integration/cmake_project/CustomDirTest.py b/tests/integration/cmake_project/CustomDirTest.py new file mode 100644 index 0000000000000000000000000000000000000000..d99e6de9d4ab03d3105780d00d038aff6cbd0d7d --- /dev/null +++ b/tests/integration/cmake_project/CustomDirTest.py @@ -0,0 +1,4 @@ +from pystencilssfg import SourceFileGenerator + +with SourceFileGenerator() as sfg: + sfg.code("#define NOTHING") diff --git a/tests/integration/test_cmake.py b/tests/integration/test_cmake.py index 1f0d9b2dc55a6be773a87b5ecd9b937dd2d08251..94853ac1b8143ff7149e5a268e086decfed1af61 100644 --- a/tests/integration/test_cmake.py +++ b/tests/integration/test_cmake.py @@ -45,3 +45,7 @@ def test_cmake_project(tmp_path, config_source): assert 'arg0 = "apples";' in content assert 'arg1 = "bananas";' in content assert 'arg2 = "unicorns";' in content + + custom_dir_output = tmp_path / "my-output" / "CustomDirTest.hpp" + assert custom_dir_output.exists() + assert "#define NOTHING" in custom_dir_output.read_text()