commercialhaskell / stack

The Haskell Tool Stack
http://haskellstack.org
BSD 3-Clause "New" or "Revised" License
3.98k stars 842 forks source link

Stack for Linux AArch64 (ARM64) #5709

Closed dboreham closed 6 months ago

dboreham commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

ghcup provides aarch64 stack binaries.

dboreham commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

The ARM64/AArch64 stack CI has suddenly started failing with commit 75f3170a92adf9a1885fc653bd464ba080f9699b. 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 commented 2 years ago

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 commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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

dewijones92 commented 2 years ago

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

thanks

mpilgrem commented 2 years ago

@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 containsstack-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 commented 2 years ago

@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 https://github.com/commercialhaskell/stack/issues/5733#issuecomment-1214175646 I have linux + docker exp

mpilgrem commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago

@dboreham This will rectify this situation :D https://github.com/commercialhaskell/stack/issues/5733#issuecomment-1214175646

mpilgrem commented 2 years ago

@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 commented 2 years ago

Hello.

I live in Android/Termux/Void linux, ( ditched Ubuntu server, because broken for both Ruby & Haskell ) used GHCup to install both Haskell & Stack,

finally figured-out that stack can't work until one populates it "config.yaml" file with at least 1 option ( which seems daft: why create an empty config file that breaks stack? ) and can't get stack to install hindent.

The error it gives is:

"$ stack install hindent Writing implicit global project config file to: /home/$ME/.stack/global-project/stack.yaml Note: You can change the snapshot via the resolver field there. Using latest snapshot resolver: lts-19.19 Unable to find installation URLs for OS key: linux-aarch64-tinfo6"

that last line is exactly what googled me to here.

stack 2.5.7, btw.

where the hell do we find "installation URLs for OS key: linux-aarch64-tinfo6", or what can we set up, to cause stack to work correctly?

mpilgrem commented 2 years ago

@libweirdness, Hello! Let me see if I can help you to some extent.

[1] First of all, you refer to an 'empty' config.yaml. I assume you are talking about the global configuration file in the Stack root (the directory output by stack path --stack-root). It should not be empty. If the file does not exist, I would expect Stack to create it, with content like this:

# This file contains default non-project-specific settings for 'stack', used
# in all projects.  For more information about stack's configuration, see
# http://docs.haskellstack.org/en/stable/yaml_configuration/

# The following parameters are used by "stack new" to automatically fill fields
# in the cabal config. We recommend uncommenting them and filling them out if
# you intend to use 'stack new'.
# See https://docs.haskellstack.org/en/stable/yaml_configuration/#templates
templates:
  params:
#    author-name:
#    author-email:
#    copyright:
#    github-username:

# The following parameter specifies stack's output styles; STYLES is a
# colon-delimited sequence of key=value, where 'key' is a style name and
# 'value' is a semicolon-delimited list of 'ANSI' SGR (Select Graphic
# Rendition) control codes (in decimal). Use "stack ls stack-colors --basic"
# to see the current sequence.
# stack-colors: STYLES

What did/does yours contain?

[2] Second, on Windows 11 (but the commands on Linux should be the same), this is my experience of building hindent with Stack from scratch (extracts only, of build output):

$ stack unpack hindent # Get and unpack hindent from Hackage
Unpacked hindent (from Hackage) to D:\Users\mike\Code\Haskell\hindent-5.3.4\

$ cd hindent-5.3.4
$ stack init # hindent-5.3.4 is not packaged with a stack.yaml file
Looking for .cabal or package.yaml files to use to init the project.
Using cabal packages:
- .\

Selecting the best among 18 snapshots...

* Matches https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/19.yaml

Selected resolver: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/19.yaml
Initialising configuration using resolver: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/19.yaml
Total number of user packages considered: 1
Writing configuration to file: stack.yaml
All done.

$ stack build # Stack has already downloaded the needed GHC on my system
[... build output ...]
hindent                      > copy/register
Installing library in D:\Users\mike\Code\Haskell\hindent-5.3.4\.stack-work\install\f8cad0ce\lib\x86_64-windows-ghc-9.0.2\hindent-5.3.4-A9N4vI8lsRH9xt748D7M3V
Installing executable hindent in D:\Users\mike\Code\Haskell\hindent-5.3.4\.stack-work\install\f8cad0ce\bin
Registering library for hindent-5.3.4..
Completed 58 action(s).

$ stack exec -- hindent --version
hindent 5.3.4

[3] I think the error message "Unable to find installation URLs for OS key: linux-aarch64-tinfo6" means that there is no GHC 9.0.2 binary distribution for the OS/architecture/variant Linux/AArch64/tinfo6. I don't know what is meant by variant 'tinfo6' (Linux is not my thing) but the AArch64 version of GHC 9.0.2 is described here: https://www.haskell.org/ghc/download_ghc_9_0_2.html#linux_aarch64 and it is know to Stack as OS key "linux-aarch64".

libweirdness commented 2 years ago

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 commented 2 years ago

@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 https://github.com/commercialhaskell/stack/issues/5709#issuecomment-1216409039 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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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

dewijones92 commented 2 years ago

@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 commented 2 years ago

@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 commented 2 years ago

@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 commented 2 years ago

Nice work @mpilgrem!

mpilgrem commented 2 years ago

@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 commented 1 year ago

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 commented 1 year ago

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

francesquini commented 1 year ago

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 commented 1 year ago

@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 commented 1 year ago

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 commented 1 year ago

@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.