From d866b7670d620157b0c1a4316faefa469ae2025e Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Fri, 23 Jun 2023 13:53:14 -0700 Subject: [PATCH] Get the ASAN toolchain working again (#7604) * Get the ASAN toolchain working again Various fixes to enable ASAN to finally work (linux x64 only). Note that this found several ASAN failures in the Anderson2021 autoscheduler tests, which are *not* fixed yet; I'll fix thus in a subsequent PR. * Remove stuff that I didn't mean to check in * Configure cuda-specific tests properly too * trigger buildbots * Update CodeGen_LLVM.cpp * Update CodeGen_LLVM.cpp * Fix sloppiness? * Update CMakeLists.txt * trigger buildbots * Use Halide_PYTHON_LAUNCHER to implement ASAN toolchain fixes (#7657) * Use new Halide_PYTHON_LAUNCHER to set env vars * Update CMake docs for Halide_SANITIZER_ENV_VARS --------- Co-authored-by: Alex Reinking --------- Co-authored-by: Alex Reinking Co-authored-by: Alex Reinking --- README_cmake.md | 45 +++++++++++++++---- cmake/HalideGeneratorHelpers.cmake | 17 +++++-- cmake/toolchain.linux-x64-asan.cmake | 16 +++++++ python_bindings/CMakeLists.txt | 26 +---------- python_bindings/src/halide/CMakeLists.txt | 7 +++ .../anderson2021/CMakeLists.txt | 45 +++++++------------ test/autoschedulers/li2018/CMakeLists.txt | 6 ++- 7 files changed, 96 insertions(+), 66 deletions(-) diff --git a/README_cmake.md b/README_cmake.md index 51686ef8bc30..06f8c5dadfde 100644 --- a/README_cmake.md +++ b/README_cmake.md @@ -11,11 +11,24 @@ The following sections cover each in detail. ## Table of Contents +- [Halide and CMake](#halide-and-cmake) + - [Table of Contents](#table-of-contents) - [Getting started](#getting-started) - [Installing CMake](#installing-cmake) + - [Cross-platform](#cross-platform) + - [Windows](#windows) + - [macOS](#macos) + - [Ubuntu Linux](#ubuntu-linux) - [Installing dependencies](#installing-dependencies) + - [Windows](#windows-1) + - [macOS](#macos-1) + - [Ubuntu](#ubuntu) - [Building Halide with CMake](#building-halide-with-cmake) - [Basic build](#basic-build) + - [Windows](#windows-2) + - [macOS and Linux](#macos-and-linux) + - [CMake Presets](#cmake-presets) + - [Installing](#installing) - [Build options](#build-options) - [Find module options](#find-module-options) - [Using Halide from your CMake build](#using-halide-from-your-cmake-build) @@ -33,6 +46,12 @@ The following sections cover each in detail. - [`add_halide_generator`](#add_halide_generator) - [`add_halide_python_extension_library`](#add_halide_python_extension_library) - [`add_halide_runtime`](#add_halide_runtime) + - [Cross compiling](#cross-compiling) + - [Use `add_halide_generator`](#use-add_halide_generator) + - [Use a super-build](#use-a-super-build) + - [Use `ExternalProject` directly](#use-externalproject-directly) + - [Use an emulator or run on device](#use-an-emulator-or-run-on-device) + - [Bypass CMake](#bypass-cmake) - [Contributing CMake code to Halide](#contributing-cmake-code-to-halide) - [General guidelines and best practices](#general-guidelines-and-best-practices) - [Prohibited commands list](#prohibited-commands-list) @@ -750,8 +769,8 @@ Variables that control package loading: | Variable | Description | |----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `Halide_SHARED_LIBS` | override `BUILD_SHARED_LIBS` when loading the Halide package via `find_package`. Has no effect when using Halide via `add_subdirectory` as a Git or `FetchContent` submodule. | -| `Halide_RUNTIME_NO_THREADS` | skip linking of Threads libraray to runtime. Should be set if your toolchain does not support it (e.g. baremetal). | -| `Halide_RUNTIME_NO_DL_LIBS` | skip linking of DL libraray to runtime. Should be set if your toolchain does not support it (e.g. baremetal). | +| `Halide_RUNTIME_NO_THREADS` | skip linking of Threads library to runtime. Should be set if your toolchain does not support it (e.g. baremetal). | +| `Halide_RUNTIME_NO_DL_LIBS` | skip linking of DL library to runtime. Should be set if your toolchain does not support it (e.g. baremetal). | Variables set by the package: @@ -767,6 +786,14 @@ Variables set by the package: | `Halide_ENABLE_EXCEPTIONS` | Whether Halide was compiled with exception support | | `Halide_ENABLE_RTTI` | Whether Halide was compiled with RTTI | +Variables that control package behavior: + +| Variable | Description | +|----------------------------|-------------| +| `Halide_PYTHON_LAUNCHER` | Semicolon separated list containing a command to launch the Python interpreter. Can be used to set environment variables for Python generators. | +| `Halide_NO_DEFAULT_FLAGS` | Off by default. When enabled, suppresses recommended compiler flags that would be added by `add_halide_generator` | + + ### Imported targets Halide defines the following targets that are available to users: @@ -866,10 +893,11 @@ author warning will be issued. To use an autoscheduler, set the `AUTOSCHEDULER` argument to a target named like `Namespace::Scheduler`, for example `Halide::Adams19`. This will set -the `autoscheduler` GeneratorParam on the generator command line to `Scheduler` and add the target to -the list of plugins. Additional plugins can be loaded by setting the `PLUGINS` -argument. If the argument to `AUTOSCHEDULER` does not contain `::` or it does -not name a target, it will be passed to the `-s` flag verbatim. +the `autoscheduler` GeneratorParam on the generator command line to `Scheduler` +and add the target to the list of plugins. Additional plugins can be loaded by +setting the `PLUGINS` argument. If the argument to `AUTOSCHEDULER` does not +contain `::` or it does not name a target, it will be passed to the `-s` flag +verbatim. If `GRADIENT_DESCENT` is set, then the module will be built suitably for gradient descent calculation in TensorFlow or PyTorch. See @@ -954,8 +982,9 @@ and [apps/hannk](https://github.com/halide/Halide/tree/main/apps/hannk) for a co If `PYSTUB` is specified, then a Python Extension will be built that wraps the Generator with CPython glue to allow use of the Generator Python 3.x. The result will be a a shared library of the form -`_pystub..so`, where describes the specific Python version and platform (e.g., `cpython-310-darwin` for Python 3.10 on macOS.) See -`README_python.md` for examples of use. +`_pystub..so`, where describes the specific Python +version and platform (e.g., `cpython-310-darwin` for Python 3.10 on macOS.). +See `README_python.md` for examples of use. #### `add_halide_python_extension_library` diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 817423973e9b..f62da88b1f7b 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -244,11 +244,23 @@ function(add_halide_library TARGET) if (NOT TARGET Halide::Python) message(FATAL_ERROR "This version of Halide was built without support for Python bindings; rebuild using WITH_PYTHON_BINDINGS=ON to use this rule with Python Generators.") endif () + if (NOT TARGET Python3::Interpreter) message(FATAL_ERROR "You must call find_package(Python3) in your CMake code in order to use this rule with Python Generators.") endif () - set(PYTHONPATH "$/..") - set(GENERATOR_CMD ${CMAKE_COMMAND} -E env PYTHONPATH=${PYTHONPATH} ${Python3_EXECUTABLE} $) + + if (CMAKE_VERSION VERSION_LESS 3.24) + set(arg_sep "") + else () + set(arg_sep "--") + endif () + + set( + GENERATOR_CMD + ${CMAKE_COMMAND} -E env "PYTHONPATH=$/.." ${arg_sep} + ${Halide_PYTHON_LAUNCHER} + "$" $ + ) set(GENERATOR_CMD_DEPS ${ARG_FROM} Halide::Python ${py_src}) else() set(GENERATOR_CMD "${ARG_FROM}") @@ -785,4 +797,3 @@ function(_Halide_gengen_ensure) _Halide_place_dll(_Halide_gengen) endif () endfunction() - diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index b19e37f01162..14f101042a23 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -33,3 +33,19 @@ set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/env) # Can't mix -fsanitize=address with -fsanitize=fuzzer set(WITH_TEST_FUZZ OFF) + +if (NOT DEFINED Halide_SHARED_ASAN_RUNTIME_LIBRARY) + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} "-print-file-name=libclang_rt.asan.so" + OUTPUT_VARIABLE Halide_SHARED_ASAN_RUNTIME_LIBRARY + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif () + +set(Halide_SHARED_ASAN_RUNTIME_LIBRARY "${Halide_SHARED_ASAN_RUNTIME_LIBRARY}" + CACHE FILEPATH "Library to preload when running Python tests.") + +set( + Halide_PYTHON_LAUNCHER + ${CMAKE_COMMAND} -E env ASAN_OPTIONS=detect_leaks=0 LD_PRELOAD=${Halide_SHARED_ASAN_RUNTIME_LIBRARY} +) diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index 5bbbbdbde2ba..590ecc432e10 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -62,22 +62,6 @@ endif () # A helper for creating tests with correct PYTHONPATH and sanitizer preloading ## -if (Halide_ASAN_ENABLED) - if (NOT DEFINED Halide_Python_ASAN_LIBRARY) - # TODO: this assumes clang-on-Linux, we could be smarter here and check - # CMAKE_CXX_COMPILER_ID to behave differently on GNU, AppleClang, or - # MSVC. - execute_process( - COMMAND ${CMAKE_CXX_COMPILER} "-print-file-name=libclang_rt.asan.so" - OUTPUT_VARIABLE Halide_Python_ASAN_LIBRARY - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - endif () - - set(Halide_Python_ASAN_LIBRARY "${Halide_Python_ASAN_LIBRARY}" - CACHE FILEPATH "Library to preload when running Python tests.") -endif () - function(add_python_test) cmake_parse_arguments(ARG "" "FILE;LABEL" "PYTHONPATH;ENVIRONMENT;TEST_ARGS" ${ARGN}) @@ -85,20 +69,13 @@ function(add_python_test) list(TRANSFORM ARG_PYTHONPATH PREPEND "PYTHONPATH=path_list_prepend:") list(PREPEND ARG_ENVIRONMENT "HL_TARGET=${Halide_TARGET}") - if (Halide_Python_ASAN_LIBRARY) - if (APPLE) - list(PREPEND ARG_ENVIRONMENT "DYLD_INSERT_LIBRARIES=${Halide_Python_ASAN_LIBRARY}") - else () - list(PREPEND ARG_ENVIRONMENT "LD_PRELOAD=${Halide_Python_ASAN_LIBRARY}") - endif () - endif () cmake_path(GET ARG_FILE STEM test_name) set(test_name "${ARG_LABEL}_${test_name}") add_test( NAME "${test_name}" - COMMAND Python3::Interpreter "$" ${ARG_TEST_ARGS} + COMMAND ${Halide_PYTHON_LAUNCHER} "$" "$" ${ARG_TEST_ARGS} ) set_tests_properties( "${test_name}" @@ -128,4 +105,3 @@ endif () if (WITH_TUTORIALS) add_subdirectory(tutorial) endif () - diff --git a/python_bindings/src/halide/CMakeLists.txt b/python_bindings/src/halide/CMakeLists.txt index 5b85d545965e..c0f48f569eb1 100644 --- a/python_bindings/src/halide/CMakeLists.txt +++ b/python_bindings/src/halide/CMakeLists.txt @@ -51,6 +51,13 @@ set_target_properties( LIBRARY_OUTPUT_DIRECTORY "$/halide" EXPORT_NAME Python ) +if (Halide_ASAN_ENABLED) + set_target_properties( + Halide_Python + PROPERTIES + CMAKE_SHARED_LINKER_FLAGS -shared-libasan + ) +endif () target_link_libraries(Halide_Python PRIVATE Halide::Halide) # TODO: There's precious little information about why Python only sometimes prevents DLLs from loading from the PATH diff --git a/src/autoschedulers/anderson2021/CMakeLists.txt b/src/autoschedulers/anderson2021/CMakeLists.txt index 60a4db197fd9..39bc91ae5929 100644 --- a/src/autoschedulers/anderson2021/CMakeLists.txt +++ b/src/autoschedulers/anderson2021/CMakeLists.txt @@ -77,67 +77,56 @@ endif () if (WITH_TESTS) ## + function(_add_test TARGET) + add_test(NAME ${TARGET} COMMAND ${TARGET}) + set_tests_properties(${TARGET} + PROPERTIES + # This is a workaround for issues with the nvidia driver under ASAN + # https://forums.developer.nvidia.com/t/cuda-runtime-library-and-addresssanitizer-incompatibilty/63145 + ENVIRONMENT ASAN_OPTIONS=protect_shadow_gap=0 + LABELS Anderson2021) + endfunction() + add_executable(anderson2021_test_function_dag test_function_dag.cpp FunctionDAG.cpp) target_include_directories(anderson2021_test_function_dag PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_function_dag PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_function_dag COMMAND anderson2021_test_function_dag) - set_tests_properties(anderson2021_test_function_dag - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_function_dag) add_executable(anderson2021_test_bounds test/bounds.cpp FunctionDAG.cpp LoopNest.cpp GPULoopInfo.cpp Tiling.cpp) target_include_directories(anderson2021_test_bounds PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_bounds PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_bounds COMMAND anderson2021_test_bounds) - set_tests_properties(anderson2021_test_bounds - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_bounds) add_executable(anderson2021_test_parser test/parser.cpp) target_include_directories(anderson2021_test_parser PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_parser PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_parser COMMAND anderson2021_test_parser) - set_tests_properties(anderson2021_test_parser - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_parser) add_executable(anderson2021_test_state test/state.cpp FunctionDAG.cpp LoopNest.cpp GPULoopInfo.cpp State.cpp Tiling.cpp) target_include_directories(anderson2021_test_state PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_state PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_state COMMAND anderson2021_test_state) - set_tests_properties(anderson2021_test_state - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_state) add_executable(anderson2021_test_storage_strides test/storage_strides.cpp FunctionDAG.cpp LoopNest.cpp GPULoopInfo.cpp State.cpp Tiling.cpp) target_include_directories(anderson2021_test_storage_strides PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_storage_strides PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_storage_strides COMMAND anderson2021_test_storage_strides) - set_tests_properties(anderson2021_test_storage_strides - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_storage_strides) add_executable(anderson2021_test_thread_info test/thread_info.cpp LoopNest.cpp FunctionDAG.cpp GPULoopInfo.cpp Tiling.cpp) target_include_directories(anderson2021_test_thread_info PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_thread_info PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_thread_info COMMAND anderson2021_test_thread_info) - set_tests_properties(anderson2021_test_thread_info - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_thread_info) add_executable(anderson2021_test_tiling test/tiling.cpp Tiling.cpp) target_include_directories(anderson2021_test_tiling PRIVATE "${Halide_SOURCE_DIR}/src/autoschedulers/anderson2021") target_link_libraries(anderson2021_test_tiling PRIVATE ASLog Halide::Halide Halide::Tools Halide::Plugin) - add_test(NAME anderson2021_test_tiling COMMAND anderson2021_test_tiling) - set_tests_properties(anderson2021_test_tiling - PROPERTIES - LABELS Anderson2021) + _add_test(anderson2021_test_tiling) endif() diff --git a/test/autoschedulers/li2018/CMakeLists.txt b/test/autoschedulers/li2018/CMakeLists.txt index 438cbf298c4a..d108a27495a2 100644 --- a/test/autoschedulers/li2018/CMakeLists.txt +++ b/test/autoschedulers/li2018/CMakeLists.txt @@ -33,8 +33,10 @@ if (WITH_PYTHON_BINDINGS) else() find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module) - add_test(NAME li2018_gradient_autoscheduler_test_py - COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/test.py" $) + add_test( + NAME li2018_gradient_autoscheduler_test_py + COMMAND ${Halide_PYTHON_LAUNCHER} "$" "${CMAKE_CURRENT_SOURCE_DIR}/test.py" $ + ) set(PYTHONPATH "$/..") list(TRANSFORM PYTHONPATH PREPEND "PYTHONPATH=path_list_prepend:")