Skip to content

Build from source on Linux ARM64 too - #61

Merged
perazz merged 3 commits into
fortran-lang:mainfrom
kunalKumar-13:fix/60-linux-arm64-source-fallback
Oct 5, 2026
Merged

perazz merged 3 commits into
fortran-lang:mainfrom
kunalKumar-13:fix/60-linux-arm64-source-fallback

Conversation

@kunalKumar-13

Copy link
Copy Markdown
Contributor

Answering the question in #60 — "shouldn't there be an automatic fallback to build from source, and if so why isn't that working?"

There is one, and it is gated on macOS:

if (process.platform === 'darwin' && arch === 'arm64') {

So on an ARM64 Linux runner it never runs. fpm publishes no linux-arm64 asset — confirmed against the v0.13.0 release, which has linux-x86_64, macos-arm64, macos-x86_64 and windows-x86_64 and nothing else — so all six URLs the action tries return 404, on real hardware:

404  fpm-0.13.0-linux-arm64
404  fpm-0.13.0-linux-arm64-gcc-10 .. gcc-14

and the action stops with Error while trying to fetch fpm - please check that a version exists at the above release url, which points at the version rather than at the missing architecture.

What this changes

install.sh makes no assumption about the platform beyond a POSIX shell and a Fortran compiler — no uname, no OS branching — it bootstraps from the single-file fpm-0.8.0.F90 and builds the requested version with it. The same fallback that serves macOS ARM64 serves Linux ARM64, so the gate is widened to cover it and the messages now name the platform they are running on instead of hardcoding macOS and brew.

It also adds a return after that setFailed. Execution carried on to path.dirname(fpmPath) with fpmPath still undefined, so the real reason was buried under a second, unrelated error — visible in the screenshot on the issue:

The "path" argument must be of type string. Received undefined

Verification

Run on an Ubuntu 26.04 aarch64 VM by executing the action itself, not a simulation of it:

result
main exit 1, no fpm, both errors above
this branch exit 0, No pre-built linux-arm64 binary found, falling back to building from source, fpm installed and added to path at ~/.local/bin

The installed binary is ELF 64-bit LSB pie executable, ARM aarch64, reports Version: 0.13.0, alpha, and fpm new demo --app && fpm run prints hello from project demo.

macOS ARM64 is unaffected — checked on an arm64 Mac, where fpm-0.13.0-macos-arm64-gcc-12 still downloads and the fallback is never reached.

The new Test-linux-arm64 job covers this on ubuntu-24.04-arm. I kept it out of the main matrix and pinned it to one version, because each run compiles fpm and multiplying it across the seven versions would be a lot of CI time for the same signal — happy to fold it into the matrix instead if you would rather have the coverage.

Note this does not remove the need for fortran-lang/fpm#1282; a published linux-arm64 binary would still be faster than building. This makes the runner work in the meantime.

Fixes #60

fpm publishes no linux-arm64 release asset, so on an ARM64 Linux runner
every download the action tries returns 404 -- the bare filename and all
five compiler-suffixed ones. The build-from-source fallback that would
cover this was gated on 'process.platform === darwin', so it never ran
and the action failed with

    Error while trying to fetch fpm - please check that a version exists
    at the above release url.

which points at the version, not at the missing architecture.

install.sh makes no assumption about the platform beyond a POSIX shell
and a Fortran compiler -- it bootstraps from the single-file fpm-0.8.0.F90
and builds the requested version with it -- so the same fallback serves
Linux ARM64. Widen the gate to cover it and make the messages name the
platform they are running on rather than hardcoding macOS.

Also return after that setFailed. Execution used to carry on to
path.dirname(fpmPath) with fpmPath undefined, so the real reason was
buried under a second, unrelated error:

    The "path" argument must be of type string. Received undefined

Verified on an Ubuntu 26.04 aarch64 VM by running the action itself:

  before  exit 1, no fpm, both errors above
  after   exit 0, falls back, fpm 0.13.0 built and added to the path,
          'fpm new demo --app && fpm run' prints hello from project demo

macOS ARM64 is unaffected: its release asset exists, so it still takes
the download path and never reaches the fallback.

The new job covers this on ubuntu-24.04-arm. It is separate from the
matrix, with one version, because each run compiles fpm.

Fixes fortran-lang#60

@bonachea bonachea left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this!

Some minor suggestions for improvement on the implementation..

Comment thread .github/workflows/test-workflow.yml Outdated
Comment on lines +59 to +65
Test-linux-arm64:
runs-on: ubuntu-24.04-arm
strategy:
fail-fast: false
matrix:
fpm-version: ["v0.13.0"]
node-version: ["24.x"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you've cloned the entire job, mostly for the purpose of adding a single job to the matrix. This is probably unnecessary, as it's likely better to just add the single job and keep the rest of the job step factored.

You can do this using the jobs.<job_id>.strategy.matrix.include syntax. The code you want in the step above is something like this:

--- a/.github/workflows/test-workflow.yml
+++ b/.github/workflows/test-workflow.yml
@@ -10,10 +10,17 @@ jobs:
       matrix:
         os: [ubuntu-latest, macos-14, macos-15, windows-latest]
         fpm-version: ["v0.9.0", "v0.10.1", "v0.11.0", "v0.12.0", "v0.13.0", "latest", "current"]
         node-version: ["24.x"]
 
+        include:
+          # There is no linux-arm64 release asset, so every download in the action fails
+          # on this runner and only the build-from-source fallback can install fpm. Kept
+          # as a separate job with one version, because each run compiles fpm. See #60.
+          - os: ubuntu-24.04-arm
+            fpm-version: "v0.13.0"
+
     steps:
       - name: Checkout
         uses: actions/checkout@v5
 
       - name: Use Node.js ${{ matrix.node-version }}

Comment thread .github/workflows/test-workflow.yml Outdated
Comment on lines +76 to +79
- name: Install gfortran
run: |
sudo apt-get update
sudo apt-get install -y gfortran-13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully this step is not actually necessary?

The Ubuntu2404-Arm64 runner already includes:

GNU Fortran: 12.4.0, 13.3.0, 14.2.0

The MacOS system setup step above to install gcc@12 is to fix a missing library dependency needed by the fpm binary on the macos runners, it has (almost) nothing to do with building from source.

Comment thread index.js Outdated
// fails. install.sh makes no assumption about the platform beyond a
// POSIX shell and a Fortran compiler, so the same fallback that serves
// macOS ARM64 serves Linux ARM64 too. See issue #60.
if ((process.platform === 'darwin' || process.platform === 'linux') && arch === 'arm64') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this still conditional on platform?

IIUC If the binary downloads above already failed, that means we either build from source here or the entire action is going to fail.

IMO remove the platform gating entirely here. That makes the action more future-proof against changes in the fpm binary assets.

Suggested change
if ((process.platform === 'darwin' || process.platform === 'linux') && arch === 'arm64') {

… gate

Three changes from @bonachea's review.

Use strategy.matrix.include for the linux-arm64 runner instead of a
second copy of the job. node-version is restated in the include entry:
ubuntu-24.04-arm is not in the os list, so the entry cannot merge into an
existing combination and instead becomes a new one carrying only the keys
named there -- without it, matrix.node-version is empty for that job.

Drop the gfortran install step. The Ubuntu2404-Arm64 image already ships
GNU Fortran 12.4.0, 13.3.0 and 14.2.0, so it was doing nothing. The macOS
gcc@12 step is unrelated -- that one fixes a runtime library the released
binary links against, not a build.

Remove the platform gate on the source fallback. Once every download has
failed it is build from source or fail outright, so the gate could only
turn a possible success into a certain failure. Nothing about install.sh
is macOS- or Linux-specific, and installFromSource already reports a clear
error when no suitable gfortran is present.

Folding the job also drops its 'fpm new demo && fpm run' step, so the
matrix now runs 'fpm --version' for every combination instead. That keeps
the arm64 job proving the built binary actually executes, rather than only
that the action exited 0.
@kunalKumar-13

Copy link
Copy Markdown
Contributor Author

Thanks — all three taken, and the matrix one was clearly right; I'd cloned the job rather than thinking about include.

Folding into the matrix. Done, with one addition to your diff: I had to restate node-version in the include entry. ubuntu-24.04-arm isn't in the os list, so the entry can't be merged into an existing combination without overwriting os, and GitHub instead creates a new combination carrying only the keys named in the entry. matrix.node-version would have been empty for that job and actions/setup-node would have got a blank version. Restating it is the smallest fix; flagging it because it's easy to miss.

The gfortran step. You're right, gone. I'd pattern-matched it off the macOS step without checking the runner image, and as you say that one is about a runtime library the released binary links against, not about building. Ubuntu2404-Arm64 ships 12.4.0, 13.3.0 and 14.2.0 already.

The platform gate. Also gone. Your reasoning holds: by the time we reach that branch every download has failed, so the gate could only convert a possible success into a certain failure. And installFromSource already fails with a clear message when it can't find a usable gfortran, so removing the gate doesn't make a bad platform any more confusing than it was.

One thing to flag, since it's the one place I didn't simply follow the suggestion. Folding the job also removed its fpm new demo --app && fpm run step, which was the only thing proving the source-built binary actually executes — without it the arm64 job only shows the action exited 0. Rather than special-casing a step for one matrix entry, I added fpm --version for every combination:

      - name: Check that fpm runs
        run: fpm --version

That does mean 28 existing jobs now run a check they didn't before. I think that's a fair trade for a one-line universal smoke test, but it's your call — happy to gate it to the arm64 entry, or restore the fuller demo build there, if you'd rather keep the change narrow.

@bonachea bonachea left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for the improvements!

To clarify, I'm not a maintainer of this action, I'm the user who originally reported the problem in #60. But I'm very happy to see a potential fix!

Now we need workflow approval and review from a maintainer, perhaps @perazz ?

@kunalKumar-13

Copy link
Copy Markdown
Contributor Author

Thanks — and thanks for pushing back on the first version, the matrix suggestion in particular was clearly the right shape.

Confirming the state so a maintainer knows exactly what's needed rather than having to work it out: the Test workflow has two runs against this branch, both sitting at action_required:

completed / action_required   Test   2026-09-07T20:07
completed / action_required   Test   2026-09-10T21:42

So nothing has actually executed yet — this is the first-time-contributor gate, not a failure. Someone with write access needs to approve the run before there's any CI signal at all, and that includes the new ubuntu-24.04-arm matrix entry, which is the whole point of the change and the one job I can't verify locally.

I won't re-ping since you've already tagged @perazz. Happy to rebase or split it if that makes review easier.

@bonachea

Copy link
Copy Markdown

So nothing has actually executed yet — this is the first-time-contributor gate, not a failure. Someone with write access needs to approve the run

I agree a maintainer of this repo needs to approve the workflow before the pull_request event will run CI.

before there's any CI signal at all, and that includes the new ubuntu-24.04-arm matrix entry, which is the whole point of the change and the one job I can't verify locally.

This part is inaccurate: the CI has already run on your branch within your Github fork for the push action, where we can see the new entry is working as intended.

@kunalKumar-13

Copy link
Copy Markdown
Contributor Author

You're right, and I should have looked at my own fork's runs before saying that. Thanks for the correction.

The push run does cover it, and it covers more than I'd credited — the ARM64 job exercises the whole path end to end:

21:42:45  No pre-built linux-arm64 binary found, falling back to building from source
21:49:17  Run fpm --version
21:49:17  Version:     0.13.0, alpha

So on ubuntu-24.04-arm every download fails, installFromSource runs, and about six and a half minutes later there is a working fpm on PATH. That is the change working, not just compiling — which is what the Check that fpm runs step was added for.

One thing that is genuinely still unverified, and I don't want to overstate this one either: only v0.13.0 runs on ARM, deliberately, since each ARM job builds from source. The old-version guard (< v0.9.0 → setFailed) has no ARM coverage. It's shared with the macOS ARM64 path that was already there and I didn't change its logic, only its message, so I left it at one entry rather than adding six more source builds to every run. Happy to add a v0.8.x ARM entry if you'd rather see that branch exercised too.

The pull_request runs still need a maintainer to approve them, but that's a formality now rather than the only signal.

@bonachea

Copy link
Copy Markdown

OK someone approved the pull_request action on Sept 11, which completed successfully, including the new Linux+ARM job.

Now we just need someone with repo write access to press the "Merge" button.

@perazz would you please do the honors? 😃

@perazz perazz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM except the above comment, than you @kunalKumar-13 @bonachea

Comment thread .github/workflows/test-workflow.yml Resolved
@bonachea

bonachea commented Oct 1, 2026

Copy link
Copy Markdown

@kunalKumar-13 why did you close this PR unmerged?

I believe the user-facing need addressed by this PR remains this unresolved, and this appears to be the correct approach...

@kunalKumar-13

Copy link
Copy Markdown
Contributor Author

sorry, shouldn't have closed this, reopening. @perazz no known issue with older versions on arm, i only ran 0.13.0 there to keep ci short since every arm job builds from source. i'll add it to the matrix and see if the older ones build.

@kunalKumar-13 kunalKumar-13 reopened this Oct 2, 2026

@bonachea bonachea left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@perazz please confirm this PR now satisfies your expressed concern?

@perazz
perazz merged commit eef8f4a into fortran-lang:main Oct 5, 2026
35 checks passed
perazz added a commit to fortran-lang/fpm that referenced this pull request Nov 10, 2026
Add an ubuntu-24.04-arm gcc 14 row named linux-arm64, built with the
same static release flags as linux-x86_64, so that
fpm-<version>-linux-arm64-gcc-14 is uploaded with the other gcc 14
artifacts and setup-fpm finds it on Linux arm64 runners.

fpm v0.13.0 has no linux-arm64 asset, so the bootstrap relies on the
build-from-source fallback in fortran-lang/setup-fpm#61, which is on
setup-fpm main but not yet in a release; pin that commit for now.

Also check that the Linux --static release binaries really are static.

Fixes #1282
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

setup-fpm fails on Linu/ARM64

3 participants