diff --git a/.scripts/build_steps.sh b/.scripts/build_steps.sh index ba4b251..856f469 100755 --- a/.scripts/build_steps.sh +++ b/.scripts/build_steps.sh @@ -43,6 +43,8 @@ setup_conda_rc "${FEEDSTOCK_ROOT}" "${RECIPE_ROOT}" "${CONFIG_FILE}" source run_conda_forge_build_setup + + # make the build number clobber make_build_number "${FEEDSTOCK_ROOT}" "${RECIPE_ROOT}" "${CONFIG_FILE}" diff --git a/.scripts/run_win_build.bat b/.scripts/run_win_build.bat index 65650bf..a45c34f 100755 --- a/.scripts/run_win_build.bat +++ b/.scripts/run_win_build.bat @@ -24,7 +24,7 @@ set "CONDA_LIBMAMBA_SOLVER_NO_CHANNELS_FROM_INSTALLED=1" :: Provision the necessary dependencies to build the recipe later echo Installing dependencies -mamba.exe install "python=3.10" pip mamba conda-build conda-forge-ci-setup=4 "conda-build>=24.1" -c conda-forge --strict-channel-priority --yes +mamba.exe install pip mamba conda-build conda-forge-ci-setup=4 "conda-build>=24.1" -c conda-forge --strict-channel-priority --yes if !errorlevel! neq 0 exit /b !errorlevel! :: Set basic configuration @@ -48,7 +48,7 @@ if NOT [%HOST_PLATFORM%] == [%BUILD_PLATFORM%] ( ) if NOT [%flow_run_id%] == [] ( - set "EXTRA_CB_OPTIONS=%EXTRA_CB_OPTIONS% --extra-meta flow_run_id=%flow_run_id% remote_url=%remote_url% sha=%sha%" + set "EXTRA_CB_OPTIONS=%EXTRA_CB_OPTIONS% --extra-meta flow_run_id=%flow_run_id% remote_url=%remote_url% sha=%sha%" ) call :end_group diff --git a/build-locally.py b/build-locally.py index 8ac9b84..6788aea 100755 --- a/build-locally.py +++ b/build-locally.py @@ -1,5 +1,5 @@ #!/bin/sh -"""exec' "python3" "$0" "$@" #""" # fmt: off # fmt: on +"""exec" "python3" "$0" "$@" #""" # fmt: off # fmt: on # # This file has been generated by conda-smithy in order to build the recipe # locally. diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 201783a..c3de525 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -2,7 +2,10 @@ {% set sha256 = "e08cb87f4773da97fa7b5f035de8763abc656d87d5773e62f6da0587d1f0ec20" %} # this is set to PYBIND11_INTERNALS_VERSION -{% set abi_version = "4" %} +# since 2.12.0 pybind11 defines two ABI version. 4 and 5 for 3.12+ or msvc. +# https://github.com/pybind/pybind11/blob/v2.12.0/include/pybind11/detail/internals.h#L40 +{% set abi_version = "4" %} # [py<312 and not win] +{% set abi_version = "5" %} # [py>=312 or win] package: name: pybind11-split @@ -14,7 +17,7 @@ source: sha256: {{ sha256 }} build: - number: 0 + number: 1 requirements: build: @@ -33,8 +36,9 @@ outputs: source_files: - include/pybind11/detail/internals.h commands: - # make sure the internals version matches the package version - - if [ $(grep "#define PYBIND11_INTERNALS_VERSION" include/pybind11/detail/internals.h | cut -d' ' -f3) != "{{ abi_version }}" ]; then exit 1; fi + # the ABI version depends on both python version and operating system, so just check if the used version is one of the one defined in the header + - matched=false; while read -r version; do [ "$version" -eq "{{ abi_version }}" ] && { matched=true; break; }; done < <(awk '/define PYBIND11_INTERNALS_VERSION/{print $NF}' include/pybind11/detail/internals.h); [ "$matched" = true ] && exit 0 || exit 1 + - name: pybind11-global script: build-pybind11-global.sh # [unix] @@ -62,6 +66,9 @@ outputs: - name: pybind11 script: build-pybind11.sh # [unix] script: build-pybind11.bat # [win] + build: + script_env: + - EXPECTED_PYBIND11_INTERNALS_VERSION={{ abi_version }} requirements: build: - python # [build_platform != target_platform] @@ -80,8 +87,12 @@ outputs: run_constrained: - pybind11-abi =={{ abi_version }} test: + files: + - test_abi imports: - pybind11 + script: run-test-pybind11.sh # [unix] + script: run-test-pybind11.bat # [win] commands: - test -f ${PREFIX}/share/cmake/pybind11/pybind11Config.cmake # [unix] - if exist %LIBRARY_PREFIX%\share\cmake\pybind11\pybind11Config.cmake (exit 0) else (exit 1) # [win] @@ -89,6 +100,11 @@ outputs: - if exist %LIBRARY_INC%\pybind11\pybind11.h (exit 0) else (exit 1) # [win] - test -f $(python -c "import pybind11 as py; print(py.get_include())")/pybind11/pybind11.h # [unix] - if exist $(python -c "import pybind11 as py; print(py.get_include())")\pybind11\pybind11.h (exit 0) else (exit 1) # [win] + requires: + - cmake + - {{ compiler('c') }} + - {{ compiler('cxx') }} + - ninja about: home: https://github.com/pybind/pybind11/ diff --git a/recipe/run-test-pybind11.bat b/recipe/run-test-pybind11.bat new file mode 100644 index 0000000..d9b91b5 --- /dev/null +++ b/recipe/run-test-pybind11.bat @@ -0,0 +1,27 @@ +cd test_abi + +REM debug env variable +set + +REM Cleanup the build folder +rmdir /s /q build +if errorlevel 1 exit 1 + +REM Configure the project +cmake -GNinja -S. -Bbuild -DCMAKE_BUILD_TYPE=Release +if errorlevel 1 exit 1 + +REM Build the project and extract the line with PYBIND11_INTERNALS_VERSION= +for /F "tokens=*" %%i in ('cmake --build build ^| findstr /R /C:"^PYBIND11_INTERNALS_VERSION="') do set "line=%%i" +if errorlevel 1 exit 1 + +REM Extract the value after the equals sign in the line PYBIND11_INTERNALS_VERSION= +for /F "tokens=2 delims==" %%a in ("%line%") do set "version=%%a" + +REM Compare to the environment variable EXPECTED_PYBIND11_INTERNALS_VERSION +if "%version%"=="%EXPECTED_PYBIND11_INTERNALS_VERSION%" ( + echo Versions match, compilation: "%version%" expected: "%EXPECTED_PYBIND11_INTERNALS_VERSION%" +) else ( + echo Error: PYBIND11_INTERNALS_VERSION version mismatch, compilation: "%version%" expected: "%EXPECTED_PYBIND11_INTERNALS_VERSION%" + exit 1 +) diff --git a/recipe/run-test-pybind11.sh b/recipe/run-test-pybind11.sh new file mode 100644 index 0000000..023ef48 --- /dev/null +++ b/recipe/run-test-pybind11.sh @@ -0,0 +1,30 @@ +cd test_abi + +# Debug env variables +env + +# Cleanup the build folder +rm -rf ./build + +# Configure the project +cmake -GNinja -S. -Bbuild -DCMAKE_BUILD_TYPE=Release + +# Build the project and extract the line with PYBIND11_INTERNALS_VERSION= +line=$(cmake --build build | grep 'PYBIND11_INTERNALS_VERSION=') + +# Check if the line was found +if [ -z "$line" ]; then + echo "Error: PYBIND11_INTERNALS_VERSION not found." + exit 1 +fi + +# Extract the value after the equals sign +version=${line#PYBIND11_INTERNALS_VERSION=} + +# Compare to the environment variable EXPECTED_PYBIND11_INTERNALS_VERSION +if [ "$version" = "$EXPECTED_PYBIND11_INTERNALS_VERSION" ]; then + echo "Versions match - compilation: $version expected: $EXPECTED_PYBIND11_INTERNALS_VERSION" +else + echo "Error: Version mismatch - compilation: $version expected: $EXPECTED_PYBIND11_INTERNALS_VERSION" + exit 1 +fi diff --git a/recipe/test_abi/CMakeLists.txt b/recipe/test_abi/CMakeLists.txt new file mode 100644 index 0000000..289d826 --- /dev/null +++ b/recipe/test_abi/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required (VERSION 3.25) + +project(pybind11testabi) + +find_package(pybind11 REQUIRED) + +pybind11_add_module(test_abi_module test_abi.cpp) diff --git a/recipe/test_abi/test_abi.cpp b/recipe/test_abi/test_abi.cpp new file mode 100644 index 0000000..52cfe2d --- /dev/null +++ b/recipe/test_abi/test_abi.cpp @@ -0,0 +1,32 @@ +// Dummy module used only to print the PYBIND11_INTERNALS_VERSION version +// during the compilation process +#include + +#define STRINGIFY(x) #x +#define TO_STRING(x) STRINGIFY(x) + +#if defined(_MSC_VER) + // MSVC specific pragma + #pragma message ("PYBIND11_INTERNALS_VERSION=" TO_STRING(PYBIND11_INTERNALS_VERSION)) +#else + #pragma message "PYBIND11_INTERNALS_VERSION=" TO_STRING(PYBIND11_INTERNALS_VERSION) +#endif + +// The rest is just a copy of https://github.com/pybind/cmake_example/blob/7a94877f581a14de4de1a096fb053a55fc2a66bf/src/main.cpp +// to get a valid pybind11 module + +#include + +int add(int i, int j) { + return i + j; +} + +namespace py = pybind11; + +PYBIND11_MODULE(cmake_example, m) { + m.def("add", &add, R"pbdoc( + Add two numbers + + Some other explanation about the add function. + )pbdoc"); +}