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

Allow GHCup to build & run on OpenBSD #1138

Merged
merged 2 commits into from
Dec 19, 2024

Conversation

habibalamin
Copy link
Collaborator

@habibalamin habibalamin commented Oct 21, 2024

Fix #707.

This doesn't ensure that GHCup's GHC build scripts/manifests work for OpenBSD, merely that it itself builds and runs on OpenBSD.

@habibalamin habibalamin changed the title Add OpenBSD support Allow GHCup to build & run on OpenBSD Oct 21, 2024
lib/GHCup/Types.hs Show resolved Hide resolved
cabal.ghc964.Unix.project Outdated Show resolved Hide resolved
@hasufell
Copy link
Member

@habibalamin You need to rebase against master. Please let me know if there's anything else blocking you.

@hasufell
Copy link
Member

@habibalamin we're planning a new release... before the end of the year. Do you think we can get this in?

@habibalamin
Copy link
Collaborator Author

habibalamin commented Nov 19, 2024

Hey, yeah sorry. I'll try and get that done in a bit.

You might be interested to hear that Greg Steuck and I finally got GHC working to run on and produce (seemingly working) binaries for OpenBSD/arm64, by cross-compiling from OpenBSD/amd64.

It should, God willing, land in the OpenBSD 7.7 release, which is the upcoming one.

`libarchive` (the Haskell package, not its upstream C library) vendors
the `config.h` header files generated by autoconf for each platform it
supports instead of using autoconf (or even CMake, which the C library
offers as an option). So apart from those specific platforms, just use
`tar` & `zip`.

`lzma-static` currently does the same, but we're gonna fix it upstream
then update the minimum version bounds on our dependency of it.
"mingw32" -> pure PlatformResult { _platform = Windows, _distroVersion = Nothing }
what -> throwE $ NoCompatiblePlatform what
lift $ logDebug $ "Identified Platform as: " <> T.pack (prettyShow pfr)
pure pfr
where
getOpenBSDVersion = lift $ fmap _stdOut $ executeOut "uname" ["-r"] Nothing
Copy link
Member

@hasufell hasufell Nov 20, 2024

Choose a reason for hiding this comment

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

Are you sure uname is the OpenBSD version and not just the kernel?

What are the outputs? Are they purely numeric? Otherwise we will have a hard time matching on them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think the BSDs have a kernel version distinct from the OS version, since they're all developed by the same people under a single umbrella; a release is the kernel, plus base packages (userland), plus ports (package repository for that version).

I developed these changes on my real OpenBSD/amd64 machine and tested the uname -r command after reading the man page at the time.

OpenBSD's man page for uname says:

    -r      Print the operating system release.  On OpenBSD, the format is
            digit.digit.

(and digit.digit is underlined, but (GitHub's) Markdown doesn't seem to support that, nor setting monospace font quote without a code block which makes things literal anyway.)

However, I just realised the man page doesn't specify, and I hadn't considered, what would happen on OpenBSD-snapshot or -current (which are non-stable tracks that some OpenBSD users do prefer)? I'm gonna check on a VM now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is what I get on my -snapshot VM:

OpenBSD 7.6-current (GENERIC.MP) #243: Mon Nov 18 13:30:33 MST 2024

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code.  With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

You have new mail.
foo# uname -r
7.6

I generally stick to release, but I do think the login message starting with 7.6-current is correct, even though it's -snapshot, because according to the docs I just checked, -current is essentially following trunk and can only be done by building from source oneself, and -snapshot is just a snapshot of -current compiled for release as non-stable.

So yeah, -r is always a release number and nothing else.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Comments on this Reddit thread basically confirm that there's no such thing as a -snapshot track, so that was my bad; snapshots are just compiled releases of the -current track.

Copy link
Member

Choose a reason for hiding this comment

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

GHCup currently doesn't run on OpenBSD (or any platform not explicitly
supported), even if it builds. This adds explicit support for OpenBSD.

We may later not block it from running on unsupported platforms, even
when we don't explicitly make sure our build scripts work for them or
provide bindists or CI for them.
@hasufell
Copy link
Member

How do I test these changes? I have private freebsd runners with pots. Afaiu there is a way to have OpenBSD pots, is there?

@habibalamin
Copy link
Collaborator Author

I don't understand what you mean by pots.

@hasufell
Copy link
Member

I don't understand what you mean by pots.

https://pot.pizzamig.dev/

@habibalamin
Copy link
Collaborator Author

I mean, the site mentions that you can use jails or VMs, so I suppose you could have an OpenBSD pot if you virtualise it, but the documentation seems to only focus on jails for now.

Last I used FreeBSD, their hypervisor was far more developed than OpenBSD, and it should definitely be able to virtualise OpenBSD.

@dfordivam
Copy link
Collaborator

I have private freebsd runners with pots.

Just clarifying why this is necessary. Is this to boot up a fresh FreeBSD runner for each CI run?,
ie the CI job triggers creation of a container or the CI runner runs inside a container?

@hasufell
Copy link
Member

The CI runner runs inside a manually created FreeBSD jail.

@hasufell
Copy link
Member

I tried with beehyve and beehyve-vm with no success.

@habibalamin
Copy link
Collaborator Author

habibalamin commented Nov 23, 2024

SourceHut supports OpenBSD latest and one version behind (multiple architectures). They have an API you can use to submit builds. I don't know if that works for you.

@hasufell
Copy link
Member

CI is generally a waste of time without having local access to the platform, where you can do proper step-by-step analysis.

VirtualBox VMs are awfully slow and waste tons of space, so I was hoping to get it done via beehyve, but it does not have good UX. So I'm not sure how much time I can invest.

@habibalamin
Copy link
Collaborator Author

This page from a BSD blog I've seen before has a guide which seems decent, though I haven't tried it.

They show two methods to run both FreeBSD and OpenBSD in a bhyve VM; one using stock bhyve, one using a package to make it easier to work with called vm-bhyve.

@hasufell
Copy link
Member

This page from a BSD blog I've seen before has a guide which seems decent, though I haven't tried it.

They show two methods to run both FreeBSD and OpenBSD in a bhyve VM; one using stock bhyve, one using a package to make it easier to work with called vm-bhyve.

I was able to create a VM and boot into the OpenBSD guest installer. But I'm unable to make networking (internet connection via the host) work. None of the tutorials really go into that.

@habibalamin
Copy link
Collaborator Author

Do you have an /etc/hostname.if file, where hostname is literal, and if is the name of your network interface (it should be vio0 for the first VirtIO network card)?

I have an OpenBSD VM on UTM (a QEMU frontend), but (lately?) all my QEMU VMs (maybe due to a UTM update) seem to require bridged networking to work. I think either way, the hostname.if file should contain something like this (for any ethernet, not just VirtIO virtual NICs):

inet6 autoconf
inet autoconf

I get a vio0: offload features 0x0 failed error messages popping up in my console every now and again, but it works.

Try that, then run doas sh /etc/netstart. doas is the built-in sudo-like tool. Check out man doas.conf for how to configure it, it's very easy, or just run as root in the VM.

@hasufell
Copy link
Member

OpenBSD is not installed yet, so I have limited access to tools. I'm inside the install medium where I get asked questions about network config. There is an option autoconf, but it does not work: there is no DHCP. It fails.

@habibalamin
Copy link
Collaborator Author

Ah, I'm guessing you're using the installation medium which downloads the file sets on demand, instead of preloading them on.

Would you be able to give me access to the FreeBSD instance so I can debug, and then give you the installation instructions?

@hasufell
Copy link
Member

Can you send me your ssh pubkey signed with your gpg key corresponding to the mail you use in github?

You can find my mail in the git commits.

@hasufell
Copy link
Member

hasufell commented Dec 2, 2024

@habibalamin I was swamped... I try to get to it this week

@hasufell
Copy link
Member

hasufell commented Dec 6, 2024

I'm using Vultr now which has OpenBSD virtual cloud servers. But cabal update seems to hang forever. So I can't test this PR.

Edit: appears it's just VERY slow.

@hasufell
Copy link
Member

hasufell commented Dec 6, 2024

Ok, I can compile and run it.

Do we have any bindists at all that I can test this against?

@habibalamin
Copy link
Collaborator Author

No, there are no OpenBSD/amd64 bindists for 7.6 at the moment AFAIK.

I can give you a build script to build one, if you like. It might have to be tomorrow, though. Or you can figure it out from OpenBSD's port.

@hasufell
Copy link
Member

hasufell commented Dec 6, 2024

I get build errors when compiling GHC:

# cabal-configure (for _build/stage1/libraries/ghc-prim/setup-config)
| Remove directory _build/stage1/libffi/build
| Remove directory _build/libffi-3.4.6
| Run Tar Extract: libffi-tarballs/libffi-3.4.6.tar.gz => _build/stage1
Command line: /bin/tar -x -f libffi-tarballs/libffi-3.4.6.tar.gz -C _build/stage1
===> Command failed with error code: 1
tar: input compressed with gzip; use the -z option to decompress it
Command failed
Build failed.

Which is weird, because hadrian is supposed to add the correct flags: https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.8/hadrian/src/Hadrian/Builder/Tar.hs#L36-43

@habibalamin
Copy link
Collaborator Author

GNU tar detects the compression, so the GHC doesn't provide the -z flag, but OpenBSD tar needs it. Install gtar and pass TAR=gtar to the environment when invoking the build. Let me get the build script I used for arm64, it'll probably have a few of these non-architecture-specific stuff for OpenBSD.

@hasufell
Copy link
Member

hasufell commented Dec 6, 2024

Yeah, I'm not sure if I have the time for this. But I need at least one bindist to actually test installation.

@habibalamin
Copy link
Collaborator Author

No worries, I'll build one for you this weekend.

@habibalamin
Copy link
Collaborator Author

habibalamin commented Dec 8, 2024

Okay, I built a bindist, but turns out the configure call has to provide the same -Wl,--no-execute-only -Qunused-arguments -Wl,-z,nobtcfi flags to CONF_CC_OPTS_STAGE2 and CONF_GCC_LINKER_OPTS_STAGE{0,1,2} as the original build does (on OpenBSD).

Without it, it'll install fine, but will compile broken (segfaulting) binaries.

The bindist initially has those settings, but the configure invocation clobbers them, and we need the configure call to set the prefix to something other than the default /usr/local that the bindists are usually set to.

I didn't have to do this for the cross-compiled bindists I did for OpenBSD, which also used those flags for the build, and I haven't done the investigation to figure out why the difference.

Either way, you can find the bindist here. SHA512 checksum should be 434a4d8fea24728dfda78ee3aed05457f3d56ffca7d7e31077c77b7015945d418b53aaf4a45499fa1c08d6f76596c292ca9d5954437903a45abbd02c1ff26125.

@habibalamin
Copy link
Collaborator Author

I suppose the PR will have to be modified to pass those flags when configureing bindists on OpenBSD? Let me know if that's a requirement for this PR to be merged or if we can do that in a separate PR along with the OpenBSD-specific build manifests.

@hasufell
Copy link
Member

hasufell commented Dec 8, 2024

Okay, I built a bindist, but turns out the configure call has to provide the same -Wl,--no-execute-only -Qunused-arguments -Wl,-z,nobtcfi flags to CONF_CC_OPTS_STAGE2 and CONF_GCC_LINKER_OPTS_STAGE{0,1,2} as the original build does (on OpenBSD).

Without it, it'll install fine, but will compile broken (segfaulting) binaries.

I'm not sure that's a good long term strategy to fidget with such variables during bindist configure.

I've told GHC HQ before that the configure script of the bindist needs to be a proper interface to the "GHC settings file".

How are other platforms handled that need specific link flags to produce correct binaries @bgamari @AndreasPK?

@bgamari
Copy link
Collaborator

bgamari commented Dec 11, 2024

I'm not sure that's a good long term strategy to fidget with such variables during bindist configure.

Indeed it is not.

How are other platforms handled that need specific link flags to produce correct binaries @bgamari @AndreasPK?

The way to proceed here is to introduce configure checks to check for the conditions that make these flags necessary and when found apply them to the configuration.

Many checks like this can be found in GHC's m4 directory. A relevant example might be the Darwin -no_fixup_chains check.

@habibalamin
Copy link
Collaborator Author

That makes sense.

I think these flags are just necessary in general on OpenBSD. They're used in the amd64 port Makefile, and we also had to use them when cross-compiling a port to arm64.

So I guess that's a $HostOS check for OpenBSD and append the necessary flags to the necessary CONF_* variables, right?

@hasufell
Copy link
Member

@habibalamin do you mind preparing a GHC PR?

@habibalamin
Copy link
Collaborator Author

I think it'd be better that a ./configure within a bindist not wipe any flags set from the build (unless explicitly undone with --no-xyz) simply because the user wanted to set a prefix or something.

We can improve the configure checks in the original build, but fundamentally, the bindist configure should default to flags set in the original build as well.

Anyway, I don't really have much time to work on this any further. I'll try to get to it before the end of the year, but I can't promise anything. Otherwise, it'll have to wait until the new year.

@hasufell
Copy link
Member

Okay, I built a bindist, but turns out the configure call has to provide the same -Wl,--no-execute-only -Qunused-arguments -Wl,-z,nobtcfi flags to CONF_CC_OPTS_STAGE2 and CONF_GCC_LINKER_OPTS_STAGE{0,1,2} as the original build does (on OpenBSD).

Can you provide a follow up PR?

@hasufell hasufell merged commit 0c3b09b into haskell:master Dec 19, 2024
51 checks passed
@habibalamin
Copy link
Collaborator Author

habibalamin commented Dec 19, 2024

A followup PR to GHC upstream to add the configure checks (and possibly also make it so that running configure in the bindist doesn't by default undo options set in the build)?

Or are you talking about a followup PR to GHCup (to provide those linker flags when installing the bindist with GHCup downstream or what)?

(Based on the new ticket you created, I'm assuming the latter.)

@hasufell
Copy link
Member

Or are you talking about a followup PR to GHCup (to provide those linker flags when installing the bindist with GHCup downstream or what)?

Yes

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.

Add OpenBSD and NetBSD?
4 participants