From d4a875db14cf9fbf78007254f77de45f8b51c878 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 28 Oct 2021 19:33:48 -0700 Subject: [PATCH] Add helper for cross-compiling Halide generators. 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. --- cmake/HalideGeneratorHelpers.cmake | 84 +++++++++++++++++++ test/integration/xc/CMakeLists.txt | 17 ++-- test/integration/xc/{generators => }/add.cpp | 0 test/integration/xc/add/CMakeLists.txt | 13 --- test/integration/xc/generators/CMakeLists.txt | 24 ------ 5 files changed, 95 insertions(+), 43 deletions(-) rename test/integration/xc/{generators => }/add.cpp (100%) delete mode 100644 test/integration/xc/add/CMakeLists.txt delete mode 100644 test/integration/xc/generators/CMakeLists.txt diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 6b0330733232..704867926998 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -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. diff --git a/test/integration/xc/CMakeLists.txt b/test/integration/xc/CMakeLists.txt index 29b4140a3b01..49e63a0b17e9 100644 --- a/test/integration/xc/CMakeLists.txt +++ b/test/integration/xc/CMakeLists.txt @@ -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) diff --git a/test/integration/xc/generators/add.cpp b/test/integration/xc/add.cpp similarity index 100% rename from test/integration/xc/generators/add.cpp rename to test/integration/xc/add.cpp diff --git a/test/integration/xc/add/CMakeLists.txt b/test/integration/xc/add/CMakeLists.txt deleted file mode 100644 index 2ceaa49a4a94..000000000000 --- a/test/integration/xc/add/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Only need the platform-independent / source-only helpers. -find_package(HalideHelpers REQUIRED) - -add_halide_library(add FROM xc::add_gen - TARGETS cmake - REGISTRATION add_reg_cpp) -add_library(xc::add ALIAS add) - -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) diff --git a/test/integration/xc/generators/CMakeLists.txt b/test/integration/xc/generators/CMakeLists.txt deleted file mode 100644 index 4d852987cb6a..000000000000 --- a/test/integration/xc/generators/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(xc-generators) - -## -## Dependencies -## - -find_package(Halide REQUIRED) - -## -## Create generator target -## - -add_executable(add_gen add.cpp) -add_executable(xc::add_gen ALIAS add_gen) -target_link_libraries(add_gen PRIVATE Halide::Generator) - -## -## Export (staging) -## - -export(TARGETS add_gen - NAMESPACE xc:: - FILE "${CMAKE_BINARY_DIR}/share/xc-generators/xc-generators-config.cmake")