Description
Error is encountered when a Fortran benchmark for a Level-2+ BLAS routine whose Fortran source declares an EXTERNAL Fortran dependency on another stdlib package (e.g., dgemm calling xerbla, dger calling xerbla). The benchmark fails to link with a missing-symbol error for the dependency.
The underlying defect is in @stdlib/utils/library-manifest. When the resolver is queried with any task other than build (notably task: 'benchmark'), Fortran source files belonging to dependencies are not surfaced.
Fortran sources are currently declared only inside the build task entry of each Fortran-using package's manifest — so when library-manifest walks the dependency tree under task: 'benchmark', it merges each dependency's benchmark entry, which contains only C sources, and the dependency's .f files never appear in the merged result.
For example, in blas/base/xerbla/manifest.json:
task: 'build', os: 'linux', blas: '', wasm: false → src: ["./src/xerbla.f", "./src/xerbla.c"]
task: 'benchmark', os: 'linux', blas: '', wasm: false → src: ["./src/xerbla.c"] (no .f)
The native-addon build path works bc binding.gyp/include.gypi calls library-manifest with no explicit task, defaulting to task: 'build', where the .f declarations exist.
The same condition silently affects every merged Fortran benchmark for a Level-2+ BLAS routine that exercises a cross-package Fortran symbol. Level-1 BLAS Fortran benchmarks (e.g., daxpy, dscal, dasum) have no cross-package Fortran dependencies and link cleanly, which is why the gap has not surfaced more broadly.
The recurring local fix is a Makefile patch in the consuming package that hardcodes a relative path to a sibling package's .f file (e.g., ../../../xerbla/src/xerbla.f inside dger's benchmark Makefile). This couples one package to another package's file-tree layout. If xerbla is ever moved within the package tree (e.g., to @stdlib/blas/base/utils/xerbla), every consumer's hardcoded path silently breaks, and a contributor performing the migration has no way to discover the breakage short of running every affected benchmark. The manifest-based @stdlib/... reference model exists precisely so packages don't reach into each other's file trees this way. See @kgryte's comment on PR #11332.
A second, downstream contributor to the symptom is that tools/scripts/compile_fortran_benchmark only resolves include directories from the manifest, while its C counterpart tools/scripts/compile_c_benchmark resolves include, src, libraries, and libpath. Patching only this wrapper might be too narrow, since it wouldn't address future Fortran-linking contexts that go through library-manifest.
Per office hours discussion, the fix should live in @stdlib/utils/library-manifest so that Fortran source files are resolved uniformly when resolving a package's dependency tree, regardless of the task the caller queried.
Once the resolver is correct, downstream cleanup for the Fortran benchmark wrapper in tools/scripts/ should consume the resolved source list (mirroring its C counterpart), and the merged Fortran benchmark Makefiles' hardcoded SOURCE_FILES defaults should match the C-benchmark Makefile convention.
Related Issues
Related PRs #11332 and #11333.
Questions
No.
Demo
No response
Reproduction
# In a checkout of stdlib develop:
cd lib/node_modules/@stdlib/blas/base/dger/benchmark/fortran
make
Expected Results
Benchmark links successfully; xerbla resolves via the manifest dependency graph (dger's manifest already lists @stdlib/blas/base/xerbla as a dependency under task: 'benchmark'.
Actual Results
Undefined symbols for architecture arm64:
"_xerbla", referenced from:
_dger in ccCfvnCt.o
ld: symbol(s) not found for architecture arm64
collect2: error: ld returned 1 exit status
make: *** [benchmark.length.out] Error 1
Linker fails with an unresolved reference to xerbla. The dependency's .f source is never surfaced because library-manifest only declares Fortran sources under task: 'build'.
Version
develop
Environments
N/A
Browser Version
No response
Node.js / npm Version
No response
Platform
Reproduces on any platform with gfortran + make (linux/macOS verified).
Checklist
Description
Error is encountered when a Fortran benchmark for a Level-2+ BLAS routine whose Fortran source declares an
EXTERNALFortran dependency on another stdlib package (e.g.,dgemmcallingxerbla,dgercallingxerbla). The benchmark fails to link with a missing-symbol error for the dependency.The underlying defect is in @stdlib/utils/library-manifest. When the resolver is queried with any task other than
build(notablytask: 'benchmark'), Fortran source files belonging to dependencies are not surfaced.Fortran sources are currently declared only inside the
buildtask entry of each Fortran-using package's manifest — so whenlibrary-manifestwalks the dependency tree undertask: 'benchmark', it merges each dependency'sbenchmarkentry, which contains only C sources, and the dependency's.ffiles never appear in the merged result.For example, in blas/base/xerbla/manifest.json:
task: 'build',os: 'linux',blas: '',wasm: false→src: ["./src/xerbla.f", "./src/xerbla.c"]task: 'benchmark',os: 'linux',blas: '',wasm: false→src: ["./src/xerbla.c"](no.f)The native-addon build path works bc
binding.gyp/include.gypicallslibrary-manifestwith no explicittask, defaulting totask: 'build', where the.fdeclarations exist.The same condition silently affects every merged Fortran benchmark for a Level-2+ BLAS routine that exercises a cross-package Fortran symbol. Level-1 BLAS Fortran benchmarks (e.g., daxpy, dscal, dasum) have no cross-package Fortran dependencies and link cleanly, which is why the gap has not surfaced more broadly.
The recurring local fix is a Makefile patch in the consuming package that hardcodes a relative path to a sibling package's
.ffile (e.g.,../../../xerbla/src/xerbla.finsidedger's benchmark Makefile). This couples one package to another package's file-tree layout. Ifxerblais ever moved within the package tree (e.g., to@stdlib/blas/base/utils/xerbla), every consumer's hardcoded path silently breaks, and a contributor performing the migration has no way to discover the breakage short of running every affected benchmark. The manifest-based @stdlib/... reference model exists precisely so packages don't reach into each other's file trees this way. See @kgryte's comment on PR #11332.A second, downstream contributor to the symptom is that tools/scripts/compile_fortran_benchmark only resolves include directories from the manifest, while its C counterpart tools/scripts/compile_c_benchmark resolves include, src, libraries, and libpath. Patching only this wrapper might be too narrow, since it wouldn't address future Fortran-linking contexts that go through library-manifest.
Per office hours discussion, the fix should live in
@stdlib/utils/library-manifestso that Fortran source files are resolved uniformly when resolving a package's dependency tree, regardless of thetaskthe caller queried.Once the resolver is correct, downstream cleanup for the Fortran benchmark wrapper in
tools/scripts/should consume the resolved source list (mirroring its C counterpart), and the merged Fortran benchmark Makefiles' hardcodedSOURCE_FILESdefaults should match the C-benchmark Makefile convention.Related Issues
Related PRs #11332 and #11333.
Questions
No.
Demo
No response
Reproduction
Expected Results
Benchmark links successfully; xerbla resolves via the manifest dependency graph (
dger's manifest already lists@stdlib/blas/base/xerblaas a dependency undertask: 'benchmark'.Actual Results
Linker fails with an unresolved reference to xerbla. The dependency's
.fsource is never surfaced becauselibrary-manifestonly declares Fortran sources undertask: 'build'.Version
develop
Environments
N/A
Browser Version
No response
Node.js / npm Version
No response
Platform
Reproduces on any platform with gfortran + make (linux/macOS verified).
Checklist