Add initial files

This commit is contained in:
llamasoft 2022-07-10 23:53:08 -04:00
parent bdbb62faf3
commit b82f418fc1
27 changed files with 1484 additions and 0 deletions

77
.github/workflows/release.yml vendored Normal file
View File

@ -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

45
.gitignore vendored Normal file
View File

@ -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

59
CONTRIBUTING.md Normal file
View File

@ -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.

23
Dockerfile Normal file
View File

@ -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"]

21
LICENSE.md Normal file
View File

@ -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.

335
Makefile Normal file
View File

@ -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 <template.mak)
# but unfortunately the function wasn't added until GNU Make 4.0.
all_recipes :=
define create_recipes
name := $(strip $(1))
version := $(strip $(2))
url := $(strip $(3))
bin_names := $(notdir $(strip $(4)))
lib_names := $(notdir $(strip $(5)))
ifeq (,$$(name))
$$(error Package name cannot be empty)
else ifeq (,$$(version))
$$(error Package version for $$(name) cannot be empty)
else ifeq (,$$(url))
$$(error Package url for $$(name) cannot be empty)
else ifeq (,$$(bin_names)$$(lib_names))
$$(error The $$(name) package must provide at least one binary or library)
else ifneq (,$$(filter $$(name),$$(all_recipes)))
$$(error A recipe for $$(name) has already been created.)
else
all_recipes += $$(name)
endif
src := $$(SOURCE_ROOT)/$$(name)-$$(version)
bin_paths := $$(addprefix $$(OUTPUT)/bin/,$$(bin_names))
lib_paths := $$(addprefix $$(SYSROOT)/lib/,$$(lib_names))
# Export library names as variables for other recipes to depend on.
$$(foreach lib,$$(lib_paths),$$(eval $$(call export_library,$$(lib))))
# Building any one of the programs or libraries builds them all.
.PHONY: $$(bin_names) $$(lib_names)
$$(bin_names) $$(lib_names): | $$(bin_paths) $$(lib_paths)
# Bind variables to all of this package's recipes.
# These variable names will be reused later by other packages,
# so binding them here the only way to guarantee the correct value.
$$(bin_paths) $$(lib_paths): override URL := $$(url)
$$(bin_paths) $$(lib_paths): override SRC := $$(src)
# We potentially have multiple output files generated from one recipe.
# If not handled correctly, building one program from the list can result in the
# recipe running once per program instead of just once overall.
# To work around this, we make each binary depend on an intermediate flag.
# See: https://stackoverflow.com/a/10609434/477563
BUILD_FLAG := $$(SYSROOT)/$$(name).built
.INTERMEDIATE: $$(BUILD_FLAG)
ifneq (,$$(bin_paths))
# Binaries need to be copied from SYSROOT/bin/ to OUTPUT/bin/.
$$(bin_paths): $$(BUILD_FLAG) | $$$$(MUSL)
$$(eval $$(call activate_toolchain,$$@))
mkdir -p "$$(@D)"
mv "$$(SYSROOT)/bin/$$(@F)" "$$@"
- $$(STRIP) --strip-unneeded "$$@"
ls -al "$$@"
endif
ifneq (,$$(lib_paths))
# Libraries are already in their final location.
$$(lib_paths): $$(BUILD_FLAG) | $$$$(MUSL) ;
endif
# This is main build recipe that the package's makefile must provide.
# It should take the source code and output the built programs
# and libraries into the SYSROOT directory tree.
# Here we merely provide the recipe definition and base dependencies.
$$(BUILD_FLAG): $$(src) | $$$$(MUSL)
$$(src):
$$(call untar_to_dir,$$(URL),$$@)
endef
# Never implicitly pass this makefile's command-line variables
# to other instances of make. This prevents TARGET, ARCH, etc,
# from tainting the other builds. Unfortunately, simply clearing
# the MAKEOVERRIDES variable isn't enough because make will
# auto-export any explicitly defined command-line variables.
define unexport_var
_var_assignment := $(1)
_var_parts := $$(subst =, ,$$(_var_assignment))
_var_name := $$(firstword $$(_var_parts))
_var_name := $$(subst :, ,$$(_var_name))
unexport $$(_var_name)
endef
$(foreach assignment,$(MAKEOVERRIDES),$(eval $(call unexport_var,$(assignment))))
MAKEOVERRIDES =
######################### Recipes ##########################
# Disable implicit rules.
.SUFFIXES:
# Secondary expansion is required because some programs will
# depend on library path variables that haven't been defined yet.
.SECONDEXPANSION:
# Don't allow different programs to be built simultaneously,
# but do allow those programs to compile in parallel.
# Building programs in parallel makes it much more difficult
# to notice and diagnose build failure reasons.
.NOTPARALLEL:
# Import all of the individual build components.
include $(MAKEFILE_DIR)/include/*.mak
# If no TARGET was specified, default to the usage guide.
.DEFAULT_GOAL := $(if $(TARGET),default,usage)
.PHONY: all
all: $(ALL_PROGRAMS)
ls -al "$(OUTPUT)/bin"
.PHONY: default
default: $(DEFAULT_PROGRAMS)
ls -al "$(OUTPUT)/bin"
.PHONY: help usage
help usage:
$(info $(USAGE))
# Apparently the help output varies between toolchains so we'll try both.
.PHONY: archlist
archlist: | $$(MUSL)
$(eval $(call activate_toolchain,$@))
-@ "$(CC)" -march="x" 2>&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)')

164
README.md Normal file
View File

@ -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! 😉

9
docker_build.sh Executable file
View File

@ -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 "$@"

64
include/_template.mak Normal file
View File

@ -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)

29
include/bash.mak Normal file
View File

@ -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)

39
include/busybox.mak Normal file
View File

@ -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)

49
include/curl.mak Normal file
View File

@ -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)

33
include/dropbear.mak Normal file
View File

@ -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)

38
include/libressl.mak Normal file
View File

@ -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

30
include/musl.mak Normal file
View File

@ -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),$@)

31
include/ncurses.mak Normal file
View File

@ -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

33
include/netcat.mak Normal file
View File

@ -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)

79
include/nmap.mak Normal file
View File

@ -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 <net/bpf.h> 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)

59
include/openssl.mak Normal file
View File

@ -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

26
include/pcap.mak Normal file
View File

@ -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

27
include/readline.mak Normal file
View File

@ -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

47
include/socat.mak Normal file
View File

@ -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

58
include/strace.mak Normal file
View File

@ -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 2>/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

31
include/tcpdump.mak Normal file
View File

@ -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)

25
include/wolfssl.mak Normal file
View File

@ -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

24
include/zlib.mak Normal file
View File

@ -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

29
include/zstd.mak Normal file
View File

@ -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)