From 0f99544366b10be5edf921a5b349a22ba03738e3 Mon Sep 17 00:00:00 2001 From: Roland Schwan Date: Fri, 1 Nov 2024 11:32:58 +0100 Subject: [PATCH] include blasfeo in python built --- .github/workflows/wheels.yml | 12 ++++----- CMakeLists.txt | 42 +++++++++++++++++++++++++----- ci/build_install_blasfeo.sh | 32 +++++++++++++++++++++++ ci/cibuildwheel_matrix.py | 21 ++++++++------- ci/cibw_before_all_linux.sh | 29 +++++++++++++++++++++ ci/cibw_before_all_macos_arm64.sh | 19 ++++++++++++++ ci/cibw_before_all_macos_x86_64.sh | 21 +++++++++++++++ ci/cibw_before_all_windows.sh | 21 +++++++++++++++ ci/download_blasfeo.sh | 12 +++++++++ interfaces/python/CMakeLists.txt | 40 +++++++++++++++++++++++++++- 10 files changed, 225 insertions(+), 24 deletions(-) create mode 100644 ci/build_install_blasfeo.sh create mode 100644 ci/cibw_before_all_linux.sh create mode 100644 ci/cibw_before_all_macos_arm64.sh create mode 100644 ci/cibw_before_all_macos_x86_64.sh create mode 100644 ci/cibw_before_all_windows.sh create mode 100644 ci/download_blasfeo.sh diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index c668b89..098a52e 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -10,10 +10,6 @@ on: types: - published -env: - CIBW_ARCHS_LINUX: x86_64 i686 aarch64 - CIBW_ARCHS_MACOS: x86_64 arm64 - jobs: setup_build_targets: name: Setup build targets @@ -30,7 +26,7 @@ jobs: uses: actions/setup-python@v3 - name: Install cibuildwheel - run: python -m pip install cibuildwheel==2.16.5 + run: python -m pip install cibuildwheel==2.21.3 - name: Generate strategy matrix id: set-matrix @@ -57,9 +53,11 @@ jobs: platforms: all - name: Build wheels - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.21.3 env: - CIBW_BEFORE_ALL: mkdir -p build_external && cd build_external && bash ../ci/install_eigen.sh + CIBW_BEFORE_ALL_LINUX: bash ci/cibw_before_all_linux.sh + CIBW_BEFORE_ALL_WINDOWS: bash ci/cibw_before_all_windows.sh + CIBW_BEFORE_ALL_MACOS: bash ci/cibw_before_all_macos_${{ runner.os == macos-14 && 'arm64' || 'x86_64' }}.sh CIBW_BUILD: ${{ matrix.target.build }} - uses: actions/upload-artifact@v3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d6e713..3c87864 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,22 +167,52 @@ if (BUILD_WITH_TEMPLATE_INSTANTIATION) target_compile_options(piqp PRIVATE ${compiler_flags}) target_link_options(piqp PRIVATE ${compiler_flags}) + create_piqp_library(piqp_header_only_no_blasfeo_linked INTERFACE) create_piqp_library(piqp_header_only INTERFACE) + target_link_libraries(piqp_header_only INTERFACE piqp_header_only_no_blasfeo_linked) else () message(STATUS "Building without template instantiation") create_piqp_library(piqp INTERFACE) + create_piqp_library(piqp_header_only_no_blasfeo_linked INTERFACE) create_piqp_library(piqp_header_only INTERFACE) + target_link_libraries(piqp_header_only INTERFACE piqp_header_only_no_blasfeo_linked) endif () +function(CREATE_BLASFEO_LIBRARY library_name library_dir) + find_library(library_lib NAMES blasfeo HINTS "${library_dir}/lib") + + add_library(${library_name} UNKNOWN IMPORTED) + set_target_properties(${library_name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${library_dir}/include") + set_property(TARGET ${library_name} APPEND PROPERTY IMPORTED_LOCATION "${library_lib}") + + message(STATUS "Found ${library_name}: ${library_dir}/include ${library_lib}") +endfunction() + if (BUILD_WITH_BLASFEO) # Find Blasfeo find_package(blasfeo REQUIRED) + # Create architecture specific library for blasfeo. + # Used in Python and Matlab interfaces. + if (DEFINED BLASFEO_X64_DIR) + create_blasfeo_library(blasfeo_x64 ${BLASFEO_X64_DIR}) + endif () + if (DEFINED BLASFEO_X64_AVX2_DIR) + create_blasfeo_library(blasfeo_x64_avx2 ${BLASFEO_X64_AVX2_DIR}) + endif () + if (DEFINED BLASFEO_X64_AVX512_DIR) + create_blasfeo_library(blasfeo_x64_avx512 ${BLASFEO_X64_AVX512_DIR}) + endif () + if (DEFINED BLASFEO_ARM64_DIR) + create_blasfeo_library(blasfeo_arm64 ${BLASFEO_ARM64_DIR}) + endif () + target_compile_definitions(piqp PUBLIC PIQP_HAS_BLASFEO) target_link_libraries(piqp PUBLIC blasfeo) target_compile_definitions(piqp_header_only INTERFACE PIQP_HAS_BLASFEO) + target_compile_definitions(piqp_header_only_no_blasfeo_linked INTERFACE PIQP_HAS_BLASFEO) target_link_libraries(piqp_header_only INTERFACE blasfeo) endif () @@ -211,8 +241,8 @@ if (BUILD_WITH_OPENMP) target_compile_definitions(piqp PUBLIC PIQP_HAS_OPENMP) target_link_libraries(piqp PUBLIC OpenMP::OpenMP_CXX) - target_compile_definitions(piqp_header_only INTERFACE PIQP_HAS_OPENMP) - target_link_libraries(piqp_header_only INTERFACE OpenMP::OpenMP_CXX) + target_compile_definitions(piqp_header_only_no_blasfeo_linked INTERFACE PIQP_HAS_OPENMP) + target_link_libraries(piqp_header_only_no_blasfeo_linked INTERFACE OpenMP::OpenMP_CXX) else () message(STATUS "OpenMP NOT found.") endif () @@ -220,16 +250,16 @@ endif () if (BUILD_WITH_STD_OPTIONAL) target_compile_definitions(piqp INTERFACE PIQP_STD_OPTIONAL) - target_compile_definitions(piqp_header_only INTERFACE PIQP_STD_OPTIONAL) + target_compile_definitions(piqp_header_only_no_blasfeo_linked INTERFACE PIQP_STD_OPTIONAL) endif () if (BUILD_WITH_STD_FILESYSTEM) target_compile_definitions(piqp INTERFACE PIQP_STD_FILESYSTEM) - target_compile_definitions(piqp_header_only INTERFACE PIQP_STD_FILESYSTEM) + target_compile_definitions(piqp_header_only_no_blasfeo_linked INTERFACE PIQP_STD_FILESYSTEM) endif () if (DEBUG_PRINTS) target_compile_definitions(piqp INTERFACE PIQP_DEBUG_PRINT) - target_compile_definitions(piqp_header_only INTERFACE PIQP_DEBUG_PRINT) + target_compile_definitions(piqp_header_only_no_blasfeo_linked INTERFACE PIQP_DEBUG_PRINT) endif () add_library(piqp::piqp ALIAS piqp) @@ -280,7 +310,7 @@ if (ENABLE_INSTALL) ) install( - TARGETS piqp piqp_header_only + TARGETS piqp piqp_header_only_no_blasfeo_linked piqp_header_only EXPORT piqpTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/ci/build_install_blasfeo.sh b/ci/build_install_blasfeo.sh new file mode 100644 index 0000000..aa8c9e8 --- /dev/null +++ b/ci/build_install_blasfeo.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# This file is part of PIQP. +# +# Copyright (c) 2024 EPFL +# +# This source code is licensed under the BSD 2-Clause License found in the +# LICENSE file in the root directory of this source tree. + +BLASFEO_TARGET=${1:-GENERIC}; +ARCH_SUFFIX=${2:-}; + +echo "Installing blasfeo..." + +cd blasfeo +mkdir "build_$ARCH_SUFFIX" +cd "build_$ARCH_SUFFIX" +cmake .. -DCMAKE_BUILD_TYPE=Release -DBLASFEO_CROSSCOMPILING=ON -DTARGET="$BLASFEO_TARGET" ${3:+-DCMAKE_INSTALL_PREFIX="$3"} +cmake --build . +case "$(uname -sr)" in + CYGWIN*|MINGW*|MINGW32*|MSYS*) # detect windows + cmake --install . + ;; + *) # other OS + if [ "$EUID" -ne 0 ] # check if already root + then + sudo cmake --install . + else + cmake --install . + fi + ;; +esac diff --git a/ci/cibuildwheel_matrix.py b/ci/cibuildwheel_matrix.py index 6267477..e28323b 100644 --- a/ci/cibuildwheel_matrix.py +++ b/ci/cibuildwheel_matrix.py @@ -2,17 +2,18 @@ import subprocess import json -platforms = ['linux', 'macos', 'windows'] -runners = { - 'linux': 'ubuntu-22.04', - 'macos': 'macos-12', - 'windows': 'windows-2022', -} +platforms = [ + ('linux', 'ubuntu-22.04', 'x86_64,i686,aarch64'), + ('macos', 'macos-12', 'x86_64'), + ('macos', 'macos-14', 'arm64'), + ('windows', 'windows-2022', 'x86,AMD64') +] targets = [] -for platform in platforms: +for platform, runner, archs in platforms: - platform_targets = subprocess.check_output(['cibuildwheel', '--platform', platform, '--print-build-identifiers']) + platform_targets = subprocess.check_output(['cibuildwheel', '--platform', platform, '--archs', archs, + '--print-build-identifiers']) platform_targets = platform_targets.decode('utf-8') platform_targets = platform_targets.strip('\n').split('\n') @@ -27,11 +28,11 @@ for python_version, group_targets in grouped_targets.items(): targets.append({ 'version': python_version, - 'os': runners[platform], + 'os': runner, 'build': ' '.join(group_targets), }) -# print('matrix=' + json.dumps({'target': targets})) +print(targets) with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: print('matrix=' + json.dumps({'target': targets}), file=fh) diff --git a/ci/cibw_before_all_linux.sh b/ci/cibw_before_all_linux.sh new file mode 100644 index 0000000..11437e6 --- /dev/null +++ b/ci/cibw_before_all_linux.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# This file is part of PIQP. +# +# Copyright (c) 2024 EPFL +# +# This source code is licensed under the BSD 2-Clause License found in the +# LICENSE file in the root directory of this source tree. + +mkdir -p build_external +cd build_external + +bash ../ci/install_eigen.sh + +bash ../ci/download_blasfeo.sh +bash ../ci/build_install_blasfeo.sh GENERIC generic + +case $(uname -m) in + x86_64) + bash ../ci/build_install_blasfeo.sh X64_INTEL_CORE x64 /opt/blasfeo_x64 + bash ../ci/build_install_blasfeo.sh X64_INTEL_HASWELL x64_avx2 /opt/blasfeo_x64_avx2 + bash ../ci/build_install_blasfeo.sh X64_INTEL_SKYLAKE_X arm64 /opt/blasfeo_x64_avx512 + export CMAKE_ARGS="-DBLASFEO_X64_DIR=/opt/blasfeo_x64 -DBLASFEO_X64_AVX2_DIR=/opt/blasfeo_x64_avx2 -DBLASFEO_X64_AVX512_DIR=/opt/blasfeo_x64_avx512" + ;; + aarch64|arm64) + bash ../ci/build_install_blasfeo.sh ARMV8A_APPLE_M1 arm64 /opt/blasfeo_arm64 + export CMAKE_ARGS="-DBLASFEO_ARM64_DIR=/opt/blasfeo_arm64" + ;; +esac diff --git a/ci/cibw_before_all_macos_arm64.sh b/ci/cibw_before_all_macos_arm64.sh new file mode 100644 index 0000000..881aba4 --- /dev/null +++ b/ci/cibw_before_all_macos_arm64.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# This file is part of PIQP. +# +# Copyright (c) 2024 EPFL +# +# This source code is licensed under the BSD 2-Clause License found in the +# LICENSE file in the root directory of this source tree. + +mkdir -p build_external +cd build_external + +bash ../ci/install_eigen.sh + +bash ../ci/download_blasfeo.sh +bash ../ci/build_install_blasfeo.sh GENERIC generic +bash ../ci/build_install_blasfeo.sh ARMV8A_APPLE_M1 arm64 /opt/blasfeo_arm64 + +export CMAKE_ARGS="-DBLASFEO_ARM64_DIR=/opt/blasfeo_arm64" diff --git a/ci/cibw_before_all_macos_x86_64.sh b/ci/cibw_before_all_macos_x86_64.sh new file mode 100644 index 0000000..564e633 --- /dev/null +++ b/ci/cibw_before_all_macos_x86_64.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# This file is part of PIQP. +# +# Copyright (c) 2024 EPFL +# +# This source code is licensed under the BSD 2-Clause License found in the +# LICENSE file in the root directory of this source tree. + +mkdir -p build_external +cd build_external + +bash ../ci/install_eigen.sh + +bash ../ci/download_blasfeo.sh +bash ../ci/build_install_blasfeo.sh GENERIC generic +bash ../ci/build_install_blasfeo.sh X64_INTEL_CORE x64 /opt/blasfeo_x64 +bash ../ci/build_install_blasfeo.sh X64_INTEL_HASWELL x64_avx2 /opt/blasfeo_x64_avx2 +bash ../ci/build_install_blasfeo.sh X64_INTEL_SKYLAKE_X arm64 /opt/blasfeo_x64_avx512 + +export CMAKE_ARGS="-DBLASFEO_X64_DIR=/opt/blasfeo_x64 -DBLASFEO_X64_AVX2_DIR=/opt/blasfeo_x64_avx2 -DBLASFEO_X64_AVX512_DIR=/opt/blasfeo_x64_avx512" diff --git a/ci/cibw_before_all_windows.sh b/ci/cibw_before_all_windows.sh new file mode 100644 index 0000000..564e633 --- /dev/null +++ b/ci/cibw_before_all_windows.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# This file is part of PIQP. +# +# Copyright (c) 2024 EPFL +# +# This source code is licensed under the BSD 2-Clause License found in the +# LICENSE file in the root directory of this source tree. + +mkdir -p build_external +cd build_external + +bash ../ci/install_eigen.sh + +bash ../ci/download_blasfeo.sh +bash ../ci/build_install_blasfeo.sh GENERIC generic +bash ../ci/build_install_blasfeo.sh X64_INTEL_CORE x64 /opt/blasfeo_x64 +bash ../ci/build_install_blasfeo.sh X64_INTEL_HASWELL x64_avx2 /opt/blasfeo_x64_avx2 +bash ../ci/build_install_blasfeo.sh X64_INTEL_SKYLAKE_X arm64 /opt/blasfeo_x64_avx512 + +export CMAKE_ARGS="-DBLASFEO_X64_DIR=/opt/blasfeo_x64 -DBLASFEO_X64_AVX2_DIR=/opt/blasfeo_x64_avx2 -DBLASFEO_X64_AVX512_DIR=/opt/blasfeo_x64_avx512" diff --git a/ci/download_blasfeo.sh b/ci/download_blasfeo.sh new file mode 100644 index 0000000..455a6c0 --- /dev/null +++ b/ci/download_blasfeo.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# This file is part of PIQP. +# +# Copyright (c) 2024 EPFL +# +# This source code is licensed under the BSD 2-Clause License found in the +# LICENSE file in the root directory of this source tree. + +echo "Downloading blasfeo..." + +git clone https://github.com/giaf/blasfeo.git blasfeo diff --git a/interfaces/python/CMakeLists.txt b/interfaces/python/CMakeLists.txt index f7415dc..9b2a7b9 100644 --- a/interfaces/python/CMakeLists.txt +++ b/interfaces/python/CMakeLists.txt @@ -40,7 +40,7 @@ endif() function(CREATE_PIQP_PYTHON_TARGET target_name COMPILE_OPTIONS) pybind11_add_module(${target_name} src/piqp_python.cpp) target_compile_options(${target_name} PRIVATE ${COMPILE_OPTIONS}) - target_link_libraries(${target_name} PRIVATE piqp_header_only) + target_link_libraries(${target_name} PRIVATE piqp_header_only_no_blasfeo_linked) target_compile_definitions(${target_name} PRIVATE PYTHON_MODULE_NAME=${target_name}) # PIQP_VERSION_INFO is defined by setup.py and passed into the C++ code as a define (VERSION_INFO) here. target_compile_definitions(${target_name} PRIVATE VERSION_INFO=${PIQP_VERSION_INFO}) @@ -63,3 +63,41 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") create_piqp_python_target(piqp_python_avx2 "${AVX2_COMPILE_OPTION};${FMA_COMPILE_OPTION}") create_piqp_python_target(piqp_python_avx512 "${AVX512_COMPILE_OPTION};${FMA_COMPILE_OPTION}") endif() + +if (BUILD_WITH_BLASFEO) + # if x86/amd64 + if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + # if 64bit + if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86_64)|(X86_64)|(amd64)|(AMD64)") + if (TARGET blasfeo_x64) + target_link_libraries(piqp_python PRIVATE blasfeo_x64) + else () + target_link_libraries(piqp_python PRIVATE blasfeo) + endif () + if (TARGET blasfeo_x64_avx2) + target_link_libraries(piqp_python_avx2 PRIVATE blasfeo_x64_avx2) + else () + target_link_libraries(piqp_python_avx2 PRIVATE blasfeo) + endif () + if (TARGET blasfeo_x64_avx512) + target_link_libraries(piqp_python PRIVATE blasfeo_x64_avx512) + else () + target_link_libraries(piqp_python_avx512 PRIVATE blasfeo) + endif () + else () + target_link_libraries(piqp_python PRIVATE blasfeo) + target_link_libraries(piqp_python_avx2 PRIVATE blasfeo) + target_link_libraries(piqp_python_avx512 PRIVATE blasfeo) + endif () + + # if arm64 + elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "(ARM64)|(arm64)|(aarch64)") + if (TARGET blasfeo_arm64) + target_link_libraries(piqp_python PRIVATE blasfeo_arm64) + else () + target_link_libraries(piqp_python PRIVATE blasfeo) + endif () + else () + target_link_libraries(piqp_python PRIVATE blasfeo) + endif() +endif ()