From af03050db3fc1eb0ffad9b2784d48a5bc11a8f51 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Mon, 26 Jul 2021 16:09:03 +0200 Subject: [PATCH] build: Make build system more BSD friendly --- Makefile | 15 +++-- README.md | 125 +++++++++++++++++++++++----------------- aux/make_toolchain.sh | 17 +++--- decompressor/Makefile | 2 +- limine-install/Makefile | 1 - stage23/Makefile | 7 ++- stage23/gensyms.sh | 11 ++-- 7 files changed, 102 insertions(+), 76 deletions(-) diff --git a/Makefile b/Makefile index 410fccd0..d4c45a15 100644 --- a/Makefile +++ b/Makefile @@ -2,19 +2,24 @@ PREFIX = /usr/local DESTDIR = PATH := $(shell pwd)/toolchain/bin:$(PATH) -SHELL := /usr/bin/env bash + +NCPUS := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1) TOOLCHAIN = x86_64-elf TOOLCHAIN_CC = $(TOOLCHAIN)-gcc ifeq ($(shell export "PATH=$(PATH)"; command -v $(TOOLCHAIN_CC) ; ), ) -TOOLCHAIN_CC := gcc +TOOLCHAIN_CC := cc endif ifneq ($(MAKECMDGOALS), toolchain) +ifneq ($(MAKECMDGOALS), distclean) +ifneq ($(MAKECMDGOALS), distclean2) ifneq ($(shell export "PATH=$(PATH)"; $(TOOLCHAIN_CC) -dumpmachine | head -c 6), x86_64) -$(error No suitable x86_64 GCC compiler found, please install an x86_64 GCC toolchain or run "make toolchain") +$(error No suitable x86_64 C compiler found, please install an x86_64 C toolchain or run "make toolchain") +endif +endif endif endif @@ -29,7 +34,7 @@ all: .PHONY: bin/limine-install bin/limine-install: - $(MAKE) -C limine-install LIMINE_HDD_BIN=`realpath bin`/limine-hdd.bin + $(MAKE) -C limine-install LIMINE_HDD_BIN="`pwd`/bin/limine-hdd.bin" [ -f limine-install/limine-install ] && cp limine-install/limine-install bin/ || true [ -f limine-install/limine-install.exe ] && cp limine-install/limine-install.exe bin/ || true @@ -149,7 +154,7 @@ test-clean: .PHONY: toolchain toolchain: - aux/make_toolchain.sh "`realpath ./toolchain`" -j`nproc` + MAKE="$(MAKE)" aux/make_toolchain.sh "`pwd`/toolchain" -j$(NCPUS) gnu-efi: git clone https://git.code.sf.net/p/gnu-efi/code --branch=3.0.13 --depth=1 $@ diff --git a/README.md b/README.md index d42c4c58..f4acddc7 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,13 @@ ### What is Limine? -Limine is an advanced x86/x86_64 BIOS/UEFI Bootloader which supports *modern* PC features -such as Long Mode, 5-level paging, and SMP (multicore), to name a few. +Limine is a modern, advanced x86/x86_64 BIOS/UEFI multiprotocol bootloader used +as the reference implementation for the +[stivale protocols](https://github.com/stivale/stivale). ### Support Limine -Like Limine and want to support it? Donate Bitcoin to `bc1q00d59y75crpapw7qp8sea5j5sx6l4k2ssjylf9` :) +Like Limine and want to support it? Donate Bitcoin to +`bc1q00d59y75crpapw7qp8sea5j5sx6l4k2ssjylf9` :) ### Limine's boot menu @@ -15,8 +17,8 @@ Like Limine and want to support it? Donate Bitcoin to `bc1q00d59y75crpapw7qp8sea [Photo by Chris Kane from Pexels](https://www.pexels.com/photo/reflection-of-building-on-body-of-water-at-daytime-166360/) ### Supported boot protocols -* Linux * stivale and stivale2 (Limine's native boot protocols, see [their specifications](https://github.com/stivale/stivale) for details) +* Linux * Multiboot 1 * Chainloading @@ -33,26 +35,30 @@ Like Limine and want to support it? Donate Bitcoin to `bc1q00d59y75crpapw7qp8sea ## Binary releases -For convenience, for point releases, binaries are distributed. These binaries are -shipped in the `-binary` branches and tags of this repository (see [branches](https://github.com/limine-bootloader/limine/branches/all) and [tags](https://github.com/limine-bootloader/limine/tags)). +For convenience, for point releases, binaries are distributed. These binaries +are shipped in the `-binary` branches and tags of this repository +(see [branches](https://github.com/limine-bootloader/limine/branches/all) and +[tags](https://github.com/limine-bootloader/limine/tags)). For example, to clone the latest binary release of the `v2.x` branch one can do ```bash git clone https://github.com/limine-bootloader/limine.git --branch=v2.0-branch-binary --depth=1 ``` -or, to clone a specific binary point release (for example v2.29) +or, to clone a specific binary point release (for example v2.40) ```bash -git clone https://github.com/limine-bootloader/limine.git --branch=v2.29-binary --depth=1 +git clone https://github.com/limine-bootloader/limine.git --branch=v2.40-binary --depth=1 ``` -Additionally, the absolute latest Limine binary release can be obtained by fetching -the `latest-binary` branch: +Additionally, the absolute latest Limine binary release can be obtained by +fetching the `latest-binary` branch: ```bash git clone https://github.com/limine-bootloader/limine.git --branch=latest-binary --depth=1 ``` -`limine-install` binaries are provided for Linux and Windows. In case one wants to -rebuild `limine-install`, simply use `make` in the binary release. +`limine-install` binaries are provided for Linux and Windows. + +In case one wants to rebuild `limine-install`, simply use `make` in the binary +release. ## Building the bootloader @@ -64,35 +70,39 @@ rebuild `limine-install`, simply use `make` in the binary release. ### Building the toolchain -This step can take a long time, but it will ensure that the compiler will work with -Limine. If on an x86_64 host, with GCC or Clang installed, you can also skip to the next paragraph. +This step can take a long time, but it will ensure that the toolchain will work +with Limine. If on an x86_64 host, with GCC or Clang installed, you can skip to +the next paragraph in order to use the system's toolchain instead. -The toolchain building process depends on the following packages: `bash`, `make`, -`curl`, `gcc`, `g++`, `GNU binutils`. +The toolchain's build process depends on the following packages: `GNU make`, +`curl`, `gcc/clang`, `g++/clang++`. Building the toolchain can be accomplished by running: ```bash -make toolchain +make toolchain # (or gmake where applicable) ``` -*The above step may take a while* ### Building Limine -In order to build Limine, the following packages have to be installed: `bash`, `make`, -`git`, `nasm`, `mtools` (optional, necessary to build `limine-eltorito-efi.bin`). -Furthermore, either the toolchain must have been built in the previous paragraph, -or `gcc` or `llvm/clang` must also be installed. -`GNU binutils` is necessary in order to build the UEFI port of Limine. A full -LLVM toolchain without `GNU binutils` can be used to build the BIOS port instead. +In order to build Limine, the following packages have to be installed: +`GNU make`, `git`, `nasm`, `mtools` (optional, necessary to build +`limine-eltorito-efi.bin`). +Furthermore, either the toolchain must have been built in the previous +paragraph, or `gcc` or `llvm/clang` must also be installed. +`GNU binutils` is necessary in order to build the UEFI ports of Limine. A full +LLVM toolchain without `GNU binutils` can be used to build just the BIOS port +instead. -Both the UEFI and BIOS ports of the bootloader can be built, using `GCC/GNU binutils`, with: +Both the UEFI and BIOS ports of the bootloader can be built, using +`GCC/GNU binutils` (which includes the shipped toolchain), with: ```bash -make +make # (or gmake where applicable) ``` -It is possible to pass `make` additional flags, most relevantly, `TOOLCHAIN=` which -allows one to specify an alternative toolchain for the build system to use -(the default is `x86_64-elf`, falling back to no-triple, or host, toolchain). +It is possible to pass `make` additional flags, most relevantly, +`TOOLCHAIN=`, which allows one to specify an alternative toolchain for the build +system to use (the default is `x86_64-elf`, falling back to no-triple, or host, +toolchain). The generated bootloader files are going to be in `bin`. @@ -100,29 +110,36 @@ The generated bootloader files are going to be in `bin`. In order to build the BIOS port fully using clang/LLVM, run `make` as such: ```bash +# (or gmake where applicable) make limine-bios bin/limine-install CC="clang" TOOLCHAIN="llvm" TOOLCHAIN_CC="clang" TOOLCHAIN_LD="ld.lld" ``` -And in order to build the UEFI port using clang/LLVM + `GNU binutils`, run `make` as such: + +And in order to build the UEFI port using clang/LLVM + `GNU binutils`, run +`make` as such: ```bash +# (or gmake where applicable) make limine-uefi TOOLCHAIN="llvm" TOOLCHAIN_CC="clang" TOOLCHAIN_LD="ld" TOOLCHAIN_OBJCOPY="objcopy" ``` +Where `ld` and `objcopy` refer to GNU binutils versions of them. Specify their +full path if necessary. + ## Installing Limine binaries This step is optional as the bootloader binaries can be used from the `bin` or -release directory just fine. This step will only install them in a `share` and `bin` -directories in the specified `PREFIX` (default is `/usr/local`). +release directory just fine. This step will only install them to a `share` and +`bin` directories in the specified `PREFIX` (default is `/usr/local`). -Use `make install` to install Limine binaries, optionally specifying a prefix with a -`PREFIX=...` option. +Use `make install` to install the Limine binaries, optionally specifying a +different prefix with `make install PREFIX=/myprefix`. ## How to use ### UEFI -The `BOOTX64.EFI` file is a vaild EFI application that can be simply copied to the -`/EFI/BOOT` directory of a FAT formatted EFI system partition. This file can be -installed there and coexist with a BIOS installation of Limine (see below) so that -the disk will be bootable by both BIOS and UEFI. +The `BOOTX64.EFI` file is a vaild EFI application that can be simply copied to +the `/EFI/BOOT` directory of a FAT formatted EFI system partition. This file can +be installed there and coexist with a BIOS installation of Limine (see below) so +that the disk will be bootable on both BIOS and UEFI systems. The boot device must to contain the `limine.cfg` file in either the root or the `boot` directory of one of the partitions, formatted @@ -141,7 +158,8 @@ either the root or the `boot` directory of one of the partitions, formatted with a supported file system. ### BIOS/GPT -If using a GPT formatted device, there are 2 options one can follow for installation: +If using a GPT formatted device, there are 2 options one can follow for +installation: * Specifying a dedicated stage 2 partition. * Letting `limine-install` attempt to embed stage 2 within GPT structures. @@ -154,21 +172,23 @@ limine-install <1-based stage 2 partition number> ``` In case one wants to let `limine-install` embed stage 2 within GPT's structures, -simply omit the partition number, and invoke `limine-install` the same as one would -do for an MBR partitioned device. +simply omit the partition number, and invoke `limine-install` the same as one +would do for an MBR partitioned device. The boot device must to contain the `limine.sys` and `limine.cfg` files in either the root or the `boot` directory of one of the partitions, formatted with a supported file system. ### BIOS/UEFI hybrid ISO creation -In order to create a hybrid ISO with Limine, place the `limine-eltorito-efi.bin`, -`limine-cd.bin`, `limine.sys`, and `limine.cfg` files into a directory which will -serve as the root of the created ISO. +In order to create a hybrid ISO with Limine, place the +`limine-eltorito-efi.bin`, `limine-cd.bin`, `limine.sys`, and `limine.cfg` files +into a directory which will serve as the root of the created ISO. (`limine.sys` and `limine.cfg` must either be in the root or inside a `boot` -subdirectory; `limine-eltorito-efi.bin` and `limine-cd.bin` can reside anywhere). +subdirectory; `limine-eltorito-efi.bin` and `limine-cd.bin` can reside +anywhere). -Place any other file you want to be on the final ISO in said directory, then run: +Place any other file you want to be on the final ISO in said directory, then +run: ``` xorriso -as mkisofs -b \ -no-emul-boot -boot-load-size 4 -boot-info-table \ @@ -191,14 +211,15 @@ it would be `boot/limine-cd.bin`. `` is the relative path of `limine-eltorito-efi.bin` inside the root directory. -For example, if it was copied in `/boot/limine-eltorito-efi.bin`, -it would be `boot/limine-eltorito-efi.bin`. +For example, if it was copied in +`/boot/limine-eltorito-efi.bin`, it would be +`boot/limine-eltorito-efi.bin`. ### BIOS/PXE boot The `limine-pxe.bin` binary is a valid PXE boot image. In order to boot Limine from PXE it is necessary to setup a DHCP server with -support for PXE booting. This can either be accomplished using a single DHCP server -or your existing DHCP server and a proxy DHCP server such as dnsmasq. +support for PXE booting. This can either be accomplished using a single DHCP +server or your existing DHCP server and a proxy DHCP server such as dnsmasq. `limine.cfg` and `limine.sys` are expected to be on the server used for boot. @@ -213,5 +234,5 @@ More info on the format of `limine.cfg` can be found in `CONFIG.md`. Limine uses a stripped-down version of [tinf](https://github.com/jibsen/tinf). ## Discord server -We have a [Discord server](https://discord.gg/QEeZMz4) if you need support, info, or -you just want to hang out with us. +We have a [Discord server](https://discord.gg/QEeZMz4) if you need support, +info, or you just want to hang out with us. diff --git a/aux/make_toolchain.sh b/aux/make_toolchain.sh index 5ddb3c9d..4376cd7c 100755 --- a/aux/make_toolchain.sh +++ b/aux/make_toolchain.sh @@ -1,10 +1,9 @@ #!/bin/sh -set -e -set -x +set -ex TARGET=x86_64-elf -BINUTILSVERSION=2.36.1 +BINUTILSVERSION=2.37 GCCVERSION=11.1.0 CFLAGS="-O2 -pipe" @@ -33,8 +32,8 @@ tar -xf ../gcc-$GCCVERSION.tar.gz mkdir build-binutils cd build-binutils ../binutils-$BINUTILSVERSION/configure CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror --enable-targets=x86_64-elf,x86_64-pe -make -make install +$MAKE +$MAKE install cd .. cd gcc-$GCCVERSION @@ -43,8 +42,8 @@ cd .. mkdir build-gcc cd build-gcc ../gcc-$GCCVERSION/configure CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers -make all-gcc -make all-target-libgcc -make install-gcc -make install-target-libgcc +$MAKE all-gcc +$MAKE all-target-libgcc +$MAKE install-gcc +$MAKE install-target-libgcc cd .. diff --git a/decompressor/Makefile b/decompressor/Makefile index 32526362..f1e21fd8 100644 --- a/decompressor/Makefile +++ b/decompressor/Makefile @@ -11,7 +11,7 @@ TOOLCHAIN_LD = $(TOOLCHAIN)-ld TOOLCHAIN_OBJCOPY = $(TOOLCHAIN)-objcopy ifeq ($(shell command -v $(TOOLCHAIN_CC) ; ), ) -TOOLCHAIN_CC := gcc +TOOLCHAIN_CC := cc endif ifeq ($(shell command -v $(TOOLCHAIN_LD) ; ), ) TOOLCHAIN_LD := ld diff --git a/limine-install/Makefile b/limine-install/Makefile index 9e7349e7..11602be9 100644 --- a/limine-install/Makefile +++ b/limine-install/Makefile @@ -5,7 +5,6 @@ PREFIX = /usr/local DESTDIR = LIMINE_HDD_BIN = limine-hdd.bin -BUILD_DIR = $(shell realpath .) CFLAGS = -O2 -pipe -Wall -Wextra diff --git a/stage23/Makefile b/stage23/Makefile index 17cb128e..9dd4043c 100644 --- a/stage23/Makefile +++ b/stage23/Makefile @@ -25,7 +25,7 @@ TOOLCHAIN_OBJDUMP = $(TOOLCHAIN)-objdump TOOLCHAIN_READELF = $(TOOLCHAIN)-readelf ifeq ($(shell command -v $(TOOLCHAIN_CC) ; ), ) -TOOLCHAIN_CC := gcc +TOOLCHAIN_CC := cc endif ifeq ($(shell command -v $(TOOLCHAIN_LD) ; ), ) TOOLCHAIN_LD := ld @@ -46,7 +46,7 @@ endif COM_OUTPUT = false E9_OUTPUT = false -BUILD_ID := $(shell dd if=/dev/urandom count=8 bs=1 2>/dev/null | od -An -t x8 | sed 's/^ /0x/') +BUILD_ID := $(shell dd if=/dev/urandom count=8 bs=1 2>/dev/null | od -An -t x4 | sed 's/^ /0x/g;s/ //g') LIMINE_VERSION := $(shell cat ../version 2>/dev/null || ( git describe --exact-match --tags `git log -n1 --pretty='%h'` 2>/dev/null || ( git log -n1 --pretty='%h' && echo -n "(`git branch --show-current`)" ) ) ) WERROR = -Werror @@ -231,7 +231,8 @@ $(BUILDDIR)/gnu-efi: cp -r ../gnu-efi $(BUILDDIR)/ # gnu-efi's build system is broken and fails to actually detect clang. # This is a workaround. - sed -i 's/-maccumulate-outgoing-args//g' $(BUILDDIR)/gnu-efi/Make.defaults + sed 's/-maccumulate-outgoing-args//g' < "$(BUILDDIR)/gnu-efi/Make.defaults" > sed.tmp + mv sed.tmp "$(BUILDDIR)/gnu-efi/Make.defaults" ifeq ($(TARGET), uefi) diff --git a/stage23/gensyms.sh b/stage23/gensyms.sh index e92203ca..e91a7014 100755 --- a/stage23/gensyms.sh +++ b/stage23/gensyms.sh @@ -1,13 +1,14 @@ -#!/usr/bin/env bash +#!/bin/sh -set -e -o pipefail +set -e +set -o pipefail || true TMP1=$(mktemp) TMP2=$(mktemp) TMP3=$(mktemp) TMP4=$(mktemp) -$1 -t "$2" | sed '/\bd\b/d' | sort > "$TMP1" +$1 -t "$2" | sed '/[[:<:]]d[[:>:]]/d' | sort > "$TMP1" grep "\.text" < "$TMP1" | cut -d' ' -f1 > "$TMP2" grep "\.text" < "$TMP1" | awk 'NF{ print $NF }' > "$TMP3" @@ -16,11 +17,11 @@ echo "global $3_map" >> "$TMP4" echo "$3_map:" >> "$TMP4" if [ "$4" = "32" ]; then - paste -d'$' "$TMP2" "$TMP3" | sed 's/^/dd 0x/g' | sed 's/$/", 0/g' | sed 's/\$/\ndb "/g' >> "$TMP4" + paste -d'$' "$TMP2" "$TMP3" | sed 's/^/dd 0x/g;s/$/", 0/g;s/\$/\ndb "/g' >> "$TMP4" echo "dd 0xffffffff" >> "$TMP4" nasm -f elf32 "$TMP4" -o $3.map.o elif [ "$4" = "64" ]; then - paste -d'$' "$TMP2" "$TMP3" | sed 's/^/dq 0x/g' | sed 's/$/", 0/g' | sed 's/\$/\ndb "/g' >> "$TMP4" + paste -d'$' "$TMP2" "$TMP3" | sed 's/^/dq 0x/g;s/$/", 0/g;s/\$/\ndb "/g' >> "$TMP4" echo "dq 0xffffffffffffffff" >> "$TMP4" nasm -f elf64 "$TMP4" -o $3.map.o fi