Giter VIP home page Giter VIP logo

binary-gentoo's Introduction

pre-commit Build and smoke test

binary-gentoo

About

binary-gentoo is a collection of simple CLI tools to help build Gentoo packages on a non-Gentoo Linux host, primarily. A typical scenario is operation of an active Gentoo binary package host — an active "binhost".

Secondarily, binary-gentoo can also build Gentoo packages on a Gentoo host with Docker isolation and a full emerge perspective (while not affecting your host system).

There currently four CLI tools that follow the Unix philosophy and are meant to be combined using a glue language like Bash:

  • gentoo-build – Builds a Gentoo package with Docker isolation
  • gentoo-clean — Clean Gentoo pkgdir/distdir files using eclean of app-portage/gentoolkit with Docker isolation
  • gentoo-local-queue – Manages simple file-based push/pop build task queues
  • gentoo-packages — Do operations on pkgdir (other than emaint --fix binhost)
  • gentoo-tree-diff – Lists packages/versions/revisions that one portdir has over another
  • gentoo-tree-sync – Brings a given portdir directory (and its backup) up to date

binary-gentoo is software libre licensed under the GNU Affero GPL version 3 or later license.

Installation

Install Docker, Python >=3.8, pip and rsync and then:

# pip install binary-gentoo

Active Binhost Operation

To set-up an active binhost using binary-gentoo you will likely need a virtual machine with…

  • Enough resources, i.e. probably
    • >=2 virtual cores
    • >=8 GB RAM
    • >=100 GB disk space
  • Some distribution of Linux
  • Auto-updates enabled to stay reasonably secure over time
  • Runtime dependencies installed:
    • Docker
    • Python >=3.8
    • rsync
  • An SSH or an HTTP daemon (to serve the produced binaries to your consuming Gentoo boxes, unless that is done from another machine)
  • An up-to-date copy of the /etc/portage folder to use
  • An up-to-date text file with the names of all packages to build, e.g. generated by EIX_LIMIT=0 eix -I --only-names
  • A set of compile flags (CFLAGS, CXXFLAGS, LDFLAGS, CPU_FLAGS_X86) that works for both the producing machine and the consuming machine(s) and ideally resolve-march-native installed — more on finding the ideal flags below
  • Two portdir copies — one synced with gentoo-tree-sync (or some form of git pull), the other brought back in sync using rsync after a call to gentoo-tree-diff
  • A glue script that…
    • respects your inclusion list (e.g. grep -q -f installed.txt -F <<<"${atom}" || continue if a few false positives are okay)
    • respects your exclusion list (e.g. something like *sys-kernel/*|*-bin-*|*-9999*|*acct-*/*)
    • pushes gentoo-tree-diff news onto the queue
    • pops off the queue, extracts the atom using e.g. jq -r .atom, and then let's gentoo-build do a build
    • loops forever
    • sleeps every now and then
    • runs gentoo-clean every now and then

Determining Ideal Build Flags

Let me give a concrete example.

Consumer Machine

On the consumer machine, we have this hardware situation:

# lscpu | fgrep 'Model name' | sed 's,^.\{33\},,'
Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz

# resolve-march-native
-march=sandybridge -maes --param l1-cache-line-size=64 --param l1-cache-size=32 --param l2-cache-size=3072 -O2 -pipe

# cpuid2cpuflags
CPU_FLAGS_X86: aes avx mmx mmxext pclmul popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3

Producer Machine

On the producer machine, we have this hardware situation:

# lscpu | fgrep 'Model name' | sed 's,^.\{33\},,'
QEMU Virtual CPU version 2.5+

# resolve-march-native
-march=k8-sse3 -maes -mcx16 -mno-3dnow -mno-3dnowa -mpclmul -mpopcnt -mrdrnd -msahf -msse4 -msse4.1 -msse4.2 -mssse3 -mtune=k8 --param=l1-cache-line-size=64 --param=l1-cache-size=64 --param=l2-cache-size=512 -O2 -pipe

# cpuid2cpuflags
CPU_FLAGS_X86: aes mmx mmxext pclmul popcnt rdrand sse sse2 sse3 sse4_1 sse4_2 ssse3

Resulting Producer Build Flags

Simplified, we are looking for flags that are as close to the consumer machines as possible while still resulting in binaries, that both the consumer machines and the producer machine can execute (so that the producer machine is be able to install and run the binaries of dependencies of the package of interest).

For the example above, I ended up with these values for the producer machine:

  • CFLAGS: -march=x86-64 -mtune=sandybridge -maes --param l1-cache-line-size=64 --param l1-cache-size=32 --param l2-cache-size=3072 -mpclmul -mpopcnt -msse4.1 -msse4.2 -mssse3 -O2 -pipe (note -march and -mtune in particular)
  • CXXFLAGS: same as CFLAGS
  • LDFLAGS: whatever portageq envvar LDFLAGS on the consumer machine returns
  • CPU_FLAGS_X86: aes mmx mmxext pclmul popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3 (i.e. without avx and without rdrand)

Design Decisions

  • All code in binary-gentoo must work on a non-Gentoo Linux machine, provided that it has Docker installed and working internet access.

  • Big packages like Chromium need a pile of RAM and CPU time. Therefore, the build defaults to MAKETOPTS=-j1 the package of interest is emerged separate from it dependencies. That allows to build e.g. a package of Chromium in a VM with only 8 GB of RAM.

  • With regard to dependency constraints, some packages can be built without conflicts but not be installed without conflicts. Hence the default is to only install dependencies, but not the package of interest.

binary-gentoo's People

Contributors

dependabot[bot] avatar hartwork avatar vojeroen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

binary-gentoo's Issues

[gentoo-build] Image gentoo/stage3 not working for complex builds

First of all: thanks for creating and sharing these tools. It was exactly what I was looking for!

I have been trying it out and it works like a charm for simple builds. However, I found that the gentoo/stage3 image is not good enough for more complex builds, e.g. based on the default/linux/amd64/17.1/desktop/plasma profile. It starts complaining about circular dependencies and slot conflicts.

I needed a way to create a custom docker image, with more up to date packages and dependency conflicts already resolved, that could be used for these complex builds. I have made some modifications to your tools so that they could be used to generate this image as well.

I'll be submitting a pull request, if you're interested you can review it and see if you are open to merging it in your toolset.

This is the script I'm using to generate my base image, using the modifications in the pull request. It builds up the image in several steps, upgrading outdated packages in the process. The steps for freetype and harfbuzz are necessary to circumvent some dependencies as explained in this forum topic.

In all gentoo-build commands, I'm then using the arg --docker-image gentoo-build-host to use this image for builds.

#!/usr/bin/env bash

# ~/portage-image/ is an empty directory, to keep a default config for the image build
# ~/portage/ contains the /etc/portage config of the consumer system

DOCKER_IMAGE="gentoo/stage3:amd64"
GENTOO_PROFILE="default/linux/amd64/17.1/desktop/plasma"
CFLAGS="<your CFLAGS>"
CXXFLAGS="${CFLAGS}"
LDFLAGS="<your LDFLAGS>"
CPU_FLAGS_X86="<your CPU_FLAGS_X86>"
MAKEOPTS="-j3 "

docker pull "${DOCKER_IMAGE}"

gentoo-image --docker-image "${DOCKER_IMAGE}" --gentoo-profile "default/linux/amd64/17.1" --makeopts "${MAKEOPTS}" --etc-portage ~/portage-image/ --distdir ~/distdir/ --portdir ~/portdir/ --pkgdir ~/pkgdir/ --logdir ~/logdir/ --cflags "${CFLAGS}" --cxxflags "${CXXFLAGS}" --ldflags "${LDFLAGS}" --cpu-flags-x86 "${CPU_FLAGS_X86}" --update @world                                                  

gentoo-image --docker-image "gentoo-build-host" --gentoo-profile "default/linux/amd64/17.1" --makeopts "${MAKEOPTS}" --etc-portage ~/portage-image/ --distdir ~/distdir/ --portdir ~/portdir/ --pkgdir ~/pkgdir/ --logdir ~/logdir/ --cflags "${CFLAGS}" --cxxflags "${CXXFLAGS}" --ldflags "${LDFLAGS}" --cpu-flags-x86 "${CPU_FLAGS_X86}" --use "-truetype -harfbuzz" media-libs/freetype                

gentoo-image --docker-image "gentoo-build-host" --gentoo-profile "default/linux/amd64/17.1" --makeopts "${MAKEOPTS}" --etc-portage ~/portage-image/ --distdir ~/distdir/ --portdir ~/portdir/ --pkgdir ~/pkgdir/ --logdir ~/logdir/ --cflags "${CFLAGS}" --cxxflags "${CXXFLAGS}" --ldflags "${LDFLAGS}" --cpu-flags-x86 "${CPU_FLAGS_X86}" --use "-truetype -harfbuzz" media-libs/harfbuzz                

gentoo-image --docker-image "gentoo-build-host" --gentoo-profile "default/linux/amd64/17.1" --makeopts "${MAKEOPTS}" --etc-portage ~/portage-image/ --distdir ~/distdir/ --portdir ~/portdir/ --pkgdir ~/pkgdir/ --logdir ~/logdir/ --cflags "${CFLAGS}" --cxxflags "${CXXFLAGS}" --ldflags "${LDFLAGS}" --cpu-flags-x86 "${CPU_FLAGS_X86}" --use "truetype harfbuzz" media-libs/freetype                  

gentoo-image --docker-image "gentoo-build-host" --gentoo-profile "${GENTOO_PROFILE}" --makeopts "${MAKEOPTS}" --etc-portage ~/portage/ --distdir ~/distdir/ --portdir ~/portdir/ --pkgdir ~/pkgdir/ --logdir ~/logdir/ --cflags "${CFLAGS}" --cxxflags "${CXXFLAGS}" --ldflags "${LDFLAGS}" --cpu-flags-x86 "${CPU_FLAGS_X86}" --update @world                                                             

cron execution of gentoo-tree-sync fails

Hi,

I'm setting up a cron to daily build new packages, but it isn't working and my logs show the error the input device is not a TTY:

+ gentoo-tree-sync --docker-image gentoo/stage3:amd64 --backup-to /home/portage/portdir-prev /home/portage/portdir
the input device is not a TTY
ERROR: Command "docker run -it --rm -v /home/portage/portdir:/usr/portage:rw -v /home/portage/portdir-prev:/mnt/portage-backup:rw gentoo/stage3:amd64 sh -c 'set -x && rsync --archive --delete --verbose --progress /usr/portage/ /mnt/portage-backup/ && ln -s /usr/portage /var/db/repos/gentoo && env PORTDIR=/usr/portage emerge-webrsync --verbose'" returned non-zero exit status 1.

The same command works perfectly when launched from the command line. I believe it is coming from the -it arguments that are passed to docker run. Is there a specific reason to include these? Otherwise it might be a good idea to remove them.

overlays are not supported

I'm just going to leave this here for future reference but I don't have an immediate need for this myself. Might be an interesting enhancement if/when you have the time, or if users are asking for it.

I noticed that overlays are not supported. I can image there will be users that will want to build packages from other sources/overlays.

Kubler Comparison

What is the differences, and pros/cons of binary-gentoo vs using kubler to build binary packages?

Kubler is designed to build docker images, it builds them inside docker containers (clean), and will keep the binary packages cached on the host file system. It requires bash4 and docker.

I raised same thing on Kubler's end edannenberg/kubler#207

[gentoo-tree-sync] Idea: Also handle the "old portdir" sync

Requirement
In order for gentoo-tree-diff to work, you need an old and a new portdir. The obvious way to handle this, is to do something like this:

rm -rf portdir-old
mv portdir portdir-old
mkdir portdir
gentoo-tree-sync portdir
gentoo-tree-diff portdir-old portdir

The problem with this way, is that the first command (rm -rf portdir-old) will fail because the permissions of the files in that directory are set in such a way that the user running this script, cannot delete them. In fact, the content of portdir is owned by root (as set by the container that is executed by the gentoo-tree-sync command).

As I don't want the "portage user" on my machine to have sudo rights, there is no way for that user to delete the old portdir. It would be interesting if binary-gentoo offers a nice way to handle this, because keeping an old and a new portdir is needed for it to work.

Proposal for solution
The maintenance of the old portdir could be taken care of by gentoo-tree-sync. Something like gentoo-tree-sync --old-portdir portdir-old portdir, which would then do the following:

  • delete the contents of the directory specified by --old-portdir
  • move the contents of portdir to the directory specified by --old-portdir
  • sync the portage tree to portdir (existing functionality)

If you have other ideas, let me know. If you agree that this should be solved by binary-gentoo and when agreed upon a solution, I can see if I can implement this.

Chroot build

Im currious if you can do a marginally less isolated build ie pop a stage 3 , and inject libs ie emerge ?x
or mount local files to the chroot..

Ie debian rpi4 aarch64, ie for gentoo or rpi4 distro.

Namely ghc is a royally a pia.. , ie inject via bind mounts ghc , build gentoo ghc , move over to gentoo on rpi.. via usb , upgrade from then on to hearts content..
Few esoteric forensics tools , that i wish weren't in haskell.. but...

Sometimes they have ghc-aarch64 starters on gentoo, but not oftentimes.. of lately .. nor a bin using deb.. to limp the initial compilation along..

Even a debian chroot to gentoo in a docker for ghc that spits out ghc packaged would be a plus.

Anyway a script to do this even as an addition could prove useful..

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.