blob: 4109930d3fb0da29a94b344dc08052e189d81db7 (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
# 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

# TOOLSDIR and BUILDDIR are named relative to the project root because the
# version recipe changes into the root before using them. CGIT_SRC and
# CGIT_BUILD lead to the sources and the output from vendor/git, where
# everything else here runs.
CGIT_ROOT  = ../..
SRCDIR     = source
TOOLSDIR   = tools
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.
$(CGIT_BUILD)/VERSION: force-version
	@mkdir -p $(CGIT_BUILD)/
	@cd $(CGIT_ROOT) && \
		'$(SHELL_PATH_SQ)' $(TOOLSDIR)/gen-version.sh "$(CGIT_VERSION)" $(BUILDDIR)/VERSION
-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 and dlsym needs a non-conforming cast. 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_C99_FORMAT
	CFLAGS += -DNO_C99_FORMAT
endif

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

$(CGIT_OBJS): $(CGIT_BUILD)/%.o: $(CGIT_SRC)/%.c GIT-CFLAGS $(CGIT_BUILD)/CGIT-CFLAGS \
		$(missing_dep_dirs)
	$(QUIET_CC)$(CC) -o $@ -c $(dep_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))

$(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) $(CGIT_CFLAGS) $(SPARSE_FLAGS) $<

cgit-sparse: $(CGIT_SP_OBJS)