@@ -208,7 +208,7 @@ function(_Halide_library_from_generator TARGET)
208208 set (compiler_log_extension ".halide_compiler_log" )
209209 set (conceptual_stmt_extension ".conceptual.stmt" )
210210 set (conceptual_stmt_html_extension ".conceptual.stmt.html" )
211- # set(cpp_stub_extension ".stub.h") # not implemented
211+ # set(cpp_stub_extension ".stub.h") # handled by add_halide_stub()
212212 set (device_code_extension ".device_code" )
213213 set (featurization_extension ".featurization" )
214214 set (function_info_header_extension ".function_info.h" )
@@ -465,6 +465,83 @@ function(_Halide_set_osx_arch TARGET TRIPLE)
465465 endif ()
466466endfunction ()
467467
468+ ##
469+ # Function to generate a C++ stub header from a Halide generator.
470+ #
471+ # Stubs allow one Generator to compose another at Halide compile time by
472+ # inlining the sub-generator's pipeline definition. The stub header provides
473+ # a type-safe C++ interface (Inputs, Outputs, GeneratorParams structs and a
474+ # static generate() method) for the sub-generator.
475+ #
476+ # The generated <name>.stub.h must be available when compiling the composite
477+ # generator, and the composite generator executable must link the component
478+ # generators' sources so that their HALIDE_REGISTER_GENERATOR factory
479+ # functions are present at link time.
480+ #
481+ # Usage:
482+ # add_halide_stub(<target> FROM <generator_target>
483+ # [GENERATOR <name>]
484+ # [OUTPUT_DIR <dir>])
485+ #
486+ # The GENERATOR name defaults to TARGET and controls both the -g flag and the
487+ # output filename (<GENERATOR>.stub.h).
488+ ##
489+
490+ function (add_halide_stub TARGET )
491+ set (options "" )
492+ set (oneValueArgs FROM GENERATOR OUTPUT_DIR)
493+ set (multiValueArgs "" )
494+ cmake_parse_arguments (ARG "${options} " "${oneValueArgs} " "${multiValueArgs} " ${ARGN} )
495+
496+ if (NOT ARG_FROM)
497+ message (FATAL_ERROR "add_halide_stub requires FROM specifying a generator target" )
498+ endif ()
499+
500+ if (NOT ARG_GENERATOR)
501+ set (ARG_GENERATOR "${TARGET} " )
502+ endif ()
503+
504+ if (NOT ARG_OUTPUT_DIR)
505+ set (ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR} " )
506+ endif ()
507+
508+ cmake_path (SET ARG_OUTPUT_DIR "${ARG_OUTPUT_DIR} " )
509+ cmake_path (ABSOLUTE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR} " NORMALIZE )
510+
511+ _Halide_compute_generator_cmd (
512+ FROM "${ARG_FROM} "
513+ OUT_COMMAND generator_cmd
514+ OUT_DEPENDS generator_cmd_deps
515+ )
516+
517+ # Absolute path to the generated stub header.
518+ cmake_path (SET stub_file NORMALIZE "${ARG_OUTPUT_DIR} /${ARG_GENERATOR} .stub.h" )
519+
520+ # Relative path for add_custom_command OUTPUT (avoids Xcode .rule file collisions).
521+ cmake_path (RELATIVE_PATH stub_file BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR} "
522+ OUTPUT_VARIABLE stub_file_rel )
523+
524+ add_custom_command (
525+ OUTPUT "${stub_file_rel} "
526+ COMMAND ${generator_cmd}
527+ -g "${ARG_GENERATOR} "
528+ -n "${ARG_GENERATOR} "
529+ -o "${ARG_OUTPUT_DIR} "
530+ -e cpp_stub
531+ DEPENDS ${generator_cmd_deps}
532+ VERBATIM
533+ )
534+
535+ add_library ("${TARGET} " INTERFACE )
536+ add_custom_target ("${TARGET} .update" DEPENDS "${stub_file} " )
537+ set_property (TARGET "${TARGET} .update" PROPERTY FOLDER "Halide Internal" )
538+ add_dependencies ("${TARGET} " "${TARGET} .update" )
539+ target_sources ("${TARGET} " INTERFACE
540+ FILE_SET HEADERS
541+ BASE_DIRS "${ARG_OUTPUT_DIR} "
542+ FILES "${stub_file} " )
543+ endfunction ()
544+
468545##
469546# Function to simplify writing the CMake rules for invoking a generator executable
470547# and getting a usable CMake library out of it.
@@ -477,7 +554,7 @@ function(add_halide_library TARGET)
477554
478555 # See Module.cpp for list of extra outputs. The following outputs intentionally do not appear:
479556 # - `c_header` is always generated
480- # - `cpp_stub` is not available
557+ # - `cpp_stub` is handled by add_halide_stub()
481558 # - `object` is selected for CMake-target-compile
482559 # - `static_library` is selected for cross-compile
483560 set (extra_output_names
0 commit comments