Skip to content

Multi target support #35

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

Open
wants to merge 4 commits into
base: wip/make-build-pre-zig
Choose a base branch
from

Conversation

hasufell
Copy link
Member

As well as being invoked via triplet symlink.

@hasufell hasufell requested a review from hsyl20 July 29, 2025 05:35
@hasufell hasufell linked an issue Jul 29, 2025 that may be closed by this pull request
5 tasks
@hasufell hasufell force-pushed the wip/multi-target-support branch from 5158146 to 8b1e18e Compare July 29, 2025 05:35
Copy link

@angerman angerman left a comment

Choose a reason for hiding this comment

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

I guess we'll need to overhaul this program completely at some point.

This change looks good. I've left a few comments with ideas.

@angerman
Copy link

Oof, CI also tells us we don't really test this program at all on its own, just as part of the whole 😅 nothing to fix now, just an observation.

mt <- getTarget my_flags
dir <- case mt of
Nothing -> pure dir'
Just target -> pure (dir' </> "targets" </> target </> "lib")
Copy link

Choose a reason for hiding this comment

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

This path should be kept in sync with ghc: perhaps add a helper function where getBaseDir is? If it's not possible because of staging, some comment would be useful to remember this.

Copy link
Member Author

Choose a reason for hiding this comment

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

The code in GHC is a bit different:

ghc/ghc/Main.hs

Lines 142 to 161 in 1c9db51

targettopdir <- Just <$> do
topdir <- findTopDir mbMinusB
let targets_dir = topdir </> "targets"
-- list targets when asked
when list_targets $ do
putStrLn $ "Installed targets (in " ++ targets_dir ++ "):"
doesDirectoryExist targets_dir >>= \case
True -> do
ds <- listDirectory targets_dir
forM_ ds (\d -> putStrLn $ " - " ++ d)
False -> pure ()
exitSuccess
-- otherwise select the appropriate target
case mbTarget of
Nothing -> pure topdir
Just target -> do
let r = targets_dir </> target </> "lib"
doesDirectoryExist r >>= \case
True -> pure r
False -> throwGhcException (UsageError $ "Couldn't find specific target `" ++ target ++ "' in `" ++ r ++ "'")

What did you have in mind?

Copy link

Choose a reason for hiding this comment

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

I was thinking about something like getTargetDir :: FilePath -> String -> IO FilePath taking the topdir and the target name and returning the target dir.

As well as being invoked via triplet symlink.
@hasufell hasufell force-pushed the wip/multi-target-support branch from 8b1e18e to 2de8dce Compare July 29, 2025 11:38
@hasufell hasufell changed the title feat: make ghc-pkg support '--target' Multi target support Aug 1, 2025
@hasufell hasufell requested review from hsyl20 and angerman August 1, 2025 13:37
@hasufell
Copy link
Member Author

hasufell commented Aug 4, 2025

Instructions to test:

  • checkout this branch
  • run: make CABAL=_build/stage0/bin/cabal
  • make sure emscripten is installed and the emscripten env script has been sourced: https://emscripten.org/docs/getting_started/downloads.html
  • run: make CABAL=_build/stage0/bin/cabal stage2-javascript-unknown-ghcjs
  • clone miso example from https://github.com/haskell-miso/miso-counter.git
  • compile miso example via something like (example from my machine) /home/hasufell/git/ghc/_build/stage0/bin/cabal build -W /home/hasufell/git/ghc/_build/stage2/bin/ghc -w /home/hasufell/git/ghc/_build/stage2/bin/javascript-unknown-ghcjs-ghc --with-gcc=emcc --allow-newer=ghc-bignum

Copy link

@angerman angerman left a comment

Choose a reason for hiding this comment

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

👏 This is great work! I've left a few comments with throughts.

AutoApply_V32.cmm
AutoApply_V64.cmm

common ghcjs
Copy link

Choose a reason for hiding this comment

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

This should really be called rts-javascript, or rts-ghcjs or something like that.

Copy link

Choose a reason for hiding this comment

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

To align with the other common stanzas: rts-js-sources being the best?

AutoApply_V32.cmm
AutoApply_V64.cmm

common ghcjs
import: rts-base-config
Copy link

Choose a reason for hiding this comment

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

This seems to deviate from how other common stanzas are done? This should just be in the conditional below: rts-base-config, rts-ghcjs, or similar.

visibility: public
build-depends: rts
Copy link

Choose a reason for hiding this comment

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

Good! This is an oversignt, and already part of rts-base-config.

utils/genprimopcode
utils/deriveConstants

if !arch(javascript)
Copy link

Choose a reason for hiding this comment

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

Suggested change
if !arch(javascript)
-- We do not want to compile the utilities to javascript. Also terminfo (and haskeline) don't make sense for javascript.
if !arch(javascript)

Comment on lines 79 to 111
if arch(javascript)
constraints:
Cabal source,
Cabal-syntax source,
array source,
base source,
binary source,
bytestring source,
containers source,
deepseq source,
directory source,
exceptions source,
file-io source,
filepath source,
hpc source,
integer-gmp source,
mtl source,
os-string source,
parsec source,
pretty source,
process source,
rts source,
rts-headers source,
rts-fs source,
stm source,
system-cxx-std-lib source,
template-haskell source,
text source,
time source,
transformers source,
unix source,
xhtml source,
Win32 source
Copy link

Choose a reason for hiding this comment

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

The indentation is meant to signify dependencies?

Why do we need the source constraint here? We should have acomment explaining why this is done, and if this is a cabal defect that needs to be rectified or something else.

Comment on lines +261 to +263
$(call run_and_log, HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \
PATH=$(PWD)/_build/stage1/bin:$(PATH) \
$(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) rts:nonthreaded-nodebug )
Copy link

Choose a reason for hiding this comment

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

This really feels like a bug, why do we need to build this explicitly here, why is this not brought into scope automatically?

Makefile Outdated
javascript-unknown-ghcjs-libs: private CC=emcc
javascript-unknown-ghcjs-libs: _build/stage2/bin/javascript-unknown-ghcjs-ghc-pkg _build/stage2/bin/javascript-unknown-ghcjs-ghc _build/stage2/lib/targets/javascript-unknown-ghcjs/lib/settings _build/stage2/lib/targets/javascript-unknown-ghcjs/bin/unlit _build/stage2/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d
# Force cabal to replan
rm -rf _build/stage2/javascript-unknown-ghcjs/cache
Copy link

Choose a reason for hiding this comment

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

Wow, this seems ... odd? @andreabedini what's going on here?

Makefile Outdated
rm -rf _build/stage2/javascript-unknown-ghcjs/cache
$(call run_and_log, HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \
PATH=$(PWD)/_build/stage2/bin:$(PATH) \
$(CABAL_BUILD) -W $(GHC2) --happy-options="--template=$(abspath _build/stage2/src/happy-lib-2.1.5/data/)" rts:nonthreaded-nodebug )
Copy link

Choose a reason for hiding this comment

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

Do you remember what the underlying reason for the happy-lib-... path thing was? Can we add a comment to remember why this was needed?

Makefile Outdated
$(CABAL_BUILD) -W $(GHC2) --happy-options="--template=$(abspath _build/stage2/src/happy-lib-2.1.5/data/)" rts:nonthreaded-nodebug )
$(call run_and_log, HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \
PATH=$(PWD)/_build/stage2/bin:$(PATH) \
$(CABAL_BUILD) -W $(GHC2) --happy-options="--template=$(abspath _build/stage2/src/happy-lib-2.1.5/data/)" $(STAGE2_TARGET_LIBS) )
Copy link

Choose a reason for hiding this comment

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

Can't the STAGE2_CROSS_TARET_LIBS contain rts:nonthreaded-nodebug? If not, why not?

Makefile Outdated
@@ -176,6 +182,33 @@ STAGE2_UTIL_EXECUTABLES := \
runghc \
unlit

STAGE2_TARGET_LIBS := \
Copy link

Choose a reason for hiding this comment

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

This is for the CROSS compiler, right? Can we rename it to STAGE2_CROSS_TARET_LIBS then?

@hasufell
Copy link
Member Author

hasufell commented Aug 7, 2025

I've stage3-ified this and added musl cross compiler support.

@hsyl20
Copy link

hsyl20 commented Aug 11, 2025

Updated build instructions afaict:

Instructions to test:

  • checkout this branch
  • run: make CABAL=_build/stage0/bin/cabal twice. it should print "Binary distribution created."
  • optional: make sure emscripten is installed and the emscripten env script has been sourced: https://emscripten.org/docs/getting_started/downloads.html (not needed if globally installed, as with the ArchLinux package)
  • run: make CABAL=_build/stage0/bin/cabal stage3-javascript-unknown-ghcjs (stage3, not stage2)
  • install iserv for JS: cp ghc-interp.js _build/stage2/lib/targets/javascript-unknown-ghcjs/lib
  • clone miso example from https://github.com/haskell-miso/miso-counter.git
  • compile miso example via something like (example from my machine) /home/hasufell/git/ghc/_build/stage0/bin/cabal build -W /home/hasufell/git/ghc/_build/stage2/bin/ghc -w /home/hasufell/git/ghc/_build/stage3/bin/javascript-unknown-ghcjs-ghc --with-gcc=emcc --allow-newer=ghc-bignum (stage3, not stage2).

These instructions worked for me.

Note that replacing build with run in the last command rebuilds everything for some reason.

Then it fails with:

/home/hsyl20/projects/ghc/scratch/miso/miso-counter/dist-newstyle/build/host/javascript-ghcjs/ghc-9.13/miso-counter-0.1-app/build/app/app:163760
  var e = new WebAssembly.RuntimeError(what);
          ^

RuntimeError: Aborted('HEAP8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ))

that someone reported (again? I've already seen it) 2 days ago: https://gitlab.haskell.org/ghc/ghc/-/issues/26290

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.

Multi-target support for GHC
3 participants