Skip to content

Commit

Permalink
Add helper for cross-compiling Halide generators.
Browse files Browse the repository at this point in the history
Created a new function, `add_halide_generator`, that helps users write correct
cross-compiling builds by establishing the following convention for them:

1. Define Halide generators and libraries in the same project
2. Assume two builds: a host build and a cross build.
3. When creating a generator, check to see if we can load a pre-built version of
   the target.
4. If so, just use it, and add aliases to make sure all the names line up.
5. If not, make sure the full Halide package is loaded and create a target for
   the generator.
     a. If `CMAKE_CROSSCOMPILING` is set, then _warn_ the user (the variable is
        unreliable on macOS) that something seems fishy.
     b. Create export rules for the generator. It creates a package
        `PACKAGE_NAME` and appends to its `EXPORT_FILE`.
     c. Create a custom target also named `PACKAGE_NAME` for building the
        generators.
     d. Create an alias `${PACKAGE_NAMESPACE}${TARGET}`.
6. Users are expected to use the alias in conjunction `add_halide_library`.
   Users can test the existence of `TARGET` to determine whether a pre-built one
   was loaded (and set additional properties if not).
7. Setting `${PACKAGE_NAME}_ROOT` is enough to load pre-built generators.

`PACKAGE_NAME` is `${PROJECT_NAME}-generators` by default.
`PACKAGE_NAMESPACE` is `${PROJECT_NAME}::generators::` by default.
`EXPORT_FILE` is `${PROJECT_BINARY_DIR}/cmake/${PACKAGE_NAME}-config.cmake` by
default.

Users are free to avoid the helper if it would not fit their workflow.
  • Loading branch information
alexreinking committed Oct 29, 2021
1 parent 541bc37 commit d4a875d
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 43 deletions.
84 changes: 84 additions & 0 deletions cmake/HalideGeneratorHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,90 @@ define_property(TARGET PROPERTY Halide_GENERATOR_HAS_POST_BUILD
BRIEF_DOCS "On a Halide generator target, true if Halide.dll copy command has already been added."
FULL_DOCS "On a Halide generator target, true if Halide.dll copy command has already been added.")

##
# Function to simplify writing the CMake rules for creating a generator executable
# that follows our recommended cross-compiling workflow.
##

function(add_halide_generator TARGET)
set(options "")
set(oneValueArgs PACKAGE_NAME PACKAGE_NAMESPACE EXPORT_FILE)
set(multiValueArgs SOURCES)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if (NOT ARG_PACKAGE_NAME)
set(ARG_PACKAGE_NAME "${PROJECT_NAME}-generators")
endif ()

if (NOT ARG_PACKAGE_NAMESPACE)
set(ARG_PACKAGE_NAMESPACE "${PROJECT_NAME}::generators::")
endif ()

if (NOT ARG_EXPORT_FILE)
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/cmake")
set(ARG_EXPORT_FILE "${PROJECT_BINARY_DIR}/cmake/${ARG_PACKAGE_NAME}-config.cmake")
endif ()

if (NOT ARG_SOURCES)
set(ARG_SOURCES "${ARG_UNPARSED_ARGUMENTS}")
endif ()

_Halide_try_load_generators()

# Communicate found information to the caller
set(${ARG_PACKAGE_NAME}_FOUND "${${ARG_PACKAGE_NAME}_FOUND}" PARENT_SCOPE)

set(gen "${ARG_PACKAGE_NAMESPACE}${TARGET}")
if (NOT TARGET "${gen}")
if (NOT TARGET "${ARG_PACKAGE_NAME}")
add_custom_target("${ARG_PACKAGE_NAME}")
endif ()

if (NOT Halide_FOUND)
find_package(Halide REQUIRED)
endif ()

add_executable(${TARGET} ${ARG_SOURCES})
add_executable(${gen} ALIAS ${TARGET})
target_link_libraries(${TARGET} PRIVATE Halide::Generator)

add_dependencies("${ARG_PACKAGE_NAME}" ${TARGET})
export(TARGETS ${TARGET}
NAMESPACE ${ARG_PACKAGE_NAMESPACE}
APPEND FILE "${ARG_EXPORT_FILE}")
endif ()
endfunction()

# NOTE: this function must only be called by add_halide_generator
# since it reads from its scope.
function(_Halide_try_load_generators)
# Don't repeatedly run the search for the tools package.
if (NOT DEFINED ${ARG_PACKAGE_NAME}_FOUND)
# Some toolchains, like Emscripten, try to disable finding packages
# outside their sysroots, but we always want to find the native
# generators. Setting CMAKE_FIND_ROOT_PATH_BOTH here overrides
# the toolchain search preference. This is okay since a user can
# always override this call by setting ${ARG_PACKAGE_NAME}_ROOT.
find_package(${ARG_PACKAGE_NAME} QUIET
CMAKE_FIND_ROOT_PATH_BOTH)

# Communicate found information to the caller
set(${ARG_PACKAGE_NAME}_FOUND "${${ARG_PACKAGE_NAME}_FOUND}" PARENT_SCOPE)

if (NOT ${ARG_PACKAGE_NAME}_FOUND AND CMAKE_CROSSCOMPILING)
message(WARNING
"${ARG_PACKAGE_NAME} were not found and it looks like you are cross-compiling. "
"This is likely to fail. Please set -D${ARG_PACKAGE_NAME}_ROOT=... at the CMake "
"command line to the build directory of a host-built ${PROJECT_NAME}.")
endif ()
endif ()
endfunction()

##
# Function to simplify writing the CMake rules for invoking a generator executable
# and getting a usable CMake library out of it.
##

function(add_halide_library TARGET)
##
# Set up argument parsing for extra outputs.
Expand Down
17 changes: 11 additions & 6 deletions test/integration/xc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ project(xc)

enable_testing()

if (CMAKE_CROSSCOMPILING)
find_package(xc-generators REQUIRED)
else ()
add_subdirectory(generators)
endif ()
# Only need the platform-independent / source-only helpers.
find_package(HalideHelpers REQUIRED)

add_subdirectory(add)
add_halide_generator(add_gen add.cpp)
add_halide_library(add FROM xc::generators::add_gen
REGISTRATION add_reg_cpp)

add_executable(run_add ${add_reg_cpp})
target_link_libraries(run_add PRIVATE add Halide::RunGenMain)

add_test(NAME run_add
COMMAND run_add --output_extents=[10,10] --benchmarks=all)
File renamed without changes.
13 changes: 0 additions & 13 deletions test/integration/xc/add/CMakeLists.txt

This file was deleted.

24 changes: 0 additions & 24 deletions test/integration/xc/generators/CMakeLists.txt

This file was deleted.

0 comments on commit d4a875d

Please sign in to comment.