avh4 / elm-format

elm-format formats Elm source code according to a standard set of rules based on the official Elm Style Guide

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build darwin-arm64 release binaries

avh4 opened this issue · comments

I don't have my own M1 hardware to build on, so we're waiting for Github Actions to support M1.


Workaround

You can build your own darwin-arm64 binaries as follows:

TODO... You'll still need changes from #769 for this to work.

# Install ghcup <https://www.haskell.org/ghcup/>
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

# Install ghc
ghcup install ghc 9.0.2
ghcup set ghc 9.0.2

# Get elm-format source code
git clone https://github.com/avh4/elm-format
cd elm-format
git switch --detach 15578927a7fd327abd9c619031243c0abe96c57b

# Build elm-format
./build.sh -- build

The final binary will be ./_build/elm-format


Probably the easiest way to do this is to hope that github hosted runners get support for darwin-arm64, and we can build the binaries on CI.

External blockers:

Other notes:

keywords: arm

This issue is blocking even the possibility of github actions support: actions/runner-images#2187

I guess more importantly, this is blocked by ghc support for arm64: https://gitlab.haskell.org/ghc/ghc/-/issues/18664

I guess more importantly, this is blocked by ghc support for arm64:

This should be possible now with recent GHC versions. GHC 9.2.1-rc1 changelog mentions:

GHC 9.2 will bring a number of exciting features including:

A native code generation backend for AArch64, significantly reducing
compilation times on ARM platforms such as the Apple M1.

I think ghc 8.10.7 also supports arm64. (getting to ghc 9 will be additional work, see #725)

Is it worth considering homebrew as a way of distributing arm elm-format binaries? Brew is widely used, and supports building apple silicon "bottles".

There is an existing brew elm-format formula (https://github.com/Homebrew/homebrew-core/blob/master/Formula/elm-format.rb) but it currently depends_on arch: :x86_64.

I have tried updating this formula, but my experience building haskell packages is pretty limited, and I got myself into rather a tangle:

Does ghc need to be bumped to 9.0.2 as suggested by readme?

@mloughran GHC 8.10.7 is able to compile darwin-arm64 binaries.

GHC 8.10.7 is able to compile darwin-arm64 binaries.

@Janiczek Thanks, I saw that too – however the cabal.project file specifies ghc-8.10.4 at release 0.8.5, and the main branch has been updated to 9.0.2 (#768). When I compile I get pages of build errors – which may or may not be related to these issues – and I don't want to hijack this thread with Haskell build debugging! I suspect someone familiar with the Haskell toolchain could figure it out though :)

I'm not familiar with how homebrew works internally... Do you know which version of ghc it provides for folks that install ghc/haskell with homebrew?

elm-format-0.8.5 still used ghc 8.10.4, so I'd expect bumping that to 8.10.7 would probably work fine.

(Though the main branch uses ghc 9.0.2, and I'm expecting to update to ghc 9.2 or 9.4 before the next future release.)

I'm not familiar with how homebrew works internally... Do you know which version of ghc it provides for folks that install ghc/haskell with homebrew?

My understanding is that when building from source brew simply creates a tmp directory and executes the commands in the install method. In theory tools can simply install whatever build tools are required within that prefix, which is what this formula does. Of course in practice anything can happen – brew is no Nix!

elm-format-0.8.5 still used ghc 8.10.4, so I'd expect bumping that to 8.10.7 would probably work fine.

This seems promising. Running brew install --build-from-source elm-format with mloughran/homebrew-core@a36f62f fails at the build.sh step with https://gist.github.com/mloughran/d4e3467bfe9abe1f22eb78ce5c69142f. @avh4 any thoughts?

Hmm, looks like some of the dependencies are conflicting. A quick thing to try would be to have the brew script delete the cabal.project.freeze file

Ah, yeah, it's because ghc-8.10.7 uses a different version of base compared to ghc-8.10.4.

I made a branch that updates the freeze file https://github.com/avh4/elm-format/compare/ghc-8.10.7#diff-0b691f96fc8719139319225235e815688efd0423a88f3a397c994c05bf5a0c7c= but I think you could just have the brew script delete cabal.project.freeze and it should all work fine.

Oh, though if you're building with build.sh, then it might need a cabal.project.freeze file to exist, which after deleting it you can regenerate it with cabal freeze. Or alternatively you could build with cabal build instead of build.sh.

Thanks. Tried building with the ghc-8.10.7 branch, now getting the following build output: https://gist.github.com/mloughran/95d973a11228ae97dc9a6d9a4b28f89c. No idea what all the LLVM warnings are about. cabal build fails with something similar – https://gist.github.com/mloughran/b22d5c3aca1aeafb9c540fe6fc6357d4.

Not sure at this stage if the issue is my system or apple silicon... – brew formula changes at Homebrew/homebrew-core@master...mloughran:homebrew-core:elm-format-apple-silicon if anyone else wants to have a go!

Is that log from you running the brew formula locally? Or from brew's CI system?

I found this: https://haskell-cafe.haskell.narkive.com/WxaFromX/ghc-could-not-execute-opt which seems to match the "ghc: could not execute: opt" message. I guess you need brew install llvm and not just the llvm provided by XCode? (Though that's apparently the case for a long time, so I'm not sure why the previous brew formula didn't have the same issue)

Running brew install --build-from-source elm-format locally logs a file for each step in the build process.

Adding llvm as an explicit dependency was indeed required. Do the last few lines of https://gist.github.com/mloughran/c989268f0445785127fbb9cbc6f96e10 make any sense to you?

Oh, yep, I guess I gave bad advice before... cabal: can't find source for Build_elm_format in src, generated that file is normally generated based on the current git commit:

Does homebrew actually clone the real git repo at the given tag?
If so, then doing ./build.sh generated/Build_elm_format.hs should work to generate it (will require git to be available on the PATH) -- or, in contrast to what I said before, I guess it would be simpler to do ./build.sh _build/elm-format instead of cabal build so it will generate it automatically.

If homebrew doesn't actually clone the git repo, then you can echo -n "module Build_elm_format where\ngitDescribe :: String\ngitDescribe = \"0.8.5\"" > generated/Build_elm_format.hs (or ideally interpolate the current version number for 0.8.5).

Here's some addition to the workaround building M1 binary on my local M1 machine.

To fix ffitarget_arm64.h related error while running ./build.sh -- build

export C_INCLUDE_PATH="`xcrun --show-sdk-path`/usr/include/ffi"

To fix unhandled operating system: ("darwin","aarch64") error, edit Shakefiles/Platform.hs file on line 22

platform :: Platform
platform =
    case (System.Info.os, System.Info.arch) of
        ("linux", "x86_64") -> Linux
        ("darwin", "x86_64") -> Mac
        ("darwin", "aarch64") -> Mac             -- Add this line
        ("osx", "x86_64") -> Mac
        ("mingw32", "x86_64") -> Windows
        ("win32", "x86_64") -> Windows
        other -> error ("unhandled operating system: " ++ show other)

To add up @avh4 's original comment,

# Install ghcup <https://www.haskell.org/ghcup/>
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

# Install ghc
ghcup install ghc 9.0.2
ghcup set ghc 9.0.2

# Install cabal
ghcup install cabal 

# Get elm-format source code
git clone https://github.com/avh4/elm-format
cd elm-format
git switch --detach 15578927a7fd327abd9c619031243c0abe96c57b

# set C_INCLUDE_PATH so that cabal is able to find 'ffitarget_arm64.h'
export C_INCLUDE_PATH="`xcrun --show-sdk-path`/usr/include/ffi"

# edit Shakefiles/Platform.hs so platform function can handle ("darwin", "aarch64")

# Build elm-format
./build.sh -- build 

Then, I could have _build/elm-format binary which is ~4 times faster than the x86 binary.

Thanks to self-hosted runners provided by Lamdera, this has been implemented in #784

A resulting binary of the current development branch can be found at the bottom of this page: https://github.com/avh4/elm-format/actions/runs/4140939854

(If anyone wants to pursue distribution of elm-format through other package managers, such as homebrew, please open a new issue for that.)