blob: 876e353826ad02e665ef95e666a1219b7cc33839 (plain)
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# The rules that compile and link cgit itself. They run with the bundled Git
# tree as the working directory so that Git's build variables and platform
# detection can be reused, which is why every path back into the project leads
# through CGIT_ROOT. The top level Makefile invokes it roughly as
#
#     make -C vendor/git -f ../../source/cgit.mk ../../build/cgit
#
# so sources are read from ../../source and all output is written to
# ../../build.
include Makefile

# BUILDDIR is named relative to the project root because the version recipe
# changes into the root before using it. CGIT_SRC and CGIT_BUILD lead to the
# sources and the output from vendor/git, where everything else here runs.
CGIT_ROOT  = ../..
SRCDIR     = source
BUILDDIR   = build
CGIT_SRC   = $(CGIT_ROOT)/$(SRCDIR)
CGIT_BUILD = $(CGIT_ROOT)/$(BUILDDIR)

# Read again here because a sub make inherits only the variables the top level
# Makefile exports, which leaves out the build options this file reads.
-include $(CGIT_ROOT)/cgit.conf

# The CGIT_ values used below are exported by the top level Makefile. git
# describe names the version when it runs at the top of the cgit working tree,
# rather than in the bundled git, and CGIT_VERSION stands in for a tarball or
# a clone with no tags. The file is left alone when its line is unchanged,
# since everything that includes it would otherwise rebuild.
$(CGIT_BUILD)/VERSION: force-version
	@mkdir -p $(CGIT_BUILD)/
	@cd $(CGIT_ROOT) && version='$(CGIT_VERSION)' && \
	if test "$$(git rev-parse --git-dir 2>/dev/null)" = .git && \
		described=$$(git describe --abbrev=4 HEAD 2>/dev/null); then \
		version=$$described; \
	fi && \
	line="CGIT_VERSION = $$version" && \
	if test "$$(cat $(BUILDDIR)/VERSION 2>/dev/null)" != "$$line"; then \
		echo "$$line" >$(BUILDDIR)/VERSION && echo "$$line"; \
	fi
-include $(CGIT_BUILD)/VERSION
.PHONY: force-version

# Pinned so a compiler moving its default, as GCC 15 did to gnu23, cannot
# change what the sources mean. The GNU dialect because git's headers use GNU
# extensions. Git keeps its own choice.
CGIT_STD ?= gnu17

# CGIT_CFLAGS is tracked separately so that changing it does not force a rebuild
# of Git itself.
CGIT_CFLAGS += -std=$(CGIT_STD)
CGIT_CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
CGIT_CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
CGIT_CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'

# Reaches only the cgit objects, so a caller can tighten the build, the way the
# release build passes -Werror=format-security, without holding git's own
# sources to the same standard.
CGIT_CFLAGS += $(CGIT_EXTRA_CFLAGS)

PKG_CONFIG ?= pkg-config

ifdef NO_LUA
	LUA_MESSAGE := linking without specified Lua support
	CGIT_CFLAGS += -DNO_LUA
else
ifeq ($(LUA_PKGCONFIG),)
	LUA_PKGCONFIG := $(shell for pc in luajit lua lua5.5 lua5.4 lua5.3 lua5.2 lua5.1; do \
			$(PKG_CONFIG) --exists $$pc 2>/dev/null && echo $$pc && break; \
			done)
	LUA_MODE := autodetected
else
	LUA_MODE := specified
endif
ifneq ($(LUA_PKGCONFIG),)
	LUA_MESSAGE := linking with $(LUA_MODE) $(LUA_PKGCONFIG)
	LUA_LIBS := $(shell $(PKG_CONFIG) --libs $(LUA_PKGCONFIG) 2>/dev/null)
	LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKGCONFIG) 2>/dev/null)
	CGIT_LIBS += $(LUA_LIBS)
	CGIT_CFLAGS += $(LUA_CFLAGS)
else
	LUA_MESSAGE := linking without autodetected Lua support
	NO_LUA := YesPlease
	CGIT_CFLAGS += -DNO_LUA
endif

endif

# The filters reach libc's write through dlsym, which lives in a library of its
# own on the systems that use GNU libc.
ifneq (,$(filter $(uname_S),Linux GNU GNU/kFreeBSD))
	CGIT_LIBS += -ldl
endif

# The cache sends a stored page straight to stdout with sendfile where it can.
# Only Linux is assumed to offer it, so everywhere else falls back to reading
# and writing the file by hand.
ifeq ($(uname_S),Linux)
	HAVE_LINUX_SENDFILE = YesPlease
endif

ifdef HAVE_LINUX_SENDFILE
	CGIT_CFLAGS += -DHAVE_LINUX_SENDFILE
endif

CGIT_OBJ_NAMES += cgit.o
CGIT_OBJ_NAMES += cache.o
CGIT_OBJ_NAMES += cmd.o
CGIT_OBJ_NAMES += config.o
CGIT_OBJ_NAMES += filter.o
CGIT_OBJ_NAMES += html.o
CGIT_OBJ_NAMES += parsing.o
CGIT_OBJ_NAMES += scan-tree.o
CGIT_OBJ_NAMES += shared.o
CGIT_OBJ_NAMES += ui-atom.o
CGIT_OBJ_NAMES += ui-blame.o
CGIT_OBJ_NAMES += ui-blob.o
CGIT_OBJ_NAMES += ui-clone.o
CGIT_OBJ_NAMES += ui-commit.o
CGIT_OBJ_NAMES += ui-diff.o
CGIT_OBJ_NAMES += ui-empty.o
CGIT_OBJ_NAMES += ui-log.o
CGIT_OBJ_NAMES += ui-patch.o
CGIT_OBJ_NAMES += ui-plain.o
CGIT_OBJ_NAMES += ui-refs.o
CGIT_OBJ_NAMES += ui-repolist.o
CGIT_OBJ_NAMES += ui-shared.o
CGIT_OBJ_NAMES += ui-snapshot.o
CGIT_OBJ_NAMES += ui-ssdiff.o
CGIT_OBJ_NAMES += ui-stats.o
CGIT_OBJ_NAMES += ui-summary.o
CGIT_OBJ_NAMES += ui-tag.o
CGIT_OBJ_NAMES += ui-tree.o

CGIT_OBJS := $(addprefix $(CGIT_BUILD)/,$(CGIT_OBJ_NAMES))

# Only cgit.c references CGIT_VERSION, so only its objects rebuild when the
# version changes.
CGIT_VERSION_OBJS := $(addprefix $(CGIT_BUILD)/,cgit.o cgit.sp)
$(CGIT_VERSION_OBJS): $(CGIT_BUILD)/VERSION
$(CGIT_VERSION_OBJS): EXTRA_CPPFLAGS = -DCGIT_VERSION='"$(CGIT_VERSION)"'

# Git builds its list of dependency files with := before this file adds the
# cgit objects, so those are missing from it and have to be picked up here.
cgit_dep_files := $(foreach f,$(CGIT_OBJS),$(dir $f).depend/$(notdir $f).d)
cgit_dep_files_present := $(wildcard $(cgit_dep_files))
ifneq ($(cgit_dep_files_present),)
include $(cgit_dep_files_present)
endif

ifeq ($(wildcard $(CGIT_BUILD)/.depend),)
missing_dep_dirs += $(CGIT_BUILD)/.depend
endif

$(CGIT_BUILD)/.depend:
	@mkdir -p $@

$(CGIT_BUILD)/CGIT-CFLAGS: FORCE
	@mkdir -p $(CGIT_BUILD)/
	@FLAGS='$(subst ','\'',$(CGIT_CFLAGS))'; \
		OLD=`cat $(CGIT_BUILD)/CGIT-CFLAGS 2>/dev/null`; \
		if test x"$$FLAGS" != x"$$OLD"; then \
			echo 1>&2 "    * new CGit build flags"; \
			echo "$$FLAGS" >$(CGIT_BUILD)/CGIT-CFLAGS; \
		fi

# compdb_args and missing_compdb_dir are git's, and stay empty unless
# GENERATE_COMPILATION_DATABASE asks clang for a -MJ entry per object, which
# puts cgit's sources in the database beside git's.
$(CGIT_OBJS): $(CGIT_BUILD)/%.o: $(CGIT_SRC)/%.c GIT-CFLAGS $(CGIT_BUILD)/CGIT-CFLAGS \
		$(missing_dep_dirs) $(missing_compdb_dir)
	$(QUIET_CC)$(CC) -o $@ -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $(CGIT_CFLAGS) $<

$(CGIT_BUILD)/cgit: $(CGIT_OBJS) GIT-LDFLAGS $(GITLIBS)
	@echo 1>&2 "    * $(LUA_MESSAGE)"
	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) $(CGIT_LIBS)

CGIT_SP_OBJS := $(patsubst %.o,%.sp,$(CGIT_OBJS))

# Git's SPARSE_FLAGS name a -std of their own, so they come ahead of
# CGIT_CFLAGS for sparse to read the sources in the dialect they build in.
$(CGIT_SP_OBJS): $(CGIT_BUILD)/%.sp: $(CGIT_SRC)/%.c GIT-CFLAGS $(CGIT_BUILD)/CGIT-CFLAGS FORCE
	$(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $(SPARSE_FLAGS) $(CGIT_CFLAGS) $<

cgit-sparse: $(CGIT_SP_OBJS)