|
| 1 | +#[===================================================================[ |
| 2 | + Protocol Autogen - Code generation for protocol wrapper classes |
| 3 | +#]===================================================================] |
| 4 | + |
| 5 | +# Function to set up code generation for protocol_autogen module |
| 6 | +# This runs at configure time to generate C++ wrapper classes from macro files |
| 7 | +function (setup_protocol_autogen) |
| 8 | + # Directory paths |
| 9 | + set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail") |
| 10 | + set(AUTOGEN_HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen") |
| 11 | + set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts") |
| 12 | + |
| 13 | + # Input macro files |
| 14 | + set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro") |
| 15 | + set(LEDGER_ENTRIES_MACRO "${MACRO_DIR}/ledger_entries.macro") |
| 16 | + set(SFIELDS_MACRO "${MACRO_DIR}/sfields.macro") |
| 17 | + |
| 18 | + # Python scripts |
| 19 | + set(GENERATE_TX_SCRIPT "${SCRIPTS_DIR}/generate_tx_classes.py") |
| 20 | + set(GENERATE_LEDGER_SCRIPT "${SCRIPTS_DIR}/generate_ledger_classes.py") |
| 21 | + set(REQUIREMENTS_FILE "${SCRIPTS_DIR}/requirements.txt") |
| 22 | + |
| 23 | + # Create output directories |
| 24 | + file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/transactions") |
| 25 | + file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/ledger_objects") |
| 26 | + |
| 27 | + # Find Python3 - check if already found by Conan or find it ourselves |
| 28 | + if (NOT Python3_EXECUTABLE) |
| 29 | + find_package(Python3 COMPONENTS Interpreter QUIET) |
| 30 | + endif () |
| 31 | + |
| 32 | + if (NOT Python3_EXECUTABLE) |
| 33 | + # Try finding python3 executable directly |
| 34 | + find_program(Python3_EXECUTABLE NAMES python3 python) |
| 35 | + endif () |
| 36 | + |
| 37 | + if (NOT Python3_EXECUTABLE) |
| 38 | + message(FATAL_ERROR "Python3 not found. Code generation cannot proceed.") |
| 39 | + return() |
| 40 | + endif () |
| 41 | + |
| 42 | + message(STATUS "Using Python3 for code generation: ${Python3_EXECUTABLE}") |
| 43 | + |
| 44 | + # Set up Python virtual environment for code generation |
| 45 | + set(VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv") |
| 46 | + |
| 47 | + # Determine the Python executable path in the venv |
| 48 | + if (WIN32) |
| 49 | + set(VENV_PYTHON "${VENV_DIR}/Scripts/python.exe") |
| 50 | + set(VENV_PIP "${VENV_DIR}/Scripts/pip.exe") |
| 51 | + else () |
| 52 | + set(VENV_PYTHON "${VENV_DIR}/bin/python") |
| 53 | + set(VENV_PIP "${VENV_DIR}/bin/pip") |
| 54 | + endif () |
| 55 | + |
| 56 | + # Check if venv needs to be created or updated |
| 57 | + set(VENV_NEEDS_UPDATE FALSE) |
| 58 | + if (NOT EXISTS "${VENV_PYTHON}") |
| 59 | + set(VENV_NEEDS_UPDATE TRUE) |
| 60 | + message(STATUS "Creating Python virtual environment for code generation...") |
| 61 | + elseif ("${REQUIREMENTS_FILE}" IS_NEWER_THAN "${VENV_DIR}/.requirements_installed") |
| 62 | + set(VENV_NEEDS_UPDATE TRUE) |
| 63 | + message(STATUS "Updating Python virtual environment (requirements changed)...") |
| 64 | + endif () |
| 65 | + |
| 66 | + # Create/update virtual environment if needed |
| 67 | + if (VENV_NEEDS_UPDATE) |
| 68 | + message(STATUS "Setting up Python virtual environment at ${VENV_DIR}") |
| 69 | + execute_process(COMMAND ${Python3_EXECUTABLE} -m venv "${VENV_DIR}" |
| 70 | + RESULT_VARIABLE VENV_RESULT ERROR_VARIABLE VENV_ERROR) |
| 71 | + if (NOT VENV_RESULT EQUAL 0) |
| 72 | + message(FATAL_ERROR "Failed to create virtual environment: ${VENV_ERROR}") |
| 73 | + endif () |
| 74 | + |
| 75 | + message(STATUS "Installing Python dependencies...") |
| 76 | + execute_process(COMMAND ${VENV_PIP} install --upgrade pip RESULT_VARIABLE PIP_UPGRADE_RESULT |
| 77 | + OUTPUT_QUIET ERROR_VARIABLE PIP_UPGRADE_ERROR) |
| 78 | + if (NOT PIP_UPGRADE_RESULT EQUAL 0) |
| 79 | + message(WARNING "Failed to upgrade pip: ${PIP_UPGRADE_ERROR}") |
| 80 | + endif () |
| 81 | + |
| 82 | + execute_process(COMMAND ${VENV_PIP} install -r "${REQUIREMENTS_FILE}" |
| 83 | + RESULT_VARIABLE PIP_INSTALL_RESULT ERROR_VARIABLE PIP_INSTALL_ERROR) |
| 84 | + if (NOT PIP_INSTALL_RESULT EQUAL 0) |
| 85 | + message(FATAL_ERROR "Failed to install Python dependencies: ${PIP_INSTALL_ERROR}") |
| 86 | + endif () |
| 87 | + |
| 88 | + # Mark requirements as installed |
| 89 | + file(TOUCH "${VENV_DIR}/.requirements_installed") |
| 90 | + message(STATUS "Python virtual environment ready") |
| 91 | + endif () |
| 92 | + |
| 93 | + # Generate transaction classes at configure time |
| 94 | + message(STATUS "Generating transaction classes from transactions.macro...") |
| 95 | + execute_process(COMMAND ${VENV_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}" |
| 96 | + --header-dir "${AUTOGEN_HEADER_DIR}/transactions" --sfields-macro |
| 97 | + "${SFIELDS_MACRO}" |
| 98 | + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" |
| 99 | + RESULT_VARIABLE TX_GEN_RESULT |
| 100 | + OUTPUT_VARIABLE TX_GEN_OUTPUT |
| 101 | + ERROR_VARIABLE TX_GEN_ERROR) |
| 102 | + if (NOT TX_GEN_RESULT EQUAL 0) |
| 103 | + message(FATAL_ERROR "Failed to generate transaction classes:\n${TX_GEN_ERROR}") |
| 104 | + else () |
| 105 | + message(STATUS "Transaction classes generated successfully") |
| 106 | + endif () |
| 107 | + |
| 108 | + # Generate ledger entry classes at configure time |
| 109 | + message(STATUS "Generating ledger entry classes from ledger_entries.macro...") |
| 110 | + execute_process(COMMAND ${VENV_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}" |
| 111 | + --header-dir "${AUTOGEN_HEADER_DIR}/ledger_objects" --sfields-macro |
| 112 | + "${SFIELDS_MACRO}" |
| 113 | + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" |
| 114 | + RESULT_VARIABLE LEDGER_GEN_RESULT |
| 115 | + OUTPUT_VARIABLE LEDGER_GEN_OUTPUT |
| 116 | + ERROR_VARIABLE LEDGER_GEN_ERROR) |
| 117 | + if (NOT LEDGER_GEN_RESULT EQUAL 0) |
| 118 | + message(FATAL_ERROR "Failed to generate ledger entry classes:\n${LEDGER_GEN_ERROR}") |
| 119 | + else () |
| 120 | + message(STATUS "Ledger entry classes generated successfully") |
| 121 | + endif () |
| 122 | + |
| 123 | + # Add the generated header directory to the module's include path |
| 124 | + target_include_directories( |
| 125 | + xrpl.libxrpl.protocol_autogen PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> |
| 126 | + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) |
| 127 | + |
| 128 | + # Install generated headers |
| 129 | + install(DIRECTORY "${AUTOGEN_HEADER_DIR}/" |
| 130 | + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/xrpl/protocol_autogen" FILES_MATCHING |
| 131 | + PATTERN "*.h") |
| 132 | +endfunction () |
0 commit comments