Building expo react native android app on nixos

Hi everyone,

I am trying to build a react native android application using the expo build tool

I am able to upload my app to my android device using the Expo go app, But I cannot build the apk outright as gradle attempts to write some files to a location in the nix store (which it can’t since the nix store is readonly)

here is my repo where I am trying to accomplish this

to reproduce the issue you can run the following commands after connecting an android device to your machine

nix develop
npm ci
npm run android

and here is the console output of running these commands

 npm run android

> nix-expo-attempt@1.0.0 android
> expo run:android

› Building app...
Configuration on demand is an incubating feature.
> Task :gradle-plugin:compileKotlin UP-TO-DATE
> Task :gradle-plugin:compileJava NO-SOURCE
> Task :gradle-plugin:pluginDescriptors UP-TO-DATE
> Task :gradle-plugin:processResources UP-TO-DATE
> Task :gradle-plugin:classes UP-TO-DATE
> Task :gradle-plugin:jar UP-TO-DATE
> Task :gradle-plugin:inspectClassesForKotlinIC UP-TO-DATE
Checking the license for package Android SDK Build-Tools 30.0.3 in /nix/store/vhpffskv3h1skfaa4vx2lak07fypjrpz-androidsdk/libexec/android-sdk/licenses
License for package Android SDK Build-Tools 30.0.3 accepted.
Preparing "Install Android SDK Build-Tools 30.0.3 (revision: 30.0.3)".
Warning: Failed to read or create install properties file.
Checking the license for package Android SDK Platform 33 in /nix/store/vhpffskv3h1skfaa4vx2lak07fypjrpz-androidsdk/libexec/android-sdk/licenses
License for package Android SDK Platform 33 accepted.
Preparing "Install Android SDK Platform 33 (revision: 3)".
Warning: Failed to read or create install properties file.

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> Could not determine the dependencies of null.
   > Failed to install the following SDK components:
         platforms;android-33 Android SDK Platform 33
         build-tools;30.0.3 Android SDK Build-Tools 30.0.3
     The SDK directory is not writable (/nix/store/vhpffskv3h1skfaa4vx2lak07fypjrpz-androidsdk/libexec/android-sdk)


* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 3s
5 actionable tasks: 5 up-to-date
Error: /home/jenkin/workspace/nix-expo-attempt/android/gradlew exited with non-zero code: 1
Error: /home/jenkin/workspace/nix-expo-attempt/android/gradlew exited with non-zero code: 1
    at ChildProcess.completionListener (/home/jenkin/workspace/nix-expo-attempt/node_modules/@expo/spawn-async/build/spawnAsync.js:52:23)
    at Object.onceWrapper (node:events:629:26)
    at ChildProcess.emit (node:events:514:28)
    at maybeClose (node:internal/child_process:1105:16)
    at ChildProcess._handle.onexit (node:internal/child_process:305:5)
    ...
    at Object.spawnAsync [as default] (/home/jenkin/workspace/nix-expo-attempt/node_modules/@expo/spawn-async/build/spawnAsync.js:17:21)
    at spawnGradleAsync (/home/jenkin/workspace/nix-expo-attempt/node_modules/@expo/cli/build/src/start/platforms/android/gradle.js:72:46)
    at Object.assembleAsync (/home/jenkin/workspace/nix-expo-attempt/node_modules/@expo/cli/build/src/start/platforms/android/gradle.js:52:18)
    at runAndroidAsync (/home/jenkin/workspace/nix-expo-attempt/node_modules/@expo/cli/build/src/run/android/runAndroidAsync.js:36:24)

any help solving this issue would be much appreciated

1 Like

Welll it seems Gradle is trying to download the and install the Android SDK and failing to do so, since the SDK is located on the read-only Nix store.

I guess there should be a way to tell Gradle not to install the SDK, and where to find it.

Hello there,

First, I would like to thank you for pointing me in the right direction. I was trying to figure out how to build a react native app in NixOS and didn’t even think about using flakes.

I copied your flake and ran into the same problem, but I was able to solve it by defining my own android composition with the required versions.

Here is the flake that worked for me

{
  description = "ecommerce";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    flake-utils.url = "github:numtide/flake-utils";
    android-nixpkgs.url = "github:tadfisher/android-nixpkgs";
  };

  outputs = { self, nixpkgs, flake-utils, android-nixpkgs }: flake-utils.lib.eachDefaultSystem (system:
    let
      pkgs = import nixpkgs {
        inherit system;
        config = {
          android_sdk.accept_license = true;
          allowUnfree = true;
        };
      };

      pinnedJDK = pkgs.jdk17;
      buildToolsVersion = "34.0.0";
      ndkVersion = "25.1.8937393";
      androidComposition = pkgs.androidenv.composeAndroidPackages {
        cmdLineToolsVersion = "8.0";
        toolsVersion = "26.1.1";
        platformToolsVersion = "34.0.4";
        buildToolsVersions = [ buildToolsVersion "33.0.1" ];
        includeEmulator = false;
        emulatorVersion = "30.3.4";
        platformVersions = [ "34" ];
        includeSources = false;
        includeSystemImages = false;
        systemImageTypes = [ "google_apis_playstore" ];
        abiVersions = [ "armeabi-v7a" "arm64-v8a" ];
        cmakeVersions = [ "3.10.2" "3.22.1" ];
        includeNDK = true;
        ndkVersions = [ ndkVersion ];
        useGoogleAPIs = false;
        useGoogleTVAddOns = false;
        includeExtras = [
          "extras;google;gcm"
        ];
      };
      sdk = androidComposition.androidsdk;
    in
    {
      devShell = pkgs.mkShell rec {
        buildInputs = with pkgs; [
          # Android
          pinnedJDK
          sdk
          pkg-config
        ];

        JAVA_HOME = pinnedJDK;
        ANDROID_SDK_ROOT = "${androidComposition.androidsdk}/libexec/android-sdk";
        ANDROID_NDK_ROOT = "${ANDROID_SDK_ROOT}/ndk-bundle";

        GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_SDK_ROOT}/build-tools/${buildToolsVersion}/aapt2";
      };
    });
}

This flake got me the closest to working from anything else I’ve read online, but now I’m encountering this error trying to build my react-native app with expo:

      /nix/store/psvyy0kbz423j2apxlzrkwn2zj6iw347-androidsdk/libexec/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld: error while loading shared libraries: libxml2.so.2: cannot open shared object file: No such file or directory
      clang: error: unable to execute command: No such file or directory
      clang: error: linker command failed due to signal (use -v to see invocation)
      ninja: build stopped: subcommand failed.

I’ve tried explicitly adding libxml2.dev to the buildInputs, and setting LD_LIBRARY_PATH = "${pkgs.libxml2.dev}/include" but those don’t work.

Running pkg-config --cflags libxml-2.0 outputs -I/nix/store/37979sqc7yw9ps0c4xl9jjkhq0w1hw8b-libxml2-2.12.7-dev/include/libxml2 from my shell, so I’m not sure what’s going wrong.

Any ideas on how to get around this?

I got past this by adding libxml2 to the LD_LIBRARY_PATH.

shellHook = ''
  export LD_LIBRARY_PATH="${pkgs.libxml2.out}/lib:$LD_LIBRARY_PATH"
'';

Also, for reference, I have a working set up using this android composition:

        androidBuildToolsVersion = "34.0.0";
        androidNdkVersion="26.1.10909125";
        androidComposition = pkgs.androidenv.composeAndroidPackages {
          buildToolsVersions = [ androidBuildToolsVersion];
          platformVersions = [ "34" ];
          cmakeVersions = [ "3.10.2" "3.22.1" ];
          includeNDK = true;
          ndkVersions = [ androidNdkVersion ];
        };
        androidSdk = androidComposition.androidsdk;

After hours of trying I’ve finally managed to successfully build locally with expo on NixOS through distrobox
I used the Arch image (distrobox-create --name arch --image archlinux:latest), ran sudo pacman -Syu and didn’t do much else apart from the obvious npx expo run:android
I think the build ran successfully on the first try!

@arilebedey

distrobox is the most sane solution for early NixOS adopters that don’t want to leave it

i also successfully builded the apk with it

tried raw android-nixpkgs and buildFHSEnv but always getting a runtime dependecy download error

@eletrolitico i’ll try this solution, few flakes i’ve saw using this composeAndroidPackages funtion

seems that you’ve tried using android-nixpkgs

i really liked distrobox

i’ve downloaded standard android-studio deps and i’m managing them with the IDE

standard thing

the flake above is damn simple, i just want to track some programs

installed ubuntu and managed the structure in a stardard way

do you think is worth the time tracking so much deps since react native has the capability of generating android-ish gradle specs without need to change?

since distrobox keeps track of user folder, it can execute standard FHS binaries on the container, avoiding hassle with android nested dynamic deps build time download errors

despite of all, it’s always a learning adventure

IHMO, android developing is the perfect storm on NixOS