Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Two narrow correctness fixes in the standalone CLI -> CMake translation and
its CMake target properties; the pipeline stages themselves are unchanged.
generate --cmake resolved prebuilt objects, archives, and shared libraries to
absolute paths and then rewrote every absolute item back to a relative string,
so a real file path reached target_link_libraries() as a bare token and the
linker read it as a library name (-l../lib/libnative.a). Path-backed items now
render as "${CMAKE_CURRENT_LIST_DIR}/<relative>", keeping the three categories
distinct - object/archive/shared library to a path, named library to a name,
arg: to a linker argument - in their original order.
--native-library-dir became LINK_OPTIONS "-L<dir>", which carries no runtime
meaning, so an extension could link and then fail to import. prik_add_module()
gains LIBRARY_DIRS, mapped to target_link_directories() plus the target's
BUILD_RPATH, and generate --cmake emits LIBRARY_DIRS instead of a raw -L.
INSTALL_RPATH stays under project control.
Also fixes a bare Python float in the installed-wheel CMake test: PRIK's
documented scalar policy requires numpy.float64, and CI reached that assertion
once the isolated wheel install succeeded.
Changed: prik/cmake.py (link-item rendering, LIBRARY_DIRS emission),
cmake/UsePRIK.cmake (LIBRARY_DIRS argument, link directories, BUILD_RPATH),
CMake guide and CLI reference docs, CHANGELOG.
Tests: two end-to-end regressions in tests/fortran/infrastructure/building/
end_to_end/test_cmake_builds.py that configure, build, import, and call - one
linking a real prebuilt .o and .a from a sibling directory, one importing an
extension backed by a shared library in a non-system directory with no loader
path able to resolve it. The ordered-link-item ordering test is kept.
Verified: all five suite roots green (fortran -m "not real_library" 2534, c
646, docs 745, tools/workflows 64) plus the CI toolchain-smoke lane (8) and a
CMake-file rerun with LD_LIBRARY_PATH set. Static gate clean: ruff check and
format, version check, bandit, vulture, radon policy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NrtPVjqMKNLJ1cYsteWiKG
Three narrow fixes in the packaged CMake helper; the pipeline stages are unchanged. The native OBJECT target filtered LINK_LIBRARIES through if(TARGET ...), which forwarded "debug Foo optimized Bar" as plain Foo and Bar with their keywords stripped, so both configurations' usage requirements reached the native sources at once, and dropped generator-expression entries entirely because they are not targets. PRIK_LINK_LIBRARIES now passes through unchanged, so CMake applies the caller's own selection rules. The extension target keeps the same LINK_LIBRARIES for the final link. CMake compiles .C as C++ while PRIK plans such a source as C, so the two would disagree about the compiler. prik_add_module() and generate --cmake now reject that suffix with a message naming the reason, and generation fails before a project is written rather than at CMake configure time. A module contributing native Fortran sources now checks that CMake's Fortran language is enabled, instead of failing later with a less direct error. Changed: cmake/UsePRIK.cmake (native link forwarding, suffix validation, Fortran language check), prik/cmake.py (fail-fast .C rejection), CMake guide docs, CHANGELOG. Tests: five regressions in tests/fortran/infrastructure/building/end_to_end/ test_cmake_builds.py - a parametrized Debug/Release pair whose native source #errors when the wrong configuration's definition arrives or the right one is missing, .C rejection at both the helper and CLI level, and the Fortran language diagnostic. All five fail against the pre-fix helper and pass with it. Verified: test_cmake_builds.py plus tests/docs 782 passed, CI toolchain-smoke lane 8 passed, static gate clean (ruff check and format, version check, bandit, vulture, radon policy). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NrtPVjqMKNLJ1cYsteWiKG
CMake configuration ran PRIK's whole semantic pipeline -- preprocessing, parsing, semantic IR, policy completion, wrapper planning, C and Fortran lowering, and a compiled Fortran type probe -- purely to discover which files it would later generate, then ran all of it again at build time to actually write them. Configuration now asks a structural question instead, and the pipeline runs exactly once, during the build. The structural query derives everything CMake needs from the module name and its declared shape: the generated filenames, the link driver, and the mandatory ABI flags its compiler profile states. Vendor detection is a lookup on the driver's name, so no compiler runs. Querying a 300-procedure module's plan drops from 2.54s to 0.41s, and the query no longer grows with source size. Configuration cannot read a source, so the generated file list must not depend on what analysis finds. PRIK now names the optional compilation units up front and always writes them: a module needing no collision adapter still gets <module>_adapters.c, and a Fortran module needing no bridge still gets bind_c_<module>_wrapper.f90. An unused unit holds a placeholder that defines no symbol and compiles clean under -Wall -Wextra -pedantic -Werror. A semantic edit therefore changes a file's contents, not the build graph, and never needs a reconfigure. Configure-time and build-time calls share one function, so the files CMake declares are exactly the files generation fills. Transitive semantic inputs -- nested C headers, Fortran INCLUDE files, imported contracts -- now reach CMake through a depfile written during generation, replacing the CMAKE_CONFIGURE_DEPENDS wiring that existed because a bridge source could appear or disappear. That uses add_custom_command DEPFILE, so the packaged helper requires CMake 3.21; verified working under both Ninja and Unix Makefiles. UsePRIK.cmake drops from 560 to 482 lines: gone are the plan-tree path rebasing, the per-compilation-unit JSON application, the semantic dependency wiring, and every semantic JSON read. Compile flags now use compile-language generator expressions, so no source properties remain and cross-target flag leakage is structurally impossible. The internal heavy --plan mode had no other consumer and is removed. Changed: prik/naming/generated_files.py (new, sole owner of generated filenames, replacing inline spellings in planning, codegen, and build integration), prik/cmake.py (StructuralLayout), prik/cli.py (--cmake-plan, --declared-layout, --depfile), prik/pipeline/build.py (placeholder units, depfile writer, --plan removal), cmake/UsePRIK.cmake, CMake guide, CHANGELOG. Tests: configure succeeds for a source PRIK cannot parse and fails only at build time; the bridge and adapter filenames stay fixed while their contents round-trip between placeholder and real without a reconfigure; placeholders compile under strict conformance flags; an unchanged rebuild reruns nothing; and --lto reaches both target kinds' compile lines and the link. The existing nested-header and nested-INCLUDE tests now exercise the depfile. The obsolete "reconfigures when a bridge appears" test is replaced by its inverse. Verified: full CI-shaped suite 3990 passed, CMake suite 42 passed, static gate clean. The installed-wheel test cannot run on this machine and is unchanged; packaging picks up the new module through packages.find. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NrtPVjqMKNLJ1cYsteWiKG
Package the CMake helper inside the distribution as prik/cmake_modules so an entry point can name it, and register that directory under cmake.module. A scikit-build-core build then puts it on CMAKE_MODULE_PATH itself, so a project needs only include(UsePRIK). A new PRIKConfig.cmake beside the helper loads it for find_package(PRIK CONFIG REQUIRED), and both modules still install to share/prik/cmake, so cmake_module_dir() and that prefix layout are unchanged. Add `prik cmake-dir` and `prik install-dir` so a shell can substitute the packaged module directory or PRIK's installation prefix into -DPRIK_DIR= and -DCMAKE_PREFIX_PATH=. An installation prefix is not a CMake fact, so it lives in the new prik/installation.py, and it reports that PRIK is not installed rather than naming a prefix that holds none of its data. Fail the Ubuntu and macOS unit-test jobs when CMake is missing, since the CMake integration tests would otherwise deselect themselves and leave the job green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
`pip install --user` writes data files under the user base rather than under sys.prefix, so install_dir() missed that installation entirely and reported PRIK as uninstalled. data_roots() now searches the user base as well, and _helper_path() reaches a user-installed share/prik/cmake through the same list. The root is only searched while the interpreter would import from the user site at all. A virtual environment, -s, and -I all switch that off, and the data there then belongs to an installation this interpreter cannot use, so naming its prefix would point CMake at a different PRIK than the one answering. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
examples/cmake/ builds one Fortran module through every route a CMake project can use to reach PRIK: scikit-build-core's cmake.module entry point, CMAKE_MODULE_PATH, PRIK_DIR, and an installation prefix. One CMakeLists.txt serves all four; only the line that loads PRIK changes, selected by the PRIK_DISCOVERY cache option. check_discovery_routes.sh builds and calls the extension once per route and reports a route whose prerequisite is missing rather than failing it, so the script is also how a contributor checks a route in their own environment. The CMake guide keeps the route documentation and gains the scikit-build-core build-requirement snippet, rather than repeating the routes in a tutorial page. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
install_dir() searched candidate prefixes and returned the first holding share/prik, so a global installation could answer for a `pip install --user` one: -DCMAKE_PREFIX_PATH="$(prik install-dir)" would then point CMake at a different PRIK than the one that ran. cmake-dir never had that problem, because it starts from the imported package. The prefix now comes from the running distribution's recorded data file, located through importlib.metadata and resolved to the prefix above share/prik/cmake. Both commands are exact about the same installation. A distribution answers only when it provides the package running here, either by recording it or by being an editable install over the tree containing it. An editable install records no data files at all, so it reports that rather than a prefix, and data_roots() remains only the last-resort search that finds a packaged UsePRIK.cmake. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
The section opened with the execute_process() lookup, which is the longest of the routes and the one fewest projects need. It now opens with find_package(PRIK CONFIG REQUIRED) configured by -DPRIK_DIR="$(prik cmake-dir)", and the remaining routes follow under "Discovery alternatives": an installation prefix, a module path, scikit-build-core, and asking a specific interpreter. That last route keeps its example and gains the reason to reach for it: the others answer for whichever prik the shell resolves, while it matches the interpreter CMake itself selected. Its command becomes `-m prik cmake-dir` rather than an inline import of cmake_module_dir(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
The page had four headings, one of which carried three quarters of it: the minimal project, every discovery route, the whole prik_add_module() surface as continuous prose, and the regeneration contract all sat under "Existing CMake project". It now moves from a minimal working project, to finding PRIK's CMake modules, to the common options, to languages and flags, to why rebuilds behave, to generating a standalone project. Both option surfaces become tables: the discovery routes, and every prik_add_module() keyword. The keyword table is checked against the helper's own cmake_parse_arguments sets, which is how MODULE_DIRS and LINK_OPTIONS gain a stated purpose rather than only a mention. The front matter keeps the two-phase contract and defers the fixed file list and dependency file to the new regeneration section, and the opening paragraph now links the CLI build guide it assumes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
"Every route above answers for whichever prik the shell resolves" was wrong for scikit-build-core: that route never consults the shell. The backend reads the cmake.module entry point from the PRIK installed in its own build environment, which is the distribution named in build-system.requires and need not be the one on PATH. The sentence now scopes the claim to the three command-line routes and states what scikit-build-core uses instead. The discovery table also gains the distinction a large project needs: PRIK_DIR is package-specific, while CMAKE_PREFIX_PATH is the search path every find_package() call shares. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMz3kPhNruZUmNkDAMT9KJ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.