[BUG] Fortran source files don't propagate through `library-manifest` dependency resolution outside `task: 'build'`
- Dominant language
- JavaScript
- Stars
- 6k
- Forks
- 1.3k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 611
Description
### 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](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/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](https://github.com/stdlib-js/stdlib/blob/develop/lib/node_modules/%40stdlib/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`](https://github.com/stdlib-js/stdlib/blob/develop/lib/node_modules/%40stdlib/blas/base/dger/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](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/daxpy/benchmark/fortran), [dscal](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/dscal/benchmark/fortran), [dasum](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/dasum/benchmark/fortran)) 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](https://github.com/stdlib-js/stdlib/pull/11332#issuecomment-4212459653).
A second, downstream contributor to the symptom is that [tools/scripts/compile_fortran_benchmark](https://github.com/stdlib-js/stdlib/blob/develop/tools/scripts/compile_fortran_benchmark) only resolves include directories from the manifest, while its C counterpart [tools/scripts/compile_c_benchmark](https://github.com/stdlib-js/stdlib/blob/develop/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
```shell
# 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
```shell
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
- [x] Read and understood the [Code of Conduct](https://github.com/stdlib-js/stdlib/blob/develop/CODE_OF_CONDUCT.md).
- [x] Searched for existing issues and pull requests.
Contributor guide
Research direction
Reproduce the failure from lib/node_modules/@stdlib/blas/base/dger/benchmark/fortran with make, then inspect @stdlib/utils/library-manifest and the dger and xerbla manifest.json files. Check tools/scripts/compile_fortran_benchmark and the merged Fortran benchmark Makefiles against the C benchmark path. Done means benchmark dependency resolution exposes xerbla's Fortran source without hardcoded sibling paths and the benchmark links successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fortran, javascript
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100