File: Makefile

package info (click to toggle)
vifm 0.14.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,252 kB
  • sloc: ansic: 179,567; sh: 5,445; makefile: 723; perl: 347; python: 76; xml: 26
file content (385 lines) | stat: -rw-r--r-- 11,966 bytes parent folder | download | duplicates (2)
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# Overview
# --------
#
# This is a non-recursive Makefile for running vifm tests using stic.
#
# Vifm is built before running any tests as its object files are used for tests.
# Necessary include and link directives are picked up from the main Makefile.
#
# Each test-suite (directory) is run in a separate sandbox directory.  During
# compilation two defines are available:
#  - TEST_DATA_PATH -- path to test-data/ directory (might be RO)
#  - SANDBOX_PATH   -- path to sandbox for the suite (always RW)
#
# Test suites can be run concurrently.
#
# Usage
# -----
#
# By default tests are built in release mode.
#
# make              -- builds and runs all tests
# make build        -- builds all tests without running them
# make check        -- builds all tests and then runs them
# make <dir>        -- runs specific test suite
# make <dir>.<name> -- runs specific fixture
#
# make DEBUG=1 ...        -- builds debug version
# make DEBUG=gdb ...      -- builds debug version and loads suite into gdb
# make DEBUG=rr ...       -- builds debug version and loads suite into rr
# make DEBUG=valgrind ... -- builds debug version and runs it under valgrind
#                            (see valgrind-report file after a run)
#
# make VERBOSE=1 ... -- enables verbose printing of commands
#
# make TEST_RUN_PREFIX=wine -- sets run command prefix
#
# make clean -- removes various build artifacts
#
# make TESTS_CFLAGS=... TESTS_LDFLAGS... -- prepend something to CFLAGS/LDFLAGS
#
# "B" variable might be set to build tree root to run tests out of the source
# tree.

# don't undefine $TERM if we're going to invoke gdb or it will prevent its TUI
# from starting
ifneq ($(DEBUG),gdb)
    # don't pass $TERM to tests, they should work without a terminal and this
    # variable
    unexport TERM
endif

# hide terminal multiplexers and graphic systems, so tests behave consistently
unexport STY TMUX DISPLAY WAYLAND_DISPLAY

# determine kind of OS that is running
ifeq ($(OS),Windows_NT)
    ifeq ($(shell uname -o 2> /dev/null),Cygwin)
        unix_env := true
    else
        win_env := true
    endif
else
    ifeq ($(CROSS),)
        ifeq ($(shell id -u),0)
            $(warning warning: running tests as root disables chmod-based ones)
        endif
        unix_env := true
    else
        win_env := true
    endif
endif

ifdef DEBUG
    BINSUBDIR := debug/
endif

# test for a bad directory path which breaks the Makefile
ifndef win_env
    # testing for # seems to work only for some versions of GNU Make
    ifneq (,$(findstring :,$(PWD)))
        $(error Paths with : break tests' Makefile)
    endif
endif

# path to build tree
B ?=
# path to storage for intermediate build files
BUILD := $(B)bin/build/$(BINSUBDIR)

# engine
suites += abbrevs autocmds cmds commands completion keys options parsing
suites += text_buffer variables
# io
suites += ioeta ionotif iop ior
# ui
suites += colmgr column_view viewcolumns_parser
# everything else
suites += bmarks escape fileops filetype filter lua menus misc undo utils

# these are built, but not automatically executed
apps := fuzz io_tester_app regs_shmem_app

# obtain list of sources that are being tested
vifm_src := ./ cfg/ compat/ engine/ int/ io/ io/private/ lua/ lua/lua/ menus/
vifm_src += modes/ modes/dialogs/ ui/ utils/
vifm_src := $(wildcard $(addprefix ../src/, $(addsuffix *.c, $(vifm_src))))
vifm_src := $(filter-out %/tags.c %/xxhash.c, $(vifm_src))

# filter out generally non-testable or sources for another platform
vifm_src := $(filter-out %/src/./vifm.c %/win_helper.c, $(vifm_src))
ifndef unix_env
    vifm_src := $(filter-out %/desktop.c %/media_menu.c %/mntent.c %_nix.c, \
                             $(vifm_src))
endif
ifndef win_env
    vifm_src := $(filter-out %/wcwidth.c %/volumes_menu.c %_win.c, $(vifm_src))
endif

vifm_obj := $(B)../src/./tags.o $(vifm_src:%.c=$(B)%.o)

tests_lib := $(BUILD)libtest-support.a
tests_lib_src := $(wildcard test-support/*.c)
tests_lib_obj := $(patsubst %.c,$(BUILD)%.o,$(tests_lib_src))

# make sure that there is one compile_info.c object file in the list
vifm_obj := $(filter-out %/compile_info.o, $(vifm_obj))
vifm_obj += $(B)../src/compile_info.o

ifdef unix_env
    make_args := -C $(B)../src/
endif
ifdef win_env
    make_args  := -C $(B)../src/ -f $(abspath ../src/Makefile.win)
    exe_suffix := .exe
endif

CC = $(CROSS)gcc
AR = $(CROSS)ar

# handling of verbosity (non-verbose by default)
ifdef VERBOSE
    V = 1
else
    V = 0
endif
ACTUAL_CC := $(CC)
ACTUAL_AR := $(AR)
CC_0 = @echo "Compiling $@..."; $(ACTUAL_CC)
CC_1 = $(ACTUAL_CC)
AR_0 = @echo "Archiving $@..."; $(ACTUAL_AR)
AR_1 = $(ACTUAL_AR)
LD_0 = @echo "Linking $@..."; $(ACTUAL_CC)
LD_1 = $(ACTUAL_CC)
AT_0 = @
AT_1 =
# redefine commands according to verbosity state
override CC = $(CC_$(V))
override AR = $(AR_$(V))
override LD = $(LD_$(V))
AT = $(AT_$(V))

# setup compile and link flags (partially depends on OS)
override CFLAGS := $(TESTS_CFLAGS) -MMD -MP -pipe \
                   -Wall -Wno-char-subscripts \
                   -Itest-support/ -Itest-support/stic/ \
                   -include $(B)../build-aux/config.h \
                   -DTEST
override LDFLAGS := $(TESTS_LDFLAGS)
ifdef unix_env
    MF := $(abspath $(B)../src/Makefile)
    ifneq ($(wildcard $(MF)),)
        override LDFLAGS += \
            $(shell grep -m1    'LIBS =' $(MF) | sed 's/^[^=]*=//') \
            $(shell grep -m1 'LDFLAGS =' $(MF) | sed 's/^[^=]*=//')

        override CFLAGS  += \
            $(shell grep -m1          'CPPFLAGS =' $(MF) | sed 's/^[^=]*=//') \
            $(shell grep -m1      'TESTS_CFLAGS =' $(MF) | sed 's/^[^=]*=//') \
            $(shell grep -m1 'SANITIZERS_CFLAGS =' $(MF) | sed 's/^[^=]*=//')
    endif

    override CFLAGS += -I/usr/include/ncursesw
    export UBSAN_OPTIONS := halt_on_error=1
endif
ifdef win_env
    override CFLAGS += -pthread
    override LDFLAGS += \
        $(shell sed -n '/LIBS :=/{s/^[^=]\+=//p;q}' ../src/Makefile.win)
    # this part is in conditional of ../src/Makefile.win
    ifeq ($(OS),Windows_NT)
        override LDFLAGS += -lpdcurses
    else
        override LDFLAGS += -lcurses
    endif
endif
override CFLAGS += -fcommon
ifeq (,$(findstring -lpthread,$(LDFLAGS)))
    override LDFLAGS += -pthread
endif

# work around clang
ifeq (,$(findstring clang,$(shell $(ACTUAL_CC) --version)))
    ifneq (,$(findstring --coverage, $(LDFLAGS)))
        # clang is inconvenient with regard to this flag, don't do coverage with
        # it
        override CFLAGS += --coverage
        override LDFLAGS += --coverage
    endif

    # don't precompile header with clang (on OS X gcc is likely to be a symlink
    # to clang) because it handles macros in a different way
    GCH_DEP := $(BUILD)test-support/stic/stic.h.gch

    # this flag seems to be gcc-specific and clang freaks out on it with -Werror
    override CFLAGS += -Wno-format-truncation
endif

ifdef DEBUG
    override CFLAGS += -g -O0
    override LDFLAGS += -g
    ifdef unix_env
        override LDFLAGS += -rdynamic
    else
        override CFLAGS += -gdwarf-3
    endif

    ifeq ($(DEBUG),gdb)
        TEST_RUN_PREFIX := gdb -q --args
    endif
    ifeq ($(DEBUG),rr)
        TEST_RUN_PREFIX := rr record
    endif
    ifeq ($(DEBUG),valgrind)
        TEST_RUN_PREFIX := valgrind --track-origins=yes --leak-check=full \
                           --log-file=valgrind-report --error-exitcode=5 \
                           --suppressions=$(abspath .)/../src/.valgrind.supp
        TEST_RUN_POST := || (e=$$$$?; if [ $$$$e -eq 5 ]; then \
                                          cat valgrind-report; \
                                      fi; \
                                      exit $$$$e)
    endif
endif

.PHONY: check build clean $(suites) $(apps) appsources

# check and build targets are defined mostly in suite_template
check: build
	@if [ "$$(find "$(SANDBOX_PATH)" -mindepth 2 | wc -l)" -ne 0 ]; then \
	    echo "ERROR: sandbox isn't empty"; \
	    find $(SANDBOX_PATH) -mindepth 2; \
	    false; \
	fi

clean:
	$(RM) -r $(B)bin/ $(SANDBOX_PATH)/

# disable implicit rules to prevent compiling main sources here
.SUFFIXES:

# sources target groups dependencies to avoid invoking nested make per target
$(vifm_obj) ../src/./tags.c: appsources
	@# this receipt is needed to make Make recognize that targets were updated

appsources: $(vifm_src)
	$(MAKE) $(make_args) vifm$(exe_suffix)

$(BUILD)test-support/%.o: test-support/%.c | $(BUILD)test-support
	$(CC) -c -o $@ $(CFLAGS) $<

$(BUILD)test-support/stic/stic.o: test-support/stic/stic.c \
                                | $(BUILD)test-support/stic
	$(CC) -c -o $@ $(CFLAGS) $<

$(BUILD)test-support/stic/stic.h.gch: test-support/stic/stic.h \
                                    | $(BUILD)test-support/stic
	$(CC) -c -o $@ $(CFLAGS) $<

$(tests_lib): $(BUILD)test-support/stic/stic.o $(tests_lib_obj) \
            | $(BUILD)
	$(AR) cr $@ $^

$(BUILD) $(B)bin/$(BINSUBDIR) $(BUILD)test-support $(BUILD)test-support/stic:
	$(AT)mkdir -p $@

# this function of two arguments (array and element) returns index of the
# element in the array
pos = $(strip $(eval T := ) \
              $(eval i := 0) \
              $(foreach elem, $1, \
                        $(if $(filter $2,$(elem)), \
                             $(eval i := $(words $T)), \
                             $(eval T := $T $(elem)))) \
              $i)

ifeq (,$(findstring wine,$(TEST_RUN_PREFIX)))
    ifeq ($B,)
        SANDBOX_PATH := $(abspath .)/sandbox
    else
        SANDBOX_PATH := $(B)sandbox
    endif
    TEST_DATA_PATH := $(abspath .)/test-data
else
    SANDBOX_PATH := sandbox
    TEST_DATA_PATH := test-data
endif

ifneq ($(shell find "$(SANDBOX_PATH)" -mindepth 2 2> /dev/null | wc -l),0)
    $(shell $(RM) -r $(SANDBOX_PATH))
endif


# suite definition template, takes single argument: name of the suite
define suite_template

$1.src := $$(sort $$(wildcard $1/*.c))
$1.obj := $$($1.src:%.c=$(BUILD)%.o)
$1.bin := $(B)bin/$(BINSUBDIR)$1$(exe_suffix)
$1.fixtures := $$(subst /,.,\
                        $$(patsubst %.c,%,$$(filter-out %/suite.c,$$($1.src))))

deps += $$($1.obj:.o=.d)

$$($1.bin): $$($1.obj) $(vifm_obj) $(tests_lib) | $(B)bin/$(BINSUBDIR)
	$$(LD) -o $$@ $$^ $(LDFLAGS)

$(BUILD)$1/%.o: $1/%.c $(GCH_DEP) $(BUILD)$1/filelist \
              | $(BUILD)$1 $(SANDBOX_PATH)/$1
	$$(CC) -c -o $$@ $(CFLAGS) -include test-support/stic/stic.h \
	                 -DTESTID=$$(call pos, $$($1.obj), $$@) \
	                 -DMAXTESTID=$$(words $$($1.obj)) $$< \
	                 -DSUITE_NAME="$1" \
	                 -DTEST_DATA_PATH='"$(TEST_DATA_PATH)"' \
	                 -DSANDBOX_PATH='"$(SANDBOX_PATH)/$1"' \

$(BUILD)$1/filelist: $1/. | $(BUILD)$1
	@if [ ! -f "$$@" -o "$$$$(cat $$@ 2> /dev/null)" != '$$($1.src)' ]; then \
		echo -n '$$($1.src)' > $$@; \
	fi

$(BUILD)$1:
	$(AT)mkdir -p $$@

$(SANDBOX_PATH)/$1:
ifeq ($(SANDBOX_PATH),sandbox)
	$(AT)mkdir -p $(B)$$@
else
	$(AT)mkdir -p $$@
endif

$1: $$($1.bin)
ifeq ($B,)
	@$(TEST_RUN_PREFIX) $$< -s $(TEST_RUN_POST)
else
	@cd $B && $(TEST_RUN_PREFIX) $$< -s $(TEST_RUN_POST)
endif

# this runs separate fixtures, targets are of the form dir.name
.PHONY: $$($1.fixtures)
$$($1.fixtures): $$($1.bin)
ifeq ($B,)
	@$(TEST_RUN_PREFIX) $$^ -s -f $$(subst .,/,$$@).c $(TEST_RUN_POST)
else
	@cd $B && $(TEST_RUN_PREFIX) $$^ -s -f $$(subst .,/,$$@).c $(TEST_RUN_POST)
endif

build: $$($1.bin)

# don't add apps to the list of things to run automatically
ifeq (,$(filter $1,$(apps)))
check: $1
endif

endef

# walk throw list of suites+apps and instantiate template for each one
$(foreach suite, $(suites) $(apps), $(eval $(call suite_template,$(suite))))

# extra dependencies between test fixtures
misc: | $(regs_shmem_app.bin)
lua: | $(io_tester_app.bin)

# import dependencies calculated by the compiler
include $(wildcard $(deps) \
                   $(BUILD)test-support/stic/stic.h.d \
                   $(BUILD)test-support/*.d)