Java support for iOS builds for Clojurescript

Is there a way to install Java on a MacOS build machine?

Clojure builds are failing on MacOS without it:

Script 'eas-build-post-install' is present in package.json, running it...
> checkup-checklist@1.0.0 eas-build-post-install
> npx shadow-cljs release app
[stderr] shadow-cljs - config: /Users/expo/workingdir/build/shadow-cljs.edn
[stderr] The operation couldn’t be completed. Unable to locate a Java Runtime.
[stderr] Please visit http://www.java.com for information on installing Java.
[stderr] ===== ERROR =================
[stderr] java process exit with non-zero exit code
[stderr] =============================
npm exited with non-zero code: 1

I can’t find this mentioned anywhere in documentation or forums.

  • Managed workflow
  • eas-cli 3.4.1

Hi @peterbee

It should be possible to download and install it in the eas-build-pre-install hook, I think. Not sure of the details, e.g. where to download it from.

Alternatively you should be able to build the ClojureScript locally before running eas build.

Good idea, thanks! I have been investigating how to install Java on the build machine, but am running into roadblocks so far.

I’m optimistic about compiling locally first. However, when I ran npm run eas-build-post-install locally and then eas build --platform ios, I get a different EAS build error:

❌  error: File ...<my-add-name>.app/main.jsbundle does not exist.

It seems that something isn’t being generated or uploaded to EAS. I’ve been investigating to figure out when/where that file is generated but I have not found it yet.

Let me know if you can point me in the right direction.

Thanks!

Update: I had to remove the app directory from .gitignore to upload the compiled files to EAS. Then the build completed successfully. :+1:

1 Like

I haven’t tried this, but this is what I would try:

  • Check if homebrew is already installed on the build instances. If not you could try installing it as follows. Otherwise just run brew install temurin11 in a hook
  • Download https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh and save it to something like scripts/install-homebrew.sh
  • Create a script that runs bash scripts/install-homebrew.sh followed by brew install temurin11, but only if running on macOS.
  • See if that works. If it complains about running as root, you could patch the install-homebrew.sh script to skip that check.
  • You might need to add stuff to the PATH or specify the full path to the brew command

Note: Of course this would increase the time it takes to build and seems rather wasteful to do every time. Not sure if you can cache this somehow. Alternatively, maybe you can tar up a local installation of java and host it somewhere, then download and untar it during the build. Or maybe you can cache it somehow, but I think the EAS caching stuff is currently only for dependencies

EDIT: Actually I’ve just re-read the “Custom caching” section and it looks like it could maybe be used to cache a tar file. So maybe you could check for the tar file and untar it to the right place if it exists. If it doesn’t exist, install it with Homebrew and then tar it up so that it can be cached for next time. See: Build schema for eas.json - Expo Documentation

Yes, EAS uses .gitignore by default to decide what to upload or ignore. You can work around this by copying .gitignore to .easignore and then removing app only from .easignore.

But you run the risk of .gitignore and .easignore getting out of sync.

It might make sense just to commit the app directory to Git.

Good news, Homebrew is already installed on the macOS build workers!

So you should just be able to install temurin11 or whatever in a build hook. I’ve been told it might be a good idea to set HOMEBREW_NO_AUTO_UPDATE=1 to speed things up. Also, you’d want to avoid running this for the Android builds.

You could do the temurin install in a pre-install hook and the ClojureScript build in a post-install hook, but they can also just be done in the same hook. Doing stuff in the pre-install hook is a lot faster while you’re testing and tweaking the hook script, though, because you don’t have to wait for several other steps before you know whether it’s working as intended :slight_smile:

I tried this last night and it worked fine:

build-cljs.sh

#!/bin/bash

set -e

if [[ "$EAS_BUILD_PLATFORM" == "ios" ]]; then
  HOMEBREW_NO_AUTO_UPDATE=1 brew install homebrew/cask-versions/temurin11
fi

exec npx shadow-cljs release app

package.json

{
  "scripts": {
[...]
    "eas-build-post-install": "./build-cljs.sh"
  },
}

The only issue is that it seems shadow-cljs does not exit with a non-zero exit status if e.g. there’s no shadow-cljs.edn file. So the build continues and will run into errors later because there’s no app directory.