blob: cf5f31dd31ff84ac0c4149ce972c4f39c65d4fed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# The entry point for building and installing cgit. The program itself is
# compiled inside the bundled Git tree by source/cgit.mk, which this file
# invokes with the paths and the defaults it needs. Everything that is not
# compilation, that is the install and uninstall rules and the housekeeping
# targets, is driven from here.

.DEFAULT_GOAL := all
.SUFFIXES:

# Every build target here runs a sub make in the one Git tree, and two of them
# at once would compile the same objects side by side. The sub makes still
# run their own jobs in parallel.
.NOTPARALLEL:

# CGIT_ROOT leads from inside the Git tree back to the project root, because
# the cgit build runs with vendor/git as its working directory.
SRCDIR   = source
ASSETDIR = assets
EXTDIR   = custom/extensions
GITDIR   = vendor/git
BUILDDIR = build
CGIT_ROOT = ../..

# The Git release that get-git fetches when the submodule is not checked out.
# Keep it in step with the commit the submodule is pinned to, and the sum in
# step with the one kernel.org lists for the tarball in sha256sums.asc.
GIT_VERSION = 2.56.0
GIT_SHA256 = 26c56c296b38c0695b26fa95f475f1d01704d2d38e73465ca30b0b2f5dc789d3
GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VERSION).tar.xz
GIT_TARBALL = git-$(GIT_VERSION).tar.xz

# The defaults compiled into cgit and the directories make install writes to,
# all overridable through cgit.conf.
CGIT_VERSION = v2.11.0
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

# The standard GNU install directories, under the lowercase names packaging
# expects. filterdir is the one cgit-specific addition.
prefix = /usr/local
libdir = $(prefix)/lib
filterdir = $(libdir)/cgit/filters

# The files that go into the data path and the filter directory. One list each
# drives both install and uninstall, so the two can never drift apart.
ASSETS  = cgit.css
ASSETS += cgit.js
ASSETS += cgit.png
ASSETS += favicon.ico
ASSETS += robots.txt
FILTER_FILES = $(notdir $(wildcard $(EXTDIR)/*.lua))

INSTALL = install

# Reuse Git's platform detection, then let the user override any of the
# settings above through cgit.conf. Both includes must stay after the defaults.
-include $(GITDIR)/config.mak.uname
-include cgit.conf

export CGIT_VERSION CGIT_SCRIPT_NAME CGIT_CONFIG CACHE_ROOT

.PHONY: all
all: cgit

# NO_GETTEXT and NO_TCLTK leave out Git's translations and its Tcl tools, none
# of which cgit uses, so the build needs no libintl, msgfmt or tclsh. NO_RUST
# keeps Cargo out of the build. Git 2.55 inverted the flag that used to be
# WITH_RUST, so Rust is now compiled in unless it is turned off, and leaving
# this out would quietly make Cargo a build requirement. Git 3.0 drops the
# choice entirely, at which point this stops working and Rust becomes mandatory.
# Git's own build defaults prefix to $HOME and compiles it in as its fallback
# runtime prefix, so without the last flag every binary carries the home
# directory of whoever built it and no two builders get the same bytes.
GIT_BUILD_FLAGS = NO_CURL=1 NO_GETTEXT=1 NO_OPENSSL=1 NO_RUST=1 NO_TCLTK=1 prefix='$(prefix)'

# Apple's linker otherwise stamps each object's mtime into the debug map, so
# two builds of the same sources would differ.
export ZERO_AR_DATE = 1

.PHONY: cgit
cgit:
	+@$(MAKE) -C $(GITDIR) -f $(CGIT_ROOT)/$(SRCDIR)/cgit.mk \
		$(CGIT_ROOT)/$(BUILDDIR)/cgit $(EXTRA_GIT_TARGETS) $(GIT_BUILD_FLAGS)

# The same program without Lua, built beside the full one so a change cannot
# break that configuration unnoticed. The suite runs both.
.PHONY: cgit-nolua
cgit-nolua:
	+@$(MAKE) -C $(GITDIR) -f $(CGIT_ROOT)/$(SRCDIR)/cgit.mk \
		$(CGIT_ROOT)/$(BUILDDIR)/nolua/cgit NO_LUA=1 BUILDDIR=$(BUILDDIR)/nolua $(GIT_BUILD_FLAGS)

.PHONY: sparse
sparse:
	+@$(MAKE) -C $(GITDIR) -f $(CGIT_ROOT)/$(SRCDIR)/cgit.mk $(GIT_BUILD_FLAGS) cgit-sparse

.PHONY: test
test: cgit-with-git
	+@$(MAKE) cgit-nolua
	+@$(MAKE) -C tests all

# The test helpers link against a fully built Git tree, so this asks the sub
# make for Git's own all target alongside cgit.
.PHONY: cgit-with-git
cgit-with-git:
	+@$(MAKE) cgit EXTRA_GIT_TARGETS=all

.PHONY: install
install: all
	$(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_SCRIPT_PATH)
	$(INSTALL) -m 0755 $(BUILDDIR)/cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
	$(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH)
	$(INSTALL) -m 0644 $(addprefix $(ASSETDIR)/,$(ASSETS)) $(DESTDIR)$(CGIT_DATA_PATH)
	$(INSTALL) -m 0755 -d $(DESTDIR)$(filterdir)
	$(INSTALL) -m 0644 $(addprefix $(EXTDIR)/,$(FILTER_FILES)) $(DESTDIR)$(filterdir)

.PHONY: uninstall
uninstall:
	$(RM) $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
	$(RM) $(addprefix $(DESTDIR)$(CGIT_DATA_PATH)/,$(ASSETS))
	$(RM) $(addprefix $(DESTDIR)$(filterdir)/,$(FILTER_FILES))

# The descent into tests is guarded because tests/Makefile includes git's
# config.mak.uname, which needs the submodule present.
.PHONY: clean
clean:
	$(RM) -r $(BUILDDIR)
	@if test -e $(GITDIR)/config.mak.uname; then $(MAKE) -C tests clean; fi

.PHONY: cleanall
cleanall: clean
	@if test -e $(GITDIR)/Makefile; then $(MAKE) -C $(GITDIR) clean; fi

# The tarball is checked against its sum before anything is unpacked from it.
# Each system ships its own fetcher and sum tool (curl or wget on Linux and
# macOS, fetch on FreeBSD, ftp on OpenBSD and NetBSD, sha256 on the BSDs), so
# the first one present is used, and xz is piped to tar for a tar that cannot
# read it, as OpenBSD's cannot.
.PHONY: get-git
get-git:
	mkdir -p $(dir $(GITDIR))
	@if command -v curl >/dev/null; then curl -fL -o $(GIT_TARBALL) $(GIT_URL); \
	elif command -v wget >/dev/null; then wget -O $(GIT_TARBALL) $(GIT_URL); \
	elif command -v fetch >/dev/null; then fetch -o $(GIT_TARBALL) $(GIT_URL); \
	else ftp -o $(GIT_TARBALL) $(GIT_URL); fi
	@if command -v sha256sum >/dev/null; then sum=$$(sha256sum $(GIT_TARBALL)); \
	elif command -v shasum >/dev/null; then sum=$$(shasum -a 256 $(GIT_TARBALL)); \
	elif command -v sha256 >/dev/null; then sum=$$(sha256 -q $(GIT_TARBALL)); \
	else sum=$$(openssl dgst -sha256 -r $(GIT_TARBALL)); fi; \
	test "$${sum%% *}" = '$(GIT_SHA256)' || \
		{ echo 'get-git: $(GIT_TARBALL) does not match its sum' >&2; $(RM) $(GIT_TARBALL); exit 1; }
	@if command -v xz >/dev/null; then xz -dc $(GIT_TARBALL) | tar -xf -; else tar -xJf $(GIT_TARBALL); fi
	rm -rf $(GITDIR) && mv git-$(GIT_VERSION) $(GITDIR)
	$(RM) $(GIT_TARBALL)

.PHONY: tags
tags:
	@mkdir -p $(BUILDDIR)
	find $(SRCDIR) -name '*.[ch]' | xargs ctags -f $(BUILDDIR)/tags