diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..315a863 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,77 @@ +name: Automated Releases + +on: + push: + branches: + - main + tags: + - "v*" + pull_request: {} + +jobs: + automated-releases: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + target: + - aarch64-linux-musl + - arm-linux-musleabi + - i686-linux-musl + - mips-linux-musl + - mipsel-linux-musl + - x86_64-linux-musl + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.target }} + cancel-in-progress: true + + env: + TARGET: "${{ matrix.target }}" + OUTPUT: "output/${{ matrix.target }}/bin" + + steps: + - name: Install Prerequisites + run: | + sudo apt-get install -y \ + gcc g++ \ + make autoconf automake libtool patch \ + flex bison \ + wget \ + tar gzip bzip2 xz-utils + + - name: Checkout Repo + uses: actions/checkout@v3 + + - name: Build Toolchain + run: make -w -j2 TARGET="${TARGET}" musl + + - name: Build Static Binaries + run: make -w -j2 TARGET="${TARGET}" all + + - name: Binary Listing + run: cd "${OUTPUT}" && ls -al "./"* + + - name: Binary Types + run: cd "${OUTPUT}" && file "./"* + + - name: Binary Hashes + run: cd "${OUTPUT}" && sha1sum "./"* | tee "hashes.sha1" + + - name: Package Results + run: tar --strip-components=3 -czvf "${TARGET}.tar.gz" "${OUTPUT}/"* + + - name: Package Hash + run: sha1sum "${TARGET}.tar.gz" + + - name: Create Release + uses: softprops/action-gh-release@v1 + if: github.event_name == 'push' + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_type == 'tag' && github.ref_name || 'latest' }} + prerelease: ${{ github.ref_type != 'tag' }} + generate_release_notes: ${{ github.ref_type == 'tag' }} + files: "${{ matrix.target }}.tar.gz" + fail_on_unmatched_files: true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63aa482 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Placeholder directories +output +sources +sysroot + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6359a83 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,59 @@ +# Contributing + +Adding your favorite program to this project is easy! + + +## Getting Started + +Starting by taking a look at the [makefile template](include/_template.mak) provided with this project. +It includes all of the required makefile components in addition to an explanation of what each section does. + +Next, take a look at some of the makefiles for simpler programs like [tcpdump](include/tcpdump.mak) and libraries like [zlib](include/zlib.mak). + +Lastly, experiment with what it takes to compile your program manually. +You'll need to work out details such as: + +- Is running `autoreconf` required? + - For some packages on certain build machines (e.g. [ncurses](include/ncurses.mak) on macOS), running autoreconf will cause the build to fail. + - For other packages, autoreconf (e.g. [netcat](include/netcat.mak)) is mandatory. + - If possible, avoid running autoreconf unless absolutely necessary. +- Does the package use a regular GNU Autoconf `configure` script or something custom? + - Regular configure scripts should always use the standard values for `--host`, `--prefix`, etc. + - Custom configure scripts may need these values supplied differently (e.g. [OpenSSL](include/openssl.mak)). + - Other packages may not use a configure script at all (e.g. [busybox](include/busybox.mak) and [zstd](include/zstd.mak)). +- What options or flags are required for a static build? +- Does the package use libtool? +- Does the package depend on any libraries? + +To make experimentation easier, use `make TARGET=... env` to dump the environment variables set by the toolkit. +Importing these values into the shell environment will "activate" the cross-compiler toolchain so that most +makefiles and configuration scripts will use the cross-compiler instead of the system's default compiler. + + +## Selecting a Program + +When selecting a program to contribute, it should: +- Be written in C/C++. +- Be reasonably small in size. +- Be something that other people might want to use. +- Result in a self-contained binary with no external dependencies. + + +## Pull Request Requirements + +When submitting a pull request, please ensure that: + +- The output program(s) are *actually* statically linked. + - For some packages, `--disable-shared` and `--enable-static` alone are not enough (e.g. [curl](include/curl.mak)). + - The `file` utility can be used to determine if the output program was statically linked. +- The output program(s) are *actually* cross-compiled for the selected target. + - Some packages like [busybox](include/busybox.mak) may attempt to ignore the toolkit's + environment variables and use the system's default compiler instead. + - The `file` utility can be used to approximate the output program's target. + - `sysroot/[TARGET]/bin/[TARGET]-readelf -A` can be used to inspect detailed architecture information. +- The package builds successfully for multiple cross-compiler targets. + - Packages that depend on platform-specific assembly code may fail to build for other targets. +- Makefiles for any required libraries are also included in the pull request. + +While not required, I strongly recommending testing your package by building it with the [docker_build.sh](docker_build.sh) script. +This is a good way to check for reproducibility, missing dependencies, or build ordering issues. \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d9492e8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +# Despite convention, Ubuntu's "latest" tag points to the latest LTS release. +FROM ubuntu:latest + +LABEL org.opencontainers.image.authors="llamasoft@rm-rf.email" +LABEL org.opencontainers.image.url="https://github.com/llamasoft/static-builder" + +# This is all that's required for the build process. +# Some packages are already installed but are included for completeness. +RUN apt-get update \ + && apt-get install -y \ + gcc g++ \ + make autoconf automake libtool patch \ + flex bison \ + wget \ + tar gzip bzip2 xz-utils + +RUN mkdir -p "/build" +COPY "Makefile" "/build/" +COPY "include" "/build/include" +VOLUME "/build" + +WORKDIR "/build" +ENTRYPOINT ["/usr/bin/make", "-w"] diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..3258283 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 llamasoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..46eeda6 --- /dev/null +++ b/Makefile @@ -0,0 +1,335 @@ +########################## Usage ########################### + +define USAGE +======================================== +USAGE: make TARGET=musl-toolchain [ARCH=cpu-arch] [program ...] +The TARGET value must be a musl-cross-make toolchain target. +The optional ARCH value must be a valid GCC -march CPU type. + +Examples targets: + TARGET=arm-linux-musleabi + TARGET=arm-linux-musleabihf ARCH=armv7-a+fp + TARGET=mips-linux-musl + TARGET=mipsel-linux-muslsf + TARGET=x86_64-linux-musl + ... + For additional targets, consult the musl manual: + https://musl.libc.org/doc/1.1.24/manual.html + +Goals: + all + Builds all available programs: + $(sort $(ALL_PROGRAMS)) + default + Builds default subset of programs: + $(sort $(DEFAULT_PROGRAMS)) + musl + Builds the cross-compiler toolchain for TARGET. + archlist + Shows available CPU architectures for TARGET. + env + Shows shell commands to activate TARGET toolchain. + usage + Shows this message. + mostlyclean + Removes source code and temporary objects. + clean + Removes cross-compiler toolchain, sources, and objects. +======================================== +endef + +required_features := else-if order-only second-expansion target-specific +missing_features := $(filter-out $(.FEATURES),$(required_features)) +ifneq (,$(missing_features)) +$(error This version of make is missing required features: $(required_features)) +endif + + + +########################## Flags ########################### + +# We need access to `command -v` to check if programs exist. +SHELL := /bin/bash + +CFLAGS = -g0 -Os +CXXFLAGS = $(CFLAGS) + +# Just in case the user forgets that we're doing static builds. +override LDFLAGS += -static +override CFLAGS += -static $(if $(ARCH),-march=$(ARCH)) +override CXXFLAGS += -static $(if $(ARCH),-march=$(ARCH)) + +# Some builds need to be explicitly given these paths. +override LDFLAGS += -L$(SYSROOT)/lib +override CFLAGS += -I$(SYSROOT)/include +override CXXFLAGS += -I$(SYSROOT)/include + +# Attempt to make builds reproducible. +# For most builds, this will get you a byte-for-byte identical output +# regardless of which machine you cross-compiled from. Failing that, +# two builds from the same build machine are identical. +ifneq (0,$(REPRODUCIBLE)) +export SOURCE_DATE_EPOCH := 0 +override CFLAGS += -ffile-prefix-map=$(MAKEFILE_DIR)=. +override CXXFLAGS += -ffile-prefix-map=$(MAKEFILE_DIR)=. +endif + +# Intermediate files will be larger and build times will be slightly longer +# but the final binary can sometimes be much smaller. +ifneq (0,$(EXTRA_SMALL)) +override LDFLAGS += -Wl,--gc-sections +override CFLAGS += -ffunction-sections -fdata-sections +override CXXFLAGS += -ffunction-sections -fdata-sections +endif + +# The download command should take two extra arguments: OUTPUT_FILE URL +ifneq (,$(shell command -v curl)) +DOWNLOAD := curl --silent --show-error -L -o +else ifneq (,$(shell command -v wget)) +DOWNLOAD := wget --no-verbose -c -O +else +$(error No curl or wget detected, please manually specify the DOWNLOAD command.) +endif + +# LibreSSL is a drop-in replacement for OpenSSL that's smaller and easier to build. +OPENSSL := libressl +# OPENSSL := openssl + +BUILD_TRIPLE := $(shell $(CC) -dumpmachine 2>/dev/null) +CONFIGURE_DEFAULTS = --build="$(BUILD_TRIPLE)" --host="$(TARGET)" --prefix="$(SYSROOT)" + + +########################## Paths ########################### + +# NOTE: these paths need to be absolute. +# All other paths are built from these, including the toolchain binaries. +# A relative path would be useless once we `cd` into a source code directory. +MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +MAKEFILE_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH))) + +SOURCE_ROOT := $(MAKEFILE_DIR)/sources +OUTPUT_ROOT := $(MAKEFILE_DIR)/output +TOOLCHAIN_ROOT := $(MAKEFILE_DIR)/sysroot + +SYSROOT := $(TOOLCHAIN_ROOT)/$(TARGET) +OUTPUT := $(OUTPUT_ROOT)/$(TARGET) +PKG_CONFIG_PATH := $(TOOLCHAIN_ROOT)/lib/pkgconfig + +# Having whitespace in our build paths _will_ result in failures. +# In addition to failures, a path containing whitespace may cause an +# improperly quoted $(RM) to delete things outside of the build directory. +ifneq (1,$(words $(MAKEFILE_DIR))) +$(error Whitespace detected in build path. This _will_ result in build failures.) +endif + + +######################## Functions ######################### + +# These "activate" functions are meant to be used with $(eval $(call ...)) +define activate_paths +$(1): export SYSROOT=$(SYSROOT) +$(1): export PREFIX=$(SYSROOT) +$(1): export PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) +endef + +define activate_toolchain +$(call activate_paths,$(1)) +$(1): export AR=$(SYSROOT)/bin/$(TARGET)-ar +$(1): export AS=$(SYSROOT)/bin/$(TARGET)-as +$(1): export CC=$(SYSROOT)/bin/$(TARGET)-cc +$(1): export CXX=$(SYSROOT)/bin/$(TARGET)-g++ +$(1): export LD=$(SYSROOT)/bin/$(TARGET)-ld +$(1): export NM=$(SYSROOT)/bin/$(TARGET)-nm +$(1): export OBJCOPY=$(SYSROOT)/bin/$(TARGET)-objcopy +$(1): export OBJDUMP=$(SYSROOT)/bin/$(TARGET)-objdump +$(1): export RANLIB=$(SYSROOT)/bin/$(TARGET)-ranlib +$(1): export READELF=$(SYSROOT)/bin/$(TARGET)-readelf +$(1): export STRIP=$(SYSROOT)/bin/$(TARGET)-strip +endef + +# Downloads and unpacks a tar file. +define untar_to_dir +mkdir -p "$(dir $(2))" +$(DOWNLOAD) "$(2).tgz" "$(1)" +mkdir -p "$(2).tmp" +tar --strip-components=1 -C "$(2).tmp" -xf "$(2).tgz" +$(RM) "$(2).tgz" +mv "$(2).tmp" "$(2)" +endef + +# Creates variables based on library names. +# This makes it easier for packages to depend on libraries +# that will be created by other packages. +# For example $(eval $(call export_library,/path/to/libsomething.a)) +# will set libsomething := /path/to/libsomething.a +define export_library +$(basename $(notdir $(1))) := $(1) +endef + +# Creates generic recipe chains for a package's binaries and libraries. +# This is where the magic happens! +# This would have been much cleaner to create with $(file &1 | grep -F "valid arguments" || true + -@ "$(CC)" --target-help 2>&1 | sed -n '/Known.*-march/,/^$$/p' || true + +# Cleans all sources except for musl. +.PHONY: mostlyclean +mostlyclean: + - $(RM) -r \ + $(filter-out $(MUSL_SRC),$(wildcard $(SOURCE_ROOT)/*-*)) \ + "$(SOURCE_ROOT)/"*.tgz \ + "$(SOURCE_ROOT)/"*.tmp + +# Cleans all compiled results. +.PHONY: clean +clean: mostlyclean +ifneq (,$(TARGET)) + - $(RM) -r "$(OUTPUT)" + - $(RM) -r "$(SYSROOT)" +else + - $(RM) -r "$(OUTPUT_ROOT)" + - $(RM) -r "$(TOOLCHAIN_ROOT)" +endif + +# Cleans musl toolchain artifacts. +.PHONY: distclean +distclean: clean + - $(RM) -r "$(SOURCE_ROOT)" + +# Dumps the toolchain variables for use in shell environments. +# Meant to be used as: eval "$(make --silent TARGET=toolchain env)" +.PHONY: env +env: +ifeq (,$(TARGET)) + $(error TARGET is required to dump environment variables) +endif + $(info $(subst : ,,$(call activate_toolchain))) + $(info LDFLAGS='$(LDFLAGS)') + $(info CFLAGS='$(CFLAGS)') + $(info CXXFLAGS='$(CXXFLAGS)') \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f6322bf --- /dev/null +++ b/README.md @@ -0,0 +1,164 @@ +# Static Cross-compiler Automation Toolkit +## A toolkit that simplifies cross-compiling static binaries for any Linux target. + +[![Automated Releases](https://github.com/llamasoft/static-cross-bins/actions/workflows/release.yml/badge.svg)](https://github.com/llamasoft/static-cross-bins/actions/workflows/release.yml) + +Currently supported: +- Binaries: + [bash](include/bash.mak), + [busybox](include/busybox.mak), + [curl](include/curl.mak), + [dropbear](include/dropbear.mak), + [netcat](include/netcat.mak), + [nmap](include/nmap.mak), + [socat](include/socat.mak), + [strace](include/strace.mak), + [tcpdump](include/tcpdump.mak), + [zstd](include/zstd.mak) +- Libraries: + [curl](include/curl.mak), + [libressl](librinclude/libressl.mak), + [ncurses](ncuinclude/ncurses.mak), + [openssl](opeinclude/openssl.mak), + [pcap](include/pcap.mak), + [readline](readinclude/readline.mak), + [wolfssl](wolinclude/wolfssl.mak), + [zlib](include/zlib.mak) + +🤖 Pre-compiled binaries for common targets can be found on the [releases page](https://github.com/llamasoft/static-cross-bins/releases)! + +**Pull requests are welcome!** +Want to add your favorite tool? See [CONTRIBUTING](CONTRIBUTING.md) for details! + + +# 💻 Supported Targets 💻 + +Any Linux target supported by [musl-cross-make](https://github.com/richfelker/musl-cross-make) is supported. +This includes, but is not limited to: + +- ARM +- MicroBlaze +- MIPS +- PowerPC +- RISC-V +- x86 +- x86_64 + +For a complete list of targets, consult the latest [musl documentation](https://musl.libc.org/doc/1.1.24/manual.html). + +⭐️ Once a target toolchain has been built, a list of all supported CPU *architectures* can be displayed with: +`make TARGET=your-target-here archlist` + + +# 🧰 Build Requirements 🧰 + +This project uses [musl-cross-make](https://github.com/richfelker/musl-cross-make) to build a cross-compiler toolchain and compile all prerequisites for the output binaries. +As a result, only a small number of common build packages are required: + +- curl *or* wget +- GCC + recommended packages + - gcc, g++, make, autoconf, autotools, libtool, flex, bison +- Archive utilities + - tar, gzip, bzip2, xz-utils + +Alternately, the provided [Dockerfile](Dockerfile) and [build.sh](build.sh) script can be used for a reproducible build environment. + +⭐️ Builds have been successfully completed on Ubuntu, Debian, macOS, and RaspberryPi OS. + + +# 🛠 Usage 🛠 + +``` +USAGE: make TARGET=musl-toolchain [ARCH=cpu-arch] [program ...] +The TARGET value must be a musl-cross-make toolchain target. +The optional ARCH value must be a valid GCC -march CPU type. + +Examples targets: + TARGET=arm-linux-musleabi + TARGET=arm-linux-musleabihf ARCH=armv7-a+fp + TARGET=mips-linux-musl + TARGET=mipsel-linux-muslsf + TARGET=x86_64-linux-musl + ... + For additional targets, consult the musl manual: + https://musl.libc.org/doc/1.1.24/manual.html + +Goals: + all + Builds all available programs: + ... + default + Builds default subset of programs: + ... + musl + Builds the cross-compiler toolchain for TARGET. + archlist + Shows available CPU architectures for TARGET. + env + Shows shell commands to activate TARGET toolchain. + usage + Shows this message. + mostlyclean + Removes source code and temporary objects. + clean + Removes cross-compiler toolchain, sources, and objects. +``` + +## Basic Examples + +Building the **default** subset of binaries for MIPS: +`make TARGET=mips-linux-musl default` + +Building **all** binaries for the ARMv7 architecture (with hardware floating point support): +`make TARGET=arm-linux-musleabihf ARCH=armv7-a+fp all` + +Building **only the cross-compiler** toolchain for a generic ARM target: +`make TARGET=arm-linux-musleabi musl` + +**Listing** all ARCH values supported by the x86 target: +`make TARGET=x86-linux-musl archlist` + +Output shell **environment variables** for manual cross-compiling: +`make TARGET=mipsel-linux-muslsf env` + +## Advanced Examples + +Optimizing binaries for speed instead of size: +`make TARGET=... CFLAGS="-O2" all` + +Build binaries using OpenSSL instead of LibreSSL: +`make TARGET=... OPENSSL=openssl all` + +Tweaking a package's configuration using `*_CONFIG` flags: +`make TARGET=... curl CURL_CONFIG="--extra-curl-configs"` + + +# 📖 FAQ 📖 + +### What inspired this project? +I occasionally tinker with embedded Linux environments that don't have access to package managers or compilers. +Being able to statically cross-compile my favorite tools makes it much easier to work on those systems. + +### How long does this take to build? +Using `make -j` for parallel builds, the musl cross-compiler can be built in 15-30 minutes depending on the target. +From there, building all of the programs usually takes 10-15 minutes. + +For example build times, check this project's GitHub Actions workflows. + +### What if I want *even smaller* binaries? +You can shrink the binaries by a further 40% by using a packer like [UPX](https://upx.github.io/). +I've decided not to include UPX for a few reasons: +- Some anti-virus programs will detect UPX packed binaries as potentially malicious. +- I wanted the pre-compiled binaries on the releases page to be reproducible. +- Running packed binaries requires additional memory, something most embedded environments don't have. + +### Why distribute pre-compiled binaries? +Because some people are lazy and I absolutely respect that. 😎 + +### Are the pre-compiled binaries [reproducible](https://reproducible-builds.org/)? +To the best of my ability, *yes*. +Building the binaries using the [docker_build.sh](docker_build.sh) script *should* result in byte-for-byte identical results. +Alternately, fork the repo and trigger the [GitHub Actions workflow](.github/workflows/release.yml) that builds and publishes the releases. + +### When will __________ be added to the toolkit? +As soon as you submit a [pull request](CONTRIBUTING.md) to add it! 😉 diff --git a/docker_build.sh b/docker_build.sh new file mode 100755 index 0000000..bd2da28 --- /dev/null +++ b/docker_build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Use this script for reproducible builds! +# Any arguments supported by make are supported here. +# Example: ./docker_build.sh -j TARGET=arm-linux-musleabi all +set -e + +docker build -t static-builder . +docker run -it -v "${PWD}/output":"/build/output" --rm static-builder "$@" \ No newline at end of file diff --git a/include/_template.mak b/include/_template.mak new file mode 100644 index 0000000..83972c3 --- /dev/null +++ b/include/_template.mak @@ -0,0 +1,64 @@ +NAME := example +EXAMPLE_VERSION := 1.2.3 + +# The download URL should point to a tar archive of some sort. +# On most systems, tar will handle most compression formats, so +# tar/gzip, tar/bzip2, etc, are fine. If the archive is in a different +# format, a recipe to create $(SRC) will need to be provided. +EXAMPLE_URL := https://example.com/releases/example-$(EXAMPLE_VERSION).tar.gz + +# The list of all programs that the package builds. +# These targets can be called and built from the command line. +# If the package provides no programs, leave this list empty. +EXAMPLE_PROGRAMS := program-a program-b program-c + +# The list of library names that the package builds. +# If the package provides no libraries, leave this list empty. +# Libraries will be represented as variables so that other packages may use them. +# For example, libsomething.a will be available as $$(libsomething). +EXAMPLE_LIBRARIES := libexample.a + +# Allow the user to add any make, autoconf, or configure options that they want. +# Feel free to put any reasonable default values here. +EXAMPLE_CONFIG = --disable-unpopular-feature --disable-bulky-feature + +# This creates the recipe chain that downloads, extracts, builds, and strips +# the binaries created by this package. This makes it so that only the main +# build recipe's contents need to be provided by the package author. +$(eval $(call create_recipes, \ + $(NAME), \ + $(EXAMPLE_VERSION), \ + $(EXAMPLE_URL), \ + $(EXAMPLE_PROGRAMS), \ + $(EXAMPLE_LIBRARIES), \ +)) + +# This is the main build recipe! +# Using $(BUILD_FLAG) as a target, it must compile the sources in $(SRC) and +# install the resulting programs and libraries into $(SYSROOT). If the package +# depends on any libraries, add their variable representations to this target's +# dependency list. For example, if the package depends on libsomething.a, +# add $$(libsomething) to $(BUILD_FLAG)'s dependencies. +$(BUILD_FLAG): $$(libz) +# This activates the cross-compiler toolchain by setting/exporting a lot of variables. +# Without this, builds would default to the system's compilers and libraries. + $(eval $(call activate_toolchain,$@)) +# The configure step defines what features should be enabled for the program. +# If available, the --host and --prefix values should always be the values below. +# Try to only hard-code the flags that are critical to a successful static build. +# Optional flags should be put in EXAMPLE_CONFIG so the user can override them. + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --enable-static --disable-shared \ + --with-zlib="$(SYSROOT)" \ + $(EXAMPLE_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install + +# All programs should add themselves to the ALL_PROGRAMS list. +# ALL_PROGRAMS += $(EXAMPLE_PROGRAMS) + +# Only programs that most users would want should be added to DEFAULT_PROGRAMS. +# DEFAULT_PROGRAMS += $(EXAMPLE_PROGRAMS) \ No newline at end of file diff --git a/include/bash.mak b/include/bash.mak new file mode 100644 index 0000000..7cd5d19 --- /dev/null +++ b/include/bash.mak @@ -0,0 +1,29 @@ +NAME := bash +BASH_VERSION := 5.1.16 +BASH_URL := https://ftp.gnu.org/gnu/bash/bash-$(BASH_VERSION).tar.gz +BASH_PROGRAMS := bash +BASH_LIBRARIES := + +BASH_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(BASH_VERSION), \ + $(BASH_URL), \ + $(BASH_PROGRAMS), \ + $(BASH_LIBRARIES), \ +)) + +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --enable-static-link \ + $(BASH_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install + +ALL_PROGRAMS += $(BASH_PROGRAMS) +DEFAULT_PROGRAMS += $(BASH_PROGRAMS) \ No newline at end of file diff --git a/include/busybox.mak b/include/busybox.mak new file mode 100644 index 0000000..9b03365 --- /dev/null +++ b/include/busybox.mak @@ -0,0 +1,39 @@ +NAME := busybox +BUSYBOX_VERSION := 1.35.0 +BUSYBOX_URL := https://busybox.net/downloads/busybox-$(BUSYBOX_VERSION).tar.bz2 +BUSYBOX_PROGRAMS := busybox +BUSYBOX_LIBRARIES := + +BUSYBOX_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(BUSYBOX_VERSION), \ + $(BUSYBOX_URL), \ + $(BUSYBOX_PROGRAMS), \ + $(BUSYBOX_LIBRARIES), \ +)) + +# The CONFIG_ options need to be passed to almost every make +# invocation unless we modify the config files directly. +BUSYBOX_DEFAULTS := CONFIG_PREFIX="$(SYSROOT)" CONFIG_STATIC="y" +BUSYBOX_DEFAULTS += CONFIG_INSTALL_APPLET_DONT="y" +BUSYBOX_DEFAULTS += CONFIG_INSTALL_APPLET_SYMLINKS="n" + +# NOTE: the busybox makefile doesn't respect our exported toolchain +# variables (CC, LD, etc) so the build must use make's -e flag to +# force our environment variables to take precedence. +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" defconfig + $(MAKE) -C "$(SRC)" -e \ + $(BUSYBOX_DEFAULTS) \ + $(BUSYBOX_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" -e install \ + $(BUSYBOX_DEFAULTS) \ + $(BUSYBOX_CONFIG) + +ALL_PROGRAMS += $(BUSYBOX_PROGRAMS) +DEFAULT_PROGRAMS += $(BUSYBOX_PROGRAMS) \ No newline at end of file diff --git a/include/curl.mak b/include/curl.mak new file mode 100644 index 0000000..457c79d --- /dev/null +++ b/include/curl.mak @@ -0,0 +1,49 @@ +NAME := curl +CURL_VERSION := 7.83.1 +CURL_URL := https://github.com/curl/curl/releases/download/curl-$(subst .,_,$(CURL_VERSION))/curl-$(CURL_VERSION).tar.gz +CURL_PROGRAMS := curl +CURL_LIBRARIES := libcurl.a + +CURL_CONFIG = + +# WolfSSL results in a much smaller binary (around 1MB). +# The only reason you'd use OpenSSL here is if you already +# need the library for other things and don't care about size. +CURL_SSL := wolfssl +# CURL_SSL := openssl + +$(eval $(call create_recipes, \ + $(NAME), \ + $(CURL_VERSION), \ + $(CURL_URL), \ + $(CURL_PROGRAMS), \ + $(CURL_LIBRARIES), \ +)) + +# This package uses libtool and needs LDFLAGS to include -all-static +# in order to produce a statically linked binary. However, the +# configure script doesn't use libtool, so the flag must be injected +# at built-time only, otherwise the configure will fail. +# See https://stackoverflow.com/a/54168321/477563 +$(BUILD_FLAG): $$(libz) + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --disable-shared --enable-static --with-$(CURL_SSL) \ + $(CURL_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(filter -L%,$(LDFLAGS))" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" LDFLAGS="$(LDFLAGS) -all-static" + $(MAKE) -C "$(SRC)" install-exec + +# Update dependencies based on chosen SSL library. +ifeq ($(CURL_SSL),wolfssl) +$(BUILD_FLAG): $$(libwolfssl) +else ifeq ($(CURL_SSL),openssl) +$(BUILD_FLAG): $$(libssl) +else +$(error Invalid CURL_SSL selection: $(CURL_SSL)) +endif + +ALL_PROGRAMS += $(CURL_PROGRAMS) +DEFAULT_PROGRAMS += $(CURL_PROGRAMS) \ No newline at end of file diff --git a/include/dropbear.mak b/include/dropbear.mak new file mode 100644 index 0000000..1e569b1 --- /dev/null +++ b/include/dropbear.mak @@ -0,0 +1,33 @@ +NAME := dropbear +DROPBEAR_VERSION := 2022.82 +DROPBEAR_URL := https://github.com/mkj/dropbear/archive/refs/tags/DROPBEAR_$(DROPBEAR_VERSION).tar.gz +DROPBEAR_PROGRAMS := dropbear dbclient dropbearkey dropbearconvert scp +DROPBEAR_LIBRARIES := + +DROPBEAR_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(DROPBEAR_VERSION), \ + $(DROPBEAR_URL), \ + $(DROPBEAR_PROGRAMS), \ + $(DROPBEAR_LIBRARIES), \ +)) + +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --sbindir="$(SYSROOT)/bin" --enable-static \ + $(DROPBEAR_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" PROGRAMS="$(DROPBEAR_PROGRAMS)" + $(MAKE) -C "$(SRC)" install PROGRAMS="$(DROPBEAR_PROGRAMS)" + +# If not explicitly disabled, dropbear needs zlib. +ifeq (,$(findstring disable-zlib,$(DROPBEAR_CONFIG))) +$(BUILD_FLAG): $$(libz) +endif + +ALL_PROGRAMS += $(DROPBEAR_PROGRAMS) \ No newline at end of file diff --git a/include/libressl.mak b/include/libressl.mak new file mode 100644 index 0000000..38f18ab --- /dev/null +++ b/include/libressl.mak @@ -0,0 +1,38 @@ +ifeq (libressl,$(OPENSSL)) + +NAME := libressl +LIBRESSL_VERSION := 3.5.3 +LIBRESSL_URL := https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-$(LIBRESSL_VERSION).tar.gz +LIBRESSL_PROGRAMS := openssl +LIBRESSL_LIBRARIES := libssl.a libcrypto.a libtls.a + +LIBRESSL_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(LIBRESSL_VERSION), \ + $(LIBRESSL_URL), \ + $(LIBRESSL_PROGRAMS), \ + $(LIBRESSL_LIBRARIES), \ +)) + +# This package uses libtool and needs LDFLAGS to include -all-static +# in order to produce a statically linked binary. However, the +# configure script doesn't use libtool, so the flag must be injected +# at built-time only, otherwise the configure will fail. +# See https://stackoverflow.com/a/54168321/477563 +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --disable-shared --enable-static \ + --disable-tests --disable-asm \ + $(LIBRESSL_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" LDFLAGS="$(LDFLAGS) -all-static" + $(MAKE) -C "$(SRC)" install-exec + +ALL_PROGRAMS += $(LIBRESSL_PROGRAMS) + +endif \ No newline at end of file diff --git a/include/musl.mak b/include/musl.mak new file mode 100644 index 0000000..f017b5a --- /dev/null +++ b/include/musl.mak @@ -0,0 +1,30 @@ +# musl-cross-make hasn't had an official release since 2020 but has had many +# updates and bigfixes since then. Instead, we'll download a commit directly. +NAME := musl-cross-make +MUSL_VERSION := fe91582 +MUSL_URL := https://github.com/richfelker/musl-cross-make/tarball/$(MUSL_VERSION) +MUSL_SRC := $(SOURCE_ROOT)/$(NAME)-$(MUSL_VERSION) +MUSL := $(SYSROOT)/bin/$(TARGET)-cc + +MUSL_CONFIG = + +# NOTE: we can't use create_recipes otherwise musl will depend on itself. + +.PHONY: musl +musl: | $(MUSL) + +$(MUSL): | $(MUSL_SRC) + $(eval $(call activate_paths,$@)) +# Remove tar verbose flag as it results in over 120k lines of output. + sed -i".bak" "s/xvf/xf/" "$(MUSL_SRC)/Makefile" + $(MAKE) -C "$(MUSL_SRC)" \ + TARGET="$(TARGET)" \ + COMMON_CONFIG='CFLAGS="-g0 -Os" CXXFLAGS="-g0 -Os" LDFLAGS="-s"' \ + DL_CMD="$(DOWNLOAD)" \ + $(MUSL_CONFIG) + $(MAKE) -C "$(MUSL_SRC)" install \ + TARGET="$(TARGET)" \ + OUTPUT="$(SYSROOT)" + +$(MUSL_SRC): + $(call untar_to_dir,$(MUSL_URL),$@) \ No newline at end of file diff --git a/include/ncurses.mak b/include/ncurses.mak new file mode 100644 index 0000000..726c5d8 --- /dev/null +++ b/include/ncurses.mak @@ -0,0 +1,31 @@ +NAME := ncurses +NCURSES_VERSION := 6.3 +NCURSES_URL := https://ftp.gnu.org/gnu/ncurses/ncurses-$(NCURSES_VERSION).tar.gz +NCURSES_PROGRAMS := +NCURSES_LIBRARIES := libncurses.a libncurses++.a libform.a libmenu.a libpanel.a + +NCURSES_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(NCURSES_VERSION), \ + $(NCURSES_URL), \ + $(NCURSES_PROGRAMS), \ + $(NCURSES_LIBRARIES), \ +)) + +# NOTE: do not autoreconf or it can cause the build to fail. +# It emits a lot of obsolete macro warnings then the build +# spews hundreds of warnings about redefined preprocessor macros +# before finally failing for unrelated reasons. +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --without-manpages --without-progs --disable-ext-funcs \ + --without-tack --without-tests --without-debug \ + $(NCURSES_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" libs + $(MAKE) -C "$(SRC)" install.libs \ No newline at end of file diff --git a/include/netcat.mak b/include/netcat.mak new file mode 100644 index 0000000..80bac7f --- /dev/null +++ b/include/netcat.mak @@ -0,0 +1,33 @@ +NAME := netcat +NETCAT_VERSION := 0.7.1 +NETCAT_URL := https://downloads.sourceforge.net/project/netcat/netcat/$(NETCAT_VERSION)/netcat-$(NETCAT_VERSION).tar.gz +NETCAT_PROGRAMS := netcat +NETCAT_LIBRARIES := + +NETCAT_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(NETCAT_VERSION), \ + $(NETCAT_URL), \ + $(NETCAT_PROGRAMS), \ + $(NETCAT_LIBRARIES), \ +)) + +# NOTE: this is the "original" netcat, not the BSD version. +# The bundled configure script is so out of date that it's +# never heard of musl and thinks it's invalid. +# Because of this, forcing autoreconf to run is mandatory. +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && autoreconf -if + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + $(NETCAT_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install-exec + +ALL_PROGRAMS += $(NETCAT_PROGRAMS) +DEFAULT_PROGRAMS += $(NETCAT_PROGRAMS) \ No newline at end of file diff --git a/include/nmap.mak b/include/nmap.mak new file mode 100644 index 0000000..4a251d0 --- /dev/null +++ b/include/nmap.mak @@ -0,0 +1,79 @@ +NAME := nmap +NMAP_VERSION := 7.92 +NMAP_URL := https://nmap.org/dist/nmap-$(NMAP_VERSION).tgz +NMAP_PROGRAMS := nmap nping ncat +NMAP_LIBRARIES := + +# Enabling OpenSSL adds around 2.5MB. +NMAP_CONFIG = --without-openssl + +$(eval $(call create_recipes, \ + $(NAME), \ + $(NMAP_VERSION), \ + $(NMAP_URL), \ + $(NMAP_PROGRAMS), \ + $(NMAP_LIBRARIES), \ +)) + +# NOTE: a lot of the libraries included with nmap will attempt to use the +# system's AR and RANLIB unless specifically overridden. Normally make's -e +# flag would fix this but it isn't passed to recursive calls to other makefiles. +# To make matters frustrating: +# - liblua doesn't use ARFLAGS and instead embeds them in AR. +# - libnetutil doesn't use ARFLAGS and instead embeds them in the make recipe. +# - libz actually uses AR=libtool with corresponding ARFLAGS. +# The net result is that at least one library has to be built manually. +# BONUS: because the nmap binary depends on phony targets, the binary is always +# rebuilt, even when calling the install target. To prevent having to pass +# STATIC to multiple make calls, we'll go directly to calling the install target. +# This is easily one of the work makefiles I've ever had to deal with. +# BONUS BONUS: even though nmap comes with libz, we have to use our own copy +# because on most systems libz will attempt to build a static and a shared library. +# However, nmap passes the static build flags to both, causing it to fail. +$(BUILD_FLAG): $$(libpcap) $$(libz) + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --without-zenmap --without-nmap-update --without-ndiff \ + --with-libpcap="$(SYSROOT)" \ + --with-libz="$(SYSROOT)" \ + --with-libpcre=included \ + --with-libssh2=included \ + --with-liblua=included \ + $(NMAP_CONFIG) \ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" build-lua \ + AR="$(AR) cr" RANLIB="$(RANLIB)" + $(MAKE) -C "$(SRC)" install \ + AR="$(AR)" ARFLAGS="cr" RANLIB="$(RANLIB)" STATIC="-static" + +# The libdnet included with nmap configures settings based on the build +# machine, not the machine we're cross-compiling for. As a result, some flags +# (e.g. procfs, Berkeley Packet Filter) may end up with incorrect values. +# For compatibility, we'll override some of the configure script's internal +# variables to ensure we use the generic Linux ethernet driver. + +# Berkeley Packet Filter determined based on presence of /dev/bpf0. +# The musl toolchain doesn't have so this must be disabled. +$(BUILD_FLAG): export ac_cv_dnet_bsd_bpf=no + +# Determined based on contents of /proc/sys/kernel/ostype, if present. +# This should be present on all non-antique versions of Linux. +$(BUILD_FLAG): export ac_cv_dnet_linux_procfs=yes + +# The musl toolchain has these headers even if the build system doesn't. +$(BUILD_FLAG): export ac_cv_dnet_linux_pf_packet=yes +$(BUILD_FLAG): export ac_cv_header_linux_if_tun_h=yes + +# If not explicitly disabled, nmap prefers having OpenSSL. +# Due to a quirk in the included libssh2 library, if we supply our own OpenSSL +# library then we also have to supply our own libz because libssh2 expects libz +# to already be compiled even though nmap hasn't built it yet. +ifeq (,$(findstring without-openssl,$(NMAP_CONFIG))) +$(BUILD_FLAG): $$(libssl) $$(libcrypto) +override NMAP_CONFIG := $(filter-out --with%openssl%,$(NMAP_CONFIG)) +override NMAP_CONFIG := $(NMAP_CONFIG) --with-openssl="$(SYSROOT)" +endif + +ALL_PROGRAMS += $(NMAP_PROGRAMS) \ No newline at end of file diff --git a/include/openssl.mak b/include/openssl.mak new file mode 100644 index 0000000..fd2a3a8 --- /dev/null +++ b/include/openssl.mak @@ -0,0 +1,59 @@ +ifeq (openssl,$(OPENSSL)) + +NAME := openssl +OPENSSL_VERSION := 3.0.4 +OPENSSL_URL := https://github.com/openssl/openssl/archive/refs/tags/openssl-$(OPENSSL_VERSION).tar.gz +OPENSSL_PROGRAMS := openssl +OPENSSL_LIBRARIES := libssl.a libcrypto.a + +OPENSSL_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(OPENSSL_VERSION), \ + $(OPENSSL_URL), \ + $(OPENSSL_PROGRAMS), \ + $(OPENSSL_LIBRARIES), \ +)) + +# OpenSSL decided to use a custom configure script +# that requires an OpenSSL-specific CPU target. +# If we have ARCH defined then the -march in our CFLAGS +# will generate the correct result for us. If not, +# we need to pick the closest OpenSSL target based +# on the toolchain that we're currently using. +define get_openssl_target +ifeq (,$(OPENSSL_TARGET)) +ifneq (,$(filter x86_64-%,$(TARGET))) +OPENSSL_TARGET := linux-x86_64 +else ifneq (,$(filter aarch64-%,$(TARGET))) +OPENSSL_TARGET := linux-aarch64 +else ifneq (,$(filter arm%,$(TARGET))) +OPENSSL_TARGET := linux-armv4 +else ifneq (,$(filter mips%,$(TARGET))) +OPENSSL_TARGET := linux-mips32 +else ifneq (,$(ARCH)) +OPENSSL_TARGET := linux-generic32 +else +$(warning Unable to detect OpenSSL target from musl toolchain $(TARGET).) +$(warning If the build fails, consider manually setting OPENSSL_TARGET.) +endif +endif +endef + +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + $(eval $(call get_openssl_target)) + cd "$(SRC)" && ./Configure \ + --prefix="$(SYSROOT)" \ + no-shared no-tests no-asm no-engine no-module \ + $(OPENSSL_CONFIG) \ + $(OPENSSL_TARGET) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install_sw + +ALL_PROGRAMS += $(OPENSSL_PROGRAMS) + +endif \ No newline at end of file diff --git a/include/pcap.mak b/include/pcap.mak new file mode 100644 index 0000000..32c5b0c --- /dev/null +++ b/include/pcap.mak @@ -0,0 +1,26 @@ +NAME := pcap +PCAP_VERSION := 1.10.1 +PCAP_URL := https://www.tcpdump.org/release/libpcap-$(PCAP_VERSION).tar.gz +PCAP_PROGRAMS := +PCAP_LIBRARIES := libpcap.a + +PCAP_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(PCAP_VERSION), \ + $(PCAP_URL), \ + $(PCAP_PROGRAMS), \ + $(PCAP_LIBRARIES), \ +)) + +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --disable-shared \ + $(PCAP_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install \ No newline at end of file diff --git a/include/readline.mak b/include/readline.mak new file mode 100644 index 0000000..c20a914 --- /dev/null +++ b/include/readline.mak @@ -0,0 +1,27 @@ +NAME := readline +READLINE_VERSION := 8.1.2 +READLINE_URL := https://ftp.gnu.org/gnu/readline/readline-$(READLINE_VERSION).tar.gz +READLINE_PROGRAMS := +READLINE_LIBRARIES := libreadline.a libhistory.a + +READLINE_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(READLINE_VERSION), \ + $(READLINE_URL), \ + $(READLINE_PROGRAMS), \ + $(READLINE_LIBRARIES), \ +)) + +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --disable-shared --enable-static \ + --disable-install-examples \ + $(READLINE_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install \ No newline at end of file diff --git a/include/socat.mak b/include/socat.mak new file mode 100644 index 0000000..2c74347 --- /dev/null +++ b/include/socat.mak @@ -0,0 +1,47 @@ +NAME := socat +SOCAT_VERSION := 1.7.4.3 +SOCAT_URL := http://www.dest-unreach.org/socat/download/socat-$(SOCAT_VERSION).tar.gz +SOCAT_PROGRAMS := socat procan filan +SOCAT_LIBRARIES := +# NOTE: yes, that's an insecure HTTP download URL. +# The HTTPS version provides a certificate for the wrong domain, +# so we'd have to turn off certificate verification anyways. +# There's also a git repo, but it's hosted on a different 3rd domain. + +# Enabling OpenSSL makes socat 10x larger. +SOCAT_CONFIG = --disable-openssl --disable-readline + +$(eval $(call create_recipes, \ + $(NAME), \ + $(SOCAT_VERSION), \ + $(SOCAT_URL), \ + $(SOCAT_PROGRAMS), \ + $(SOCAT_LIBRARIES), \ +)) + +# NOTE: without `-Werror-implicit-function-declaration` during configure, +# configure incorrectly detects that getprotobynumber_r is available +# even though the compilation threw an "implicit declaration" warning. +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + $(SOCAT_CONFIG) \ + CFLAGS="$(CFLAGS) -Werror-implicit-function-declaration" \ + LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install + +# If not explicitly disabled, socat prefers having OpenSSL. +ifeq (,$(findstring disable-openssl,$(SOCAT_CONFIG))) +$(BUILD_FLAG): $$(libssl) $$(libcrypto) +endif + +# If not explicitly disabled, socat prefers having readline. +ifeq (,$(findstring disable-readline,$(SOCAT_CONFIG))) +$(BUILD_FLAG): $$(libreadline) +endif + +ALL_PROGRAMS += $(SOCAT_PROGRAMS) +DEFAULT_PROGRAMS += socat \ No newline at end of file diff --git a/include/strace.mak b/include/strace.mak new file mode 100644 index 0000000..c309f50 --- /dev/null +++ b/include/strace.mak @@ -0,0 +1,58 @@ +NAME := strace +STRACE_VERSION := 5.18 +STRACE_URL := https://github.com/strace/strace/releases/download/v$(STRACE_VERSION)/strace-$(STRACE_VERSION).tar.xz +STRACE_PROGRAMS := strace +STRACE_LIBRARIES := + +STRACE_CONFIG = + +$(eval $(call create_recipes, \ + $(NAME), \ + $(STRACE_VERSION), \ + $(STRACE_URL), \ + $(STRACE_PROGRAMS), \ + $(STRACE_LIBRARIES), \ +)) + +HAVE_SED_R := $(shell sed -r '' /dev/null && echo OK) +HAVE_GSED := $(shell command -v gsed) + +# NOTE: strace's INSTALL guide specifically requests _not_ using autoreconf +# in favor of using their bootstrap script. Instead, we'll do neither. +# Also, we use --enable-mpers=no by default as it requires gawk. +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) +ifeq (,$(HAVE_SED_R)) +ifneq (,$(HAVE_GSED)) +# The makefiles and shell scripts make extensive use of GNU sed -r. +# BSD sed's -E flag almost does the same thing except that \n in +# replacements becomes a literal "n" instead of a newline. +# Unfortunately, strace makes extensive use of this feature, +# so GNU sed is required one way or another. +# The irony of using sed to fix sed commands is not lost on me. + if ! sed -r "" /dev/null &>/dev/null; then \ + for pattern in "Make*" "*.sh"; do \ + find "$(SRC)" -type f -name "$${pattern}" \ + | xargs grep -lF "sed -r" \ + | xargs sed -i".bak" "s/sed -r/gsed -r/g"; \ + done \ + fi +endif +endif + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --enable-mpers=no \ + $(STRACE_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install-exec + +# strace can't be built on aarch64 due to a bug in linux-headers-4.19. +# Once musl-cross-make supports linux-headers-4.20 or newer, this can be removed. +# See: https://www.mail-archive.com/qemu-devel@nongnu.org/msg863832.html +ifeq (,$(findstring aarch64,$(TARGET))) +ifneq (,$(HAVE_SED_R)$(HAVE_GSED)) +ALL_PROGRAMS += $(STRACE_PROGRAMS) +endif +endif \ No newline at end of file diff --git a/include/tcpdump.mak b/include/tcpdump.mak new file mode 100644 index 0000000..0107db8 --- /dev/null +++ b/include/tcpdump.mak @@ -0,0 +1,31 @@ +NAME := tcpdump +TCPDUMP_VERSION := 4.99.1 +TCPDUMP_URL := https://www.tcpdump.org/release/tcpdump-$(TCPDUMP_VERSION).tar.gz +TCPDUMP_PROGRAMS := tcpdump +TCPDUMP_LIBRARIES := + +# Adding OpenSSL's crypto library adds around 2MB. +TCPDUMP_CONFIG = --without-crypto + +$(eval $(call create_recipes, \ + $(NAME), \ + $(TCPDUMP_VERSION), \ + $(TCPDUMP_URL), \ + $(TCPDUMP_PROGRAMS), \ + $(TCPDUMP_LIBRARIES), \ +)) + +# NOTE: tcpdump can include the build machine's include directories +# if it detects pcap headers on your system. This can be disabled +# by overridden by resetting the INCLS variable to the default value. +$(BUILD_FLAG): $$(libpcap) + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + $(TCPDUMP_CONFIG) \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" INCLS="-I." + $(MAKE) -C "$(SRC)" install + +ALL_PROGRAMS += $(TCPDUMP_PROGRAMS) \ No newline at end of file diff --git a/include/wolfssl.mak b/include/wolfssl.mak new file mode 100644 index 0000000..d580a69 --- /dev/null +++ b/include/wolfssl.mak @@ -0,0 +1,25 @@ +NAME := wolfssl +WOLFSSL_VERSION := 5.3.0 +WOLFSSL_URL := https://github.com/wolfSSL/wolfssl/archive/refs/tags/v$(WOLFSSL_VERSION)-stable.tar.gz +WOLFSSL_PROGRAMS := +WOLFSSL_LIBRARIES := libwolfssl.a + +$(eval $(call create_recipes, \ + $(NAME), \ + $(WOLFSSL_VERSION), \ + $(WOLFSSL_URL), \ + $(WOLFSSL_PROGRAMS), \ + $(WOLFSSL_LIBRARIES), \ +)) + +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && autoreconf -i + cd "$(SRC)" && ./configure \ + $(CONFIGURE_DEFAULTS) \ + --disable-shared --enable-static \ + --enable-opensslall \ + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" + $(MAKE) -C "$(SRC)" install \ No newline at end of file diff --git a/include/zlib.mak b/include/zlib.mak new file mode 100644 index 0000000..5c2ce11 --- /dev/null +++ b/include/zlib.mak @@ -0,0 +1,24 @@ +NAME := zlib +ZLIB_VERSION := 1.2.12 +ZLIB_URL := https://zlib.net/zlib-$(ZLIB_VERSION).tar.gz +ZLIB_PROGRAMS := +ZLIB_LIBRARIEES := libz.a + +$(eval $(call create_recipes, \ + $(NAME), \ + $(ZLIB_VERSION), \ + $(ZLIB_URL), \ + $(ZLIB_PROGRAMS), \ + $(ZLIB_LIBRARIEES), \ +)) + +# NOTE: zlib's configure script isn't from autotools. +# It doesn't support --host or passing build flags. +# Instead, we'll pass build flags directly to the build step. +$(BUILD_FLAG): + $(eval $(call activate_toolchain,$@)) + cd "$(SRC)" && ./configure \ + --prefix="$(SYSROOT)" --static + $(MAKE) -C "$(SRC)" clean + $(MAKE) -C "$(SRC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" + $(MAKE) -C "$(SRC)" install diff --git a/include/zstd.mak b/include/zstd.mak new file mode 100644 index 0000000..7d85e15 --- /dev/null +++ b/include/zstd.mak @@ -0,0 +1,29 @@ +NAME := zstd +ZSTD_VERSION := 1.5.2 +ZSTD_URL := https://github.com/facebook/zstd/releases/download/v$(ZSTD_VERSION)/zstd-$(ZSTD_VERSION).tar.gz +ZSTD_PROGRAMS := zstd +ZSTD_LIBRARIES := libzstd.a + +$(eval $(call create_recipes, \ + $(NAME), \ + $(ZSTD_VERSION), \ + $(ZSTD_URL), \ + $(ZSTD_PROGRAMS), \ + $(ZSTD_LIBRARIES), \ +)) + +# NOTE: we have to hardcode a fake UNAME otherwise it will build file extensions +# based on our host OS, not the target OS. Also, zstd always builds both shared +# and static libraries so we must pass CFLAGS and LDFLAGS via environment variables. +# If we don't, the makefile can't append recipe-specific flags to them and it'll +# fail trying to build a static and shared library using the same flags. +# See: https://github.com/facebook/zstd/issues/3190 +$(BUILD_FLAG): $$(libz) + $(eval $(call activate_toolchain,$@)) + $(MAKE) -C "$(SRC)" clean + CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \ + $(MAKE) -C "$(SRC)" UNAME="Linux" + $(MAKE) -C "$(SRC)" install UNAME="Linux" PREFIX="$(SYSROOT)" + +ALL_PROGRAMS += $(ZSTD_PROGRAMS) +DEFAULT_PROGRAMS += $(ZSTD_PROGRAMS) \ No newline at end of file