Skip to content

Commit f993072

Browse files
committed
feat(eigen): Feature System v2 — eigen_blas provider + use_blas/use_lapacke/mpl2only
Requires mcpp >= 0.0.69 (feature defines + capabilities); older mcpp ignores the new keys (skip-unknown), so the recipe stays parseable everywhere. - eigen_blas : compile Eigen's own reference BLAS AND advertise the 'blas' capability (provides=["blas"]). - use_blas : define EIGEN_USE_BLAS + requires=["blas"] — Eigen delegates to an external BLAS bound by the resolver. - use_lapacke : define EIGEN_USE_LAPACKE + requires=["lapack"]. - mpl2only : define EIGEN_MPL2_ONLY (no capability). Header comment documents the provider-vs-consumer split and the verified mutual exclusion: enabling eigen_blas + use_blas together is self-contradictory (the blas/*_impl.h functype dispatch tables vs the -DEIGEN_USE_BLAS backend signature) — use eigen_blas alone, or use_blas with a separate provider. Verified on mcpp 0.0.69: header-only mpl2only consumer builds+runs; eigen_blas alone compiles; compile_commands.json carries EIGEN_USE_BLAS / EIGEN_MPL2_ONLY.
1 parent fdc2446 commit f993072

1 file changed

Lines changed: 59 additions & 33 deletions

File tree

pkgs/c/compat.eigen.lua

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,50 @@
1313
-- under `unsupported/Eigen/` (Tensor, AutoDiff, Splines, MatrixFunctions, …)
1414
-- resolvable out of the box.
1515
--
16-
-- Feature: `blas` — Eigen's reference BLAS implementation.
17-
-- Eigen ships a full BLAS library under `blas/` (the `eigen_blas` target in
18-
-- upstream CMake). Despite the historical name, it builds from pure C++
19-
-- (`blas/*.cpp`) + f2c-translated C (`blas/f2c/*.c`) — NO Fortran compiler
20-
-- is needed (the only `.f` files live under `blas/testing/`, the test
21-
-- suite, and are not part of the library). So it fits mcpp's sources-only
22-
-- feature gate cleanly, exactly like compat.cjson's `utils`: excluded by
23-
-- default, and compiled into the `eigen` lib when the dependency requests
24-
-- `features = ["blas"]`. The result exposes the standard BLAS symbols
25-
-- (sgemm_/dgemm_/ddot_/… , Fortran ABI) for code that wants to link a BLAS.
26-
-- Common.h pulls Eigen via a path RELATIVE to blas/ (`../Eigen/Core`), so
27-
-- the sources must compile in place — they do, since `*/blas/*.cpp` keeps
28-
-- them under the unpacked tree. Verified locally on mcpp 0.0.68.
16+
-- Features (Feature System v2, requires mcpp >= 0.0.69). The two BLAS stories
17+
-- run on ORTHOGONAL axes — do not confuse them:
2918
--
30-
-- What is NOT a feature here (and why):
31-
-- * `unsupported/` modules are header-only and live BESIDE `Eigen/` under
32-
-- the same tarball root, so the core include path (`*`) already exposes
33-
-- them; a sources-only gate cannot hide headers, so there is nothing to
34-
-- gate — they are simply available.
35-
-- * Eigen's compile-define knobs (EIGEN_MPL2_ONLY, EIGEN_USE_BLAS/LAPACKE,
36-
-- …) are preprocessor defines; the feature table carries only `sources`
37-
-- on mcpp 0.0.68, so they cannot be feature-gated yet. If mcpp later lets
38-
-- a feature contribute defines/cflags, `mpl2only` (-> -DEIGEN_MPL2_ONLY)
39-
-- would be the clean fit.
19+
-- `eigen_blas` — Eigen AS a BLAS provider.
20+
-- Eigen ships a full BLAS library under `blas/` (the `eigen_blas` target in
21+
-- upstream CMake). It builds from pure C++ (`blas/*.cpp`) + f2c-translated
22+
-- C (`blas/f2c/*.c`) — NO Fortran compiler is needed (the only `.f` files
23+
-- live under `blas/testing/`, not the library). Sources-only gate (excluded
24+
-- by default; compiled into the `eigen` lib when requested). It exposes the
25+
-- standard BLAS symbols (sgemm_/dgemm_/… , Fortran ABI) for code that wants
26+
-- to link a BLAS — so it also `provides = ["blas"]` as a capability. Common.h
27+
-- pulls Eigen via a path RELATIVE to blas/ (`../Eigen/Core`), so the sources
28+
-- compile in place under the unpacked tree.
29+
--
30+
-- `use_blas` / `use_lapacke` — Eigen CONSUMING an external BLAS/LAPACK.
31+
-- These flip Eigen's own kernels to delegate to an external implementation.
32+
-- Each contributes the package-owned define (EIGEN_USE_BLAS / EIGEN_USE_LAPACKE)
33+
-- and `requires` the abstract `blas` / `lapack` capability; the resolver binds
34+
-- one provider from the graph (the `eigen_blas` feature above can satisfy it,
35+
-- or a dedicated provider such as a future compat.openblas). Pick the provider
36+
-- with `[capabilities] blas = "<provider>"` or `--cap blas=<provider>` when
37+
-- more than one is present.
38+
--
39+
-- `mpl2only` — package-owned define EIGEN_MPL2_ONLY (no capability).
40+
--
41+
-- MUTUAL EXCLUSION: `eigen_blas` and `use_blas` are OPPOSITE roles and must NOT
42+
-- be enabled together. `eigen_blas` compiles Eigen's own BLAS implementation;
43+
-- `use_blas` defines EIGEN_USE_BLAS, which flips Eigen's headers into "delegate
44+
-- to an EXTERNAL BLAS" mode. Compiling Eigen's own BLAS sources in that mode is
45+
-- self-contradictory: the `blas/*_impl.h` dispatch tables (functype expects the
46+
-- native `const Scalar&`) no longer match the now-by-value BLAS-backend `run`
47+
-- signatures → `invalid conversion ... [-fpermissive]` on level2/level3_impl.h.
48+
-- Verified on mcpp 0.0.69: a blas TU compiles cleanly WITHOUT -DEIGEN_USE_BLAS
49+
-- and fails WITH it. So:
50+
-- * use `eigen_blas` ALONE to get a BLAS library OUT of Eigen, or
51+
-- * use `use_blas` paired with a SEPARATE `blas` provider (a future
52+
-- compat.openblas) to feed an external BLAS INTO Eigen — never both.
53+
-- The header-only path and the `use_blas`/`mpl2only` DEFINES themselves are
54+
-- proven on 0.0.69 (compile_commands.json carries EIGEN_USE_BLAS / EIGEN_MPL2_ONLY;
55+
-- a header-only `mpl2only` consumer builds+runs; `eigen_blas` alone compiles).
56+
--
57+
-- Note: `unsupported/` modules are header-only and live BESIDE `Eigen/` under the
58+
-- same tarball root, so the core include path (`*`) already exposes them; a
59+
-- sources-only gate cannot hide headers, so there is nothing to gate.
4060
--
4161
-- All `mcpp` paths are GLOBS relative to the verdir; the leading `*` absorbs
4262
-- the GitLab archive's `eigen-<tag>/` wrap layer.
@@ -92,18 +112,24 @@ package = {
92112
},
93113
sources = { "mcpp_generated/eigen_anchor.c" },
94114
targets = { ["eigen"] = { kind = "lib" } },
95-
-- Optional: compile Eigen's reference BLAS (`eigen_blas`) into the lib.
96-
-- C++ + f2c-C only, no Fortran. Off by default; pulled in with
97-
-- `features = ["blas"]`. blas/ has exactly the 5 library .cpp and
98-
-- blas/f2c/ exactly the 18 library .c (the upstream eigen_blas source
99-
-- set); the `*.cpp`/`*.c` globs match them and nothing else.
115+
-- Feature System v2 (mcpp >= 0.0.69). See the header for the
116+
-- provider-vs-consumer distinction. Old mcpp ignores the `defines`/
117+
-- `requires`/`provides` keys (skip-unknown), so this recipe still parses
118+
-- there — only the v2 behaviors are inert.
100119
features = {
101-
["blas"] = {
102-
sources = {
103-
"*/blas/*.cpp",
104-
"*/blas/f2c/*.c",
105-
},
120+
-- PROVIDER: compile Eigen's reference BLAS (eigen_blas) into the lib
121+
-- and advertise the `blas` capability. C++ + f2c-C only, no Fortran.
122+
-- blas/ has exactly the 5 library .cpp and blas/f2c/ exactly the 18
123+
-- library .c (the upstream eigen_blas set); the globs match those.
124+
["eigen_blas"] = {
125+
sources = { "*/blas/*.cpp", "*/blas/f2c/*.c" },
126+
provides = { "blas" },
106127
},
128+
-- CONSUMER: delegate Eigen's kernels to an external BLAS / LAPACK.
129+
["use_blas"] = { defines = { "EIGEN_USE_BLAS" }, requires = { "blas" } },
130+
["use_lapacke"] = { defines = { "EIGEN_USE_LAPACKE" }, requires = { "lapack" } },
131+
-- Pure package-owned define knob.
132+
["mpl2only"] = { defines = { "EIGEN_MPL2_ONLY" } },
107133
},
108134
deps = { },
109135
},

0 commit comments

Comments
 (0)