| # Copyright 2020 The Dawn & Tint Authors |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright notice, this |
| # list of conditions and the following disclaimer. |
| # |
| # 2. Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation |
| # and/or other materials provided with the distribution. |
| # |
| # 3. Neither the name of the copyright holder nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| # Check for Jinja2 |
| if (NOT DAWN_JINJA2_DIR) |
| message(STATUS "Dawn: Using system jinja2") |
| execute_process( |
| COMMAND ${Python3_EXECUTABLE} -c "import jinja2" |
| RESULT_VARIABLE RET |
| ) |
| if (NOT RET EQUAL 0) |
| message(FATAL_ERROR "Dawn: Missing dependencies for code generation, please ensure you have python-jinja2 installed.") |
| endif() |
| else() |
| message(STATUS "Dawn: using jinja2 at ${DAWN_JINJA2_DIR}") |
| message(STATUS "Dawn: using markupsafe at ${DAWN_MARKUPSAFE_DIR}") |
| endif() |
| |
| # Function to invoke a generator_lib.py generator. |
| # - SCRIPT is the name of the script to call |
| # - ARGS are the extra arguments to pass to the script in addition to the base generator_lib.py arguments |
| # - PRINT_NAME is the name to use when outputting status or errors |
| # - RESULT_VARIABLE will be modified to contain the list of files generated by this generator |
| function(DawnGenerator) |
| set(oneValueArgs SCRIPT RESULT_VARIABLE PRINT_NAME) |
| set(multiValueArgs ARGS) |
| cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) |
| |
| # Build the set of args common to all invocation of that generator. |
| set(BASE_ARGS |
| ${Python3_EXECUTABLE} |
| ${G_SCRIPT} |
| --template-dir |
| "${DAWN_TEMPLATE_DIR}" |
| --root-dir |
| "${Dawn_SOURCE_DIR}" |
| --output-dir |
| "${DAWN_BUILD_GEN_DIR}" |
| ${G_ARGS} |
| ) |
| if (DAWN_JINJA2_DIR) |
| list(APPEND BASE_ARGS --jinja2-path ${DAWN_JINJA2_DIR}) |
| endif() |
| if (DAWN_MARKUPSAFE_DIR) |
| list(APPEND BASE_ARGS --markupsafe-path ${DAWN_MARKUPSAFE_DIR}) |
| endif() |
| |
| # Call the generator to get the list of its dependencies. |
| execute_process( |
| COMMAND ${BASE_ARGS} --print-cmake-dependencies |
| OUTPUT_VARIABLE DEPENDENCIES |
| RESULT_VARIABLE RET |
| ) |
| if (NOT RET EQUAL 0) |
| message(FATAL_ERROR "Dawn: Failed to get the dependencies for ${G_PRINT_NAME}. Base args are '${BASE_ARGS}'.") |
| endif() |
| |
| # Ask CMake to re-run if any of the dependencies changed as it might modify the build graph. |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${DEPENDENCIES}) |
| |
| # Call the generator to get the list of its outputs. |
| execute_process( |
| COMMAND ${BASE_ARGS} --print-cmake-outputs |
| OUTPUT_VARIABLE OUTPUTS |
| RESULT_VARIABLE RET |
| ) |
| if (NOT RET EQUAL 0) |
| message(FATAL_ERROR "Dawn: Failed to get the outputs for ${G_PRINT_NAME}. Base args are '${BASE_ARGS}'.") |
| endif() |
| |
| # Add the custom command that calls the generator. |
| add_custom_command( |
| COMMAND ${BASE_ARGS} |
| DEPENDS ${DEPENDENCIES} |
| OUTPUT ${OUTPUTS} |
| COMMENT "Dawn: Generating files for ${G_PRINT_NAME}." |
| ) |
| |
| # Return the list of outputs. |
| set(${G_RESULT_VARIABLE} ${OUTPUTS} PARENT_SCOPE) |
| |
| # Prior to CMake 3.20 the GENERATED property is local to a directory which means that putting |
| # generated headers in INTERFACE properties causes dependent targets to complain that they |
| # cannot find the file. (because they don't see it as generated and want to check is is |
| # actually on the filesystem). |
| # Work around this by generating the files once if they aren't present at configuration time. |
| set(needToGenerate OFF) |
| foreach(path ${OUTPUTS}) |
| if (NOT EXISTS ${path}) |
| set(needToGenerate ON) |
| endif() |
| endforeach() |
| |
| if (${needToGenerate}) |
| message(STATUS "Dawn: Generating initial versions of files for ${G_PRINT_NAME}.") |
| execute_process(COMMAND ${BASE_ARGS} RESULT_VARIABLE RET) |
| if (NOT RET EQUAL 0) |
| message(FATAL_ERROR "Dawn: Failed to generate the initial version of files for ${G_PRINT_NAME}. Base args are '${BASE_ARGS}'.") |
| endif() |
| endif() |
| endfunction() |
| |
| # Helper function to call dawn_generator.py: |
| # - TARGET is the generator target to build |
| # - PRINT_NAME and RESULT_VARIABLE are like for DawnGenerator |
| function(DawnJSONGenerator) |
| set(oneValueArgs TARGET RESULT_VARIABLE) |
| cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) |
| |
| DawnGenerator( |
| SCRIPT "${Dawn_SOURCE_DIR}/generator/dawn_json_generator.py" |
| ARGS --dawn-json |
| "${Dawn_SOURCE_DIR}/src/dawn/dawn.json" |
| --wire-json |
| "${Dawn_SOURCE_DIR}/src/dawn/dawn_wire.json" |
| --targets |
| ${G_TARGET} |
| RESULT_VARIABLE RET |
| ${G_UNPARSED_ARGUMENTS} |
| ) |
| |
| # Forward the result up one more scope |
| set(${G_RESULT_VARIABLE} ${RET} PARENT_SCOPE) |
| endfunction() |