tauri-apps / tauri

Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
https://tauri.app
Apache License 2.0
84.59k stars 2.54k forks source link

cross compilling from linux to other platforms #1114

Closed Sparkenstein closed 3 years ago

Sparkenstein commented 3 years ago

Describe the bug I am trying to cross compile tauri app from my ubuntu linux to other platoforms, namely Windows and Mac OS at least. according to tauri build --help I just need to pass "Comma-separated list of target triples". but when I pass anything other than linux toolchain, it fails with different error.

is cross compilation even possible? if yes how I can do that?

Platform and Versions (please complete the following information):

OS: Ubuntu 20.04

Operating System - Linux(5.4.0-53-generic) - linux/x64

Node.js environment
  Node.js - 14.15.0
  tauri.js - 0.13.0

Rust environment
  rustc - 1.48.0
  cargo - 1.48.0
  tauri-bundler - 0.9.4

Global packages
  NPM - 6.14.8
  yarn - 1.22.10

Stack Trace ex apple:

error: failed to run custom build command for `bzip2-sys v0.1.9+1.0.8`

Caused by:
  process didn't exit successfully: `app/src-tauri/target/release/build/bzip2-sys-074c4a9a8f1c8756/build-script-build` (exit code: 1)
  --- stdout
  cargo:rerun-if-env-changed=BZIP2_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64_apple_darwin
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_apple_darwin
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_apple_darwin
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  TARGET = Some("x86_64-apple-darwin")
  OPT_LEVEL = Some("3")
  HOST = Some("x86_64-unknown-linux-gnu")
  CC_x86_64-apple-darwin = None
  CC_x86_64_apple_darwin = None
  TARGET_CC = None
  CC = None
  CROSS_COMPILE = None
  CFLAGS_x86_64-apple-darwin = None
  CFLAGS_x86_64_apple_darwin = None
  TARGET_CFLAGS = None
  CFLAGS = None
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("false")
  CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2,sse3,ssse3")
  running: "cc" "-O3" "-ffunction-sections" "-fdata-sections" "-fPIC" "-m64" "-arch" "x86_64" "-I" "bzip2-1.0.8" "-D_FILE_OFFSET_BITS=64" "-DBZ_NO_STDIO" "-o" "app/src-tauri/target/x86_64-apple-darwin/release/build/bzip2-sys-b40170476e814fe9/out/lib/bzip2-1.0.8/blocksort.o" "-c" "bzip2-1.0.8/blocksort.c"
  cargo:warning=cc: error: x86_64: No such file or directory
  cargo:warning=cc: error: unrecognized command line option ‘-arch’
  exit code: 1

  --- stderr

  error occurred: Command "cc" "-O3" "-ffunction-sections" "-fdata-sections" "-fPIC" "-m64" "-arch" "x86_64" "-I" "bzip2-1.0.8" "-D_FILE_OFFSET_BITS=64" "-DBZ_NO_STDIO" "-o" "app/src-tauri/target/x86_64-apple-darwin/release/build/bzip2-sys-b40170476e814fe9/out/lib/bzip2-1.0.8/blocksort.o" "-c" "bzip2-1.0.8/blocksort.c" with args "cc" did not execute successfully (status code exit code: 1).
nklayman commented 3 years ago

Unfortunately, we will not be able to support cross-compilation anytime soon, due to platform-specific requirements. The target arg is designed for specifying which installers you want to build for your current platform. We recommend using tauri-action to create installers for all platforms.

jaypan13 commented 2 years ago

I needed to do cross compile from Mac for Windows binary for tauri application. I believe should be same for linux host as well. As I had my docker running, was able to follow the instruction mentioned on docker website to build my image and then compile my executable. Just putting here for reference if anybody needed till this is getting added to tauri and if they don't want to use github actions.

Put below dockerfile at the root of your project - FROM rust:latest RUN apt update && apt upgrade -y RUN apt install -y g++-mingw-w64-x86-64 RUN rustup target add x86_64-pc-windows-gnu RUN rustup toolchain install stable-x86_64-pc-windows-gnu WORKDIR /app/src-tauri CMD ["cargo", "build", "--target", "x86_64-pc-windows-gnu"]

Build image docker build . -t tauri/windows

Run the image with your application docker run --rm -v ${pwd}:/app tauri/windows

If you get any exception for permission (which I got for one of my mac) just instead of above docker run command use below commands

  1. docker run --rm -it -v $(pwd):/app tauri/windows bash
  2. mkdir /temp
  3. cp -r /temp /app
  4. cd /temp/app/src-tauri
  5. cargo build --release --target x86_64-pc-windows-gnu
  6. Once image is built, without exiting interactive session, open another terminal and get container id of tauri/windows.
  7. docker cp :/temp/app/src-tauri/target/x86_64-pc-windows-gnu/release/mmwjarvis.exe .
  8. Above command will copy exe to your local machine.

Reference - https://www.docker.com/blog/cross-compiling-rust-code-for-multiple-architectures/

nicolaiunrein commented 1 year ago

For anyone copy/pasting the solution from @Jay1305

Run the image with your application docker run --rm -v ${pwd}:/app tauri/windows

the command should be: docker run --rm -v $(pwd):/app tauri/windows note the braces around pwd

FabianLars commented 1 year ago

For anyone stumbling upon this issue. Keep in mind that the generated .exe file is not really standalone. As of today the caveats (that i can remember right now) are:

kilisio commented 1 year ago

I managed to do this using vagga, a user space container. The content of my vagga.yaml are:

containers:
  tauri:
    auto-clean: true
    setup:
      - !Ubuntu jammy
      - !Sh |
          mkdir -p .vagga/home
          mkdir -p .vagga/run/user/root
      - !Sh |
          # install required packages
          apt install -y software-properties-common gpg gpg-agent gnupg-agent
          add-apt-repository ppa:apt-fast/stable
          apt-add-repository -y universe
          apt-add-repository -y multiverse

          # install base packages
          DEBIAN_FRONTEND=noninteractive apt install -y apt-fast axel aria2
          apt-fast install -y curl ca-certificates build-essential libssl-dev pkg-config cmake make tar
          curl --fail https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor > $KEYRINGS/llvm.gpg; 
          echo "deb [signed-by=$KEYRINGS/llvm.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" > /etc/apt/sources.list.d/llvm.list;
          apt update

          # install llvm
          apt-fast install -y llvm-15 lld-15 clang-15 libobjc-11-dev
          # ensure that clang/clang++ are callable directly
          ln -s clang-15 /usr/bin/clang && ln -s clang /usr/bin/clang++ && ln -s lld-15 /usr/bin/ld.lld
          # We also need to setup symlinks ourselves for the MSVC shims because they aren't in the debian packages
          ln -s clang-15 /usr/bin/clang-cl && ln -s llvm-ar-15 /usr/bin/llvm-lib && ln -s lld-link-15 /usr/bin/lld-link
          # Use clang instead of gcc when compiling binaries targeting the host (eg proc macros, build files)
          update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
          update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100

          # delete resolv.conf file; causes build time dns errors
          rm -rf /etc/resolv.conf
    environ: &envs
      HOME: /work/.vagga/home
      USER: root
      XDG_RUNTIME_DIR: /work/.vagga/run/user/root
      XDG_CACHE_HOME: /work/.vagga/home/.cache
      PATH: /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/work/.vagga/home/.local/bin:/work/.vagga/home/.cargo/bin
      CARGO_HOME: /work/.vagga/home/.cargo
      RUSTFLAGS: '-C target-feature=+crt-static'
    volumes: &vols
      /tmp: !Tmpfs
        size: 1G
  tools:
    auto-clean: true
    setup:
      - !Container tauri
      - !Env PATH: /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/work/.vagga/home/.local/bin:/work/.vagga/home/.cargo/bin
      - !Env CARGO_HOME: /work/.vagga/home/.cargo
      - !Sh |
          # rustup
          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    environ: *envs
    volumes: *vols
commands:
  init: !CapsuleCommand
    run: vagga _capsule build tauri
    description: initialize tauri container
  tools: !CapsuleCommand
    run: vagga _capsule build tools
    description: install and setup tools needed for cross compilation
  dist: !Command
    container: tools
    run: |
      # set rustup to stable version
      rustup default stable

      # add target arch
      rustup target add x86_64-pc-windows-msvc 

      # install cargo build packages
      cargo install cargo-xwin

      # change directory; /work is the root to where vagga.yaml resides; tauri-app is in the same folder as vagga.yaml
      cd /work/tauri-app/src-tauri
      cargo xwin build --release --target x86_64-pc-windows-msvc
    description: cross compile for windows
  sh: !Command
    container: tauri
    run: bash
    description: execute bash

install vagga:

    cd ~/Downloads
    rm -rf vagga*
    wget https://files.zerogw.com/vagga/vagga-0.8.1-86-g505b3ea.tar.xz
    tar -xJf vagga-0.8.1-86-g505b3ea.tar.xz
    cd vagga
        chmod +x install.sh
    sudo ./install.sh

project directory tree:

├── tauri-app
│   ├── src
│   ├── src-tauri
│   ├── .gitignore
│   ├── README.md
├── vagga.yaml

to build, cd to where vagga.yaml is, and run vagga dist

other commands: vagga init - initialize base container vagga tools - install or update build tools vagga sh - open shell inside the container

Exadra37 commented 7 months ago

@Jay1305 To solve permissions issues with running docker, instead of:

Put below dockerfile at the root of your project -
FROM rust:latest
RUN apt update && apt upgrade -y
RUN apt install -y g++-mingw-w64-x86-64 
RUN rustup target add x86_64-pc-windows-gnu 
RUN rustup toolchain install stable-x86_64-pc-windows-gnu 
WORKDIR /app/src-tauri
CMD ["cargo", "build", "--target", "x86_64-pc-windows-gnu"] 

Build image
docker build . -t tauri/windows

Run the image with your application
docker run --rm -v ${pwd}:/app tauri/windows

If you get any exception for permission (which I got for one of my mac) just instead of above docker run command use below commands

Use this:

FROM rust:latest

ARG HOST_USER_NAME="exadra37"
ARG HOST_UID="1000"
ARG HOST_GID="1000"

ENV HOST_USER_NAME=${HOST_USER_NAME} \
    HOST_HOME=/home/${HOST_USER_NAME} \
    HOST_UID=${HOST_UID} \
    HOST_GID=${HOST_GID}

ENV WORKSPACE_PATH=${HOST_HOME}/app/src-tauri

RUN groupadd -g "${HOST_GID}" "${HOST_USER_NAME}" && \
    useradd --create-home --uid "${HOST_UID}" --gid "${HOST_GID}" "${HOST_USER_NAME}"

RUN apt update && apt upgrade -y
RUN apt install -y g++-mingw-w64-x86-64 

USER "${HOST_USER_NAME}"
WORKDIR "${WORKSPACE_PATH}"

RUN rustup target add x86_64-pc-windows-gnu 
RUN rustup toolchain install stable-x86_64-pc-windows-gnu 

# BUILD WITH:
# docker build --build-arg "HOST_USER_NAME=$(id -un)" --build-arg "HOST_UID=$(id -u)" --build-arg "HOST_GID=$(id -g)" . -t tauri/windows

# RUN WIDTH:
# docker run --rm -v $(pwd):/home/$(id -un)/app/src-tauri

CMD ["cargo", "build", "--target", "x86_64-pc-windows-gnu"] 

This image will build a container matching the user in the host, thus solving any permissions issues.

Build:

docker build --build-arg "HOST_USER_NAME=$(id -un)" --build-arg "HOST_UID=$(id -u)" --build-arg "HOST_GID=$(id -g)" . -t tauri/windows

Run:

docker run --rm -v $(pwd):/home/$(id -un)/app/src-tauri tauri/windows

CC @nicolaiunrein