-
Notifications
You must be signed in to change notification settings - Fork 2
/
Makefile
689 lines (553 loc) · 24.8 KB
/
Makefile
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
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
#
# libbinrec: a recompiling translator for machine code
# Copyright (c) 2016 Andrew Church <[email protected]>
#
# This software may be copied and redistributed under certain conditions;
# see the file "COPYING" in the source code distribution for details.
# NO WARRANTY is provided with this software.
#
#
# By default, all commands will be displayed in an abbreviated form, such
# as "Compiling foo.c", instead of the actual command lines executed.
# Pass V=1 on the make command line to display the actual commands instead.
#
###########################################################################
############################## Configuration ##############################
###########################################################################
# In addition to the options below, standard build environment variables
# (CC, CFLAGS, etc.) are also recognized.
#----------------------------- Build options -----------------------------#
# BUILD_SHARED: If this variable is set to 1, the build process will
# create a shared library (typically "libbinrec.so" on Unix-like systems).
# If the variable is set to 0, no shared library will not be built.
#
# The default is 1 (a shared library will be built).
BUILD_SHARED = 1
# BUILD_STATIC: If this variable is set to 1, the build process will
# create a static library (typically "libbinrec.a" on Unix-like systems).
# If the variable is set to 0, no static library will not be built. Note
# that tests are linked against the static library, so "make test" will
# cause the static library to be built even if this variable is set to 0.
#
# It is possible, though mostly meaningless, to set both BUILD_SHARED and
# BUILD_STATIC to 0. In this case, "make" will do nothing, and "make
# install" will install only the library header file.
#
# The default is 1 (a static library will be built).
BUILD_STATIC = 1
# ENABLE_ASSERT: If this variable is set to 1, assertion checks will be
# compiled into the code to guard against bugs in the library. This
# requires support for the assert() macro and <assert.h> header in the
# system's runtime libraries. Enabling this option may have a moderate
# performance impact.
#
# The default is 1 (assertion checks will be included).
ENABLE_ASSERT = 1
# ENABLE_OPERAND_SANITY_CHECKS: If this variable is set to 1, assertion
# checks will be added on instruction operands to verify that registers
# are being used correctly. Enabling this option may have a moderate
# performance impact.
#
# The checks covered by this option differ from those covered by
# ENABLE_ASSERT in that assertion failures generally indicate logic bugs
# in the core library code which might otherwise cause a crash, while
# operand check failures generally indicate bugs in specific machine code
# translation modules which might lead to incorrect code being generated
# but are not likely to cause a crash by themselves.
#
# The default is 1 (operand sanity checks will be included).
ENABLE_OPERAND_SANITY_CHECKS = 1
# ENABLE_RTL_DEBUG_OPTIMIZE: If this variable is set to 1, optimization
# routines will output debugging information via the logging callback.
#
# The default is 1 (debugging information will be output).
ENABLE_RTL_DEBUG_OPTIMIZE = 1
# INSTALL_PKGCONFIG: If this variable is set to 1, the build process will
# install a control file for the "pkg-config" tool as
# "$(LIBDIR)/pkgconfig/binrec.pc".
#
# The default is 0 (binrec.pc will not be installed).
INSTALL_PKGCONFIG = 0
# STATIC_TESTS: If this variable is set to 1, test programs will be linked
# to the static library regardless of whether BUILD_SHARED is enabled.
#
# The default is 0 (test programs will be linked to the shared libray if
# BUILD_SHARED is set to 1).
STATIC_TESTS = 0
# STRIP_TESTS: If this variable is set to 1, test programs will be built
# with debugging information removed. This makes it harder to debug the
# programs in the debugger, but it can provide a significant savings in
# disk space consumed by the tests.
#
# The default is 0 (test programs will not be stripped).
STRIP_TESTS = 0
# TESTS: If this variable is not empty, it gives a list of tests to be
# executed for "make test" or "make coverage". Tests should be specified
# by the pathname to the test source file without the ".c" extension; for
# example, "tests/api/log" to run the test defined in tests/api/log.c.
# The default is empty (all tests will be executed).
TESTS =
# TESTS_EXCLUDE: If this variable is not empty, it gives a list of tests
# to be skipped for "make test" or "make coverage". Tests should be
# specified as for the TESTS variable. If both this variable and TESTS
# are non-empty, only tests which are both listed in TESTS and not listed
# in this variable will be executed. The default is empty (no tests will
# be skipped).
TESTS_EXCLUDE =
# WARNINGS_AS_ERRORS: If this variable is set to 1, the build will abort
# if the compiler emits any warnings.
#
# The default is 1 (warnings will abort the build).
WARNINGS_AS_ERRORS = 1
#----------------------- Installation target paths -----------------------#
# DESTDIR: Sets the location of the installation root directory. This
# string, if any, is prefixed to all target pathnames during installation,
# but it is not included in pathnames written to installed files, allowing
# the package to be installed to a non-root directory hierarchy.
#
# The default is the empty string.
DESTDIR =
# INCDIR: Sets the directory into which the library's header files
# (binrec.h and binrec++.h) will be installed.
#
# The default is "$(PREFIX)/include".
INCDIR = $(PREFIX)/include
# LIBDIR: Sets the directory into which the shared and static library
# files will be installed.
#
# The default is "$(PREFIX)/lib".
LIBDIR = $(PREFIX)/lib
# PREFIX: Sets the base directory for installation paths. This is only
# used to set the default paths for BINDIR, INCDIR, and LIBDIR, and to set
# the "prefix" tag in the pkg-config control file if it is installed.
#
# The default is "/usr/local".
PREFIX = /usr/local
###########################################################################
############################## Internal data ##############################
###########################################################################
#-------------------------------------------------------------------------#
# Note: You should never need to modify any variables below this point in #
# the file. #
#-------------------------------------------------------------------------#
# Package name:
PACKAGE = binrec
# Library version:
VERSION = 0.2
VERSION_MAJOR = $(firstword $(subst ., ,$(VERSION)))
# Library output filenames: (note that $(OSTYPE) is set below)
SHARED_LIB = lib$(PACKAGE).$(if $(filter darwin%,$(OSTYPE)),dylib,$(if $(filter mingw%,$(ARCH)),dll,so))
STATIC_LIB = lib$(PACKAGE).a
# Test source list, with optional overriding.
TEST_SOURCES_FULL := $(wildcard tests/*/*.c tests/*/*/*.c) \
tests/api/binrec++.cc
TEST_SOURCES := $(TEST_SOURCES_FULL)
ifneq ($(TESTS),)
_ := $(foreach i,$(TESTS),$(or $(filter $i.c $i.cc,$(TEST_SOURCES_FULL)),$(error Test $i not found for TESTS)))
TEST_SOURCES := $(filter $(TESTS:%=%.c) $(TESTS:%=%.cc),$(TEST_SOURCES_FULL))
endif
ifneq ($(TESTS_EXCLUDE),)
_ := $(foreach i,$(TESTS_EXCLUDE),$(or $(filter $i.c $i.cc,$(TEST_SOURCES_FULL)),$(error Test $i not found for TESTS_EXCLUDE)))
TEST_SOURCES := $(filter-out $(TESTS_EXCLUDE:%=%.c) $(TESTS_EXCLUDE:%=%.cc),$(TEST_SOURCES))
endif
# Source and object filenames:
LIBRARY_SOURCES := $(sort $(wildcard src/*.c src/*/*.c))
LIBRARY_OBJECTS := $(LIBRARY_SOURCES:%.c=%.o)
TEST_OBJECTS := $(sort $(patsubst %.c,%.o,$(filter %.c,$(TEST_SOURCES))) \
$(patsubst %.cc,%.o,$(filter %.cc,$(TEST_SOURCES))))
TEST_BINS := $(sort $(patsubst %.c,%,$(filter %.c,$(TEST_SOURCES))) \
$(patsubst %.cc,%,$(filter %.cc,$(TEST_SOURCES))))
BENCHMARK_SOURCES := $(sort $(wildcard benchmarks/*.c benchmarks/blobs/*.c))
BENCHMARK_LIB_SOURCES := \
$(sort $(wildcard benchmarks/library/*.c benchmarks/library/math/*.c))
BENCHMARK_NAMES = dhrystone whetstone
BENCHMARK_BENCH_OBJECTS := \
$(patsubst %.c,%_noopt.o,$(wildcard $(foreach i,$(BENCHMARK_NAMES),benchmarks/$i/*.c))) \
$(patsubst %.c,%_opt.o,$(wildcard $(foreach i,$(BENCHMARK_NAMES),benchmarks/$i/*.c)))
BENCHMARK_OBJECTS := $(BENCHMARK_SOURCES:%.c=%.o) \
$(BENCHMARK_LIB_SOURCES:%.c=%.o) \
$(BENCHMARK_BENCH_OBJECTS:%.c=%.o) \
tests/execute.o tests/log-capture.o
BENCHMARK_BINS := benchmarks/bench
###########################################################################
#################### Helper functions and definitions #####################
###########################################################################
# if-true: Return the second parameter if the variable named by the first
# parameter has the value 1, the third parameter (which may be omitted)
# otherwise.
if-true = $(if $(filter 1,$($1)),$2,$3)
# define-if-true: Return an appropriate -D compiler option for the given
# variable name if its value is 1, the empty string otherwise.
define-if-true = $(call if-true,$1,-D$1)
# ECHO: Expands to "@:" (a no-op) in verbose (V=1) mode, "@echo" in
# non-verbose mode. Used for displaying abbreviated command text.
ECHO = $(call if-true,V,@:,@echo)
# Q: Expands to the empty string in verbose (V=1) mode, "@" otherwise.
# Used to hide output of command lines in non-verbose mode.
Q = $(call if-true,V,,@)
###########################################################################
############################# Toolchain setup #############################
###########################################################################
# Default tool program names:
CC = cc
AR = ar
RANLIB = ranlib
GCOV = $(error gcov program unknown for this compiler)
# Try and guess what sort of compiler we're using, so we can set
# appropriate default options.
CC_TYPE = unknown
ifneq ($(filter clang%,$(subst -, ,$(CC))),)
CC_TYPE = clang
else ifneq ($(filter icc%,$(subst -, ,$(CC))),)
CC_TYPE = icc
else ifneq ($(filter gcc%,$(subst -, ,$(CC))),)
CC_TYPE = gcc
else
CC_VERSION_TEXT := $(shell $(CC) --version 2>&1)
ifneq (,$(filter clang LLVM,$(CC_VERSION_TEXT)))
CC_TYPE = clang
else ifneq (,$(filter gcc GCC,$(CC_VERSION_TEXT)))
CC_TYPE = gcc
else ifneq (__GNUC__,$(shell echo __GNUC__ | $(CC) -E - 2>/dev/null | tail -1))
# GCC invoked as "cc" may not have any "gcc" in --version output,
# so treat a compiler whose preprocessor recognizes __GNUC__ (and
# thus translates it to something else) as GCC.
CC_TYPE = gcc
endif
endif
ifeq ($(CC_TYPE),clang)
CXX := $(CC)++
BASE_FLAGS = -O2 -pipe -g -I. \
$(call if-true,WARNINGS_AS_ERRORS,-Werror) \
-Wall -Wextra -Wcast-align -Winit-self -Wpointer-arith -Wshadow \
-Wwrite-strings -Wundef -Wno-unused-parameter -Wvla
# Apple's Clang complains about unused static inline functions (sigh).
BASE_FLAGS += -Wno-unused-function
BASE_CFLAGS = $(BASE_FLAGS) -std=c99 \
-Wmissing-declarations -Wstrict-prototypes
BASE_CXXFLAGS = $(BASE_FLAGS) -std=c++11
# Some older versions of Clang don't want a "gcov" argument here or
# a filename argument ('$1') at the end of the command.
GCOV = llvm-cov gcov >/dev/null
GCOV_OPTS = -b -c
GCOV_FILE_OPTS = \
-gcno="`echo \"$1\" | sed -e 's|\.[^./]*$$|_cov.gcno|'`" \
-gcda="`echo \"$1\" | sed -e 's|\.[^./]*$$|_cov.gcda|'`" \
-o "`echo "$1" | sed -e 's|[/.]|-|g'`.out" '$1'
else ifeq ($(CC_TYPE),gcc)
GCC_MAJOR := $(shell echo __GNUC__ | $(CC) -E - | tail -1)
CXX := $(if $(filter %gcc,$(CC)),$(patsubst %gcc,%g++,$(CC)),$(patsubst %cc,%c++,$(CC)))
BASE_FLAGS = -O2 -pipe -g -I. \
-Wall -Wextra $(call if-true,WARNINGS_AS_ERRORS,-Werror) \
-Wcast-align -Winit-self -Wlogical-op -Wpointer-arith -Wshadow \
-Wwrite-strings -Wundef -Wno-unused-parameter -Wvla
ifneq (,$(filter-out 2 3 4 5 6,$(GCC_MAJOR)))
BASE_FLAGS += -Wimplicit-fallthrough=2
endif
BASE_CFLAGS = $(BASE_FLAGS) -std=c99 \
-Wmissing-declarations -Wstrict-prototypes
BASE_CXXFLAGS = $(BASE_FLAGS) -std=c++11
GCOV = gcov >/dev/null
GCOV_OPTS = -b -c -l -p
GCOV_FILE_OPTS = -o "`echo \"$1\" | sed -e 's|\.[^./]*$$|_cov.o|'`" '$1'
else ifeq ($(CC_TYPE),icc)
CXX := $(patsubst %icc,%icpc,$(CC))
BASE_FLAGS = -O2 -g -I. \
$(call if-true,WARNINGS_AS_ERRORS,-Werror) \
-Wpointer-arith -Wreturn-type -Wshadow -Wuninitialized \
-Wunknown-pragmas -Wunused-function -Wunused-variable -Wwrite-strings
BASE_CFLAGS = $(BASE_FLAGS) -std=c99 \
-Wmissing-declarations -Wstrict-prototypes
BASE_CXXFLAGS = $(BASE_FLAGS) -std=c++11
else
$(warning *** Warning: Unknown compiler type.)
$(warning *** Make sure your CFLAGS are set correctly!)
CXX = c++
endif
# Update build parameter defaults based on the compiler's target platform.
ifneq ($(filter clang gcc icc,$(CC_TYPE)),)
TARGET := $(subst -, ,$(shell $(CC) -dumpmachine))
ARCH := $(or $(firstword $(TARGET)),unknown)
OSTYPE := $(or $(word 3,$(TARGET)),unknown)
else
ARCH := unknown
OSTYPE := unknown
endif
ifneq ($(filter darwin%,$(OSTYPE)),)
SHARED_LIB_FULLNAME = $(subst .dylib,.$(VERSION_MAJOR).dylib,$(SHARED_LIB))
SHARED_LIB_LINKNAME = $(subst .dylib,.$(VERSION_MAJOR).dylib,$(SHARED_LIB))
SHARED_LIB_LDFLAGS = \
-dynamiclib \
-install_name '@rpath/$(SHARED_LIB_FULLNAME)' \
-compatibility_version $(VERSION_MAJOR) \
-current_version $(VERSION) \
-Wl,-single_module
RPATH_LDFLAG = -Wl,-rpath,$1
else ifneq ($(filter mingw%,$(ARCH)),)
SHARED_LIB_FULLNAME = $(SHARED_LIB)
SHARED_LIB_LDFLAGS = \
-shared \
-Wl,--enable-auto-image-base \
-Xlinker --out-implib -Xlinker '[email protected]'
# There's no way to hardcode a shared object path on Windows.
STATIC_TESTS = 1
else
SHARED_LIB_FULLNAME = $(SHARED_LIB).$(VERSION)
SHARED_LIB_LINKNAME = $(SHARED_LIB).$(VERSION_MAJOR)
SHARED_LIB_CFLAGS = -fPIC
SHARED_LIB_LDFLAGS = -shared -Wl,-soname=$(SHARED_LIB_LINKNAME)
RPATH_LDFLAG = -Wl,-rpath,$1
endif
# Final flag set. Note that the user-specified $(CFLAGS) reference comes
# last so the user can override any of our default flags.
ALL_DEFS = $(strip \
$(call define-if-true,ENABLE_ASSERT) \
$(call define-if-true,ENABLE_OPERAND_SANITY_CHECKS) \
$(call if-true,ENABLE_RTL_DEBUG_OPTIMIZE,-DRTL_DEBUG_OPTIMIZE) \
-DVERSION=\"$(VERSION)\")
ALL_CFLAGS = $(BASE_CFLAGS) $(ALL_DEFS) $(CFLAGS)
ALL_CXXFLAGS = $(BASE_CXXFLAGS) $(ALL_DEFS) $(CXXFLAGS)
# Libraries to use when linking test programs.
LIBS = -lm
ifneq (,$(filter darwin %linux,$(shell uname -s 2>/dev/null | tr A-Z a-z)))
LIBS += -lpthread
endif
###########################################################################
############################### Build rules ###############################
###########################################################################
#----------------------------- Entry points ------------------------------#
.PHONY: all all-shared all-static
.PHONY: install install-headers install-pc install-shared install-static install-tools
.PHONY: test clean spotless
all: $(call if-true,BUILD_SHARED,all-shared) \
$(call if-true,BUILD_STATIC,all-static)
all-shared: $(SHARED_LIB)
all-static: $(STATIC_LIB)
install: $(call if-true,BUILD_SHARED,install-shared) \
$(call if-true,BUILD_STATIC,install-static) \
install-headers \
$(call if-true,INSTALL_PKGCONFIG,install-pc)
install-headers:
$(ECHO) 'Installing header files'
$(Q)mkdir -p '$(DESTDIR)$(INCDIR)'
$(Q)cp -pf include/binrec.h include/binrec++.h '$(DESTDIR)$(INCDIR)/'
install-pc:
$(ECHO) 'Installing pkg-config control file'
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)/pkgconfig'
$(Q)sed \
-e 's|@PREFIX@|$(PREFIX)|g' \
-e 's|@INCDIR@|$(patsubst $(PREFIX)%,$${prefix}%,$(INCDIR))|g' \
-e 's|@LIBDIR@|$(patsubst $(PREFIX)%,$${prefix}%,$(LIBDIR))|g' \
-e 's|@VERSION@|$(VERSION)|g'\
<$(PACKAGE).pc.in >'$(DESTDIR)$(LIBDIR)/pkgconfig/$(PACKAGE).pc'
install-shared: all-shared
$(ECHO) 'Installing shared library'
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)'
$(Q)cp -pf $(SHARED_LIB) '$(DESTDIR)$(LIBDIR)/$(SHARED_LIB_FULLNAME)'
$(Q)$(if $(SHARED_LIB_LINKNAME),ln -sf '$(SHARED_LIB_FULLNAME)' '$(DESTDIR)$(LIBDIR)/$(SHARED_LIB_LINKNAME)')
$(Q)$(if $(filter-out $(SHARED_LIB),$(SHARED_LIB_FULLNAME)),ln -sf '$(SHARED_LIB_FULLNAME)' '$(DESTDIR)$(LIBDIR)/$(SHARED_LIB)')
install-static: all-static
$(ECHO) 'Installing static library'
$(Q)mkdir -p '$(DESTDIR)$(LIBDIR)'
$(Q)cp -pf $(STATIC_LIB) '$(DESTDIR)$(LIBDIR)/'
test: $(TEST_BINS)
$(ECHO) 'Running tests'
$(Q)ok=0 ng=0; \
for test in $^; do \
$(call if-true,V,echo "+ $${test}";) \
if "$${test}"; then \
ok=`expr $${ok} + 1`; \
else \
echo "FAIL: $${test}"; \
ng=`expr $${ng} + 1`; \
fi; \
done; \
if test $${ng} = 0; then \
echo 'All tests passed.'; \
else \
if test $${ok} = 1; then ok_s=''; else ok_s='s'; fi; \
if test $${ng} = 1; then ng_s=''; else ng_s='s'; fi; \
echo "$${ok} test$${ok_s} passed, $${ng} test$${ng_s} failed."; \
exit 1; \
fi
coverage: tests/coverage
$(ECHO) 'Running tests'
$(Q)find src -name \*.gcda -exec rm '{}' +
$(Q)tests/coverage $(call if-true,V,-v)
$(ECHO) 'Collecting coverage information'
$(Q)rm -rf .covtmp
$(Q)mkdir .covtmp
$(Q)ln -s ../src .covtmp/
$(Q)set -e; cd .covtmp && for f in $(LIBRARY_SOURCES); do \
$(call if-true,V,echo + $(GCOV) $(GCOV_OPTS) $(call GCOV_FILE_OPTS,$$f) $(GCOV_STDOUT);) \
$(GCOV) $(GCOV_OPTS) $(call GCOV_FILE_OPTS,$$f) $(GCOV_STDOUT); \
done
$(Q)rm -f .covtmp/src
$(Q)cat .covtmp/* >coverage.txt
$(Q)rm -rf .covtmp
$(ECHO) 'Coverage results written to $(abspath coverage.txt)'
clean:
$(ECHO) 'Removing object and dependency files'
$(Q)find benchmarks src tests \( -name '*.[do]' -o -name \*.d~ -o -name \*.d.tmp \) -exec rm '{}' +
$(Q)rm -f tests/libtest.a
$(Q)rm -f tests/coverage-tests.h
$(ECHO) 'Removing test executables'
$(Q)rm -f $(TEST_BINS) tests/coverage
$(ECHO) 'Removing coverage data files'
$(Q)find src tests \( -name \*.gcda -o -name \*.gcno \) -exec rm '{}' +
$(Q)rm -rf .covtmp
spotless: clean
$(ECHO) 'Removing executable and library files'
$(Q)rm -f $(SHARED_LIB) $(SHARED_LIB_LINKNAME) $(STATIC_LIB) \
$(BENCHMARK_BINS)
$(ECHO) 'Removing coverage output'
$(Q)rm -f coverage.txt
#-------------------------- Library build rules --------------------------#
$(SHARED_LIB): $(LIBRARY_OBJECTS:%.o=%_so.o)
$(ECHO) 'Linking $@'
$(Q)$(CC) $(SHARED_LIB_LDFLAGS) -o '$@' $^
ifneq ($(SHARED_LIB_LINKNAME),)
$(SHARED_LIB_LINKNAME): $(SHARED_LIB)
ln -sf '$<' '$@'
endif
$(STATIC_LIB): $(LIBRARY_OBJECTS)
$(ECHO) 'Archiving $@'
$(Q)$(AR) rcu '$@' $^
$(Q)$(RANLIB) '$@'
#--------------------------- Test build rules ----------------------------#
TEST_UTILITY_OBJECTS = \
tests/common.o \
tests/execute.o \
tests/log-capture.o \
tests/mem-wrappers.o \
tests/ppc-lut.o
TEST_LIB = tests/libtest.a
SHARED_TESTS := $(call if-true,STATIC_TESTS,0,$(call if-true,BUILD_SHARED,1,0))
TEST_SHARED_LIB_TARGET := $(call if-true,$(SHARED_TESTS),\
$(or $(SHARED_LIB_LINKNAME),$(SHARED_LIB)),\
$(STATIC_LIB))
$(TEST_BINS) : %: %.o $(TEST_LIB) $(TEST_SHARED_LIB_TARGET)
$(ECHO) 'Linking $@'
$(Q)$(if $(filter %/binrec++,$@),$(CXX),$(CC)) \
$(LDFLAGS) -o '$@' $^ $(LIBS) \
$(call if-true,SHARED_TESTS,$(call RPATH_LDFLAG,$(abspath .)))
$(Q)$(call if-true,STRIP_TESTS,strip '$@')
$(TEST_LIB): $(TEST_UTILITY_OBJECTS)
$(ECHO) 'Archiving $@'
$(Q)$(AR) rcu '$@' $^
$(Q)$(RANLIB) '$@'
tests/coverage: tests/coverage-main.o \
$(TEST_UTILITY_OBJECTS:%.o=%_cov.o) \
$(LIBRARY_OBJECTS:%.o=%_cov.o) \
$(TEST_OBJECTS:%.o=%_cov.o)
$(ECHO) 'Linking $@'
$(Q)$(CXX) $(LDFLAGS) -o '$@' $^ $(LIBS) --coverage
tests/coverage-main.o: tests/coverage-tests.h
tests/coverage-tests.h: $(TEST_SOURCES)
$(ECHO) 'Generating $@'
$(Q)( \
for file in $(TEST_OBJECTS:%.o=%); do \
file_mangled=_`echo "$${file}" | sed -e 's/[^A-Za-z0-9]/_/g'`; \
echo "TEST($${file_mangled})"; \
done \
) >'$@'
#------------------------- Benchmark build rules -------------------------#
benchmarks/bench: $(BENCHMARK_OBJECTS) $(LIBRARY_OBJECTS)
$(ECHO) 'Linking $@'
$(Q)$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o '$@' $^ $(LIBS)
BENCHMARK_LIB_FLAGS := -Ibenchmarks/library $(foreach i,$(patsubst benchmarks/library/%.c,%,$(filter-out benchmarks/library/math/%,$(BENCHMARK_LIB_SOURCES))),-D$i=benchmark_$i)
$(BENCHMARK_LIB_SOURCES:%.c=%.o): ALL_CFLAGS += $(BENCHMARK_LIB_FLAGS)
$(filter benchmarks/library/math/%,$(BENCHMARK_LIB_SOURCES:%.c=%.o)): ALL_CFLAGS += \
$(if $(filter clang gcc,$(CC_TYPE)),-Wno-shadow -Wno-attributes -Wno-implicit-fallthrough) \
$(if $(filter clang,$(CC_TYPE)),-Wno-header-guard) \
$(if $(filter gcc,$(CC_TYPE)),-Wno-old-style-declaration)
benchmarks/dhrystone/%_noopt.o: benchmarks/dhrystone/%.c benchmarks/dhrystone/dhry.h
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) -std=c89 -DBENCHMARK_ONLY -DDHRY_PREFIX=dhry_noopt_ \
$(BENCHMARK_LIB_FLAGS) -o '$@' -c '$<'
benchmarks/dhrystone/%_opt.o: benchmarks/dhrystone/%.c benchmarks/dhrystone/dhry.h
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) -std=c89 -O2 -fno-inline \
-DBENCHMARK_ONLY -DDHRY_PREFIX=dhry_opt_ \
$(BENCHMARK_LIB_FLAGS) -o '$@' -c '$<'
benchmarks/whetstone/%_noopt.o: benchmarks/whetstone/%.c
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) -std=c89 -DNO_MAIN -Dwhetstone=whetstone_noopt \
$(BENCHMARK_LIB_FLAGS) -o '$@' -c '$<'
benchmarks/whetstone/%_opt.o: benchmarks/whetstone/%.c
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) -std=c89 -O2 -fno-inline \
-DNO_MAIN -Dwhetstone=whetstone_opt \
$(BENCHMARK_LIB_FLAGS) -o '$@' -c '$<'
#----------------------- Common compilation rules ------------------------#
%.o: %.c
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) $(ALL_CFLAGS) -MMD -MF '$(@:%.o=%.d.tmp)' -o '$@' -c '$<'
$(call filter-deps,$@,$(@:%.o=%.d))
%.o: %.cc
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CXX) $(ALL_CXXFLAGS) -MMD -MF '$(@:%.o=%.d.tmp)' -o '$@' -c '$<'
$(call filter-deps,$@,$(@:%.o=%.d))
# We generate separate dependency files for shared objects even though the
# contents are the same as for static objects to avoid parallel builds
# colliding when writing the dependencies.
%_so.o: BASE_CFLAGS += $(SHARED_LIB_CFLAGS)
%_so.o: %.c
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) $(ALL_CFLAGS) -MMD -MF '$(@:%.o=%.d.tmp)' -o '$@' -c '$<'
$(call filter-deps,$@,$(@:%.o=%.d))
src/%_cov.o: BASE_CFLAGS += -O0
src/%_cov.o: src/%.c
$(ECHO) 'Compiling $< -> $@'
$(Q)$(CC) -DCOVERAGE $(ALL_CFLAGS) --coverage -MMD -MF '$(@:%.o=%.d.tmp)' -o '$@' -c '$<'
$(call filter-deps,$@,$(@:%.o=%.d))
tests/%_cov.o: tests/%.c
$(ECHO) 'Compiling $< -> $@'
$(Q)file_mangled=_`echo '$(<:%.c=%)' | sed -e 's/[^A-Za-z0-9]/_/g'`; \
$(CC) $(ALL_CFLAGS) "-Dmain=$${file_mangled}" \
$(if $(filter -Wmissing-declarations,$(ALL_CFLAGS)),-Wno-missing-declarations) \
-MMD -MF '$(@:%.o=%.d.tmp)' -o '$@' -c '$<'
$(call filter-deps,$@,$(@:%.o=%.d))
tests/%_cov.o: tests/%.cc
$(ECHO) 'Compiling $< -> $@'
$(Q)file_mangled=_`echo '$(<:%.cc=%)' | sed -e 's/[^A-Za-z0-9]/_/g'`; \
$(CXX) $(ALL_CXXFLAGS) "-Dmain=$${file_mangled}" \
-MMD -MF '$(@:%.o=%.d.tmp)' -o '$@' -c '$<'
$(call filter-deps,$@,$(@:%.o=%.d))
#-------------------- Autogenerated dependency magic ---------------------#
define filter-deps
$(Q)if test -f '$2.tmp'; then \
sed \
-e ':1' \
-e 's#\(\\ \|[^ /]\)\+/\.\./##' \
-e 't1' \
-e ':2' \
-e 's#/\./#/#' \
-e 't2' \
-e 's#^\(\([^ ]*[ ]\)*\)$(subst .,\.,$(1:%$(OBJECT_EXT)=%.h))#\1#' \
-e 's#$(subst .,\.,$1)#$1 $(1:%$(OBJECT_EXT)=%.h)#' \
<'$2.tmp' >'$2~'; \
rm -f '$2.tmp'; \
mv '$2~' '$2'; \
else \
rm -f '$2'; \
fi
endef
# Don't try to include dependency data if we're not actually building
# anything. This is particularly important for "clean" and "spotless",
# since an out-of-date dependency file which referenced a nonexistent
# target (this can arise from switching versions in place using version
# control, for example) would otherwise block these targets from running
# and cleaning out that very dependency file!
ifneq ($(filter-out clean spotless,$(or $(MAKECMDGOALS),default)),)
include $(sort $(wildcard $(patsubst %.o,%.d,\
$(LIBRARY_OBJECTS) \
$(LIBRARY_OBJECTS:%.o=%_so.o) \
$(LIBRARY_OBJECTS:%.o=%_cov.o) \
$(TEST_OBJECTS) \
$(TEST_OBJECTS:%.o=%_cov.o) \
$(TEST_UTILITY_OBJECTS) \
$(TEST_UTILITY_OBJECTS:%.o=%_cov.o) \
)))
endif
###########################################################################