Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack for Linux AArch64 (ARM64) #5709

Closed
dboreham opened this issue Apr 12, 2022 · 53 comments
Closed

Stack for Linux AArch64 (ARM64) #5709

dboreham opened this issue Apr 12, 2022 · 53 comments

Comments

@dboreham
Copy link

Apologies, I see from the history that this has come up again and again. I'd like to understand the state of Stack for ARM64. I'm attempting to use Ubuntu rather than macos.

When I follow the batteries included instructions I get this:

$ curl -sSL https://get.haskellstack.org/ | sh
Detected Linux distribution: ubuntu

Sorry, currently only 64-bit (x86_64) Linux binary is available.

But I can see from various issues and posts that there is a GHC for ARM64, and there's even a CI job for Stack on ARM64: https://github.com/commercialhaskell/stack/actions/workflows/arm64-release.yml and also binary packages shipped in this release : https://github.com/commercialhaskell/stack/releases/tag/v2.7.1 (although internet lore claims they don't work).

I suppose I'm wondering what's the gap between the things that exist and get.haskellstack.org working above? Is there a mailing list, forum or somewhere that I can read to catch up? Also if I can help or contribute to make this happen I'm happy to do that. Thanks, hope this makes sense.

@dboreham
Copy link
Author

Small update. I tried the stack aarch64 binary in release 2.7.1. It runs, but only as far as:

$ stack build
Unable to find installation URLs for OS key: linux-aarch64-tinfo6

@dboreham
Copy link
Author

dboreham commented Apr 13, 2022

Well it turns out: we can have nice things after all.

After some poking around in the stack source, I was able to persuade it to build GHC from source using the binary from release 2.7.1.

The resulting newborn stack was able to successfully run stack upgrade and then succeeded in creating, building and running the hello world project:

$ uname -a
Linux ip-172-31-59-241 5.13.0-1021-aws #23~20.04.2-Ubuntu SMP Thu Mar 31 11:41:36 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux
$ stack exec helloworld-exe
someFunc

@dboreham
Copy link
Author

I'm not sure if this issue should be resolved with a doc fix (tell users which dependencies need to be present on the system in order to motivate stack to build GHC itself vs bailing out); or if the fix is to arrange for the appropriate pre-built binaries to be available for download.

@dboreham
Copy link
Author

For posterity these are the dependencies I found were necessary on a stock Ubuntu 20 system:

sudo apt install build-essential libnuma1 libnuma-dev libtinfo-dev libtinfo5 libtinfo6 libc6-dev
sudo apt install llvm*
sudo apt install clang ninja-build
sudo apt install zlib1g-dev
sudo apt install libgmp-dev

I found some of these from this thread: https://discourse.haskell.org/t/using-stack-on-raspberry-pi/2363/15

@hasufell
Copy link
Contributor

ghcup provides aarch64 stack binaries.

@dboreham
Copy link
Author

ghcup provides aarch64 stack binaries.

Good to know! Note that as a clueless bystander a) I didn't know ghcup existed, and b) even if I did, its web page doesn't say it provides stack.

Would it make sense to update one or more of the various doc pages to help folks looking for arm support?
Note for example that this page : https://www.haskell.org/downloads/ directs you to here: https://docs.haskellstack.org/en/stable/install_and_upgrade/ for stack (which will fail), and not to ghcup, even though apparently ghcup is what you'd really want to use.

@ConnorWidtfeldt
Copy link

Are you sure it supports aarch64 stack binaries? The table on the landing page for GHCup has Stack crossed out for any aarch64 or armv7 platforms.

@dboreham
Copy link
Author

Perhaps I should ask another question, again as a clueless outsider: if the binaries can be made (I made them myself), and the install code does a check for binaries being available, what would it take to get said binaries put in the place where it's looking for them?

@hasufell
Copy link
Contributor

Are you sure it supports aarch64 stack binaries? The table on the landing page for GHCup has Stack crossed out for any aarch64 or armv7 platforms.

Yes, I am sure. The table is outdated: https://github.com/haskell/ghcup-metadata/blob/88696a0cc5ebb8fe5b15662f6a840be7c1cdd699/ghcup-0.0.7.yaml#L3071

@mpilgrem
Copy link
Member

The ARM64/AArch64 stack CI has suddenly started failing with commit 75f3170. I can't work out why. Given the changes in the commit, I find it hard to believe it is the changes. I've tried re-running the job a number of times, and it does not seem to be something ephemeral. I am not familar with ARM64 (or Unix-like operating systems). Can anyone assist? The logs seem to suggest that something is running out of resources part way through the building of stack - excerpt below:

2022-05-14T15:34:03.3116720Z Preprocessing library for stack-2.7.6..
2022-05-14T15:34:03.6411478Z Building library for stack-2.7.6..
2022-05-14T15:34:04.4718548Z [  1 of 110] Compiling Network.HTTP.StackClient
2022-05-14T15:34:06.7978437Z [  2 of 110] Compiling Path.Extended
...
2022-05-14T15:35:35.0126412Z [ 41 of 110] Compiling Stack.Types.Config
2022-05-14T15:36:35.7243522Z ##[warning]You are running out of disk space. The runner will stop working when the machine runs out of disk space. Free space left: 92 MB
2022-05-14T15:36:51.2363565Z [ 42 of 110] Compiling Stack.Types.Package
...
2022-05-14T15:37:02.2103815Z [ 49 of 110] Compiling Stack.Config.Docker
2022-05-14T15:42:33.9976151Z /tmp/ghc787_0/ghc_581.ll: hClose: resource exhausted (No space left on device)
2022-05-14T15:42:34.5648020Z Completed 5 action(s).
2022-05-14T15:42:34.5732724Z 
2022-05-14T15:42:34.5733772Z --  While building package stack-2.7.6 (scroll up to its section to see the error) using:
2022-05-14T15:42:34.5737925Z       /src/.stack-work/dist/aarch64-linux/Cabal-3.2.1.0/setup/setup --builddir=.stack-work/dist/aarch64-linux/Cabal-3.2.1.0 build lib:stack exe:stack exe:stack-integration-test --ghc-options ""
2022-05-14T15:42:34.5738898Z     Process exited with code: ExitFailure 1

@hasufell
Copy link
Contributor

I don't think github actions currently provides M1 ARM64 machines for darwin, so this is probably a private runner. Whoever administers it, should probably be notified.

@mpilgrem
Copy link
Member

@hasufell, thank you. I now understand the significance of runs-on: [self-hosted, linux, ARM64] in the arm64-release.yml file, and I have read this: https://docs.github.com/en/actions/hosting-your-own-runners. @snoyberg, if it is not you that administers the self-hosted runner for ARM64 on commercialhaskell, do you know who does?

@snoyberg
Copy link
Contributor

I cleaned up old Docker images and set a cron job to prune them automatically, that should fix it. I'd be happy if someone else is interested in maintaining the build machines, in this case we have an Oracle Cloud ARM machine running.

@hasufell
Copy link
Contributor

An alternative would be to maintain CI on GHC gitlab as well, which has runners for all platforms that GHC itself supports. I've done so in a branch here: https://gitlab.haskell.org/maerwald/stack/-/tree/717ec96c15520748f3fcee00f72504ddccaa30b5/.gitlab

I've had some issues getting certain tests to pass there, but with a little bit of work, this could be done. Since the gitlab instance is getting a full-time devops soon, this would be low-maintenance. But YMMV.

@snoyberg
Copy link
Contributor

I don't care if someone else wants to maintain a CI on GitLab, but I have no desire to try to maintain that myself.

@hasufell
Copy link
Contributor

I don't care if someone else wants to maintain a CI on GitLab, but I have no desire to try to maintain that myself.

Well, I wouldn't mind investing some more time in it. We're now building haskell-language-server on gitlab CI as well and let a github actions job pull the release artifacts.

The question is rather if you're on board with that if it works well.

@snoyberg
Copy link
Contributor

I don't know what you're asking me. Anyone is free to run a CI system for Stack anywhere they want. It sounds like you're asking for some sign-off on some decision, but I don't know what that is.

@hasufell
Copy link
Contributor

I don't know what you're asking me. Anyone is free to run a CI system for Stack anywhere they want. It sounds like you're asking for some sign-off on some decision, but I don't know what that is.

Whether stack upstream is interested to use GHC gitlab CI to create the official stack bindists.

@snoyberg
Copy link
Contributor

I'd prefer using the GitHub Actions if it's working, though we've always been open to contributions from elsewhere for bindists we don't support. If there are issues with the GitHub Actions in the future, I'm sure whoever's managing a release would be consider a GHC CI-generated executable.

@dboreham
Copy link
Author

Circling back on this one: I think that the underlying problem is that since 2.7.1 there has been no binary built for aarch64 targets. Conversation above seems to suggest this was due to build machine hoarkage, which has since been resolved. Does that mean that whenever the next release (after the latest 2.7.5) is spun, it should have an aarm64 binary?

Apologies, I'm somewhat familiar with GH actions, but not enough to know if there's a way to re-spin an old release for some targets that failed on the initial invocation.

@semihalf-mazur-hubert
Copy link

Hi, is there anything more that should be done to have arm64 binary for linux in next release?

@mpilgrem mpilgrem mentioned this issue Aug 13, 2022
@dewijones92
Copy link

Hello, just wondering if this has been resolved? I am getting
Unable to find installation URLs for OS key: linux-aarch64-tinfo6

thanks

@mpilgrem
Copy link
Member

@dewijones92, I don't know if this assists in the interim, but the arm64-release.yml GitHub workflow named ARM64 (AArch64) Release produces an artifact named 'Linux-ARM64. That .zip file contains stack-2.7.6-linux-aarch64.tar.gzand, in that archive seems to be astack` executable. I assume that has been built with the GHC at https://downloads.haskell.org/~ghc/9.2.4/ghc-9.2.4-aarch64-deb10-linux.tar.xz.

If it does help, that would be good to know.

@dewijones92
Copy link

@mpilgrem thanks but I can't find the stack exe in that tar you sent me
I am willing to help you with regards to #5733 (comment)
I have linux + docker exp

@mpilgrem
Copy link
Member

@dewijones92 Thanks for the offer of help with making a release.

On Linux-ARM64.zip, I have:

Linux-ARM64.zip\stack-2.7.6-linux-aarch64.tar.gz\stack-2.7.6-linux-aarch64.tar\stack-2.7.6-linux-aarch64\stack`

with size ~ 66 MB. Is that not the stack executable you are looking for?

@dboreham
Copy link
Author

I'm not sure if this is relevant to the recent posts here, but I'm the OP and I wanted to clarify that this issue is about the failure of the "instructions most laypeople end up finding for installing a Haskell dev environment" on aarm64 machines. It's not that you can't find the binary somewhere, somehow (for example I was able eventually to build it myself). The problem is that supposedly folks don't need to build the binary, find it under a rock, or whatever. They're expecting to get everything installed by running one shell script.

@dewijones92
Copy link

@dboreham
This will rectify this situation :D #5733 (comment)

@mpilgrem
Copy link
Member

@dboreham, for my part, that objective is fully understood. What would help me is to know that the GitHub workflow is, indeed, building something that will be of use to AArch64 users.

@libweirdness
Copy link

Thank you for replying!

My brain is down, atm, ( maintenance? : )

so I'll work at understanding this properly , later.

However, Stack got installed when I used GHCup,
and so there is no, that I know-of, distro-wide ANYthing for Haskell,
including Stack,
it's all under my user homedir.

There was a config.yaml..

here, I'll go look this up, so I'm not blathering idiocy at the whole world,
ok?

...

There is nothing, dir or file, under /etc/, with "stack" as a substring.

"$ stack path --stack-root
Aeson exception:
Error in $: parsing Locked failed, expected Object, but encountered Null"

This Aeson exception stuff began appearing after I cloned the "hindent" git repo,
& tried building it in its repo-directory.

( maybe I should just rip-out my entire linux-install, & begin clean, yet again? )

~/.stack/config.yaml

was a zero-byte file,
& blocked Stack from working,
until I edited it to contain a comprehensible line.

Then there was another file in there,
that also was zero-byte,
& also blocking Stack...

...bash history had it:

~/.stack/global-project/stack.yaml

...

I'll get back to this when I'm awake-enough to no-longer be dull-as-a-rock,
but this info should correct a couple assumptions.

Doh!

I gave-up on trying Stack,
& later it dawned on me that maybe Cabal might work?

So, I tried that,
& there were undefined references in base-4.17 to several functions who all began with
numa-*
and, iirc, numa is architecture-specific ( Non Uniform Memory Access ),
and came into our concerns when
AMD began putting RAM controllers on CPU's,
instead of chipset northbridges,
years ago.

IF Haskell's base-4.17 is borked on all ARM CPU's,
& I've seen problems for Apple M1 based machines described,
Raspberry Pi & competitors,
& me in Termux Android Void-Linux, too,
then there is an absence of several functions right in Haskell Base library,
such that "happy-", on-which "hindent" depends,
cannot be built.

Again, not awake yet, brain is dull rock,
will connect later,
& thank you for investing in helping, eh?

🙏

@mpilgrem
Copy link
Member

@libweirdness, we may to start from scratch. This is partly a 'voyage of discovery' for me too. You need three things to use Stack:

  1. the existence of at least one version of GHC built for your operating system (Linux), machine architecture (AArch64) and 'system variant' (more on that below);
  2. the Stack executable for your operating system and machine architecture on the PATH; and
  3. the Stack (in step 2) needs to know how to find/obtain the GHC (in step 1).

On 'system variant', Stack.Setup.getGhcBuilds includes this code:

 hastinfo5 <- checkLib relFileLibtinfoSo5
 hastinfo6 <- checkLib relFileLibtinfoSo6
 hasncurses6 <- checkLib relFileLibncurseswSo6
 hasgmp5 <- checkLib relFileLibgmpSo10
 hasgmp4 <- checkLib relFileLibgmpSo3
 let libComponents = concat
   [ [["tinfo6"] | hastinfo6 && hasgmp5]
   , [[] | hastinfo5 && hasgmp5]
   , [["ncurses6"] | hasncurses6 && hasgmp5 ]
   , [["gmp4"] | hasgmp4 ]
   ]

From that code extract, I understand you can use (a) the 'standard' GHC variant ([]) if your system has the libtinfo.so.5 and libgmp.so.10 libraries installed and (b) the 'tinfo6' GHC variant (["tinfo6"]) if your system has libtinfo.so.6 and libgmp.so.10. From the error message Unable to find installation URLs for OS key: linux-aarch64-tinfo6 I suspect your system is not currently set up to use the 'standard' GHC variant. That may be a dead end for you, unless (a) your system can be altered to include the missing libraries for a 'standard' set up or (b) GHCup supplies variants of GHC that the GHC developers themselves to do not provide. (I do not know what GHCup can supply on Linux.)

In respect of obtaining a Stack executable for your operating system and architecture, again I do not know what GHCup can supply. However, I do know that the Stack GitHub workflow is currently likely building such executables and providing the binary Stack as an artifact. See my comment at #5709 (comment) and the discussion that led up to it.

You may have a 'corrupt' config.yaml file. Starting from scratch, it would be a good idea to delete the ~/.stack directory. Stack will recreate that directory when it is first run. Stack will recreate things that are missing but will not fix corrupted things.

The Stack executable can be put anywhere on your PATH. However, a good place to put it on Unix-like operating systems is $HOME/.local/bin (see https://docs.haskellstack.org/en/stable/install_and_upgrade/#path).

In respect of Stack knowing where to find GHC, there are two alternative aspects of that: (1) Stack finding and obtaining GHC itself. At the moment, it can only find linux-aarch64 for GHC 9.0.2 (and other versions of GHC before that) (that is, the 'standard' variant); and (2) Stack making use of a version of GHC already on the PATH (referred to as a 'system' GHC).

To tell Stack to use a version of GHC already on the PATH, you need to pass to Stack the --system-ghc flag. Of course, that version of GHC on the path has to be consistent with what you are asking Stack to do. If you tell Stack to use resolver: lts-19.19 for example, it will need access to GHC 9.0.2.

Finally, I would add that if you have questions 'how do I get and use Stack?' you are more likely to get a quicker and fuller answer on the Haskell Community. Help is available here too, but the people who gather here are more interested in problems that are solved by changes to Stack's code base.

@libweirdness
Copy link

ok, the "tinfo" problem is fixed ( yesterday, for me ), by a distro-package.

I'll look up what that was...

ncurses-libtinfo-devel
needed to be installed.

GHCup installed a ghci, ghc, cabal, & stack, together,
and ghci I use, daily, in learning Haskell.

$ find /usr -name "libtinfo*"
/usr/lib/libtinfo.so.6
/usr/lib/libtinfo.so
/usr/lib/libtinfo.so.6.3
( the tinfo-devel package I didn't have installed, until after Stack proved to be problematic,
btw )

$ find /usr -name "libgmp*"
/usr/lib/libgmp.so
/usr/lib/libgmp.so.10.4.1
/usr/lib/libgmp.a
/usr/lib/libgmp.so.10

OK, deleting my ~/.stack/
dir...

it created a ~/.stack/ dir, with exactly 1 file in it, config.yaml, that is zero bytes.

It is Stack, itself, then, that is creating the broken config.yaml, on aarch64.

giving you this, now, to keep you in the loop.

I'll try understanding the rest of what's above, later.

( :

@libweirdness
Copy link

Oh:

ghc 8.10.7

and when I tried installing hindent with Stack ( which borked somethng, somehow, when I tried building the cloned git repo of hindent )
it got something done, before breaking.

cabal install hindent

got up until happy-
and some other package,
all sorts of things compiled,
but base-4.17 has undefined references in it, to several numa- functions,
so base is missing some aarch64 specific code.

cabal is version 3.6.2.0

I realized, finally, that aeson is borked, completely,
& that running

cabal install aeson

might fix that: it is now running, completing many builds, in the process...

@mpilgrem
Copy link
Member

@libweirdness, that is frustrating. I am reaching the limits of what I can do to help - I think it will need somebody who has access to a AArch64 machine to take things forward. Clearly something is preventing Stack from writing a config.yaml file with the contents of Stack.Config.defaultConfigYaml to disk, the writing happens in Stack.Config.getDefaultUserConfigPath.

@dboreham
Copy link
Author

fwiw when I did some testing of this issue a while back I was able to use the lowest level ARM EC2 instance on AWS for a few hours, assuming the problem is reproducible on one of the Linuxen they provide.

@semihalf-mazur-hubert
Copy link

Hi, I managed to build a docker image with haskell stack, where the config is not an empty file like mentioned in this issue.
Let me explain the steps I took.
Firstly I modified the Dockerfile a little, see a diff:

diff --git a/9.2/buster/Dockerfile b/9.2/buster/Dockerfile
index ae5c645..e05da66 100644
--- a/9.2/buster/Dockerfile
+++ b/9.2/buster/Dockerfile
@@ -1,4 +1,4 @@
-FROM buildpack-deps:buster
+FROM buildpack-deps:bullseye
 
 ENV LANG C.UTF-8
 
@@ -8,7 +8,7 @@ RUN apt-get update && \
         libtinfo-dev && \
     rm -rf /var/lib/apt/lists/*
 
-ARG STACK=2.7.5
+ARG STACK=2.7.1
 ARG STACK_RELEASE_KEY=C5705533DA4F78D8664B5DC0575159689BEFB442
 
 RUN set -eux; \
@@ -22,7 +22,8 @@ RUN set -eux; \
             # Stack does not officially support ARM64, nor do the binaries that exist work.
             # Hitting https://github.com/commercialhaskell/stack/issues/2103#issuecomment-972329065 when trying to use
             # stack-2.7.1-linux-aarch64.tar.gz
-            INSTALL_STACK="false"; \
+            #INSTALL_STACK="false"; \
+            STACK_SHA256='ac4bd34250bd8e397aca05fba1785da0642bf5bac388ccf6643e4ba1fa98ae46' \
             ;; \
         'x86_64') \
             STACK_SHA256='9bcd165358d4dcafd2b33320d4fe98ce72faaf62300cc9b0fb86a27eb670da50'; \
@@ -35,9 +36,9 @@ RUN set -eux; \
         \
         curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc; \
         GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \
-        gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY"; \
-        gpg --batch --verify stack.tar.gz.asc stack.tar.gz; \
-        gpgconf --kill all; \
+        #gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY"; \
+        #gpg --batch --verify stack.tar.gz.asc stack.tar.gz; \
+        #gpgconf --kill all; \
         \
         tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack"; \
         stack config set system-ghc --global true; \

Build ends up successfully and when running the image, the config file under ~/.stack/config.yml contains a minimal configuration:

templates:
  params: null
system-ghc: true
install-ghc: false

Also I installed packages mentioned before - without them, there was missing linux-aarch64-tinfo:

apt install build-essential libnuma1 libnuma-dev libtinfo-dev libtinfo5 libtinfo6 libc6-dev llvm* clang ninja-build zlib1g-dev libgmp-dev

Next I tried to build a helloworld project - builds and works fine and a custom one taken from github.
I didn't observed any issues, like zero sized config file. Am I missing something in reproducing this issue?
The stack seems to work just fine under arm64.

@mpilgrem
Copy link
Member

mpilgrem commented Sep 5, 2022

I have (I hope) followed the instructions accurately and published a first release candidate for Stack 2.9.1, including bindists for Linux AArch64. See: https://discourse.haskell.org/t/ann-first-release-candidate-for-stack-2-9-1/5015.

@mpilgrem mpilgrem changed the title Stack for aarch64 (again) Stack for Linux AArch64 (ARM64) Sep 6, 2022
@mpilgrem
Copy link
Member

mpilgrem commented Sep 6, 2022

I have changed this issue's title to refer expressly to Linux AArch64 and I will open a separate issue for macOS AArch64.

@dewijones92
Copy link

@mpilgrem many thanks for your efforts. But I can't get it working on my raspberry pi 4.

pi@raspberrypi:~/tmp/haskell/hask1/my-project $ stack-2.9.0.1-linux-aarch64-bin  build
Unable to find installation URLs for OS key: linux-aarch64-tinfo6

Am I missing something? thanks 😄

@mpilgrem
Copy link
Member

mpilgrem commented Sep 7, 2022

@dewijones92, my understanding (as a Windows user) of the context to all this is as follows: In the past (and perhaps today) different Linux distributions had different C libraries to handle text-based user interfaces and you needed different 'variants' of GHC built against the different libraries to work on the different Linux distributions.

It would be good to know what Linux distribution you have as your operating system (including version) on your Pi 4.

I think Stack has added -tinfo6 to the end of the 'OS key' because it has detected libtinfo.so.6 on your system.

By the way, I assume you are using a snapshot that requires GHC 9.0.2 or GHC 9.2.4.

The GHC download page for GHC 9.2.4 states:

"Generic AArch64 Linux. This is a complete build, including interactive system, profiling libraries and documentation. It was made on a Debian 10 system and requires GMP 6.1."

Historically, Stack seems to have assumed that 'Debian 10' meant libtinfo.so.5. I don't think that is correct.

Can we try this experiment? If it works, it will assist with a permanent fix. Add the following stanza to your stack.yaml file:

setup-info:
  ghc:
    linux-aarch64-tinfo6:
      9.0.2:
        url: "http://downloads.haskell.org/~ghc/9.0.2/ghc-9.0.2-aarch64-deb10-linux.tar.xz"
        content-length: 164802160
        sha1: 7dcaba567118c09bd486fb07b8dbaab66bb9a147
        sha256: cb016344c70a872738a24af60bd15d3b18749087b9905c1b3f1b1549dc01f46d
      9.2.4:
        url: "https://downloads.haskell.org/~ghc/9.2.4/ghc-9.2.4-aarch64-deb10-linux.tar.xz"
        content-length: 276846884
        sha1: 31a21434ea3f9d5ee330299541ba048727296138
        sha256: fc7dbc6bae36ea5ac30b7e9a263b7e5be3b45b0eb3e893ad0bc2c950a61f14ec

The explanation for what this is doing is here: https://docs.haskellstack.org/en/stable/yaml_configuration/#setup-info. The 'dictionary' above tells Stack to use the same version of GHC for OS key 'linux-aarch64-tinfo6' as it would use for OS key 'linux-aarch64'.

@dewijones92
Copy link

@mpilgrem

I created a new stack project and it all works now on my raspberry pi 4 😄


pi@raspberrypi:~/tmp/haskell/hask1/hask2/my-project2 $ stack build
Stack has not been tested with GHC versions above 9.0, and using 9.2.4, this may fail
Stack has not been tested with Cabal versions above 3.4, but version 3.6.3.0 was found, this may fail
Building all executables for `my-project2' once. After a successful build of all of them, only specified executables will be rebuilt.
my-project2> configure (lib + exe)
Configuring my-project2-0.1.0.0...
my-project2> build (lib + exe)
Preprocessing library for my-project2-0.1.0.0..
Building library for my-project2-0.1.0.0..
[1 of 2] Compiling Lib
[2 of 2] Compiling Paths_my_project2
Preprocessing executable 'my-project2-exe' for my-project2-0.1.0.0..
Building executable 'my-project2-exe' for my-project2-0.1.0.0..
[1 of 2] Compiling Main
[2 of 2] Compiling Paths_my_project2
Linking .stack-work/dist/aarch64-linux-tinfo6/Cabal-3.6.3.0/build/my-project2-exe/my-project2-exe ...
my-project2> copy/register
Installing library in /home/pi/tmp/haskell/hask1/hask2/my-project2/.stack-work/install/aarch64-linux-tinfo6/66423c5be1207541f9fecd22436392934441b6c9188c05b8a37034953d117c0b/9.2.4/lib/aarch64-linux-ghc-9.2.4/my-project2-0.1.0.0-CO9J5Nw7xnsHMva02SxiB8
Installing executable my-project2-exe in /home/pi/tmp/haskell/hask1/hask2/my-project2/.stack-work/install/aarch64-linux-tinfo6/66423c5be1207541f9fecd22436392934441b6c9188c05b8a37034953d117c0b/9.2.4/bin
Registering library for my-project2-0.1.0.0..
pi@raspberrypi:~/tmp/haskell/hask1/hask2/my-project2 $ stack run
Stack has not been tested with GHC versions above 9.0, and using 9.2.4, this may fail
Stack has not been tested with Cabal versions above 3.4, but version 3.6.3.0 was found, this may fail
someFunc
pi@raspberrypi:~/tmp/haskell/hask1/hask2/my-project2 $

pi@raspberrypi:~/tmp/haskell/hask1/hask2/my-project2 $ uname -a 
Linux raspberrypi 5.15.32-v8+ #1538 SMP PREEMPT Thu Mar 31 19:40:39 BST 2022 aarch64 GNU/Linux 

Here is the repo link
https://github.com/dewijones92/my-project2/tree/e374c828937b42c745b8acc7030d8dce885160ed

@mpilgrem

many thanks for your good work 😄

I also added the code from your proposed experiment and it also works 😄
https://github.com/dewijones92/my-project2/tree/3fb95c20c4b737458e287bc7f558ca0ebd64b2a7

@psibi
Copy link
Member

psibi commented Sep 8, 2022

Nice work @mpilgrem!

@mpilgrem
Copy link
Member

mpilgrem commented Sep 8, 2022

@dewijones92, that's great.

Stack asks itself 'What GHC do I need?' and, if it has not got it, it tries to fetch it. It uses a setup-info dictionary to fetch it. It only needs to fetch it once. In your case, I can see from the output aarch64-linux-tinfo6 that it has fetched what it needs under that OS key. What that means is you can now drop the setup-info: from your Stack YAML configuration files.

I also see, from Stack has not been tested with GHC versions above 9.0, and using 9.2.4, this may fail, that you are using Stack 2.7.5. You can use Stack to upgrade Stack to the cutting edge with stack upgrade --source-only --git. Warning: that may take some time to build. Or you could try the first release candidate for Stack 2.9.1 (2.9.0.1) binary again.

I now understand that the Raspberry Pi has its own distribution of Linux - Raspberry Pi OS - based on Debian (currently Debian Bullseye) https://www.raspberrypi.com/documentation/computers/os.html. I will try to update Stack's online documentation.

@francesquini
Copy link

francesquini commented Dec 28, 2022

After some digging, I have now 2 setups, both running on ARM64. The first in which Stack fails (generates empty yaml files and aeson explodes) and the second in which everything works as expected.

In both cases, GHC and friends were installed via GHCUP, running on a fresh install of Ubuntu 22.04 with all the updates applied and the same packages installed.

In both scenarios GHC, GHCI, and Cabal work without a hitch.

The difference between the two setups is that the first one (broken) runs over proot, while the second is running on a regular virtualized environment.

Stack versions tested: 2.9.1 and 2.9.3.

Thus, it stands to reason that something in stack (or something in one of its dependencies) does not like to be inside a proot env.

Now that I have these two setups, any hints to what I could do next to chase this problem down? Other than the error itself, Stack does not seem to generate detailed logs of what could be happening.

@mpilgrem
Copy link
Member

@francesquini, can you post the error itself (from Stack 2.9.3) to get a better understanding of what you are experiencing?

@francesquini
Copy link

Sure, sorry for not posting it earlier.

Immediatelly after install, I can't create a project since the global config is empty:

emilio@localhost:~/testes$ stack new proj

Error: [S-6602]
       Stack could not load and parse /home/emilio/.stack/config.yaml as a YAML
       configuraton file.
       
       While loading and parsing, Stack encountered the following error:
       
       Aeson exception:
       Error in $: parsing ConfigMonoid failed, expected Object, but encountered Null
       
       For help about the content of Stack's YAML configuration files, see (for
       the most recent release of Stack)
       http://docs.haskellstack.org/en/stable/yaml_configuration/.
emilio@localhost:~/testes$ ls -l ~/.stack/
total 4
-rw-------. 1 emilio emilio    0 Dec 27 19:44 config.yaml
drwxr-xr-x. 2 emilio emilio 3452 Dec 27 19:42 hooks

Note the 0-sized file.

No problem, I can configure it myself:

emilio@localhost:~/testes$ cat > ~/.stack/config.yaml 
templates:
  params: null
system-ghc: true
install-ghc: false

Unfortunately, that' s not enough:

emilio@localhost:~/testes$ stack new proj
Downloading template new-template to create project proj in directory proj/...
Downloaded /home/emilio/.stack/templates/new-template.hsfiles.               

Note: The following parameters were needed by the template but not provided: author-email, author-name,
      category, copyright and github-username.
      
      You can provide them in Stack's global YAML configuration file (/home/emilio/.stack/config.yaml)
      like this:
      
      templates:
        params:
          author-email: value
          author-name: value
          category: value
          copyright: value
          github-username: value
      
      Or you can pass each one on the command line as parameters like this:
      
      stack new proj new-template -p "author-email:value" -p "author-name:value" -p "category:value" -p
      "copyright:value" -p "github-username:value"
      
Looking for Cabal or package.yaml files to use to initialise Stack's project-level YAML configuration file.

Using the Cabal packages:
* proj/

Error: [S-305]
Failed to generate a Cabal file using the Hpack library on file:
/home/emilio/testes/proj/package.yaml

The error encountered was:

/home/emilio/testes/proj/package.yaml: Error while parsing $ - expected Object, but encountered Null

Note that not only the package.yaml is empty, but also LICENSE, Setup.hs, README.md, Main.hs, ... All the files generated by stack, actually.

emilio@localhost:~/testes$ ls -l proj/
total 11
-rw-------. 1 emilio emilio    0 Dec 28 14:09 CHANGELOG.md
-rw-------. 1 emilio emilio    0 Dec 28 14:09 LICENSE
-rw-------. 1 emilio emilio    0 Dec 28 14:09 README.md
-rw-------. 1 emilio emilio    0 Dec 28 14:09 Setup.hs
drwxr-xr-x. 2 emilio emilio 3452 Dec 28 14:09 app
-rw-------. 1 emilio emilio    0 Dec 28 14:09 package.yaml
drwxr-xr-x. 2 emilio emilio 3452 Dec 28 14:09 src
drwxr-xr-x. 2 emilio emilio 3452 Dec 28 14:09 test

@mpilgrem
Copy link
Member

mpilgrem commented Dec 28, 2022

@francesquini, that is very odd. The part of Stack's code that writes the files extracted from a *.hsfiles template is Stack.New.writeTemplateFiles and it looks like this:

-- | Write files to the new project directory.
writeTemplateFiles ::
       MonadIO m
    => Map (Path Abs File) LB.ByteString -> m ()
writeTemplateFiles files =
    liftIO $
    forM_
        (M.toList files)
        (\(fp,bytes) ->
              do ensureDir (parent fp)
                 writeBinaryFileAtomic fp $ lazyByteString bytes)

writeBinaryFileAtomic is from the RIO package - https://hackage.haskell.org/package/rio-0.1.22.0/docs/RIO-File.html#v:writeBinaryFileAtomic (EDIT, actually re-exported from here: https://hackage.haskell.org/package/unliftio-0.2.23.0/docs/UnliftIO-IO-File.html). I can't explain why, on your 'PRoot' system, the function thinks it has written a file but it has, in fact, only created an empty file (0 byte file) of the same name.

@mpilgrem
Copy link
Member

mpilgrem commented Dec 28, 2022

As GHC and Cabal work on your PRoot system, perhaps you could write a small piece of test code to see if writeBinaryFileAtomic is, indeed, misbehaving. EDIT: writeBinaryFileAtomic is used throughout Stack's code, and its misbehaviour would likely explain all of the 0-byte files.

@francesquini
Copy link

@mpilgrem That's interesting.... The documentation for writeBinaryFileAtomic says:

Same as writeBinaryFileDurableAtomic, except it does not guarantee durability.

The "durability", is somewhat explained in the documentation for withBinaryFileAtomic:

It means that all modification can still disappear after it has been succesfully written due to some extreme event like an abrupt power loss, but the contents will not be corrupted in case when the file write did not end successfully.

Well, I can attest I'm not having an "abrupt power loss" :), but something is making the written bytes to be lost.

I'll try to change the current call to withBinaryFileAtomic for a call to writeBinaryFileDurableAtomic, compile a new version locally and I'll let you know if this fixes this issue.

@francesquini
Copy link

@mpilgrem Indeed the problem was with RIO, in particular, with the atomic variants of writeBinaryFile....

I executed the following code on my machine:

{-# LANGUAGE NoImplicitPrelude #-}

module Main (main) where

import RIO
import RIO.File
import RIO.ByteString

main :: IO ()
main = do
  writeBinaryFile "writeBinaryFile.txt" bs
  writeBinaryFileAtomic "writeBinaryFileAtomic.txt" bs
  writeBinaryFileDurable "writeBinaryFileDurable.txt" bs
  writeBinaryFileDurableAtomic "writeBinaryFileDurableAtomic.txt" bs
  where
    bs = pack [65 .. 75]

On the 'PRoot' system, I got:

emilio@localhost:~/testrio$ ls -l
total 1312
-rwxr-xr-x. 1 emilio emilio 1334440 Dec 28 15:18 testerio-exe
-rw-rw-r--. 1 emilio emilio      11 Dec 28 15:20 writeBinaryFile.txt
-rw-rw-rw-. 1 emilio emilio       0 Dec 28 15:20 writeBinaryFileAtomic.txt
-rw-rw-r--. 1 emilio emilio      11 Dec 28 15:20 writeBinaryFileDurable.txt
-rw-rw-rw-. 1 emilio emilio       0 Dec 28 15:20 writeBinaryFileDurableAtomic.txt

On the other ARM64 machine, all files have 11 bytes each, as expected.

Fortunately, Stack source code concentrates all calls to writeBinaryFileAtomic to a reexported function from Stack's own prelude:

stack/src/Stack/Prelude.hs

Lines 293 to 296 in 503ef24

writeBinaryFileAtomic :: MonadIO m => Path absrel File -> Builder -> m ()
writeBinaryFileAtomic fp builder =
liftIO $
withBinaryFileAtomic (toFilePath fp) WriteMode (`hPutBuilder` builder)

After modifying line 296 to:

withBinaryFile (toFilePath fp) WriteMode (`hPutBuilder` builder)

or to withBinaryFileDurable, everything works as expected.

I'll open an issue for the maintainers of RIO, however, for stack itself some questions remain.

Is the use of atomic really necessary? Wouldn't durable (or even the regular version) be enough?

@francesquini
Copy link

Issue regarding the unexpected behavior above: fpco/unliftio#107

@mpilgrem
Copy link
Member

I am going to close this 'general' issue, having separated out @francesquini's PRoot-related problem.

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

No branches or pull requests

10 participants