Makefile raw
1 .NOTPARALLEL :
2
3 # Pattern rule to print variables, e.g. make print-top_srcdir
4 print-%: FORCE
5 @echo '$*'='$($*)'
6
7 # When invoking a sub-make, keep only the command line variable definitions
8 # matching the pattern in the filter function.
9 #
10 # e.g. invoking:
11 # $ make A=1 C=1 print-MAKEOVERRIDES print-MAKEFLAGS
12 #
13 # with the following in the Makefile:
14 # MAKEOVERRIDES := $(filter A=% B=%,$(MAKEOVERRIDES))
15 #
16 # will print:
17 # MAKEOVERRIDES = A=1
18 # MAKEFLAGS = -- A=1
19 #
20 # this is because as the GNU make manual says:
21 # The command line variable definitions really appear in the variable
22 # MAKEOVERRIDES, and MAKEFLAGS contains a reference to this variable.
23 #
24 # and since the GNU make manual also says:
25 # variables defined on the command line are passed to the sub-make through
26 # MAKEFLAGS
27 #
28 # this means that sub-makes will be invoked as if:
29 # $(MAKE) A=1 blah blah
30 MAKEOVERRIDES := $(filter V=%,$(MAKEOVERRIDES))
31 SOURCES_PATH ?= $(BASEDIR)/sources
32 WORK_PATH = $(BASEDIR)/work
33 BASE_CACHE ?= $(BASEDIR)/built
34 SDK_PATH ?= $(BASEDIR)/SDKs
35 NO_BOOST ?=
36 NO_LIBEVENT ?=
37 NO_QT ?=
38 NO_QR ?=
39 NO_BDB ?=
40 NO_SQLITE ?=
41 NO_WALLET ?=
42 NO_ZMQ ?=
43 NO_UPNP ?=
44 NO_USDT ?=
45 MULTIPROCESS ?=
46 LTO ?=
47 NO_HARDEN ?=
48 FALLBACK_DOWNLOAD_PATH ?= https://limenkacore.org/depends-sources
49
50 C_STANDARD ?= c11
51 CXX_STANDARD ?= c++20
52
53 BUILD = $(shell ./config.guess)
54 PATCHES_PATH = $(BASEDIR)/patches
55 BASEDIR = $(CURDIR)
56 HASH_LENGTH:=11
57 DOWNLOAD_CONNECT_TIMEOUT:=30
58 DOWNLOAD_RETRIES:=3
59 HOST_ID_SALT ?= salt
60 BUILD_ID_SALT ?= salt
61
62 ifneq ($(DEBUG),)
63 release_type=debug
64 else
65 release_type=release
66 endif
67
68 base_build_dir=$(WORK_PATH)/build
69 base_staging_dir=$(WORK_PATH)/staging
70 base_download_dir=$(WORK_PATH)/download
71 build:=$(shell ./config.sub $(BUILD))
72
73 host:=$(build)
74 ifneq ($(HOST),)
75 host:=$(HOST)
76 endif
77 HOST ?= $(BUILD)
78 canonical_host:=$(shell ./config.sub $(HOST))
79
80 build_arch =$(firstword $(subst -, ,$(build)))
81 build_vendor=$(word 2,$(subst -, ,$(build)))
82 full_build_os:=$(subst $(build_arch)-$(build_vendor)-,,$(build))
83 build_os:=$(findstring linux,$(full_build_os))
84 build_os+=$(findstring darwin,$(full_build_os))
85 build_os+=$(findstring freebsd,$(full_build_os))
86 build_os+=$(findstring netbsd,$(full_build_os))
87 build_os+=$(findstring openbsd,$(full_build_os))
88 build_os:=$(strip $(build_os))
89 ifeq ($(build_os),)
90 build_os=$(full_build_os)
91 endif
92
93 host_arch=$(firstword $(subst -, ,$(canonical_host)))
94 host_vendor=$(word 2,$(subst -, ,$(canonical_host)))
95 full_host_os:=$(subst $(host_arch)-$(host_vendor)-,,$(canonical_host))
96 host_os:=$(findstring linux,$(full_host_os))
97 host_os+=$(findstring darwin,$(full_host_os))
98 host_os+=$(findstring freebsd,$(full_host_os))
99 host_os+=$(findstring netbsd,$(full_host_os))
100 host_os+=$(findstring openbsd,$(full_host_os))
101 host_os+=$(findstring mingw32,$(full_host_os))
102
103 host_os:=$(strip $(host_os))
104 ifeq ($(host_os),)
105 host_os=$(full_host_os)
106 endif
107
108 $(host_arch)_$(host_os)_prefix=$(BASEDIR)/$(host)
109 $(host_arch)_$(host_os)_host=$(host)
110 host_prefix=$($(host_arch)_$(host_os)_prefix)
111 build_prefix=$(host_prefix)/native
112 build_host=$(build)
113
114 all: install
115
116 include hosts/$(host_os).mk
117 include hosts/default.mk
118 include builders/$(build_os).mk
119 include builders/default.mk
120 include packages/packages.mk
121
122 # Previously, we directly invoked the well-known programs using $(shell ...)
123 # to construct build_id_string. However, that was problematic because:
124 #
125 # 1. When invoking a shell, GNU Make special-cases exit code 127 (command not
126 # found) by not capturing the output but instead passing it through. This is
127 # not done for any other exit code.
128 #
129 # 2. Characters like '#' (from these programs' output) would end up in make
130 # variables like build_id_string, which would be wrongly interpreted by make
131 # when these variables were used.
132 #
133 # Therefore, we should avoid having arbitrary strings in make variables where
134 # possible. The gen_id script used here hashes the output to construct a
135 # "make-safe" id.
136 #
137 # Also note that these lines need to be:
138 #
139 # 1. After including {hosts,builders}/*.mk, since they rely on the tool
140 # variables (e.g. build_CC, host_STRIP, etc.) to be set.
141 #
142 # 2. Before including packages/*.mk (excluding packages/packages.mk), since
143 # they rely on the build_id variables
144 #
145 build_id:=$(shell env CC='$(build_CC)' C_STANDARD='$(C_STANDARD)' CXX='$(build_CXX)' CXX_STANDARD='$(CXX_STANDARD)' \
146 AR='$(build_AR)' NM='$(build_NM)' RANLIB='$(build_RANLIB)' STRIP='$(build_STRIP)' SHA256SUM='$(build_SHA256SUM)' \
147 DEBUG='$(DEBUG)' NO_HARDEN='$(NO_HARDEN)' \
148 ./gen_id '$(BUILD_ID_SALT)' 'GUIX_ENVIRONMENT=$(realpath $(GUIX_ENVIRONMENT))')
149
150 $(host_arch)_$(host_os)_id:=$(shell env CC='$(host_CC)' C_STANDARD='$(C_STANDARD)' CXX='$(host_CXX)' CXX_STANDARD='$(CXX_STANDARD)' \
151 CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CXXFLAGS='$(CXXFLAGS)' LDFLAGS='$(LDFLAGS)' \
152 AR='$(host_AR)' NM='$(host_NM)' RANLIB='$(host_RANLIB)' STRIP='$(host_STRIP)' SHA256SUM='$(build_SHA256SUM)' \
153 DEBUG='$(DEBUG)' LTO='$(LTO)' NO_HARDEN='$(NO_HARDEN)' \
154 ./gen_id '$(HOST_ID_SALT)' 'GUIX_ENVIRONMENT=$(realpath $(GUIX_ENVIRONMENT))')
155
156 boost_packages_$(NO_BOOST) = $(boost_packages)
157
158 libevent_packages_$(NO_LIBEVENT) = $(libevent_packages)
159
160 qrencode_packages_$(NO_QR) = $(qrencode_$(host_os)_packages)
161
162 qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages) $(qrencode_packages_)
163
164 bdb_packages_$(NO_BDB) = $(bdb_packages)
165 sqlite_packages_$(NO_SQLITE) = $(sqlite_packages)
166 wallet_packages_$(NO_WALLET) = $(bdb_packages_) $(sqlite_packages_)
167
168 upnp_packages_$(NO_UPNP) = $(upnp_packages)
169
170 zmq_packages_$(NO_ZMQ) = $(zmq_packages)
171 multiprocess_packages_$(MULTIPROCESS) = $(multiprocess_packages)
172 usdt_packages_$(NO_USDT) = $(usdt_$(host_os)_packages)
173
174 packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(boost_packages_) $(libevent_packages_) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) $(usdt_packages_)
175 native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
176
177 ifneq ($(zmq_packages_),)
178 packages += $(zmq_packages)
179 endif
180
181 ifeq ($(multiprocess_packages_),)
182 packages += $(multiprocess_packages)
183 native_packages += $(multiprocess_native_packages)
184 endif
185
186 all_packages = $(packages) $(native_packages)
187
188 meta_depends = Makefile config.guess config.sub funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
189
190 include funcs.mk
191
192 final_build_id_long+=$(shell $(build_SHA256SUM) toolchain.cmake.in)
193 final_build_id+=$(shell echo -n "$(final_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH))
194 $(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages)
195 rm -rf $(@D)
196 mkdir -p $(@D)
197 echo copying packages: $^
198 echo to: $(@D)
199 cd $(@D); $(foreach package,$^, $(build_TAR) xf $($(package)_cached); )
200 echo To build Limenka with these packages, pass \'--toolchain $(@D)/toolchain.cmake\' to the first CMake invocation.
201 touch $@
202
203 ifeq ($(host),$(build))
204 crosscompiling=FALSE
205 else
206 crosscompiling=TRUE
207 endif
208
209 $(host_prefix)/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(final_build_id)
210 @mkdir -p $(@D)
211 sed -e 's|@depends_crosscompiling@|$(crosscompiling)|' \
212 -e 's|@host@|$(host)|' \
213 -e 's|@host_system_name@|$($(host_os)_cmake_system_name)|' \
214 -e 's|@host_system_version@|$($(host_os)_cmake_system_version)|' \
215 -e 's|@host_arch@|$(host_arch)|' \
216 -e 's|@CC@|$(host_CC)|' \
217 -e 's|@CXX@|$(host_CXX)|' \
218 -e 's|@OSX_SDK@|$(OSX_SDK)|' \
219 -e 's|@AR@|$(host_AR)|' \
220 -e 's|@RANLIB@|$(host_RANLIB)|' \
221 -e 's|@STRIP@|$(host_STRIP)|' \
222 -e 's|@OBJCOPY@|$(host_OBJCOPY)|' \
223 -e 's|@OBJDUMP@|$(host_OBJDUMP)|' \
224 -e 's|@CFLAGS@|$(strip $(host_CFLAGS))|' \
225 -e 's|@CFLAGS_RELEASE@|$(strip $(host_release_CFLAGS))|' \
226 -e 's|@CFLAGS_DEBUG@|$(strip $(host_debug_CFLAGS))|' \
227 -e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS))|' \
228 -e 's|@CXXFLAGS_RELEASE@|$(strip $(host_release_CXXFLAGS))|' \
229 -e 's|@CXXFLAGS_DEBUG@|$(strip $(host_debug_CXXFLAGS))|' \
230 -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS))|' \
231 -e 's|@CPPFLAGS_RELEASE@|$(strip $(host_release_CPPFLAGS))|' \
232 -e 's|@CPPFLAGS_DEBUG@|$(strip $(host_debug_CPPFLAGS))|' \
233 -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS))|' \
234 -e 's|@LDFLAGS_RELEASE@|$(strip $(host_release_LDFLAGS))|' \
235 -e 's|@LDFLAGS_DEBUG@|$(strip $(host_debug_LDFLAGS))|' \
236 -e 's|@qt_packages@|$(qt_packages_)|' \
237 -e 's|@qrencode_packages@|$(qrencode_packages_)|' \
238 -e 's|@zmq_packages@|$(zmq_packages_)|' \
239 -e 's|@wallet_packages@|$(wallet_packages_)|' \
240 -e 's|@bdb_packages@|$(bdb_packages_)|' \
241 -e 's|@sqlite_packages@|$(sqlite_packages_)|' \
242 -e 's|@upnp_packages@|$(upnp_packages_)|' \
243 -e 's|@usdt_packages@|$(usdt_packages_)|' \
244 -e 's|@no_harden@|$(NO_HARDEN)|' \
245 -e 's|@multiprocess@|$(MULTIPROCESS)|' \
246 $< > $@
247 touch $@
248
249 define check_or_remove_cached
250 mkdir -p $(BASE_CACHE)/$(host)/$(package) && cd $(BASE_CACHE)/$(host)/$(package); \
251 $(build_SHA256SUM) -c $($(package)_cached_checksum) >/dev/null 2>/dev/null || \
252 ( rm -f $($(package)_cached_checksum); \
253 if test -f "$($(package)_cached)"; then echo "Checksum mismatch for $(package). Forcing rebuild.."; rm -f $($(package)_cached_checksum) $($(package)_cached); fi )
254 endef
255
256 define check_or_remove_sources
257 mkdir -p $($(package)_source_dir); cd $($(package)_source_dir); \
258 test -f $($(package)_fetched) && ( $(build_SHA256SUM) -c $($(package)_fetched) >/dev/null 2>/dev/null || \
259 ( echo "Checksum missing or mismatched for $(package) source. Forcing re-download."; \
260 rm -f $($(package)_all_sources) $($(1)_fetched))) || true
261 endef
262
263 check-packages:
264 @$(foreach package,$(all_packages),$(call check_or_remove_cached,$(package));)
265 check-sources:
266 @$(foreach package,$(all_packages),$(call check_or_remove_sources,$(package));)
267
268 $(host_prefix)/toolchain.cmake: check-packages
269
270 check-packages: check-sources
271
272 clean-all: clean
273 @rm -rf $(SOURCES_PATH) x86_64* i686* mips* arm* aarch64* powerpc* riscv32* riscv64* s390x*
274
275 clean:
276 @rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD) *.log
277
278 install: check-packages $(host_prefix)/toolchain.cmake
279
280
281 download-one: check-sources $(all_sources)
282
283 download-osx:
284 @$(MAKE) -s HOST=x86_64-apple-darwin download-one
285 download-linux:
286 @$(MAKE) -s HOST=x86_64-unknown-linux-gnu download-one
287 download-win:
288 @$(MAKE) -s HOST=x86_64-w64-mingw32 download-one
289 download: download-osx download-linux download-win
290
291 $(foreach package,$(all_packages),$(eval $(call ext_add_stages,$(package))))
292
293 .PHONY: install cached clean clean-all download-one download-osx download-linux download-win download check-packages check-sources
294 .PHONY: FORCE
295 $(V).SILENT:
296