1VERSION = $(shell grep -m1 VERSION $(SRC) | cut -f 2 -d'"')
2
3PREFIX ?= /usr/local
4MANPREFIX ?= $(PREFIX)/share/man
5DESKTOPPREFIX ?= $(PREFIX)/share/applications
6DESKTOPICONPREFIX ?= $(PREFIX)/share/icons/hicolor
7STRIP ?= strip
8PKG_CONFIG ?= pkg-config
9INSTALL ?= install
10CP ?= cp
11
12CFLAGS_OPTIMIZATION ?= -O3
13
14O_DEBUG := 0  # debug binary
15O_NORL := 0  # no readline support
16O_PCRE := 0  # link with PCRE library
17O_NOLC := 0  # no locale support
18O_NOMOUSE := 0  # no mouse support
19O_NOBATCH := 0  # no built-in batch renamer
20O_NOFIFO := 0  # no FIFO previewer support
21O_CTX8 := 0  # enable 8 contexts
22O_ICONS := 0  # support icons-in-terminal
23O_NERD := 0  # support icons-nerdfont
24O_QSORT := 0  # use Alexey Tourbin's QSORT implementation
25O_BENCH := 0  # benchmark mode (stops at first user input)
26O_NOSSN := 0  # disable session support
27O_NOUG := 0  # disable user, group name in status bar
28O_NOX11 := 0  # disable X11 integration
29O_MATCHFLTR := 0  # allow filters without matches
30
31# User patches
32O_GITSTATUS := 0 # add git status to detail view
33O_NAMEFIRST := 0 # print file name first, add uid and guid to detail view
34O_RESTOREPREVIEW := 0 # add preview pipe to close and restore preview pane
35
36# convert targets to flags for backwards compatibility
37ifneq ($(filter debug,$(MAKECMDGOALS)),)
38	O_DEBUG := 1
39endif
40ifneq ($(filter norl,$(MAKECMDGOALS)),)
41	O_NORL := 1
42endif
43ifneq ($(filter nolc,$(MAKECMDGOALS)),)
44	O_NORL := 1
45	O_NOLC := 1
46endif
47
48ifeq ($(strip $(O_DEBUG)),1)
49	CPPFLAGS += -DDEBUG
50	CFLAGS += -g
51endif
52
53ifeq ($(strip $(O_NORL)),1)
54	CPPFLAGS += -DNORL
55else ifeq ($(strip $(O_STATIC)),1)
56	CPPFLAGS += -DNORL
57else
58	LDLIBS += -lreadline
59endif
60
61ifeq ($(strip $(O_PCRE)),1)
62	CPPFLAGS += -DPCRE
63	LDLIBS += -lpcre
64endif
65
66ifeq ($(strip $(O_NOLC)),1)
67	ifeq ($(strip $(O_ICONS)),1)
68$(info *** Ignoring O_NOLC since O_ICONS is set ***)
69	else ifeq ($(strip $(O_NERD)),1)
70$(info *** Ignoring O_NOLC since O_NERD is set ***)
71	else
72		CPPFLAGS += -DNOLC
73	endif
74endif
75
76ifeq ($(strip $(O_NOMOUSE)),1)
77	CPPFLAGS += -DNOMOUSE
78endif
79
80ifeq ($(strip $(O_NOBATCH)),1)
81	CPPFLAGS += -DNOBATCH
82endif
83
84ifeq ($(strip $(O_NOFIFO)),1)
85	CPPFLAGS += -DNOFIFO
86endif
87
88ifeq ($(strip $(O_CTX8)),1)
89	CPPFLAGS += -DCTX8
90endif
91
92ifeq ($(strip $(O_ICONS)),1)
93	CPPFLAGS += -DICONS
94endif
95
96ifeq ($(strip $(O_NERD)),1)
97	CPPFLAGS += -DNERD
98endif
99
100ifeq ($(strip $(O_QSORT)),1)
101	CPPFLAGS += -DTOURBIN_QSORT
102endif
103
104ifeq ($(strip $(O_BENCH)),1)
105	CPPFLAGS += -DBENCH
106endif
107
108ifeq ($(strip $(O_NOSSN)),1)
109	CPPFLAGS += -DNOSSN
110endif
111
112ifeq ($(strip $(O_NOUG)),1)
113	CPPFLAGS += -DNOUG
114endif
115
116ifeq ($(strip $(O_NOX11)),1)
117	CPPFLAGS += -DNOX11
118endif
119
120ifeq ($(strip $(O_MATCHFLTR)),1)
121	CPPFLAGS += -DMATCHFLTR
122endif
123
124ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
125	CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw)
126	LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs   ncursesw)
127else ifeq ($(shell $(PKG_CONFIG) ncurses && echo 1),1)
128	CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncurses)
129	LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs   ncurses)
130else
131	LDLIBS_CURSES ?= -lncurses
132endif
133
134CFLAGS += -std=c11 -Wall -Wextra -Wshadow
135CFLAGS += $(CFLAGS_OPTIMIZATION)
136CFLAGS += $(CFLAGS_CURSES)
137
138LDLIBS += $(LDLIBS_CURSES) -lpthread
139
140# static compilation needs libgpm development package
141ifeq ($(strip $(O_STATIC)),1)
142	LDFLAGS += -static
143	LDLIBS += -lgpm
144endif
145
146DISTFILES = src nnn.1 Makefile README.md LICENSE
147SRC = src/nnn.c
148HEADERS = src/nnn.h
149BIN = nnn
150DESKTOPFILE = misc/desktop/nnn.desktop
151LOGOSVG = misc/logo/logo.svg
152LOGO64X64 = misc/logo/logo-64x64.png
153
154GITSTATUS = patches/gitstatus
155NAMEFIRST = patches/namefirst
156RESTOREPREVIEW = patches/restorepreview
157
158# test if we are on Mac OS X and get X.Y.Z OS version with system binary /usr/bin/sw_vers
159MACOS_VERSION := $(strip $(shell command -v sw_vers >/dev/null && [ "`sw_vers -productName`" = "Mac OS X" ] && sw_vers -productVersion))
160# if Mac OS X detected, test if its version is below 10.12.0 relying on "sort -c" returning "disorder" message if the input is not sorted
161ifneq ($(MACOS_VERSION),)
162	MACOS_BELOW_1012 := $(if $(strip $(shell printf '10.12.0\n%s' "$(MACOS_VERSION)" | sort -ct. -k1,1n -k2,2n -k3,3n 2>&1)),1)
163endif
164# if Mac OS X version is below 10.12.0, compile in the replacement clock_gettime and define MACOS_BELOW_1012 so that it's included in nnn.c
165ifneq ($(MACOS_BELOW_1012),)
166	GETTIME_C = misc/macos-legacy/mach_gettime.c
167	GETTIME_H = misc/macos-legacy/mach_gettime.h
168	SRC += $(GETTIME_C)
169	HEADERS += $(GETTIME_H)
170	CPPFLAGS += -DMACOS_BELOW_1012
171endif
172
173all: $(BIN)
174
175$(BIN): $(SRC) $(HEADERS)
176	@$(MAKE) --silent prepatch
177	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(GETTIME_C) $< $(LDLIBS)
178	@$(MAKE) --silent postpatch
179
180# targets for backwards compatibility
181debug: $(BIN)
182norl: $(BIN)
183nolc: $(BIN)
184
185install-desktop: $(DESKTOPFILE)
186	$(INSTALL) -m 0755 -d $(DESTDIR)$(DESKTOPPREFIX)
187	$(INSTALL) -m 0644 $(DESKTOPFILE) $(DESTDIR)$(DESKTOPPREFIX)
188	$(INSTALL) -m 0755 -d $(DESTDIR)$(DESKTOPICONPREFIX)/scalable/apps
189	$(INSTALL) -m 0644 $(LOGOSVG) $(DESTDIR)$(DESKTOPICONPREFIX)/scalable/apps/nnn.svg
190	$(INSTALL) -m 0755 -d $(DESTDIR)$(DESKTOPICONPREFIX)/64x64/apps
191	$(INSTALL) -m 0644 $(LOGO64X64) $(DESTDIR)$(DESKTOPICONPREFIX)/64x64/apps/nnn.png
192
193uninstall-desktop:
194	$(RM) $(DESTDIR)$(DESKTOPPREFIX)/$(DESKTOPFILE)
195	$(RM) $(DESTDIR)$(DESKTOPICONPREFIX)/scalable/apps/nnn.svg
196	$(RM) $(DESTDIR)$(DESKTOPICONPREFIX)/64x64/apps/nnn.png
197
198install: all
199	$(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin
200	$(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin
201	$(INSTALL) -m 0755 -d $(DESTDIR)$(MANPREFIX)/man1
202	$(INSTALL) -m 0644 $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1
203
204uninstall:
205	$(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN)
206	$(RM) $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1
207
208strip: $(BIN)
209	$(STRIP) $^
210
211upx: $(BIN)
212	$(STRIP) $^
213	upx -qqq $^
214
215static:
216	# regular static binary
217	make O_STATIC=1 strip
218	mv $(BIN) $(BIN)-static
219	# static binary with icons-in-terminal support
220	make O_STATIC=1 O_ICONS=1 strip
221	mv $(BIN) $(BIN)-icons-static
222	# static binary with patched nerd font support
223	make O_STATIC=1 O_NERD=1 strip
224	mv $(BIN) $(BIN)-nerd-static
225
226musl:
227	cp misc/musl/musl-static-ubuntu.sh .
228	./musl-static-ubuntu.sh 1
229	rm ./musl-static-ubuntu.sh
230
231dist:
232	mkdir -p nnn-$(VERSION)
233	$(CP) -r $(DISTFILES) nnn-$(VERSION)
234	tar -cf - nnn-$(VERSION) | gzip > nnn-$(VERSION).tar.gz
235	$(RM) -r nnn-$(VERSION)
236
237sign:
238	git archive -o nnn-$(VERSION).tar.gz --format tar.gz --prefix=nnn-$(VERSION)/ v$(VERSION)
239	gpg --detach-sign --yes nnn-$(VERSION).tar.gz
240	rm -f nnn-$(VERSION).tar.gz
241
242upload-local: sign static musl
243	$(eval ID=$(shell curl -s 'https://api.github.com/repos/jarun/nnn/releases/tags/v$(VERSION)' | jq .id))
244	# upload sign file
245	curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=nnn-$(VERSION).tar.gz.sig' \
246	    -H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/pgp-signature' \
247	    --upload-file nnn-$(VERSION).tar.gz.sig
248	# upx compress all static binaries
249	upx -qqq $(BIN)-static
250	upx -qqq $(BIN)-icons-static
251	upx -qqq $(BIN)-nerd-static
252	# upload static binary
253	tar -zcf $(BIN)-static-$(VERSION).x86_64.tar.gz $(BIN)-static
254	curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-static-$(VERSION).x86_64.tar.gz' \
255	    -H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
256	    --upload-file $(BIN)-static-$(VERSION).x86_64.tar.gz
257	# upload icons-in-terminal compiled static binary
258	tar -zcf $(BIN)-icons-static-$(VERSION).x86_64.tar.gz $(BIN)-icons-static
259	curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-icons-static-$(VERSION).x86_64.tar.gz' \
260	    -H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
261	    --upload-file $(BIN)-icons-static-$(VERSION).x86_64.tar.gz
262	# upload patched nerd font compiled static binary
263	tar -zcf $(BIN)-nerd-static-$(VERSION).x86_64.tar.gz $(BIN)-nerd-static
264	curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-nerd-static-$(VERSION).x86_64.tar.gz' \
265	    -H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
266	    --upload-file $(BIN)-nerd-static-$(VERSION).x86_64.tar.gz
267	# upload musl static binary
268	tar -zcf $(BIN)-musl-static-$(VERSION).x86_64.tar.gz $(BIN)-musl-static
269	curl -XPOST 'https://uploads.github.com/repos/jarun/nnn/releases/$(ID)/assets?name=$(BIN)-musl-static-$(VERSION).x86_64.tar.gz' \
270	    -H 'Authorization: token $(NNN_SIG_UPLOAD_TOKEN)' -H 'Content-Type: application/x-sharedlib' \
271	    --upload-file $(BIN)-musl-static-$(VERSION).x86_64.tar.gz
272
273clean:
274	$(RM) -f $(BIN) nnn-$(VERSION).tar.gz *.sig $(BIN)-static $(BIN)-static-$(VERSION).x86_64.tar.gz $(BIN)-icons-static $(BIN)-icons-static-$(VERSION).x86_64.tar.gz $(BIN)-nerd-static $(BIN)-nerd-static-$(VERSION).x86_64.tar.gz $(BIN)-musl-static $(BIN)-musl-static-$(VERSION).x86_64.tar.gz
275
276prepatch:
277ifeq ($(strip $(O_NAMEFIRST)),1)
278	patch --forward --strip=1 --input=$(NAMEFIRST)/mainline.diff
279ifeq ($(strip $(O_GITSTATUS)),1)
280	patch --forward --strip=1 --input=$(GITSTATUS)/namefirst.diff
281endif
282else ifeq ($(strip $(O_GITSTATUS)),1)
283	patch --forward --strip=1 --input=$(GITSTATUS)/mainline.diff
284endif
285ifeq ($(strip $(O_RESTOREPREVIEW)),1)
286	patch --forward --strip=1 --input=$(RESTOREPREVIEW)/mainline.diff
287endif
288
289postpatch:
290ifeq ($(strip $(O_NAMEFIRST)),1)
291ifeq ($(strip $(O_GITSTATUS)),1)
292	patch --reverse --strip=1 --input=$(GITSTATUS)/namefirst.diff
293endif
294	patch --reverse --strip=1 --input=$(NAMEFIRST)/mainline.diff
295else ifeq ($(strip $(O_GITSTATUS)),1)
296	patch --reverse --strip=1 --input=$(GITSTATUS)/mainline.diff
297endif
298ifeq ($(strip $(O_RESTOREPREVIEW)),1)
299	patch --reverse --strip=1 --input=$(RESTOREPREVIEW)/mainline.diff
300endif
301
302skip: ;
303
304.PHONY: all install uninstall strip static dist sign upload-local clean install-desktop uninstall-desktop
305