diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index eb0e807..0d1c179 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -51,7 +51,7 @@ jobs: -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_UNITY_BUILD=${{ matrix.build_type == 'Debug' || matrix.valgrind }} - -DTAPP_REFERENCE_ENABLE_TBLIS=ON + -DTAPP_REFERENCE_ENABLE_TBLIS=${{ !matrix.valgrind }} steps: - uses: actions/checkout@v4 @@ -81,14 +81,6 @@ jobs: # We'll use this as our working directory for all subsequent commands run: cmake -E make_directory ${{github.workspace}}/build - - name: Set sanitizer flags - if: ${{ matrix.sanitize }} - shell: bash - run: | - if [[ '${{ matrix.sanitize }}' = 'true' ]]; then - echo "CXXFLAGS=${{ matrix.sanitize_flags }}" >> "$GITHUB_ENV" - fi - - name: Install prerequisite MacOS packages if: ${{ startsWith(matrix.os, 'macos') }} run: brew install ninja ccache @@ -112,14 +104,19 @@ jobs: restore-keys: | ${{ matrix.config.name }}-ccache- - name: Configure CMake - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system shell: bash working-directory: ${{github.workspace}}/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE $BUILD_CONFIG + # Pass sanitizer flags via CMAKE_{C,CXX}_FLAGS (not CFLAGS/CXXFLAGS env vars) + # to prevent them from leaking into BLIS's autotools build via the environment + run: | + cmake_args=($BUILD_CONFIG) + if [[ "${{ matrix.sanitize }}" == "true" ]]; then + cmake_args+=( + "-DCMAKE_C_FLAGS=${{ matrix.sanitize_flags }}" + "-DCMAKE_CXX_FLAGS=${{ matrix.sanitize_flags }}" + ) + fi + cmake $GITHUB_WORKSPACE "${cmake_args[@]}" - name: Build @@ -139,16 +136,32 @@ jobs: working-directory: ${{github.workspace}}/build shell: bash run: | - cat > tblis.supp << 'EOF' - # Suppress uninitialized value errors in TBLIS/BLIS packm functions - # These occur in architecture-specific packing code (zen3, haswell, etc.) - # and appear to be false positives in the BLIS library - { - tblis_packm_bsmtc_uninit - Memcheck:Cond - ... - fun:*tblis*packm*bsmtc* - ... - } - EOF - valgrind --error-exitcode=1 --leak-check=full --suppressions=tblis.supp ./tapp-reference-test++ + valgrind --error-exitcode=1 --leak-check=full ./tapp-reference-demo + valgrind --error-exitcode=1 --leak-check=full ./tapp-reference-driver + + - name: Consume from build tree + if: ${{ !matrix.valgrind && !matrix.sanitize }} + shell: bash + run: | + cmake -S $GITHUB_WORKSPACE/test/consume -B ${{github.workspace}}/consume-build \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -Dtapp_DIR=${{github.workspace}}/build + cmake --build ${{github.workspace}}/consume-build + ctest --test-dir ${{github.workspace}}/consume-build --output-on-failure + + - name: Install + if: ${{ !matrix.valgrind && !matrix.sanitize }} + shell: bash + run: cmake --install ${{github.workspace}}/build --prefix ${{github.workspace}}/install + + - name: Consume from install tree + if: ${{ !matrix.valgrind && !matrix.sanitize }} + shell: bash + run: | + cmake -S $GITHUB_WORKSPACE/test/consume -B ${{github.workspace}}/consume-install \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_PREFIX_PATH=${{github.workspace}}/install + cmake --build ${{github.workspace}}/consume-install + ctest --test-dir ${{github.workspace}}/consume-install --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f2db34..866b254 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,21 +3,21 @@ cmake_minimum_required(VERSION 3.15) set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "Enable verbose output") # see https://semver.org/ -set (TAPP_REFERENCE_MAJOR_VERSION 0) -set (TAPP_REFERENCE_MINOR_VERSION 5) -set (TAPP_REFERENCE_PATCH_VERSION 0) -set (TAPP_REFERENCE_PRERELEASE_ID ) -set (TAPP_REFERENCE_BUILD_ID ) - -set(TAPP_REFERENCE_VERSION "${TAPP_REFERENCE_MAJOR_VERSION}.${TAPP_REFERENCE_MINOR_VERSION}.${TAPP_REFERENCE_PATCH_VERSION}") -if (TAPP_REFERENCE_PRERELEASE_ID) - set(TAPP_REFERENCE_EXT_VERSION "${TAPP_REFERENCE_VERSION}-${TAPP_REFERENCE_PRERELEASE_ID}") -else(TAPP_REFERENCE_PRERELEASE_ID) - set(TAPP_REFERENCE_EXT_VERSION "${TAPP_REFERENCE_VERSION}") -endif(TAPP_REFERENCE_PRERELEASE_ID) -if (TAPP_REFERENCE_BUILD_ID) - set(TAPP_REFERENCE_EXT_VERSION "${TAPP_REFERENCE_EXT_VERSION}+${TAPP_REFERENCE_BUILD_ID}") -endif(TAPP_REFERENCE_BUILD_ID) +set (TAPP_MAJOR_VERSION 0) +set (TAPP_MINOR_VERSION 5) +set (TAPP_PATCH_VERSION 0) +set (TAPP_PRERELEASE_ID ) +set (TAPP_BUILD_ID ) + +set(TAPP_VERSION "${TAPP_MAJOR_VERSION}.${TAPP_MINOR_VERSION}.${TAPP_PATCH_VERSION}") +if (TAPP_PRERELEASE_ID) + set(TAPP_EXT_VERSION "${TAPP_VERSION}-${TAPP_PRERELEASE_ID}") +else(TAPP_PRERELEASE_ID) + set(TAPP_EXT_VERSION "${TAPP_VERSION}") +endif(TAPP_PRERELEASE_ID) +if (TAPP_BUILD_ID) + set(TAPP_EXT_VERSION "${TAPP_EXT_VERSION}+${TAPP_BUILD_ID}") +endif(TAPP_BUILD_ID) # Extract the git revision tag information if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) @@ -25,85 +25,22 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse -q HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE TAPP_REFERENCE_REVISION ) + OUTPUT_VARIABLE TAPP_REVISION ) string(REGEX MATCH "[0-9a-f]*" - TAPP_REFERENCE_REVISION "${TAPP_REFERENCE_REVISION}") + TAPP_REVISION "${TAPP_REVISION}") else() - set(TAPP_REFERENCE_REVISION "unknown") + set(TAPP_REVISION "unknown") endif() -project(tapp-reference - VERSION ${TAPP_REFERENCE_VERSION} - DESCRIPTION "Reference Implementation of TAPP (Tensor Algebra Processing Primitives)" +project(tapp + VERSION ${TAPP_VERSION} + DESCRIPTION "TAPP (Tensor Algebra Processing Primitives)" LANGUAGES C HOMEPAGE_URL "https://github.com/TAPPOrg/") -include(GNUInstallDirs) - -set(TAPP_REFERENCE_INSTALL_BINDIR "bin" - CACHE PATH "TAPP REFERENCE binary install directory") -set(TAPP_REFERENCE_INSTALL_INCLUDEDIR "include" - CACHE PATH "TAPP REFERENCE INCLUDE install directory") -set(TAPP_REFERENCE_INSTALL_LIBDIR "lib" - CACHE PATH "TAPP REFERENCE LIB install directory") -set(TAPP_REFERENCE_INSTALL_DATADIR "share/mpqc/${TAPP_REFERENCE_EXT_VERSION}/data" - CACHE PATH "TAPP REFERENCE DATA install directory") -set(TAPP_REFERENCE_INSTALL_DOCDIR "share/tapp/${TAPP_REFERENCE_EXT_VERSION}/doc" - CACHE PATH "TAPP REFERENCE DOC install directory") -set(TAPP_REFERENCE_INSTALL_CMAKEDIR "lib/cmake/mpqc" - CACHE PATH "TAPP REFERENCE CMAKE install directory") - -# this provides tapp-api target -add_subdirectory(api) - -add_library(tapp-reference SHARED) - -target_sources( - tapp-reference - PRIVATE - reference_implementation/include/ref_impl.h - reference_implementation/src/error.c - reference_implementation/src/executor.c - reference_implementation/src/handle.c - reference_implementation/src/tensor.c - reference_implementation/src/product.c - ) - -set_property( - TARGET tapp-reference - PROPERTY - C_STANDARD 99 - C_STANDARD_REQUIRED YES - C_EXTENSIONS NO -) - -target_include_directories( - tapp-reference - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/reference_implementation/include -) -if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(Clang|AppleClang)$") - target_link_options(tapp-reference PRIVATE "-undefined;dynamic_lookup") -endif() - -target_link_libraries(tapp-reference PUBLIC tapp-api) - +# TBLIS requires CXX; enable_language must be called at the top level option(TAPP_REFERENCE_ENABLE_TBLIS "Build and link TBLIS and TBLIS bindings" OFF) -option(TAPP_REFERENCE_BUILD_EXERCISE "Build contraction exercise with TODOs in it." OFF) - -option(TAPP_REFERENCE_ENABLE_F16 "Turn on F16 support" OFF) -option(TAPP_REFERENCE_ENABLE_BF16 "Turn on BF16 support" OFF) - -if(TAPP_REFERENCE_ENABLE_F16) - target_compile_definitions(tapp-reference PRIVATE TAPP_REFERENCE_ENABLE_F16=1) -endif() - -if(TAPP_REFERENCE_ENABLE_BF16) - target_compile_definitions(tapp-reference PRIVATE TAPP_REFERENCE_ENABLE_BF16=1) -endif() - if(TAPP_REFERENCE_ENABLE_TBLIS) - include(CheckLanguage) check_language(CXX) if(CMAKE_CXX_COMPILER) @@ -111,52 +48,28 @@ if(TAPP_REFERENCE_ENABLE_TBLIS) else() message(FATAL_ERROR "Cannot build TBLIS as part of TAPP due to missing CXX language support; ensure that the CXX compiler can be discovered") endif() +endif() - set(TBLIS_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/tblis) - - include(FetchContent) - - FetchContent_Declare( - tblis - GIT_REPOSITORY https://github.com/devinamatthews/tblis.git - GIT_TAG 9b95712 - PREFIX ${CMAKE_CURRENT_BINARY_DIR}/_deps/tblis - UPDATE_DISCONNECTED TRUE - ) - - FetchContent_MakeAvailable(tblis) - - target_compile_definitions(tapp-reference PRIVATE TAPP_REFERENCE_ENABLE_TBLIS=1) - - target_sources( - tapp-reference - PRIVATE - tblis_bindings/tblis_bind.h - tblis_bindings/tblis_bind.cpp - ) - set_property( - TARGET tapp-reference - PROPERTY - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO - ) - target_include_directories( - tapp-reference - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/tblis_bindings - ) +include(GNUInstallDirs) - # ---------------------------------------------------------------------------- - # interface +set(TAPP_INSTALL_BINDIR "bin" + CACHE PATH "TAPP binary install directory") +set(TAPP_INSTALL_INCLUDEDIR "include" + CACHE PATH "TAPP include install directory") +set(TAPP_INSTALL_LIBDIR "lib" + CACHE PATH "TAPP library install directory") +set(TAPP_INSTALL_CMAKEDIR "lib/cmake/tapp" + CACHE PATH "TAPP CMake config install directory") +set(TAPP_INSTALL_DATADIR "share/tapp/${TAPP_EXT_VERSION}/data" + CACHE PATH "TAPP data install directory") +set(TAPP_INSTALL_DOCDIR "share/tapp/${TAPP_EXT_VERSION}/doc" + CACHE PATH "TAPP doc install directory") - target_link_libraries( - tapp-reference - PUBLIC - tblis-static - ) +# this provides tapp-api target +add_subdirectory(api) -endif() +# this provides tapp-reference target +add_subdirectory(reference_implementation) # ---------------------------------------------------------------------------- # testing @@ -182,6 +95,7 @@ if(BUILD_TESTING) tapp-reference-test++ PRIVATE tapp-reference + tblis-static ) set_property( @@ -255,7 +169,7 @@ if(BUILD_TESTING) # ---------------------------------------------------------------------------- # exercise: contraction - if(TAPP_REFERENCE_BUILD_EXERCISE) + if(TAPP_BUILD_EXERCISE) add_executable(tapp-reference-exercise_contraction) target_sources( @@ -353,3 +267,35 @@ if(BUILD_TESTING) ) endif() + +# ============================================================================ +# CMake package config / export +# ============================================================================ +include(CMakePackageConfigHelpers) + +# version file +write_basic_package_version_file(tapp-config-version.cmake + VERSION ${TAPP_VERSION} COMPATIBILITY AnyNewerVersion) + +# export targets for the build tree +export(EXPORT tapp + NAMESPACE tapp:: + FILE "${PROJECT_BINARY_DIR}/tapp-targets.cmake") + +# install target export file +install(EXPORT tapp + FILE "tapp-targets.cmake" + DESTINATION "${TAPP_INSTALL_CMAKEDIR}" + NAMESPACE tapp:: + COMPONENT reference) + +# configure the config file +configure_package_config_file(cmake/tapp-config.cmake.in + "${PROJECT_BINARY_DIR}/tapp-config.cmake" + INSTALL_DESTINATION "${TAPP_INSTALL_CMAKEDIR}") + +install(FILES + "${PROJECT_BINARY_DIR}/tapp-config.cmake" + "${PROJECT_BINARY_DIR}/tapp-config-version.cmake" + DESTINATION "${TAPP_INSTALL_CMAKEDIR}" + COMPONENT reference) diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt index 196d6e8..4531286 100644 --- a/api/CMakeLists.txt +++ b/api/CMakeLists.txt @@ -40,35 +40,16 @@ project(tapp-api include(GNUInstallDirs) -set(TAPP_API_INSTALL_BINDIR "bin" - CACHE PATH "TAPP API binary install directory") -set(TAPP_API_INSTALL_INCLUDEDIR "include" - CACHE PATH "TAPP API INCLUDE install directory") -set(TAPP_API_INSTALL_LIBDIR "lib" - CACHE PATH "TAPP API LIB install directory") -set(TAPP_API_INSTALL_DATADIR "share/mpqc/${TAPP_API_EXT_VERSION}/data" - CACHE PATH "TAPP API DATA install directory") -set(TAPP_API_INSTALL_DOCDIR "share/tapp/${TAPP_API_EXT_VERSION}/doc" - CACHE PATH "TAPP API DOC install directory") -set(TAPP_API_INSTALL_CMAKEDIR "lib/cmake/mpqc" - CACHE PATH "TAPP API CMAKE install directory") +# Install directory variables are set by the parent project (TAPP_INSTALL_*). +# When built standalone, define them here as fallback. +if (NOT DEFINED TAPP_INSTALL_INCLUDEDIR) + set(TAPP_INSTALL_INCLUDEDIR "include" + CACHE PATH "TAPP include install directory") +endif() add_library(tapp-api INTERFACE) - -target_sources( - tapp-api - PUBLIC - include/tapp.h - PRIVATE - include/tapp/tensor.h - include/tapp/product.h - include/tapp/attributes.h - include/tapp/datatype.h - include/tapp/error.h - include/tapp/executor.h - include/tapp/handle.h - include/tapp/status.h - ) +set_property(TARGET tapp-api PROPERTY EXPORT_NAME api) +add_library(tapp::api ALIAS tapp-api) set_property( TARGET tapp-api @@ -80,5 +61,11 @@ set_property( target_include_directories(tapp-api INTERFACE $ - $ + $ ) + +install(TARGETS tapp-api EXPORT tapp + COMPONENT api) +install(DIRECTORY include/ + COMPONENT api + DESTINATION "${TAPP_INSTALL_INCLUDEDIR}") diff --git a/cmake/tapp-config.cmake.in b/cmake/tapp-config.cmake.in new file mode 100644 index 0000000..54c2ebc --- /dev/null +++ b/cmake/tapp-config.cmake.in @@ -0,0 +1,51 @@ +# tapp CMake config +# Provides package "tapp" with components: api, reference +# +# Imported targets: +# tapp::api - TAPP C API headers (INTERFACE library) +# tapp::reference - TAPP reference implementation (shared library) + +@PACKAGE_INIT@ + +set(tapp_VERSION "@TAPP_VERSION@") + +# load targets (both api and reference are in the same export set) +if(NOT TARGET tapp::reference) + include("${CMAKE_CURRENT_LIST_DIR}/tapp-targets.cmake") +endif() + +# component checking +set(_tapp_supported_components api reference) +# if no components requested, default to reference (which pulls in api transitively) +if(NOT tapp_FIND_COMPONENTS) + set(tapp_FIND_COMPONENTS reference) +endif() + +foreach(_comp ${tapp_FIND_COMPONENTS}) + if(_comp STREQUAL "api") + if(TARGET tapp::api) + set(tapp_api_FOUND TRUE) + else() + set(tapp_api_FOUND FALSE) + if(tapp_FIND_REQUIRED_api) + message(FATAL_ERROR "tapp component 'api' not found (target tapp::api missing)") + endif() + endif() + elseif(_comp STREQUAL "reference") + if(TARGET tapp::reference) + set(tapp_reference_FOUND TRUE) + else() + set(tapp_reference_FOUND FALSE) + if(tapp_FIND_REQUIRED_reference) + message(FATAL_ERROR "tapp component 'reference' not found (target tapp::reference missing)") + endif() + endif() + else() + set(tapp_${_comp}_FOUND FALSE) + if(tapp_FIND_REQUIRED_${_comp}) + message(FATAL_ERROR "tapp: unknown component '${_comp}' requested") + endif() + endif() +endforeach() + +check_required_components(tapp) diff --git a/reference_implementation/CMakeLists.txt b/reference_implementation/CMakeLists.txt new file mode 100644 index 0000000..db79266 --- /dev/null +++ b/reference_implementation/CMakeLists.txt @@ -0,0 +1,105 @@ +add_library(tapp-reference SHARED) +set_property(TARGET tapp-reference PROPERTY EXPORT_NAME reference) +add_library(tapp::reference ALIAS tapp-reference) + +target_sources( + tapp-reference + PRIVATE + include/ref_impl.h + src/error.c + src/executor.c + src/handle.c + src/tensor.c + src/product.c + ) + +set_property( + TARGET tapp-reference + PROPERTY + C_STANDARD 99 + C_STANDARD_REQUIRED YES + C_EXTENSIONS NO +) + +target_include_directories( + tapp-reference + PUBLIC + $ + $ +) +if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(Clang|AppleClang)$") + target_link_options(tapp-reference PRIVATE "-undefined;dynamic_lookup") +endif() + +target_link_libraries(tapp-reference PUBLIC tapp-api) + +option(TAPP_BUILD_EXERCISE "Build contraction exercise with TODOs in it." OFF) + +option(TAPP_REFERENCE_ENABLE_F16 "Turn on F16 support" OFF) +option(TAPP_REFERENCE_ENABLE_BF16 "Turn on BF16 support" OFF) + +if(TAPP_REFERENCE_ENABLE_F16) + target_compile_definitions(tapp-reference PRIVATE TAPP_REFERENCE_ENABLE_F16=1) +endif() + +if(TAPP_REFERENCE_ENABLE_BF16) + target_compile_definitions(tapp-reference PRIVATE TAPP_REFERENCE_ENABLE_BF16=1) +endif() + +if(TAPP_REFERENCE_ENABLE_TBLIS) + + set(TBLIS_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/tblis) + + include(FetchContent) + + FetchContent_Declare( + tblis + GIT_REPOSITORY https://github.com/devinamatthews/tblis.git + GIT_TAG 9b95712 + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/_deps/tblis + UPDATE_DISCONNECTED TRUE + EXCLUDE_FROM_ALL + ) + + FetchContent_MakeAvailable(tblis) + + target_compile_definitions(tapp-reference PRIVATE TAPP_REFERENCE_ENABLE_TBLIS=1) + + target_sources( + tapp-reference + PRIVATE + tblis_bindings/tblis_bind.h + tblis_bindings/tblis_bind.cpp + ) + set_property( + TARGET tapp-reference + PROPERTY + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO + ) + target_include_directories( + tapp-reference + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/tblis_bindings + ) + + # ---------------------------------------------------------------------------- + # interface + + target_link_libraries( + tapp-reference + PRIVATE + tblis-static + ) + +endif() + +install(TARGETS tapp-reference EXPORT tapp + COMPONENT reference + LIBRARY DESTINATION "${TAPP_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${TAPP_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${TAPP_INSTALL_BINDIR}") +install(DIRECTORY include/ + COMPONENT reference + DESTINATION "${TAPP_INSTALL_INCLUDEDIR}") diff --git a/tblis_bindings/tblis_bind.cpp b/reference_implementation/tblis_bindings/tblis_bind.cpp similarity index 100% rename from tblis_bindings/tblis_bind.cpp rename to reference_implementation/tblis_bindings/tblis_bind.cpp diff --git a/tblis_bindings/tblis_bind.h b/reference_implementation/tblis_bindings/tblis_bind.h similarity index 100% rename from tblis_bindings/tblis_bind.h rename to reference_implementation/tblis_bindings/tblis_bind.h diff --git a/test/consume/CMakeLists.txt b/test/consume/CMakeLists.txt new file mode 100644 index 0000000..7ec03db --- /dev/null +++ b/test/consume/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.15) +project(tapp-consume-test LANGUAGES C) + +find_package(tapp REQUIRED COMPONENTS reference) + +add_executable(smoke smoke.c) +target_link_libraries(smoke PRIVATE tapp::reference) + +enable_testing() +add_test(NAME smoke COMMAND smoke) diff --git a/test/consume/smoke.c b/test/consume/smoke.c new file mode 100644 index 0000000..683003b --- /dev/null +++ b/test/consume/smoke.c @@ -0,0 +1,19 @@ +#include +#include +#include + +int main(void) { + TAPP_handle h; + TAPP_error err = TAPP_create_handle(&h); + if (!TAPP_check_success(err)) { + fprintf(stderr, "TAPP_create_handle failed: %d\n", (int)err); + return EXIT_FAILURE; + } + err = TAPP_destroy_handle(h); + if (!TAPP_check_success(err)) { + fprintf(stderr, "TAPP_destroy_handle failed: %d\n", (int)err); + return EXIT_FAILURE; + } + printf("tapp-reference smoke test passed\n"); + return EXIT_SUCCESS; +}