feat: ports - git port
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
# git for MontaukOS
|
||||
#
|
||||
# Upstream: https://github.com/git/git (submodule at upstream/, pinned to
|
||||
# v2.39.5).
|
||||
#
|
||||
# git is built as a plain system program (0:/os/git.elf), not an app bundle:
|
||||
# it is a command-line tool driven from the terminal.
|
||||
#
|
||||
# CONFIGURATION
|
||||
# The build must not pick up any host defaults. git derives its platform
|
||||
# settings from `uname -s` through config.mak.uname, which on this host
|
||||
# would answer "Linux" and switch on clock_gettime, getdelim, /dev/tty and
|
||||
# friends -- none of which the Montauk libc has. Every uname_* variable is
|
||||
# therefore overridden to a name config.mak.uname does not know, leaving
|
||||
# the knobs below as the only configuration.
|
||||
#
|
||||
# The NO_* list is not "things git can live without" so much as an
|
||||
# inventory of what MontaukOS does not provide yet: no threads, no
|
||||
# sockets, no iconv, no regex, no file-backed mmap. git ships portable
|
||||
# fallbacks for all of them (compat/), which is what makes this port
|
||||
# tractable at all.
|
||||
#
|
||||
# COMPAT SHIMS (compat/) supply the headers and functions the Montauk libc
|
||||
# has no equivalent of -- see compat/README for what each one does and, more
|
||||
# importantly, what it does not.
|
||||
|
||||
UPSTREAM := upstream
|
||||
COMPAT := $(CURDIR)/compat
|
||||
|
||||
PORT_NAME := git
|
||||
|
||||
include ../../mk/port.mk
|
||||
|
||||
GIT_BIN := $(UPSTREAM)/git
|
||||
GIT_INSTALL := $(MONTAUKOS)/programs/bin/os
|
||||
|
||||
# Where git's compiled-in paths point on the target. programs/bin/os is the
|
||||
# staging directory for 0:/os, so GIT_PREFIX and GIT_STAGE are two names for
|
||||
# the same place -- one as the OS sees it, one as the build host does.
|
||||
# RUNTIME_PREFIX is off (it wants /proc/self/exe), so these are baked in:
|
||||
#
|
||||
# $(GIT_PREFIX)/share/git-core/templates `git init` skeleton
|
||||
# $(GIT_PREFIX)/etc/gitconfig system-wide config
|
||||
# $(GIT_PREFIX)/libexec/git-core external subcommands (none yet;
|
||||
# every command in this build is a
|
||||
# builtin, which is what makes git
|
||||
# usable without fork/exec)
|
||||
GIT_PREFIX := 0:/os/git
|
||||
GIT_STAGE := $(GIT_INSTALL)/git
|
||||
|
||||
# `git version` string. Without an override GIT-VERSION-GEN runs `git
|
||||
# describe` on the checkout and, because the patch series is applied in the
|
||||
# working tree, reports "2.39.5.dirty" -- true but unhelpful. Name the port
|
||||
# instead: the tree really is patched, and this says by whom.
|
||||
GIT_UPSTREAM_TAG := $(shell git -C $(UPSTREAM) describe --tags --abbrev=0 2>/dev/null)
|
||||
GIT_VERSION_STR := $(patsubst v%,%,$(GIT_UPSTREAM_TAG))-montauk
|
||||
|
||||
# ==== Toolchain flags =================================================
|
||||
# CFLAGS/LDFLAGS/EXTLIBS must be passed on git's make COMMAND LINE, not
|
||||
# through the environment: its Makefile assigns `CFLAGS = -g -O2 -Wall`
|
||||
# outright, and a plain assignment beats an environment value. Only a
|
||||
# command-line assignment wins. Overriding them is safe -- git keeps its own
|
||||
# required includes and defines in BASIC_CFLAGS, which is separate and is
|
||||
# appended to ALL_CFLAGS after ours.
|
||||
|
||||
GIT_CFLAGS := \
|
||||
-std=gnu99 \
|
||||
$(PORT_CFLAGS_COMMON) \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-sign-compare \
|
||||
-I $(COMPAT) \
|
||||
-include $(COMPAT)/montauk-paths.h \
|
||||
-include $(COMPAT)/montauk-ownership.h \
|
||||
-isystem $(shell $(CC) -print-file-name=include)
|
||||
|
||||
# crt1.o carries _start; -nostdlib (from PORT_LDFLAGS_COMMON) drops the
|
||||
# driver's own startup files, so name them here.
|
||||
GIT_CRT := \
|
||||
$(SDK_LIB)/libc/crt1.o \
|
||||
$(SDK_LIB)/libc/crti.o \
|
||||
$(SDK_LIB)/libc/crtn.o
|
||||
|
||||
COMPAT_LIB := $(CURDIR)/compat/libgitcompat.a
|
||||
|
||||
GIT_LDFLAGS := $(PORT_LDFLAGS_COMMON) $(GIT_CRT)
|
||||
|
||||
# EXTLIBS lands on the link line after the objects, which is where the compat
|
||||
# archive, zlib and libc have to sit for the static link to resolve. Naming
|
||||
# libz.a here rather than letting ZLIB_PATH add -lz is deliberate: overriding
|
||||
# EXTLIBS drops git's own `EXTLIBS += -lz` append. ZLIB_PATH is still set, for
|
||||
# the -I it contributes to BASIC_CFLAGS.
|
||||
GIT_EXTLIBS := $(COMPAT_LIB) $(PORT_SYSROOT_LIB)/libz.a $(LIBC_A)
|
||||
|
||||
# ==== Build configuration =============================================
|
||||
#
|
||||
# DEFAULT_PAGER=cat is load-bearing, not a preference: git_pager() treats the
|
||||
# literal "cat" as "no pager at all" and skips the fork entirely (pager.c).
|
||||
# Left at its default it would try to spawn `less` on every `git log` and
|
||||
# fail, since MontaukOS cannot fork.
|
||||
#
|
||||
# OBJECT_CREATION_USES_RENAMES=1 because there are no hard links. Every loose
|
||||
# object is written to a temp file and then finalized; by default git tries
|
||||
# link()+unlink() first and only falls back to rename() when link fails, so
|
||||
# without this every single object write makes a doomed syscall and travels an
|
||||
# error path. The knob picks rename() up front, which is what happens anyway.
|
||||
#
|
||||
# DEFAULT_EDITOR is deliberately NOT set. With an empty environment TERM is
|
||||
# unset, so git considers the terminal dumb, git_editor() returns NULL, and
|
||||
# `git commit` with no -m says "terminal is dumb, but EDITOR unset. Please
|
||||
# supply the message using either -m or -F option." Naming an editor here
|
||||
# would replace that with a failed spawn.
|
||||
|
||||
GIT_ARGS := \
|
||||
CC=$(CC) \
|
||||
AR=$(AR) \
|
||||
CFLAGS="$(GIT_CFLAGS)" \
|
||||
LDFLAGS="$(GIT_LDFLAGS)" \
|
||||
EXTLIBS="$(GIT_EXTLIBS)" \
|
||||
uname_S=MontaukOS \
|
||||
uname_M=x86_64 \
|
||||
uname_O=MontaukOS \
|
||||
uname_R=1 \
|
||||
uname_P=x86_64 \
|
||||
uname_V=1 \
|
||||
prefix=$(GIT_PREFIX) \
|
||||
GIT_VERSION=$(GIT_VERSION_STR) \
|
||||
ZLIB_PATH=$(PORT_SYSROOT) \
|
||||
BLK_SHA1=1 \
|
||||
NO_CURL=1 \
|
||||
NO_EXPAT=1 \
|
||||
NO_OPENSSL=1 \
|
||||
NO_ICONV=1 \
|
||||
NO_GETTEXT=1 \
|
||||
NO_PTHREADS=1 \
|
||||
NO_PERL=1 \
|
||||
NO_PYTHON=1 \
|
||||
NO_TCLTK=1 \
|
||||
NO_REGEX=1 \
|
||||
NO_MMAP=1 \
|
||||
NO_IPV6=1 \
|
||||
NO_INET_NTOP=1 \
|
||||
NO_INET_PTON=1 \
|
||||
NO_HSTRERROR=1 \
|
||||
NO_SYS_SELECT_H=1 \
|
||||
NO_UNIX_SOCKETS=1 \
|
||||
NO_SETITIMER=1 \
|
||||
NO_STRUCT_ITIMERVAL=1 \
|
||||
NO_LIBGEN_H=1 \
|
||||
NO_MEMMEM=1 \
|
||||
NO_STRCASESTR=1 \
|
||||
NO_STRLCPY=1 \
|
||||
NO_STRTOUMAX=1 \
|
||||
NO_MKDTEMP=1 \
|
||||
NO_INITGROUPS=1 \
|
||||
NO_GECOS_IN_PWENT=1 \
|
||||
NO_NSEC=1 \
|
||||
NO_INSTALL_HARDLINKS=1 \
|
||||
NO_TRUSTABLE_FILEMODE=1 \
|
||||
NO_SYMLINK_HEAD=1 \
|
||||
INTERNAL_QSORT=1 \
|
||||
OBJECT_CREATION_USES_RENAMES=1 \
|
||||
DEFAULT_PAGER=cat
|
||||
|
||||
GIT_MAKE := MAKEFLAGS= $(MAKE)
|
||||
|
||||
.PHONY: all clean git-build install uninstall
|
||||
|
||||
all: git-build
|
||||
|
||||
$(COMPAT_LIB): $(wildcard compat/*.c) $(wildcard compat/*.h)
|
||||
$(CC) $(GIT_CFLAGS) -c compat/montauk-compat.c -o compat/montauk-compat.o
|
||||
$(AR) rcs $@ compat/montauk-compat.o
|
||||
@echo "Built: $@"
|
||||
|
||||
# The templates/ sub-make builds the skeleton `git init` copies into a new
|
||||
# repository (info/exclude, the sample hooks, the description file) into
|
||||
# templates/blt. Without it every `git init` warns that templates are
|
||||
# missing. It is a subdirectory build, not a target of the top Makefile, so
|
||||
# it is invoked directly -- `make templates` up there just matches the
|
||||
# directory name and does nothing.
|
||||
git-build: $(COMPAT_LIB)
|
||||
@$(call ns_patch,$(UPSTREAM))
|
||||
@# git's link rule knows nothing about EXTLIBS or the crt objects, so a
|
||||
@# rebuilt compat archive -- or a rebuilt libc, which is the one that
|
||||
@# actually catches people out -- would otherwise leave the old binary
|
||||
@# in place. Drop it and let the sub-make link again.
|
||||
@for lib in $(GIT_EXTLIBS) $(GIT_CRT); do \
|
||||
if [ -f $(GIT_BIN) ] && [ "$$lib" -nt $(GIT_BIN) ]; then \
|
||||
echo " RELINK: $$(basename $$lib) is newer than $(GIT_BIN)"; \
|
||||
rm -f $(GIT_BIN); \
|
||||
fi; \
|
||||
done
|
||||
$(GIT_MAKE) -C $(UPSTREAM) $(GIT_ARGS) git
|
||||
$(GIT_MAKE) -C $(UPSTREAM)/templates
|
||||
@test -f $(GIT_BIN) || { echo "git: expected $(GIT_BIN)" >&2; exit 1; }
|
||||
@echo "Built: $(GIT_BIN) ($$(stat -c%s $(GIT_BIN)) bytes)"
|
||||
|
||||
# Installed as a system program, not an app bundle: git is a command line
|
||||
# tool with no window. It carries no manifest and no .port marker, so
|
||||
# remember to uninstall before cutting a release ISO.
|
||||
#
|
||||
# The binary is STRIPPED on the way in -- the debug info is five sixths of
|
||||
# its size (17 MB -> 3 MB), and it all has to fit in the ramdisk.
|
||||
install: git-build
|
||||
mkdir -p $(GIT_INSTALL)
|
||||
$(TOOLCHAIN_PREFIX)strip -o $(GIT_INSTALL)/git.elf $(GIT_BIN)
|
||||
mkdir -p $(GIT_STAGE)/share/git-core
|
||||
rm -rf $(GIT_STAGE)/share/git-core/templates
|
||||
cp -rL $(UPSTREAM)/templates/blt $(GIT_STAGE)/share/git-core/templates
|
||||
@echo "installed: 0:/os/git.elf + $(GIT_PREFIX)/share/git-core/templates"
|
||||
|
||||
uninstall:
|
||||
rm -rf $(GIT_INSTALL)/git.elf $(GIT_STAGE)
|
||||
|
||||
clean:
|
||||
@$(GIT_MAKE) -C $(UPSTREAM) $(GIT_ARGS) clean >/dev/null 2>&1 || true
|
||||
@git -C $(UPSTREAM) checkout -- . 2>/dev/null || true
|
||||
rm -f $(COMPAT_LIB) compat/*.o
|
||||
Reference in New Issue
Block a user