From e0cd9ef08da8234ace80091293c1df6d887e7fac Mon Sep 17 00:00:00 2001 From: Aaron Jomy Date: Fri, 4 Sep 2026 09:58:27 +0200 Subject: [PATCH] [build] Make the build tree runnable without an install step --- CMakeLists.txt | 51 ++++++++++++++++++++++++++++----------- cmake/AddCppInterOp.cmake | 8 +++++- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20d2dc6..c3f8ed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,22 +31,23 @@ endif() set(CPPJIT_LLVM_VERSION_MIN 20) set(CPPJIT_LLVM_VERSION_MAX 22) -# CppInterOp is installed at the location cppjit ships at runtime: ask for the -# site-packages path; fall back to CMAKE_INSTALL_PREFIX for standalone builds. -execute_process( - COMMAND ${Python_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_path('platlib'))" - OUTPUT_VARIABLE _python_platlib - OUTPUT_STRIP_TRAILING_WHITESPACE -) -if(_python_platlib) - set(CPPINTEROP_INSTALL_PREFIX "${_python_platlib}") +# Runtime fallback anchor for the dispatch (see cppinterop_paths()): the +# installed package under scikit-build-core, the build tree otherwise -- +# a plain `cmake --build` yields a runnable tree under /python. +if(SKBUILD) + execute_process( + COMMAND ${Python_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_path('platlib'))" + OUTPUT_VARIABLE _python_platlib + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(CPPINTEROP_INSTALL_PREFIX "${_python_platlib}/cppjit") else() - set(CPPINTEROP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + set(CPPINTEROP_INSTALL_PREFIX "${CMAKE_BINARY_DIR}") endif() -# CppInterOp installs here; cppjit's own rules ship a subset, so the wheel -# owns every installed file. -set(CPPINTEROP_STAGE_DIR "${CMAKE_BINARY_DIR}/cppinterop-stage") +# CppInterOp stages into the build tree in the runtime layout; the wheel +# ships a subset of it. +set(CPPINTEROP_STAGE_DIR "${CMAKE_BINARY_DIR}/interop") # Acquire CppInterOp: an external prebuilt one (CppInterOp_DIR / # CMAKE_PREFIX_PATH), else the pinned ExternalProject. Exports the @@ -70,7 +71,7 @@ endif() # back to the install prefix (see cppinterop_paths()); the clang major # names the versioned compiler probed for the runtime resource dir. target_compile_definitions(cppjit PRIVATE - CPPINTEROP_INSTALL_PREFIX="${CPPINTEROP_INSTALL_PREFIX}/cppjit" + CPPINTEROP_INSTALL_PREFIX="${CPPINTEROP_INSTALL_PREFIX}" CPPINTEROP_LIBRARY="${CPPJIT_INTEROP_LIBRARY}" CPPINTEROP_INCLUDE_DIR="${CPPJIT_INTEROP_RUNTIME_INCLUDES}" CPPJIT_CLANG_MAJOR="${CPPJIT_INTEROP_CLANG_MAJOR}" @@ -108,11 +109,33 @@ set_target_properties(cppjit PROPERTIES PREFIX "lib" ) +# A plain build yields a runnable tree: the extension and the python +# sources assemble under /python, beside /interop. +if(NOT SKBUILD) + set_target_properties(cppjit PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/cppjit" + ) + add_custom_target(cppjit-python-tree ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/python/cppjit" + "${CMAKE_BINARY_DIR}/python/cppjit" + ) +endif() + # the extension lives inside the package (import cppjit.libcppjit) install(TARGETS cppjit LIBRARY DESTINATION cppjit ) +# scikit-build-core ships the python sources itself (wheel.packages); a +# plain CMake install lays them out here so PYTHONPATH= works. +if(NOT SKBUILD) + install(DIRECTORY python/cppjit + DESTINATION . + PATTERN "__pycache__" EXCLUDE + ) +endif() + # An external CppInterOp is consumed in place and nothing of it ships; # the bundled one installs with the builtin headers of the build clang, # laid out as a headers-only resource dir (only include/ ships). diff --git a/cmake/AddCppInterOp.cmake b/cmake/AddCppInterOp.cmake index 57e2ea9..38ddfb7 100644 --- a/cmake/AddCppInterOp.cmake +++ b/cmake/AddCppInterOp.cmake @@ -225,7 +225,13 @@ function(cppjit_add_cppinterop) set(_compile_includes "${CPPINTEROP_STAGE_DIR}/include") set(_runtime_includes "interop/include") set(_clang_major "${LLVM_VERSION_MAJOR}") - set(_clang_dir "interop/lib/clang/${LLVM_VERSION_MAJOR}") + # The wheel reads its bundled copy; a raw build tree bundles nothing + # and uses the build LLVM's headers where they are. + if(SKBUILD) + set(_clang_dir "interop/lib/clang/${LLVM_VERSION_MAJOR}") + else() + set(_clang_dir "${_clang_resource_dir}") + endif() endif() set(CPPJIT_INTEROP_LIBRARY "${_library}" PARENT_SCOPE)