1# Copyright 2016 The Fuchsia Authors
2# Copyright (c) 2008-2015 Travis Geiselbrecht
3#
4# Use of this source code is governed by a MIT-style
5# license that can be found in the LICENSE file or at
6# https://opensource.org/licenses/MIT
7
8LOCAL_MAKEFILE:=$(MAKEFILE_LIST)
9
10# include settings for prebuilts that are auto-updated by checkout scripts
11-include prebuilt/config.mk
12
13# try to include a file in the local dir to let the user semi-permanently set options
14-include local.mk
15include make/macros.mk
16
17# various command line and environment arguments
18# default them to something so when they're referenced in the make instance they're not undefined
19BUILDROOT ?= .
20DEBUG ?= 2
21DEBUG_HARD ?= false
22ENABLE_BUILD_LISTFILES ?= false
23ENABLE_BUILD_SYSROOT ?= false
24ENABLE_BUILD_LISTFILES := $(call TOBOOL,$(ENABLE_BUILD_LISTFILES))
25ENABLE_BUILD_SYSROOT := $(call TOBOOL,$(ENABLE_BUILD_SYSROOT))
26ENABLE_INSTALL_SAMPLES ?= false
27ENABLE_NEW_BOOTDATA := true
28ENABLE_LOCK_DEP ?= false
29ENABLE_LOCK_DEP_TESTS ?= $(ENABLE_LOCK_DEP)
30DISABLE_UTEST ?= false
31ENABLE_ULIB_ONLY ?= false
32USE_ASAN ?= false
33USE_SANCOV ?= false
34USE_PROFILE ?= false
35USE_LTO ?= false
36USE_THINLTO ?= $(USE_LTO)
37USE_CLANG ?= $(firstword $(filter true,$(call TOBOOL,$(USE_ASAN)) \
38	     		 	       $(call TOBOOL,$(USE_SANCOV)) \
39	     		 	       $(call TOBOOL,$(USE_PROFILE)) \
40	     		 	       $(call TOBOOL,$(USE_LTO))) \
41			 false)
42USE_LLD ?= $(USE_CLANG)
43ifeq ($(call TOBOOL,$(USE_LLD)),true)
44USE_GOLD := false
45else
46USE_GOLD ?= true
47endif
48THINLTO_CACHE_DIR ?= $(BUILDDIR)/thinlto-cache
49CLANG_TARGET_FUCHSIA ?= false
50USER_USE_LINKER_GC ?= true
51KERNEL_USE_LINKER_GC ?= true
52HOST_USE_ASAN ?= false
53
54ifeq ($(call TOBOOL,$(ENABLE_ULIB_ONLY)),true)
55ENABLE_BUILD_SYSROOT := false
56ifeq (,$(strip $(TOOLS)))
57$(error ENABLE_ULIB_ONLY=true requires TOOLS=build-.../tools on command line)
58endif
59endif
60
61# If no build directory suffix has been explicitly supplied by the environment,
62# generate a default based on build options.  Start with no suffix, then add
63# "-clang" if we are building with clang, and "-release" if we are building with
64# DEBUG=0
65ifeq ($(origin BUILDDIR_SUFFIX),undefined)
66BUILDDIR_SUFFIX :=
67
68ifeq ($(call TOBOOL,$(USE_ASAN)),true)
69BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-asan
70else ifeq ($(call TOBOOL,$(USE_PROFILE)),true)
71BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-profile
72else ifeq ($(call TOBOOL,$(USE_LTO)),true)
73ifeq ($(call TOBOOL,$(USE_THINLTO)),true)
74BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-thinlto
75else
76BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-lto
77endif
78else ifeq ($(call TOBOOL,$(USE_CLANG)),true)
79BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-clang
80endif
81
82ifeq ($(call TOBOOL,$(DEBUG)),false)
83BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-release
84endif
85
86endif   # if BUILDDIR_SUFFIX is empty
87
88# special rule for handling make spotless
89ifeq ($(MAKECMDGOALS),spotless)
90spotless:
91	rm -rf -- "$(BUILDROOT)"/build-*
92else
93
94# If one of our goals (from the commandline) happens to have a
95# matching project/goal.mk, then we should re-invoke make with
96# that project name specified...
97
98project-name := $(firstword $(MAKECMDGOALS))
99
100ifneq ($(project-name),)
101ifneq ($(strip $(wildcard kernel/project/$(project-name).mk \
102			  kernel/project/alias/$(project-name).mk)),)
103do-nothing := 1
104$(MAKECMDGOALS) _all: make-make
105make-make:
106	@PROJECT=$(project-name) $(MAKE) -rR -f $(LOCAL_MAKEFILE) $(filter-out $(project-name), $(MAKECMDGOALS))
107
108.PHONY: make-make
109endif
110endif
111
112# some additional rules to print some help
113include make/help.mk
114
115ifeq ($(do-nothing),)
116
117ifeq ($(PROJECT),)
118
119ifneq ($(DEFAULT_PROJECT),)
120PROJECT := $(DEFAULT_PROJECT)
121else
122$(error No project specified. Use 'make list' for a list of projects or 'make help' for additional help)
123endif
124endif
125
126# DEBUG_HARD enables limited optimizations and full debug symbols for use with gdb/lldb
127ifeq ($(call TOBOOL,$(DEBUG_HARD)),true)
128GLOBAL_DEBUGFLAGS := -O0 -g3
129endif
130GLOBAL_DEBUGFLAGS ?= -O2 -g
131
132BUILDDIR := $(BUILDROOT)/build-$(PROJECT)$(BUILDDIR_SUFFIX)
133GENERATED_INCLUDES:=$(BUILDDIR)/gen/global/include
134ZIRCON_BOOTIMAGE := $(BUILDDIR)/zircon.zbi
135KERNEL_ZBI := $(BUILDDIR)/kernel.zbi
136KERNEL_ELF := $(BUILDDIR)/zircon.elf
137KERNEL_IMAGE := $(BUILDDIR)/kernel-image.elf
138GLOBAL_CONFIG_HEADER := $(BUILDDIR)/config-global.h
139KERNEL_CONFIG_HEADER := $(BUILDDIR)/config-kernel.h
140USER_CONFIG_HEADER := $(BUILDDIR)/config-user.h
141HOST_CONFIG_HEADER := $(BUILDDIR)/config-host.h
142GLOBAL_INCLUDES := system/public system/private $(GENERATED_INCLUDES)
143GLOBAL_OPTFLAGS ?= $(ARCH_OPTFLAGS)
144# When embedding source file locations in debugging information, by default
145# the compiler will record the absolute path of the current directory and
146# make everything relative to that.  Instead, we tell the compiler to map
147# the current directory to $(DEBUG_BUILDROOT), which is the "relative"
148# location of the zircon source tree (i.e. usually . in a standalone build).
149DEBUG_BUILDROOT ?= $(BUILDROOT)
150GLOBAL_COMPILEFLAGS := $(GLOBAL_DEBUGFLAGS)
151GLOBAL_COMPILEFLAGS += -fdebug-prefix-map=$(shell pwd)=$(DEBUG_BUILDROOT)
152GLOBAL_COMPILEFLAGS += -finline -include $(GLOBAL_CONFIG_HEADER)
153GLOBAL_COMPILEFLAGS += -Wall -Wextra -Wno-multichar -Werror -Wno-error=deprecated-declarations
154GLOBAL_COMPILEFLAGS += -Wno-unused-parameter -Wno-unused-function -Werror=unused-label -Werror=return-type
155GLOBAL_COMPILEFLAGS += -fno-common
156# kernel/include/lib/counters.h and kernel.ld depend on -fdata-sections.
157GLOBAL_COMPILEFLAGS += -ffunction-sections -fdata-sections
158ifeq ($(call TOBOOL,$(USE_CLANG)),true)
159GLOBAL_COMPILEFLAGS += -nostdlibinc
160GLOBAL_COMPILEFLAGS += -no-canonical-prefixes
161GLOBAL_COMPILEFLAGS += -Wno-address-of-packed-member
162GLOBAL_COMPILEFLAGS += -Wthread-safety
163GLOBAL_COMPILEFLAGS += -Wimplicit-fallthrough
164else
165GLOBAL_COMPILEFLAGS += -Wno-nonnull-compare
166# TODO(mcgrathr): New warning in GCC 7 biting a lot of code; figure it out.
167GLOBAL_COMPILEFLAGS += -Wno-format-truncation
168endif
169GLOBAL_CFLAGS := -std=c11 -Werror-implicit-function-declaration -Wstrict-prototypes -Wwrite-strings
170GLOBAL_CPPFLAGS := -std=c++17 -fno-exceptions -fno-rtti -fno-threadsafe-statics -Wconversion -Wno-sign-conversion
171#GLOBAL_CPPFLAGS += -Weffc++
172GLOBAL_ASMFLAGS :=
173GLOBAL_LDFLAGS := -nostdlib --build-id -z noexecstack
174ifeq ($(call TOBOOL,$(USE_LLD)),true)
175GLOBAL_LDFLAGS += --pack-dyn-relocs=relr
176GLOBAL_LDFLAGS += -color-diagnostics
177endif
178# $(addprefix -L,$(LKINC)) XXX
179GLOBAL_MODULE_LDFLAGS :=
180
181# By default the sysroot is generated in "sysroot" under
182# the build directory, but this is overrideable
183ifeq ($(BUILDSYSROOT),)
184BUILDSYSROOT := $(BUILDDIR)/sysroot
185else
186# be noisy if we are
187$(info BUILDSYSROOT = $(BUILDSYSROOT))
188endif
189
190# Kernel compile flags
191KERNEL_INCLUDES := $(BUILDDIR) kernel/include
192KERNEL_COMPILEFLAGS := -ffreestanding -include $(KERNEL_CONFIG_HEADER)
193KERNEL_COMPILEFLAGS += -Wformat=2 -Wvla
194# GCC supports "-Wformat-signedness" but Clang currently does not.
195ifeq ($(call TOBOOL,$(USE_CLANG)),false)
196KERNEL_COMPILEFLAGS += -Wformat-signedness
197endif
198KERNEL_CFLAGS := -Wmissing-prototypes
199KERNEL_CPPFLAGS :=
200KERNEL_ASMFLAGS :=
201KERNEL_LDFLAGS :=
202
203# Build flags for modules that want frame pointers.
204# ngunwind, backtrace use this so that the simplisitic unwinder will work with
205# them. These are recorded here so that modules don't need knowledge of the
206# details. They just need to do:
207# MODULE_COMPILEFLAGS += $(KEEP_FRAME_POINTER_COMPILEFLAGS)
208KEEP_FRAME_POINTER_COMPILEFLAGS := -fno-omit-frame-pointer
209
210# User space compile flags
211USER_COMPILEFLAGS := -include $(USER_CONFIG_HEADER) -fPIC -D_ALL_SOURCE=1
212USER_CFLAGS :=
213USER_CPPFLAGS :=
214USER_ASMFLAGS :=
215
216# Additional flags for dynamic linking, both for dynamically-linked
217# executables and for shared libraries.
218USER_LDFLAGS := \
219    -z combreloc -z relro -z now -z text \
220    --hash-style=gnu --eh-frame-hdr
221
222ifeq ($(call TOBOOL,$(USE_LLD)),true)
223USER_LDFLAGS += -z rodynamic
224RODSO_LDFLAGS :=
225else
226RODSO_LDFLAGS := -T scripts/rodso.ld
227endif
228
229# Use linker garbage collection if enabled.
230ifeq ($(call TOBOOL,$(KERNEL_USE_LINKER_GC)),true)
231KERNEL_LDFLAGS += --gc-sections
232endif
233ifeq ($(call TOBOOL,$(USER_USE_LINKER_GC)),true)
234USER_LDFLAGS += --gc-sections
235endif
236
237# Turn on -fasynchronous-unwind-tables to get .eh_frame.
238# This is necessary for unwinding through optimized code.
239# The unwind information is part of the loaded binary. It's not that much space
240# and it allows for unwinding of stripped binaries, pc -> source translation
241# can be done offline with, e.g., scripts/symbolize.
242USER_COMPILEFLAGS += -fasynchronous-unwind-tables
243
244# TODO(ZX-2361): Remove frame pointers when libunwind and our tooling agree on
245# unwind tables. Until then compile with frame pointers in debug builds to get
246# high-quality backtraces.
247ifeq ($(call TOBOOL,$(DEBUG)),true)
248USER_COMPILEFLAGS += $(KEEP_FRAME_POINTER_COMPILEFLAGS)
249endif
250
251# We want .debug_frame for the kernel. ZX-62
252# And we still want asynchronous unwind tables. Alas there's (currently) no way
253# to achieve this with our GCC. At the moment we compile with
254# -fno-omit-frame-pointer which is good because we link with -gc-sections which
255# means .eh_frame gets discarded so GCC-built kernels don't have any unwind
256# info (except for assembly - heh)!
257# Assembler code has its own way of requesting .debug_frame vs .eh_frame with
258# the .cfi_sections directive. Sigh.
259KERNEL_COMPILEFLAGS += -fno-exceptions -fno-unwind-tables
260
261ifeq ($(call TOBOOL,$(USE_CLANG)),true)
262NO_SAFESTACK := -fno-sanitize=safe-stack -fno-stack-protector
263NO_SANITIZERS := -fno-sanitize=all -fno-stack-protector
264else
265NO_SAFESTACK :=
266NO_SANITIZERS :=
267endif
268
269USER_SCRT1_OBJ := $(BUILDDIR)/system/ulib/Scrt1.o
270
271# Additional flags for building shared libraries (ld -shared).
272USERLIB_SO_LDFLAGS := $(USER_LDFLAGS) -z defs
273
274# This is the string embedded into dynamically-linked executables
275# as PT_INTERP.  The launchpad library looks this up via the
276# "loader service", so it should be a simple name rather than an
277# absolute pathname as is used for this on other systems.
278USER_SHARED_INTERP := ld.so.1
279
280# Programs built with ASan use the ASan-supporting dynamic linker.
281ifeq ($(call TOBOOL,$(USE_ASAN)),true)
282USER_SHARED_INTERP := asan/$(USER_SHARED_INTERP)
283endif
284
285# Additional flags for building dynamically-linked executables.
286USERAPP_LDFLAGS := \
287    $(USER_LDFLAGS) -pie -dynamic-linker $(USER_SHARED_INTERP)
288
289ifeq ($(call TOBOOL,$(USE_GOLD)),false)
290# BFD ld stupidly insists on resolving dependency DSO's symbols when
291# doing a -shared -z defs link.  To do this it needs to find
292# dependencies' dependencies, which requires -rpath-link.  Gold does
293# not have this misfeature.  Since ulib/musl needs ulib/zircon and
294# everything needs ulib/musl, this covers the actual needs in the
295# build today without resorting to resolving inter-module dependencies
296# to generate -rpath-link in a general fashion.  Eventually we should
297# always use gold or lld for all the user-mode links, and then we'll
298# never need this.
299USERAPP_LDFLAGS += -rpath-link $(BUILDDIR)/ulib/zircon
300endif
301
302# Architecture specific compile flags
303ARCH_COMPILEFLAGS :=
304ARCH_CFLAGS :=
305ARCH_CPPFLAGS :=
306ARCH_ASMFLAGS :=
307
308# top level rule
309all::
310
311# master module object list
312ALLOBJS_MODULE :=
313
314# all module objects for the target (does not include hostapp)
315ALL_TARGET_OBJS :=
316
317# master object list (for dep generation)
318ALLOBJS :=
319
320# master source file list
321ALLSRCS :=
322
323# master list of packages for export
324ALLPKGS :=
325
326# anything you add here will be deleted in make clean
327GENERATED :=
328
329# anything added to GLOBAL_DEFINES will be put into $(BUILDDIR)/config-global.h
330GLOBAL_DEFINES :=
331
332# anything added to KERNEL_DEFINES will be put into $(BUILDDIR)/config-kernel.h
333KERNEL_DEFINES := LK=1 _KERNEL=1 ZIRCON_TOOLCHAIN=1
334
335# anything added to USER_DEFINES will be put into $(BUILDDIR)/config-user.h
336USER_DEFINES := ZIRCON_TOOLCHAIN=1
337
338# anything added to HOST_DEFINES will be put into $(BUILDDIR)/config-host.h
339HOST_DEFINES :=
340
341# Anything added to GLOBAL_SRCDEPS will become a dependency of every source file in the system.
342# Useful for header files that may be included by one or more source files.
343GLOBAL_SRCDEPS := $(GLOBAL_CONFIG_HEADER)
344
345# Anything added to TARGET_SRCDEPS will become a dependency of every target module file in the system.
346# Useful for header files that may be included by one or more source files.
347TARGET_MODDEPS :=
348
349# these need to be filled out by the project/target/platform rules.mk files
350TARGET :=
351PLATFORM :=
352ARCH :=
353ALLMODULES :=
354
355# this is the *true* allmodules, to check for duplicate modules
356# (since submodules do not contribute to ALLMODULES)
357DUPMODULES :=
358
359# add any external module dependencies
360MODULES := $(EXTERNAL_MODULES)
361
362# any .mk specified here will be included before build.mk
363EXTRA_BUILDRULES :=
364
365# any rules you put here will also be built by the system before considered being complete
366EXTRA_BUILDDEPS :=
367
368# any rules you put here will be built if the kernel is also being built
369EXTRA_KERNELDEPS :=
370
371# any rules you put here will be depended on in clean builds
372EXTRA_CLEANDEPS :=
373
374# build ids
375EXTRA_IDFILES :=
376
377# All kernel modules contribute to this list.
378ALLMODULE_OBJS :=
379
380# userspace apps to build and include in initfs
381ALLUSER_APPS :=
382
383# userspace app modules
384ALLUSER_MODULES :=
385
386# userspace lib modules
387ALLUSER_LIBS :=
388
389# host apps to build
390ALLHOST_APPS :=
391
392# host libs to build
393ALLHOST_LIBS :=
394
395# EFI libs to build
396ALLEFI_LIBS :=
397
398# sysroot (exported libraries and headers)
399SYSROOT_DEPS :=
400
401# For now always enable frame pointers so kernel backtraces
402# can work and define WITH_PANIC_BACKTRACE to enable them in panics
403# ZX-623
404KERNEL_DEFINES += WITH_PANIC_BACKTRACE=1 WITH_FRAME_POINTERS=1
405KERNEL_COMPILEFLAGS += $(KEEP_FRAME_POINTER_COMPILEFLAGS)
406
407KERNEL_DEFINES += WITH_KERNEL_PCIE=1
408
409# Kernel lock dependency tracking.
410ifeq ($(call TOBOOL,$(ENABLE_LOCK_DEP)),true)
411KERNEL_DEFINES += WITH_LOCK_DEP=1
412KERNEL_DEFINES += LOCK_DEP_ENABLE_VALIDATION=1
413endif
414
415# Kernel lock dependency tracking tests. By default this is enabled when
416# tracking is enabled, but can also be eanbled independently to assess whether
417# the tests build and *fail correctly* when lockdep is disabled.
418ifeq ($(call TOBOOL,$(ENABLE_LOCK_DEP_TESTS)),true)
419KERNEL_DEFINES += WITH_LOCK_DEP_TESTS=1
420endif
421
422# additional bootdata items to be included to bootdata.bin
423ADDITIONAL_BOOTDATA_ITEMS :=
424
425# manifest of files to include in the user bootfs
426USER_MANIFEST := $(BUILDDIR)/bootfs.manifest
427USER_MANIFEST_LINES :=
428# The contents of this are derived from BOOTFS_DEBUG_MODULES.
429USER_MANIFEST_DEBUG_INPUTS :=
430# Filter on manifest lines by {group} prefix.
431ifeq ($(call TOBOOL,$(ENABLE_INSTALL_SAMPLES)),true)
432USER_MANIFEST_GROUPS :=
433else
434USER_MANIFEST_GROUPS := --groups=!sample,ddk-sample
435endif
436
437# Directory in the bootfs where MODULE_FIRMWARE files go.
438FIRMWARE_INSTALL_DIR := lib/firmware
439# Directory in the source tree where MODULE_FIRMWARE files are found.
440FIRMWARE_SRC_DIR := prebuilt/downloads/firmware
441# TODO(mcgrathr): Force an absolute path for this so that every rhs in the
442# manifest either starts with $(BUILDDIR) or is absolute.
443# //scripts/build-zircon.sh needs this.
444FIRMWARE_SRC_DIR := $(abspath $(FIRMWARE_SRC_DIR))
445
446# if someone defines this, the build id will be pulled into lib/version
447BUILDID ?=
448
449# Tool locations.
450TOOLS := $(BUILDDIR)/tools
451FIDL := $(TOOLS)/fidlc
452ABIGEN := $(TOOLS)/abigen
453ZBI := $(TOOLS)/zbi
454
455# set V=1 in the environment if you want to see the full command line of every command
456ifeq ($(V),1)
457NOECHO :=
458else
459NOECHO ?= @
460endif
461
462# used to force a rule to run every time
463.PHONY: FORCE
464FORCE:
465
466# try to include the project file
467-include $(firstword $(wildcard kernel/project/$(PROJECT).mk \
468				kernel/project/alias/$(PROJECT).mk))
469ifndef TARGET
470$(error couldn't find project "$(PROJECT)" or project doesn't define target)
471endif
472include kernel/target/$(TARGET)/rules.mk
473ifndef PLATFORM
474$(error couldn't find target or target doesn't define platform)
475endif
476include kernel/platform/$(PLATFORM)/rules.mk
477
478ifeq ($(call TOBOOL,$(QUIET)),false)
479$(info PROJECT/PLATFORM/TARGET = $(PROJECT) / $(PLATFORM) / $(TARGET))
480endif
481
482include system/host/rules.mk
483include kernel/arch/$(ARCH)/rules.mk
484include kernel/top/rules.mk
485include make/abigen.mk
486
487ifeq ($(call TOBOOL,$(USE_CLANG)),true)
488GLOBAL_COMPILEFLAGS += --target=$(CLANG_ARCH)-fuchsia
489endif
490
491ifeq ($(call TOBOOL,$(USE_LTO)),true)
492ifeq ($(call TOBOOL,$(USE_CLANG)),false)
493$(error USE_LTO requires USE_CLANG)
494endif
495ifeq ($(call TOBOOL,$(USE_LLD)),false)
496$(error USE_LTO requires USE_LLD)
497endif
498# LTO doesn't store -mcmodel=kernel information in the bitcode files as it
499# does for many other codegen options so we have to set it explicitly. This
500# can be removed when https://bugs.llvm.org/show_bug.cgi?id=33306 is fixed.
501KERNEL_LDFLAGS += $(patsubst -mcmodel=%,-mllvm -code-model=%,\
502                  $(filter -mcmodel=%,$(KERNEL_COMPILEFLAGS)))
503ifeq ($(call TOBOOL,$(USE_THINLTO)),true)
504GLOBAL_COMPILEFLAGS += -flto=thin
505GLOBAL_LDFLAGS += --thinlto-jobs=8 --thinlto-cache-dir=$(THINLTO_CACHE_DIR)
506else
507GLOBAL_COMPILEFLAGS += -flto -fwhole-program-vtables
508# Full LTO doesn't require any special ld flags.
509endif
510endif
511
512ifeq ($(call TOBOOL,$(USE_SANCOV)),true)
513ifeq ($(call TOBOOL,$(USE_ASAN)),false)
514$(error USE_SANCOV requires USE_ASAN)
515endif
516endif
517
518ifeq ($(call TOBOOL,$(USE_ASAN)),true)
519ifeq ($(call TOBOOL,$(USE_CLANG)),false)
520$(error USE_ASAN requires USE_CLANG)
521endif
522
523# Compile all of userland with ASan.  ASan makes safe-stack superfluous
524# and ASan reporting doesn't really grok safe-stack, so disable it.
525# Individual modules can append $(NO_SANITIZERS) to counteract this.
526USER_COMPILEFLAGS += -fsanitize=address -fno-sanitize=safe-stack
527
528# The Clang toolchain includes a manifest for the shared libraries it provides.
529# The right-hand sides are relative to the directory containing the manifest.
530CLANG_MANIFEST := $(CLANG_TOOLCHAIN_PREFIX)../lib/$(CLANG_ARCH)-fuchsia.manifest
531CLANG_MANIFEST_LINES := \
532    $(subst =,=$(CLANG_TOOLCHAIN_PREFIX)../lib/,$(shell cat $(CLANG_MANIFEST)))
533find-clang-solib = $(filter lib/$1=%,$(CLANG_MANIFEST_LINES))
534# Every userland executable and shared library compiled with ASan
535# needs to link with $(ASAN_SOLIB).  module-user{app,lib}.mk adds it
536# to MODULE_EXTRA_OBJS so the linking target will depend on it.
537ASAN_SONAME := libclang_rt.asan.so
538ASAN_SOLIB_MANIFEST := $(call find-clang-solib,$(ASAN_SONAME))
539ASAN_SOLIB := $(word 2,$(subst =, ,$(ASAN_SOLIB_MANIFEST)))
540USER_MANIFEST_LINES += {core}$(ASAN_SOLIB_MANIFEST)
541
542# The ASan runtime DSO depends on more DSOs from the toolchain.  We don't
543# link against those, so we don't need any build-time dependencies on them.
544# But we need them alongside the ASan runtime DSO in the bootfs.
545find-clang-asan-solib = $(or $(call find-clang-solib,asan/$1), \
546			     $(call find-clang-solib,$1))
547ASAN_RUNTIME_SONAMES := libc++abi.so.1 libunwind.so.1
548ASAN_RUNTIME_MANIFEST := \
549    $(foreach soname,$(ASAN_RUNTIME_SONAMES),\
550	      {core}$(call find-clang-asan-solib,$(soname)))
551USER_MANIFEST_LINES += $(ASAN_RUNTIME_MANIFEST)
552
553TOOLCHAIN_SOLIBS += \
554    $(foreach entry,$(ASAN_SOLIB_MANIFEST) $(ASAN_RUNTIME_MANIFEST),\
555	      $(word 2,$(subst =, ,$(entry))))
556endif
557
558ifeq ($(call TOBOOL,$(USE_SANCOV)),true)
559# Compile all of userland with coverage.
560USER_COMPILEFLAGS += -fsanitize-coverage=trace-pc-guard
561NO_SANCOV := -fno-sanitize-coverage=trace-pc-guard
562NO_SANITIZERS += $(NO_SANCOV)
563else
564NO_SANCOV :=
565endif
566
567clang-print-file-name = $(shell $(CLANG_TOOLCHAIN_PREFIX)clang \
568				$(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) \
569				-print-file-name=$1)
570
571# To use LibFuzzer, we need to provide it and its dependency to the linker
572# since we're not using Clang and its '-fsanitize=fuzzer' flag as a driver to
573# lld.  Additionally, we need to make sure the shared objects are available on
574# the device.
575ifeq ($(call TOBOOL,$(USE_ASAN)),true)
576FUZZ_ALIB := $(call clang-print-file-name,libclang_rt.fuzzer.a)
577
578FUZZ_RUNTIME_SONAMES := libc++abi.so.1
579FUZZ_RUNTIME_SOLIBS := $(foreach soname,$(FUZZ_RUNTIME_SONAMES),\
580				 $(word 2,$(subst =, ,$(call find-clang-asan-solib,$(soname)))))
581
582FUZZ_EXTRA_OBJS := $(FUZZ_ALIB) $(FUZZ_RUNTIME_SOLIBS)
583else
584FUZZ_EXTRA_OBJS :=
585endif
586
587ifeq ($(call TOBOOL,$(USE_PROFILE)),true)
588USER_COMPILEFLAGS += -fprofile-instr-generate -fcoverage-mapping
589NO_PROFILE := -fno-profile-instr-generate -fno-coverage-mapping
590NO_SANITIZERS += $(NO_PROFILE)
591PROFILE_LIB := $(call clang-print-file-name,libclang_rt.profile.a)
592else
593NO_PROFILE :=
594PROFILE_LIB :=
595endif
596
597# Save these for the first module.mk iteration to see.
598SAVED_EXTRA_BUILDDEPS := $(EXTRA_BUILDDEPS)
599SAVED_GENERATED := $(GENERATED)
600SAVED_USER_MANIFEST_LINES := $(USER_MANIFEST_LINES)
601
602# recursively include any modules in the MODULE variable, leaving a trail of included
603# modules in the ALLMODULES list
604include make/recurse.mk
605
606define link-toolchain-file-cmd
607$(call BUILDECHO,generating $@)
608$(NOECHO)ln -n -f -L $< $@ 2> /dev/null || cp -f $< $@
609endef
610define toolchain-id-files
611$(foreach lib,$(TOOLCHAIN_SOLIBS),
612EXTRA_IDFILES += $$(BUILDDIR)/$(notdir $(lib)).id
613$$(BUILDDIR)/$(notdir $(lib)): $(lib); $$(link-toolchain-file-cmd)
614)
615endef
616$(eval $(toolchain-id-files))
617
618ifneq ($(EXTRA_IDFILES),)
619$(BUILDDIR)/ids.txt: $(EXTRA_IDFILES)
620	$(call BUILDECHO,generating $@)
621	@rm -f -- "$@.tmp"
622	@for f in $(EXTRA_IDFILES); do \
623	echo `cat $$f` `echo $$f | sed 's/\.id$$//g'` >> $@.tmp; \
624	done; \
625	mv $@.tmp $@
626
627EXTRA_BUILDDEPS += $(BUILDDIR)/ids.txt
628GENERATED += $(BUILDDIR)/ids.txt
629GENERATED += $(EXTRA_IDFILES)
630endif
631
632# include some rules for generating sysroot/ and contents in the build dir
633include make/sysroot.mk
634
635# make the build depend on all of the user apps
636all:: $(foreach app,$(ALLUSER_APPS),$(app) $(app).strip)
637
638# and all host tools
639all:: $(ALLHOST_APPS) $(ALLHOST_LIBS)
640
641tools:: $(ALLHOST_APPS) $(ALLHOST_LIBS)
642
643# meta rule for the kernel
644.PHONY: kernel
645kernel: $(KERNEL_ZBI) $(EXTRA_KERNELDEPS)
646ifeq ($(ENABLE_BUILD_LISTFILES),true)
647kernel: $(KERNEL_ELF).lst $(KERNEL_ELF).sym $(KERNEL_ELF).sym.sorted $(KERNEL_ELF).size
648endif
649
650ifeq ($(call TOBOOL,$(ENABLE_ULIB_ONLY)),false)
651# add the kernel to the build
652all:: kernel
653else
654# No kernel, but we want the bootfs.manifest listing the installed libraries.
655all:: user-manifest
656endif
657
658# meta rule for building just packages
659.PHONY: packages
660packages: $(ALLPKGS) $(BUILDDIR)/export/manifest
661
662$(BUILDDIR)/export/manifest: FORCE
663	@$(call BUILDECHO,generating $@ ;)\
664	$(MKDIR) ;\
665	rm -f $@.tmp ;\
666	(for p in $(sort $(notdir $(ALLPKGS))) ; do echo $$p ; done) > $@.tmp ;\
667	$(call TESTANDREPLACEFILE,$@.tmp,$@)
668
669# build depends on all packages
670all:: packages
671
672# add some automatic configuration defines
673KERNEL_DEFINES += \
674    PROJECT_$(PROJECT)=1 \
675    PROJECT=\"$(PROJECT)\" \
676    TARGET_$(TARGET)=1 \
677    TARGET=\"$(TARGET)\" \
678    PLATFORM_$(PLATFORM)=1 \
679    PLATFORM=\"$(PLATFORM)\" \
680    ARCH_$(ARCH)=1 \
681    ARCH=\"$(ARCH)\" \
682
683# debug build?
684# TODO(johngro) : Make LK and ZX debug levels independently controlable.
685ifneq ($(DEBUG),)
686GLOBAL_DEFINES += \
687    LK_DEBUGLEVEL=$(DEBUG) \
688    ZX_DEBUGLEVEL=$(DEBUG)
689endif
690
691# allow additional defines from outside the build system
692ifneq ($(EXTERNAL_DEFINES),)
693GLOBAL_DEFINES += $(EXTERNAL_DEFINES)
694$(info EXTERNAL_DEFINES = $(EXTERNAL_DEFINES))
695endif
696
697# Modules are added earlier before the recurse stage, so just print the info here
698ifneq ($(EXTERNAL_MODULES),)
699$(info EXTERNAL_MODULES = $(EXTERNAL_MODULES))
700endif
701
702ifneq ($(EXTERNAL_KERNEL_DEFINES),)
703KERNEL_DEFINES += $(EXTERNAL_KERNEL_DEFINES)
704$(info EXTERNAL_KERNEL_DEFINES = $(EXTERNAL_KERNEL_DEFINES))
705endif
706
707# prefix all of the paths in GLOBAL_INCLUDES and KERNEL_INCLUDES with -I
708GLOBAL_INCLUDES := $(addprefix -I,$(GLOBAL_INCLUDES))
709KERNEL_INCLUDES := $(addprefix -I,$(KERNEL_INCLUDES))
710
711# Path to the Goma compiler wrapper.  Defaults to using no wrapper.
712GOMACC ?=
713
714# set up paths to various tools
715ifeq ($(call TOBOOL,$(USE_CLANG)),true)
716CC := $(GOMACC) $(CLANG_TOOLCHAIN_PREFIX)clang
717AR := $(CLANG_TOOLCHAIN_PREFIX)llvm-ar
718OBJDUMP := $(CLANG_TOOLCHAIN_PREFIX)llvm-objdump
719READELF := $(CLANG_TOOLCHAIN_PREFIX)llvm-readelf
720CPPFILT := $(CLANG_TOOLCHAIN_PREFIX)llvm-cxxfilt
721SIZE := $(CLANG_TOOLCHAIN_PREFIX)llvm-size
722NM := $(CLANG_TOOLCHAIN_PREFIX)llvm-nm
723OBJCOPY := $(CLANG_TOOLCHAIN_PREFIX)llvm-objcopy
724STRIP := $(CLANG_TOOLCHAIN_PREFIX)llvm-objcopy --strip-sections
725else
726CC := $(GOMACC) $(TOOLCHAIN_PREFIX)gcc
727AR := $(TOOLCHAIN_PREFIX)ar
728OBJDUMP := $(TOOLCHAIN_PREFIX)objdump
729READELF := $(TOOLCHAIN_PREFIX)readelf
730CPPFILT := $(TOOLCHAIN_PREFIX)c++filt
731SIZE := $(TOOLCHAIN_PREFIX)size
732NM := $(TOOLCHAIN_PREFIX)nm
733OBJCOPY := $(TOOLCHAIN_PREFIX)objcopy
734STRIP := $(TOOLCHAIN_PREFIX)objcopy --strip-all
735endif
736LD := $(TOOLCHAIN_PREFIX)ld
737ifeq ($(call TOBOOL,$(USE_LLD)),true)
738LD := $(CLANG_TOOLCHAIN_PREFIX)ld.lld
739endif
740ifeq ($(call TOBOOL,$(USE_GOLD)),true)
741USER_LD := $(LD).gold
742else
743USER_LD := $(LD)
744endif
745
746LIBGCC := $(shell $(CC) $(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) -print-libgcc-file-name)
747ifeq ($(LIBGCC),)
748$(error cannot find runtime library, please set LIBGCC)
749endif
750
751# try to have the compiler output colorized error messages if available
752export GCC_COLORS ?= 1
753
754# setup bootloader toolchain
755ifeq ($(ARCH),x86)
756EFI_ARCH := x86_64
757else ifeq ($(ARCH),arm64)
758EFI_ARCH := aarch64
759endif
760
761ifeq ($(call TOBOOL,$(USE_CLANG)),true)
762EFI_AR := $(CLANG_TOOLCHAIN_PREFIX)llvm-ar
763EFI_CC := $(CLANG_TOOLCHAIN_PREFIX)clang
764EFI_CXX := $(CLANG_TOOLCHAIN_PREFIX)clang++
765EFI_LD := $(CLANG_TOOLCHAIN_PREFIX)lld-link
766EFI_COMPILEFLAGS := --target=$(EFI_ARCH)-windows-msvc
767else
768EFI_AR := $(TOOLCHAIN_PREFIX)ar
769EFI_CC := $(TOOLCHAIN_PREFIX)gcc
770EFI_CXX := $(TOOLCHAIN_PREFIX)g++
771EFI_LD := $(TOOLCHAIN_PREFIX)ld
772EFI_COMPILEFLAGS := -fPIE
773endif
774
775EFI_OPTFLAGS := -O2
776EFI_COMPILEFLAGS += -fno-stack-protector
777EFI_COMPILEFLAGS += -Wall
778EFI_CFLAGS := -fshort-wchar -std=c99 -ffreestanding
779ifeq ($(EFI_ARCH),x86_64)
780EFI_CFLAGS += -mno-red-zone
781endif
782
783
784# setup host toolchain
785# default to prebuilt clang
786FOUND_HOST_GCC ?= $(shell which $(HOST_TOOLCHAIN_PREFIX)gcc)
787HOST_TOOLCHAIN_PREFIX ?= $(CLANG_TOOLCHAIN_PREFIX)
788HOST_USE_CLANG ?= $(shell which $(HOST_TOOLCHAIN_PREFIX)clang)
789ifneq ($(HOST_USE_CLANG),)
790HOST_CC      := $(GOMACC) $(HOST_TOOLCHAIN_PREFIX)clang
791HOST_CXX     := $(GOMACC) $(HOST_TOOLCHAIN_PREFIX)clang++
792HOST_AR      := $(HOST_TOOLCHAIN_PREFIX)llvm-ar
793else
794ifeq ($(FOUND_HOST_GCC),)
795$(error cannot find toolchain, please set HOST_TOOLCHAIN_PREFIX or add it to your path)
796endif
797HOST_CC      := $(GOMACC) $(HOST_TOOLCHAIN_PREFIX)gcc
798HOST_CXX     := $(GOMACC) $(HOST_TOOLCHAIN_PREFIX)g++
799HOST_AR      := $(HOST_TOOLCHAIN_PREFIX)ar
800endif
801
802# Host compile flags
803HOST_COMPILEFLAGS := -g -O2 -Isystem/public -Isystem/private -I$(GENERATED_INCLUDES)
804HOST_COMPILEFLAGS += -Wall -Wextra
805HOST_COMPILEFLAGS += -Wno-unused-parameter -Wno-sign-compare
806HOST_CFLAGS := -std=c11
807HOST_CPPFLAGS := -std=c++17 -fno-exceptions -fno-rtti
808HOST_LDFLAGS :=
809ifneq ($(HOST_USE_CLANG),)
810# We need to use our provided libc++ and libc++abi (and their pthread
811# dependency) rather than the host library. The only exception is the
812# case when we are cross-compiling the host tools in which case we use
813# the C++ library from the sysroot.
814# TODO(TC-78): This can be removed once the Clang
815# toolchain ships with a cross-compiled C++ runtime.
816ifeq ($(HOST_TARGET),)
817ifeq ($(HOST_PLATFORM),linux)
818ifeq ($(HOST_ARCH),x86_64)
819HOST_SYSROOT ?= $(SYSROOT_linux-amd64_PATH)
820else ifeq ($(HOST_ARCH),aarch64)
821HOST_SYSROOT ?= $(SYSROOT_linux-arm64_PATH)
822endif
823# TODO(TC-77): Using explicit sysroot currently overrides location of C++
824# runtime so we need to explicitly add it here.
825HOST_LDFLAGS += -Lprebuilt/downloads/clang/lib
826# The implicitly linked static libc++.a depends on these.
827HOST_LDFLAGS += -ldl -lpthread
828endif
829endif
830HOST_LDFLAGS += -static-libstdc++
831# For host tools without C++, ignore the unused arguments.
832HOST_LDFLAGS += -Wno-unused-command-line-argument
833endif
834HOST_ASMFLAGS :=
835
836ifneq ($(HOST_TARGET),)
837HOST_COMPILEFLAGS += --target=$(HOST_TARGET)
838ifeq ($(HOST_TARGET),x86_64-linux-gnu)
839HOST_SYSROOT ?= $(SYSROOT_linux-amd64_PATH)
840else ifeq ($(HOST_TARGET),aarch64-linux-gnu)
841HOST_SYSROOT ?= $(SYSROOT_linux-arm64_PATH)
842endif
843endif
844
845ifneq ($(HOST_USE_CLANG),)
846ifeq ($(HOST_PLATFORM),darwin)
847HOST_SYSROOT ?= $(shell xcrun --show-sdk-path)
848endif
849endif
850
851ifneq ($(HOST_SYSROOT),)
852HOST_COMPILEFLAGS += --sysroot=$(HOST_SYSROOT)
853endif
854
855ifeq ($(call TOBOOL,$(HOST_USE_ASAN)),true)
856HOST_COMPILEFLAGS += -fsanitize=address
857export ASAN_SYMBOLIZER_PATH := $(HOST_TOOLCHAIN_PREFIX)llvm-symbolizer
858endif
859
860# the logic to compile and link stuff is in here
861include make/build.mk
862
863# top level target to just build the bootloader
864.PHONY: bootloader
865bootloader:
866
867# build a bootloader if needed
868include bootloader/build.mk
869
870DEPS := $(ALLOBJS:%o=%d)
871
872# put all of the build flags in various config.h files to force a rebuild if any change
873GLOBAL_DEFINES += GLOBAL_INCLUDES=\"$(subst $(SPACE),_,$(GLOBAL_INCLUDES))\"
874GLOBAL_DEFINES += GLOBAL_COMPILEFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_COMPILEFLAGS))\"
875GLOBAL_DEFINES += GLOBAL_OPTFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_OPTFLAGS))\"
876GLOBAL_DEFINES += GLOBAL_CFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CFLAGS))\"
877GLOBAL_DEFINES += GLOBAL_CPPFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_CPPFLAGS))\"
878GLOBAL_DEFINES += GLOBAL_ASMFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_ASMFLAGS))\"
879GLOBAL_DEFINES += GLOBAL_LDFLAGS=\"$(subst $(SPACE),_,$(GLOBAL_LDFLAGS))\"
880GLOBAL_DEFINES += ARCH_COMPILEFLAGS=\"$(subst $(SPACE),_,$(ARCH_COMPILEFLAGS))\"
881GLOBAL_DEFINES += ARCH_CFLAGS=\"$(subst $(SPACE),_,$(ARCH_CFLAGS))\"
882GLOBAL_DEFINES += ARCH_CPPFLAGS=\"$(subst $(SPACE),_,$(ARCH_CPPFLAGS))\"
883GLOBAL_DEFINES += ARCH_ASMFLAGS=\"$(subst $(SPACE),_,$(ARCH_ASMFLAGS))\"
884
885KERNEL_DEFINES += KERNEL_INCLUDES=\"$(subst $(SPACE),_,$(KERNEL_INCLUDES))\"
886KERNEL_DEFINES += KERNEL_COMPILEFLAGS=\"$(subst $(SPACE),_,$(KERNEL_COMPILEFLAGS))\"
887KERNEL_DEFINES += KERNEL_CFLAGS=\"$(subst $(SPACE),_,$(KERNEL_CFLAGS))\"
888KERNEL_DEFINES += KERNEL_CPPFLAGS=\"$(subst $(SPACE),_,$(KERNEL_CPPFLAGS))\"
889KERNEL_DEFINES += KERNEL_ASMFLAGS=\"$(subst $(SPACE),_,$(KERNEL_ASMFLAGS))\"
890KERNEL_DEFINES += KERNEL_LDFLAGS=\"$(subst $(SPACE),_,$(KERNEL_LDFLAGS))\"
891
892USER_DEFINES += USER_COMPILEFLAGS=\"$(subst $(SPACE),_,$(USER_COMPILEFLAGS))\"
893USER_DEFINES += USER_CFLAGS=\"$(subst $(SPACE),_,$(USER_CFLAGS))\"
894USER_DEFINES += USER_CPPFLAGS=\"$(subst $(SPACE),_,$(USER_CPPFLAGS))\"
895USER_DEFINES += USER_ASMFLAGS=\"$(subst $(SPACE),_,$(USER_ASMFLAGS))\"
896USER_DEFINES += USER_LDFLAGS=\"$(subst $(SPACE),_,$(USER_LDFLAGS))\"
897
898HOST_DEFINES += HOST_COMPILEFLAGS=\"$(subst $(SPACE),_,$(HOST_COMPILEFLAGS))\"
899HOST_DEFINES += HOST_CFLAGS=\"$(subst $(SPACE),_,$(HOST_CFLAGS))\"
900HOST_DEFINES += HOST_CPPFLAGS=\"$(subst $(SPACE),_,$(HOST_CPPFLAGS))\"
901HOST_DEFINES += HOST_ASMFLAGS=\"$(subst $(SPACE),_,$(HOST_ASMFLAGS))\"
902HOST_DEFINES += HOST_LDFLAGS=\"$(subst $(SPACE),_,$(HOST_LDFLAGS))\"
903
904#$(info LIBGCC = $(LIBGCC))
905#$(info GLOBAL_COMPILEFLAGS = $(GLOBAL_COMPILEFLAGS))
906#$(info GLOBAL_OPTFLAGS = $(GLOBAL_OPTFLAGS))
907
908# make all object files depend on any targets in GLOBAL_SRCDEPS
909$(ALLOBJS): $(GLOBAL_SRCDEPS)
910
911# make all target object files depend on any targets in TARGET_MODDEPS
912$(ALL_TARGET_OBJS): $(TARGET_MODDEPS)
913
914# any extra top level build dependencies that someone may have declared
915all:: $(EXTRA_BUILDDEPS)
916
917clean: $(EXTRA_CLEANDEPS)
918	rm -f $(ALLOBJS)
919	rm -f $(DEPS)
920	rm -f $(GENERATED)
921	rm -f $(KERNEL_ZBI) $(KERNEL_IMAGE) $(KERNEL_ELF) $(KERNEL_ELF).lst $(KERNEL_ELF).debug.lst $(KERNEL_ELF).sym $(KERNEL_ELF).sym.sorted $(KERNEL_ELF).size $(KERNEL_ELF).hex $(KERNEL_ELF).dump $(KERNEL_ELF)-gdb.py
922	rm -f $(foreach app,$(ALLUSER_APPS),$(app) $(app).lst $(app).dump $(app).strip)
923
924install: all
925	scp $(KERNEL_ZBI) 192.168.0.4:/tftproot
926
927# generate a config-global.h file with all of the GLOBAL_DEFINES laid out in #define format
928$(GLOBAL_CONFIG_HEADER): FORCE
929	@$(call MAKECONFIGHEADER,$@,GLOBAL_DEFINES,"#define __Fuchsia__ 1")
930
931# generate a config-kernel.h file with all of the KERNEL_DEFINES laid out in #define format
932$(KERNEL_CONFIG_HEADER): FORCE
933	@$(call MAKECONFIGHEADER,$@,KERNEL_DEFINES,"")
934
935# generate a config-user.h file with all of the USER_DEFINES laid out in #define format
936$(USER_CONFIG_HEADER): FORCE
937	@$(call MAKECONFIGHEADER,$@,USER_DEFINES,"")
938
939$(HOST_CONFIG_HEADER): FORCE
940	@$(call MAKECONFIGHEADER,$@,HOST_DEFINES,"")
941
942GENERATED += $(GLOBAL_CONFIG_HEADER) $(KERNEL_CONFIG_HEADER) $(USER_CONFIG_HEADER) $(HOST_CONFIG_HEADER)
943
944# Empty rule for the .d files. The above rules will build .d files as a side
945# effect. Only works on gcc 3.x and above, however.
946%.d:
947
948ifeq ($(filter $(MAKECMDGOALS), clean), )
949-include $(DEPS)
950endif
951
952endif
953
954endif # make spotless
955