-
Notifications
You must be signed in to change notification settings - Fork 1
/
Makefile
165 lines (130 loc) · 5.52 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
################################################################################
# Generic Makefile, tested with gcc and Linux and clang and OSX.
#
# For make documentation see:
# https://www.gnu.org/software/make/manual/make.html
#
# default target
all:
# build: debug by default, eg: 'make build=release'
build := debug
# architecture: eg: x86-64, core2, corei7, core-avx-i or native
arch := x86-64
################################################################################
# Locations
# Local build or an installation
ifdef CONDA_PREFIX
ENV := $(CONDA_PREFIX)
else
ENV := $(PREFIX)
endif
inc_sysroot := ${CONDA_BUILD_SYSROOT}
inc_conda := ${ENV}/include
inc_python := $(shell python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")
src_dir := ${CURDIR}/src
inc_dir := ${CURDIR}/include
build_dir := ${CURDIR}/build/$(firstword $(shell uname -s))-$(firstword $(shell uname -r))-${arch}-${build}
bin_dir := ${build_dir}/bin
test_dir := ${build_dir}/test
lib_dir := ${build_dir}/lib
obj_dir := ${build_dir}/obj
################################################################################
# Common flags and libraries (lowercase, target specific are uppercase)
cppflags := -march=${arch} -fpic -std=c++17 -Wall -isysroot ${inc_sysroot} -I${inc_dir} -isystem ${inc_conda} -isystem ${inc_python}
cppflags.debug := -g3
cppflags.release := -DNDEBUG -flto -O3
# Enable relative run-time linking to avoid setting LD_LIBRARY_PATH (works locally and in conda)
ldflags := -march=${arch} -fpic -Wall -isysroot ${CONDA_BUILD_SYSROOT} '-Wl,-rpath,$$ORIGIN/../lib' -L${lib_dir} -L${ENV}/lib
ldflags.debug :=
ldflags.release := -flto=auto -O3 -fuse-linker-plugin
syslibs := dl rt
# Enable link time optimization in static libraries using the gcc wrapper of AR
AR := ${GCC_AR}
################################################################################
# Targets
define BUILD_TARGET # takes 2 arguments, target name and paths to object files
${1}: ${2} # target depends creating these objects
${2} :| $(dir ${2}) # objects depend on their directories existing
objs += ${2}
obj_sub_dirs += $(dir ${2})
${1}: CPPFLAGS= # reset target specific cpp flags
${1}: LDFLAGS= # reset target specific linker flags
${1}: LIBS= # reset static and dynamic library linking
${1}: $(lastword $(MAKEFILE_LIST)) # relink if makefile has changed
endef
define STATIC_LIBRARY # takes 2 arguments, library name and paths to cpp files
static_libs += ${lib_dir}/$(addprefix lib,$(addsuffix .a,${1}))
$(call BUILD_TARGET,${lib_dir}/$(addprefix lib,$(addsuffix .a,${1})),$(addprefix ${obj_dir}/, $(addsuffix .o,$(basename ${2})))))
endef
define SHARED_LIBRARY # takes 2 arguments, library name and paths to cpp files
shared_libs += ${lib_dir}/$(addprefix lib,$(addsuffix .so,${1}))
$(call BUILD_TARGET,${lib_dir}/$(addprefix lib,$(addsuffix .so,${1})),$(addprefix ${obj_dir}/, $(addsuffix .o,$(basename ${2})))))
endef
define EXECUTABLE # takes 2 arguments, executable name and paths to cpp files
bins += ${bin_dir}/${1}
$(call BUILD_TARGET,${bin_dir}/${1},$(addprefix ${obj_dir}/, $(addsuffix .o,$(basename ${2})))))
endef
define RUN_TEST # takes 1 argument, test harness name
run_${1} : ${test_dir}/${1}
@echo "--- Running test-harness ${1} ---"
cd ${test_dir} && ${test_dir}/${1}
run_tests += run_${1}
endef
define TEST_HARNESS # build and run, takes 2 arguments, target name and paths to cpp files
tests += ${test_dir}/${1}
$(call BUILD_TARGET,${test_dir}/${1},$(addprefix ${obj_dir}/, $(addsuffix .o,$(basename ${2})))))
$(call RUN_TEST,${1})
endef
################################################################################
# Project Targets
include build.mk
test: ${static_libs} ${shared_libs} ${tests} ${run_tests}
all: ${static_libs} ${shared_libs} ${bins} sym_links
clean:
rm -rf ${build_dir}
rm -f ${CURDIR}/lib
rm -f ${CURDIR}/bin
.PHONY: all test clean
################################################################################
# Directory dependencies (to create directories)
# first remove duplicates
static_libs := $(sort ${static_libs})
shared_libs := $(sort ${shared_libs})
bins := $(sort ${bins})
tests := $(sort ${tests})
obj_sub_dirs := $(sort ${obj_sub_dirs})
${static_libs} :| ${lib_dir}
${shared_libs} :| ${lib_dir}
${bins} :| ${bin_dir}
${tests} :| ${test_dir}
${obj_sub_dirs} ${lib_dir} ${bin_dir} ${test_dir} :
mkdir -p $@
################################################################################
# Rules and dependencies
define CXX_COMPILE
${CXX} -c -MMD -MP -o $@ ${CPPFLAGS} ${cppflags.${build}} ${cppflags} $<
endef
define CXX_EXECUTABLE
${CXX} -o $@ ${LDFLAGS} ${ldflags.${build}} ${ldflags} $(filter %.o,$^) $(addprefix -l,${LIBS}) $(addprefix -l,${syslibs})
endef
# Objects files depend on autogenerated dependencies files
-include $(objs:%.o=%.d)
# How to create object files from cpp files
${obj_dir}/%.o: ${src_dir}/%.cpp
$(CXX_COMPILE)
# How to link static libraries
${static_libs}: ${lib_dir}/%.a:
rm -f $@ && ${AR} crv $@ $(filter %.o,$^)
# How to link shared libraries
${shared_libs}: ${lib_dir}/%.so:
${CXX} -shared -o $@ ${LDFLAGS} ${ldflags.${build}} ${ldflags} $(filter %.o,$^) $(addprefix -l,${LIBS})
# How to link executables
${bins}: ${bin_dir}/%:
$(CXX_EXECUTABLE)
# How to link test harnesses
${tests}: ${test_dir}/%:
$(CXX_EXECUTABLE)
# Update the current sym links to point to this build configuration
sym_links:
ln -sf ${build_dir}/lib ${CURDIR}/.
ln -sf ${build_dir}/bin ${CURDIR}/.