Giter VIP home page Giter VIP logo

hydrun's Introduction

hydrun ("Hydra Run")

Execute a command for the current directory on multiple architectures and operating systems.

hydrun CI Matrix

Overview

Hydra Run, or hydrun, is a thin (<200 SLOC) layer atop Docker buildx and qemu-user-static. It allows one to easily execute a command on different processor architectures and operating systems than the host.

It can, for example, be used for ...

  • Cross-compilation that "just works", without having to set up a cross-compiler (at the cost of longer build times)
  • Multi-architecture testing
  • Building arm64 binaries on GitHub actions, which doesn't support arm64 runners or Linux distros other than Ubuntu
  • Quickly getting an interactive arm64 shell for the current directory on an amd64 host or the other way round
  • Running binaries built against glibc on an Alpine Linux host
  • Making CI release builds locally reproducable and testable, without having to git push and wait

Installation

Static binaries are also available on GitHub releases.

On Linux, you can install them like so:

$ curl -L -o /tmp/hydrun "https://github.com/pojntfx/hydrun/releases/latest/download/hydrun.linux-$(uname -m)"
$ sudo install /tmp/hydrun /usr/local/bin

On macOS, you can use the following:

$ curl -L -o /tmp/hydrun "https://github.com/pojntfx/hydrun/releases/latest/download/hydrun.darwin-$(uname -m)"
$ sudo install /tmp/hydrun /usr/local/bin

On Windows, the following should work (using PowerShell as administrator):

PS> Invoke-WebRequest https://github.com/pojntfx/hydrun/releases/latest/download/hydrun.windows-x86_64.exe -OutFile \Windows\System32\hydrun.exe

You can find binaries for more operating systems and architectures on GitHub releases.

Tutorial

Before continuing, please ensure that you have both Docker buildx and qemu-user-static installed on the host.

To Get an Interactive Shell

As described in the Reference, you can get an interactive shell by using the -i flag. The -a parameter corresponds to an architecture such as amd64, arm64 or ppc64le; the -o flag corresponds to a Docker image such as debian, alpine or fedora. To for example run arm64 Debian on an amd64 host, you can do the following:

$ uname -a
Linux dev-tmp 4.19.0-10-cloud-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64 GNU/Linux
$ hydrun -a arm64 -o debian -i "bash"
root@81647bd6aa02:/data# uname -a
Linux 81647bd6aa02 4.19.0-10-cloud-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) aarch64 GNU/Linux
root@81647bd6aa02:/data# ldd $(which ls)
        libselinux.so.1 => /lib/aarch64-linux-gnu/libselinux.so.1 (0x0000005501868000)
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x000000550189e000)
        /lib/ld-linux-aarch64.so.1 (0x0000005500000000)
        libpcre.so.3 => /lib/aarch64-linux-gnu/libpcre.so.3 (0x0000005501a10000)
        libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000005501a83000)
        libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000005501a97000)

As an Alternative to Cross-Compilation

It is very easy to use hydrun to get binaries for many platforms, without having to set up cross-compilation. Consider the following C hello world program:

/* main.c */
#include <stdio.h>

int main()
{
  printf("Hello, world!\n");

  return 0;
}

Using hydrun, we can now compile it for multiple architectures:

$ ls
ls
main.c
$ hydrun -a amd64,arm64 -o gcc 'gcc -static -o hello-world.linux-$(uname -m) main.c'
$ ls
hello-world.linux-aarch64  hello-world.linux-x86_64  main.c
$ file *
hello-world.linux-aarch64: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, with debug_info, not stripped
hello-world.linux-x86_64:  ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, with debug_info, not stripped
main.c:                    C source, ASCII text

It is also possible to run/test the compiled binaries with it:

$ ls
hello-world.linux-aarch64  hello-world.linux-x86_64  main.c
$ hydrun -i -a arm64 "./hello-world.linux-aarch64"
Hello, world!
$ hydrun -i -a amd64 "./hello-world.linux-x86_64"
Hello, world!

When building larger projects or requiring dependencies, it is recommended to put the commands used into a shell script, conventionally named the Hydrunfile:

$ cat <<EOT>Hydrunfile
#!/bin/bash
apt update
apt install -y build-essentials

gcc -static -o hello-world.linux-$(uname -m) main.c
EOT
$ chmod +x ./Hydrunfile

You can now easily build like so:

$ hydrun -a amd64,arm64 "./Hydrunfile"
$ ls
hello-world.linux-aarch64  hello-world.linux-x86_64  Hydrunfile  main.c

Most of the time you'll probably want to use the Hydrunfile to install toolchains/dependencies and then call your Makefile, the Go compiler, cargo etc.

For an example, check out pojntfx/panrpc.

Usage in GitHub Actions

It is also possible to use hydrun to build multi-architecture binaries in a CI/CD system such as GitHub actions. Continuing with the C example from above, we could automatically build and release amd64 and arm64 binaries to GitHub releases using GitHub actions with the following workflow:

name: hydrun CI

on:
  push:
  pull_request:

jobs:
  build-linux:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Set up hydrun
        run: |
          curl -L -o /tmp/hydrun https://github.com/pojntfx/hydrun/releases/latest/download/hydrun.linux-$(uname -m)
          sudo install /tmp/hydrun /usr/local/bin
      - name: Build with hydrun
        run: hydrun -a amd64,arm64 ./Hydrunfile
      - name: Publish to GitHub releases
        if: ${{ github.ref == 'refs/heads/main' }}
        uses: marvinpinto/action-automatic-releases@latest
        with:
          repo_token: "${{ secrets.GITHUB_TOKEN }}"
          automatic_release_tag: "latest"
          prerelease: false
          files: |
            *.linux*

For an example, check out pojntfx/panrpc.

Reference

$ hydrun --help
Execute a command for the current directory on multiple architectures and operating systems.

See https://github.com/pojntfx/hydrun for more information.

Usage: hydrun [OPTION...] "<COMMAND...>"
  -a, --arch string         Comma-separated list of architectures to run on (default "amd64")
  -c, --context string      Directory to use in the container (default is the current working directory)
  -e, --extra-args string   Extra arguments to pass to the Docker command
  -i, --it                  Attach stdin and setup a TTY
  -j, --jobs int            Maximum amount of parallel jobs (default 1)
  -m, --mount               Enable mounting the directory specified with the context flag (default true)
  -o, --os string           Comma-separated list of operating systems (Docker images) to run on (default "debian")
  -p, --pull                Always pull the specified tags of the operating systems (Docker images)
  -q, --quiet               Disable logging executed commands
  -r, --readyOnly           Mount the directory specified as read-only

Contributing

To contribute, please use the GitHub flow and follow our Code of Conduct.

To build hydrun locally, run:

$ git clone https://github.com/pojntfx/hydrun.git
$ cd hydrun
$ go run main.go --help

Have any questions or need help? Chat with us on Matrix!

Related Projects

If you want to quickly cross-compile your Go app, check out bagop!

License

hydrun (c) 2024 Felicitas Pojtinger and contributors

SPDX-License-Identifier: AGPL-3.0

hydrun's People

Contributors

pojntfx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

hydrun's Issues

allways without cache: Unable to find image 'busybox:latest' locally

i think this is a bug not using the cache:

user@debian:/tmp$ time sudo hydrun -a amd64,arm64,riscv64,ppc64le,s390x,386,arm/v7,arm/v6 -o busybox -i "uname -a"
2021/08/25 18:35:19 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/amd64 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 36ef5c9e8638 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
2021/08/25 18:35:22 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/arm64 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 2e3d3a51835a 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) aarch64 GNU/Linux
2021/08/25 18:35:24 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/riscv64 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux fb05d35f6250 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) riscv64 GNU/Linux
2021/08/25 18:35:27 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/ppc64le busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 98837bbe6814 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) ppc64le GNU/Linux
2021/08/25 18:35:30 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/s390x busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 8db4e8ba787b 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) s390x GNU/Linux
2021/08/25 18:35:33 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/386 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 1aeb1e13768b 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
2021/08/25 18:35:35 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/arm/v7 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux eabfae95557c 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) armv7l GNU/Linux
2021/08/25 18:35:38 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/arm/v6 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 8b160c162ea6 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) armv7l GNU/Linux

real	0m21.977s
user	0m0.232s
sys	0m0.142s
user@debian:/tmp$ time sudo hydrun -a amd64,arm64,riscv64,ppc64le,s390x,386,arm/v7,arm/v6 -o busybox -i "uname -a"
2021/08/25 18:35:43 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/amd64 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 26b1ce26d590 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
2021/08/25 18:35:46 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/arm64 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 779a7ce6cad1 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) aarch64 GNU/Linux
2021/08/25 18:35:49 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/riscv64 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 93c8c9121232 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) riscv64 GNU/Linux
2021/08/25 18:35:52 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/ppc64le busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 053cbd0649ed 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) ppc64le GNU/Linux
2021/08/25 18:35:55 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/s390x busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 7638e5865104 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) s390x GNU/Linux
2021/08/25 18:35:57 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/386 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux c7bbab2b8ca0 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
2021/08/25 18:36:00 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/arm/v7 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux c54bfd26495d 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) armv7l GNU/Linux
2021/08/25 18:36:03 /usr/bin/docker run -it -v /tmp:/data:z --platform linux/arm/v6 busybox /bin/sh -c cd /data && uname -a
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
Linux 494d44328c59 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) armv7l GNU/Linux

real	0m22.765s
user	0m0.257s
sys	0m0.106s
user@debian:/tmp$ 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.