summaryrefslogtreecommitdiff
path: root/docs/handbook/cgit/building.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/handbook/cgit/building.md')
-rw-r--r--docs/handbook/cgit/building.md272
1 files changed, 272 insertions, 0 deletions
diff --git a/docs/handbook/cgit/building.md b/docs/handbook/cgit/building.md
new file mode 100644
index 0000000000..00f9e1244f
--- /dev/null
+++ b/docs/handbook/cgit/building.md
@@ -0,0 +1,272 @@
+# cgit — Building
+
+## Prerequisites
+
+| Dependency | Required | Purpose |
+|-----------|----------|---------|
+| GCC or Clang | Yes | C compiler (C99) |
+| GNU Make | Yes | Build system |
+| OpenSSL (libcrypto) | Yes | SHA-1 hash implementation (`SHA1_HEADER = <openssl/sha.h>`) |
+| zlib | Yes | Git object compression |
+| libcurl | No | Not used — `NO_CURL=1` is passed by cgit.mk |
+| Lua or LuaJIT | No | Lua filter support; auto-detected via pkg-config |
+| asciidoc / a2x | No | Man page / HTML / PDF documentation generation |
+| Python | No | Git's test harness (for `make test`) |
+
+## Build System Overview
+
+cgit uses a two-stage build that embeds itself within Git's build infrastructure:
+
+```
+cgit/Makefile
+ └── make -C git -f ../cgit.mk ../cgit
+ └── git/Makefile (included by cgit.mk)
+ └── Compile cgit objects + link against libgit.a
+```
+
+### Stage 1: Top-Level Makefile
+
+The top-level `Makefile` lives in `cgit/` and defines all user-configurable
+variables:
+
+```makefile
+CGIT_VERSION = 0.0.5-1-Project-Tick
+CGIT_SCRIPT_NAME = cgit.cgi
+CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
+CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH)
+CGIT_CONFIG = /etc/cgitrc
+CACHE_ROOT = /var/cache/cgit
+prefix = /usr/local
+libdir = $(prefix)/lib
+filterdir = $(libdir)/cgit/filters
+docdir = $(prefix)/share/doc/cgit
+mandir = $(prefix)/share/man
+SHA1_HEADER = <openssl/sha.h>
+GIT_VER = 2.46.0
+GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.xz
+```
+
+The main `cgit` target delegates to:
+
+```makefile
+cgit:
+ $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) -f ../cgit.mk ../cgit NO_CURL=1
+```
+
+This enters the `git/` subdirectory and runs `cgit.mk` from there, prefixing
+all cgit source paths with `../`.
+
+### Stage 2: cgit.mk
+
+`cgit.mk` is run inside the `git/` directory so it can `include Makefile` to
+inherit Git's build variables (`CC`, `CFLAGS`, linker flags, OS detection via
+`config.mak.uname`, etc.).
+
+Key sections:
+
+#### Version tracking
+
+```makefile
+$(CGIT_PREFIX)VERSION: force-version
+ @cd $(CGIT_PREFIX) && '$(SHELL_PATH_SQ)' ./gen-version.sh "$(CGIT_VERSION)"
+```
+
+The `gen-version.sh` script writes a `VERSION` file that is included by the
+build. Only `cgit.o` references `CGIT_VERSION`, so only that object is rebuilt
+when the version changes.
+
+#### CGIT_CFLAGS
+
+```makefile
+CGIT_CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
+CGIT_CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
+CGIT_CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
+```
+
+These compile-time constants are used in `cgit.c` as default values in
+`prepare_context()`.
+
+#### Lua detection
+
+```makefile
+LUA_PKGCONFIG := $(shell for pc in luajit lua lua5.2 lua5.1; do \
+ $(PKG_CONFIG) --exists $$pc 2>/dev/null && echo $$pc && break; \
+done)
+```
+
+If Lua is found, its `--cflags` and `--libs` are appended to `CGIT_CFLAGS` and
+`CGIT_LIBS`. If not found, `NO_LUA=YesPlease` is set and `-DNO_LUA` is added.
+
+#### Linux sendfile
+
+```makefile
+ifeq ($(uname_S),Linux)
+ HAVE_LINUX_SENDFILE = YesPlease
+endif
+
+ifdef HAVE_LINUX_SENDFILE
+ CGIT_CFLAGS += -DHAVE_LINUX_SENDFILE
+endif
+```
+
+This enables the `sendfile()` syscall in `cache.c` for zero-copy writes from
+cache files to stdout.
+
+#### Object files
+
+All cgit source files are listed explicitly:
+
+```makefile
+CGIT_OBJ_NAMES += cgit.o cache.o cmd.o configfile.o filter.o html.o
+CGIT_OBJ_NAMES += parsing.o scan-tree.o shared.o
+CGIT_OBJ_NAMES += ui-atom.o ui-blame.o ui-blob.o ui-clone.o ui-commit.o
+CGIT_OBJ_NAMES += ui-diff.o ui-log.o ui-patch.o ui-plain.o ui-refs.o
+CGIT_OBJ_NAMES += ui-repolist.o ui-shared.o ui-snapshot.o ui-ssdiff.o
+CGIT_OBJ_NAMES += ui-stats.o ui-summary.o ui-tag.o ui-tree.o
+```
+
+The prefixed paths (`CGIT_OBJS := $(addprefix $(CGIT_PREFIX),$(CGIT_OBJ_NAMES))`)
+point back to the `cgit/` directory from inside `git/`.
+
+## Quick Build
+
+```bash
+cd cgit
+
+# Download the vendored Git source (required on first build)
+make get-git
+
+# Build cgit binary
+make -j$(nproc)
+```
+
+The output is a single binary named `cgit` in the `cgit/` directory.
+
+## Build Variables Reference
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `CGIT_VERSION` | `0.0.5-1-Project-Tick` | Compiled-in version string |
+| `CGIT_SCRIPT_NAME` | `cgit.cgi` | Name of the installed CGI binary |
+| `CGIT_SCRIPT_PATH` | `/var/www/htdocs/cgit` | CGI binary install directory |
+| `CGIT_DATA_PATH` | `$(CGIT_SCRIPT_PATH)` | Static assets (CSS, JS, images) directory |
+| `CGIT_CONFIG` | `/etc/cgitrc` | Default config file path (compiled in) |
+| `CACHE_ROOT` | `/var/cache/cgit` | Default cache directory (compiled in) |
+| `prefix` | `/usr/local` | Install prefix |
+| `libdir` | `$(prefix)/lib` | Library directory |
+| `filterdir` | `$(libdir)/cgit/filters` | Filter scripts install directory |
+| `docdir` | `$(prefix)/share/doc/cgit` | Documentation directory |
+| `mandir` | `$(prefix)/share/man` | Man page directory |
+| `SHA1_HEADER` | `<openssl/sha.h>` | SHA-1 implementation header |
+| `GIT_VER` | `2.46.0` | Git version to download and vendor |
+| `GIT_URL` | `https://...git-$(GIT_VER).tar.xz` | Git source download URL |
+| `NO_LUA` | (unset) | Set to any value to disable Lua support |
+| `LUA_PKGCONFIG` | (auto-detected) | Explicit pkg-config name for Lua |
+| `NO_C99_FORMAT` | (unset) | Define if your printf lacks `%zu`, `%lld` etc. |
+| `HAVE_LINUX_SENDFILE` | (auto on Linux) | Enable `sendfile()` in cache |
+| `V` | (unset) | Set to `1` for verbose build output |
+
+Overrides can be placed in a `cgit.conf` file (included by both `Makefile` and
+`cgit.mk` via `-include cgit.conf`).
+
+## Installation
+
+```bash
+make install # Install binary and static assets
+make install-doc # Install man pages, HTML docs, PDF docs
+make install-man # Man pages only
+make install-html # HTML docs only
+make install-pdf # PDF docs only
+```
+
+### Installed files
+
+| Path | Mode | Source |
+|------|------|--------|
+| `$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)` | 0755 | `cgit` binary |
+| `$(CGIT_DATA_PATH)/cgit.css` | 0644 | Default stylesheet |
+| `$(CGIT_DATA_PATH)/cgit.js` | 0644 | Client-side JavaScript |
+| `$(CGIT_DATA_PATH)/cgit.png` | 0644 | Default logo |
+| `$(CGIT_DATA_PATH)/favicon.ico` | 0644 | Default favicon |
+| `$(CGIT_DATA_PATH)/robots.txt` | 0644 | Robots exclusion file |
+| `$(filterdir)/*` | (varies) | Filter scripts from `filters/` |
+| `$(mandir)/man5/cgitrc.5` | 0644 | Man page (if `install-man`) |
+
+## Make Targets
+
+| Target | Description |
+|--------|-------------|
+| `all` | Build the cgit binary (default) |
+| `cgit` | Explicit build target |
+| `test` | Build everything (`all` target on git) then run `tests/` |
+| `install` | Install binary, CSS, JS, images, filters |
+| `install-doc` | Install man pages + HTML + PDF |
+| `install-man` | Man pages only |
+| `install-html` | HTML docs only |
+| `install-pdf` | PDF docs only |
+| `clean` | Remove cgit objects, VERSION, CGIT-CFLAGS, tags |
+| `cleanall` | `clean` + `make -C git clean` |
+| `clean-doc` | Remove generated doc files |
+| `get-git` | Download and extract Git source into `git/` |
+| `tags` | Generate ctags for all `*.[ch]` files |
+| `sparse` | Run `sparse` static analysis via cgit.mk |
+| `uninstall` | Remove installed binary and assets |
+| `uninstall-doc` | Remove installed documentation |
+
+## Documentation Generation
+
+Man pages are generated from `cgitrc.5.txt` using `asciidoc`/`a2x`:
+
+```makefile
+MAN5_TXT = $(wildcard *.5.txt)
+DOC_MAN5 = $(patsubst %.txt,%,$(MAN5_TXT))
+DOC_HTML = $(patsubst %.txt,%.html,$(MAN_TXT))
+DOC_PDF = $(patsubst %.txt,%.pdf,$(MAN_TXT))
+
+%.5 : %.5.txt
+ a2x -f manpage $<
+
+$(DOC_HTML): %.html : %.txt
+ $(TXT_TO_HTML) -o $@+ $< && mv $@+ $@
+
+$(DOC_PDF): %.pdf : %.txt
+ a2x -f pdf cgitrc.5.txt
+```
+
+## Cross-Compilation
+
+For cross-compiling (e.g. targeting MinGW on Linux):
+
+```bash
+make CC=x86_64-w64-mingw32-gcc
+```
+
+The `toolchain-mingw32.cmake` file in the repository is for CMake-based
+projects; cgit itself uses Make exclusively.
+
+## Customizing the Build
+
+Create a `cgit.conf` file alongside the Makefile:
+
+```makefile
+# cgit.conf — local build overrides
+CGIT_VERSION = 1.0.0-custom
+CGIT_CONFIG = /usr/local/etc/cgitrc
+CACHE_ROOT = /tmp/cgit-cache
+NO_LUA = 1
+```
+
+This file is `-include`d by both `Makefile` and `cgit.mk`, so it applies to
+all build stages.
+
+## Troubleshooting
+
+| Problem | Solution |
+|---------|----------|
+| `make: *** No rule to make target 'git/Makefile'` | Run `make get-git` first |
+| `lua.h: No such file or directory` | Install Lua dev package or set `NO_LUA=1` |
+| `openssl/sha.h: No such file or directory` | Install `libssl-dev` / `openssl-devel` |
+| `sendfile: undefined reference` | Set `HAVE_LINUX_SENDFILE=` (empty) on non-Linux |
+| Build fails with `redefinition of 'struct cache_slot'` | Git's `cache.h` conflict — cgit uses `CGIT_CACHE_H` guard |
+| `dlsym: symbol not found: write` | Lua filter's `write()` interposition requires `-ldl` (auto on Linux) |
+| Version shows as `unknown` | Run `./gen-version.sh "$(CGIT_VERSION)"` or check `VERSION` file |