+# These variables are specifically meant to be overridable via the make
+# command-line.
+CC ?= clang
+NM ?= $(patsubst %clang,%llvm-nm,$(filter-out ccache sccache,$(CC)))
+AR ?= $(patsubst %clang,%llvm-ar,$(filter-out ccache sccache,$(CC)))
+EXTRA_CFLAGS ?= -O2 -DNDEBUG
+# The directory where we build the sysroot.
+SYSROOT ?= $(CURDIR)/sysroot
+# A directory to install to for "make install".
+INSTALL_DIR ?= /usr/local
+# single or posix
+THREAD_MODEL ?= single
+# dlmalloc or none
+MALLOC_IMPL ?= dlmalloc
+# yes or no
+BUILD_LIBC_TOP_HALF ?= yes
+# The directory where we're store intermediate artifacts.
+OBJDIR ?= $(CURDIR)/build
+
+# Variables from this point on are not meant to be overridable via the
+# make command-line.
+
+# Set the target variables. Multiarch triples notably omit the vendor field,
+# which happens to be what we do for the main target triple too.
+TARGET_TRIPLE = wasm32-wasi
+MULTIARCH_TRIPLE = wasm32-wasi
+
+# These variables describe the locations of various files and directories in
+# the source tree.
+DLMALLOC_DIR = $(CURDIR)/dlmalloc
+DLMALLOC_SRC_DIR = $(DLMALLOC_DIR)/src
+DLMALLOC_SOURCES = $(DLMALLOC_SRC_DIR)/dlmalloc.c
+DLMALLOC_INC = $(DLMALLOC_DIR)/include
+LIBC_BOTTOM_HALF_DIR = $(CURDIR)/libc-bottom-half
+LIBC_BOTTOM_HALF_CLOUDLIBC_SRC = $(LIBC_BOTTOM_HALF_DIR)/cloudlibc/src
+LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC = $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/include
+LIBC_BOTTOM_HALF_HEADERS_PUBLIC = $(LIBC_BOTTOM_HALF_DIR)/headers/public
+LIBC_BOTTOM_HALF_HEADERS_PRIVATE = $(LIBC_BOTTOM_HALF_DIR)/headers/private
+LIBC_BOTTOM_HALF_SOURCES = $(LIBC_BOTTOM_HALF_DIR)/sources
+LIBC_BOTTOM_HALF_ALL_SOURCES = \
+ $(shell find $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) -name \*.c) \
+ $(shell find $(LIBC_BOTTOM_HALF_SOURCES) -name \*.c)
+
+# FIXME(https://reviews.llvm.org/D85567) - due to a bug in LLD the weak
+# references to a function defined in `chdir.c` only work if `chdir.c` is at the
+# end of the archive, but once that LLD review lands and propagates into LLVM
+# then we don't have to do this.
+LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_SOURCES)/chdir.c,$(LIBC_BOTTOM_HALF_ALL_SOURCES))
+LIBC_BOTTOM_HALF_ALL_SOURCES := $(LIBC_BOTTOM_HALF_ALL_SOURCES) $(LIBC_BOTTOM_HALF_SOURCES)/chdir.c
+
+LIBWASI_EMULATED_MMAN_SOURCES = \
+ $(shell find $(LIBC_BOTTOM_HALF_DIR)/mman -name \*.c)
+LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES = \
+ $(shell find $(LIBC_BOTTOM_HALF_DIR)/clocks -name \*.c)
+LIBWASI_EMULATED_GETPID_SOURCES = \
+ $(shell find $(LIBC_BOTTOM_HALF_DIR)/getpid -name \*.c)
+LIBWASI_EMULATED_SIGNAL_SOURCES = \
+ $(shell find $(LIBC_BOTTOM_HALF_DIR)/signal -name \*.c)
+LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c
+LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c)
+LIBC_TOP_HALF_DIR = $(CURDIR)/libc-top-half
+LIBC_TOP_HALF_MUSL_DIR = $(LIBC_TOP_HALF_DIR)/musl
+LIBC_TOP_HALF_MUSL_SRC_DIR = $(LIBC_TOP_HALF_MUSL_DIR)/src
+LIBC_TOP_HALF_MUSL_INC = $(LIBC_TOP_HALF_MUSL_DIR)/include
+LIBC_TOP_HALF_MUSL_SOURCES = \
+ $(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
+ misc/a64l.c \
+ misc/basename.c \
+ misc/dirname.c \
+ misc/ffs.c \
+ misc/ffsl.c \
+ misc/ffsll.c \
+ misc/fmtmsg.c \
+ misc/getdomainname.c \
+ misc/gethostid.c \
+ misc/getopt.c \
+ misc/getopt_long.c \
+ misc/getsubopt.c \
+ misc/uname.c \
+ misc/nftw.c \
+ errno/strerror.c \
+ network/htonl.c \
+ network/htons.c \
+ network/ntohl.c \
+ network/ntohs.c \
+ network/inet_ntop.c \
+ network/inet_pton.c \
+ network/inet_aton.c \
+ network/in6addr_any.c \
+ network/in6addr_loopback.c \
+ fenv/fenv.c \
+ fenv/fesetround.c \
+ fenv/feupdateenv.c \
+ fenv/fesetexceptflag.c \
+ fenv/fegetexceptflag.c \
+ fenv/feholdexcept.c \
+ exit/exit.c \
+ exit/atexit.c \
+ exit/assert.c \
+ exit/quick_exit.c \
+ exit/at_quick_exit.c \
+ time/strftime.c \
+ time/asctime.c \
+ time/asctime_r.c \
+ time/ctime.c \
+ time/ctime_r.c \
+ time/wcsftime.c \
+ time/strptime.c \
+ time/difftime.c \
+ time/timegm.c \
+ time/ftime.c \
+ time/gmtime.c \
+ time/gmtime_r.c \
+ time/timespec_get.c \
+ time/getdate.c \
+ time/localtime.c \
+ time/localtime_r.c \
+ time/mktime.c \
+ time/__tm_to_secs.c \
+ time/__month_to_secs.c \
+ time/__secs_to_tm.c \
+ time/__year_to_secs.c \
+ time/__tz.c \
+ fcntl/creat.c \
+ dirent/alphasort.c \
+ dirent/versionsort.c \
+ env/clearenv.c \
+ env/getenv.c \
+ env/putenv.c \
+ env/setenv.c \
+ env/unsetenv.c \
+ unistd/posix_close.c \
+ stat/futimesat.c \
+ ) \
+ $(filter-out %/procfdname.c %/syscall.c %/syscall_ret.c %/vdso.c %/version.c, \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/*.c)) \
+ $(filter-out %/flockfile.c %/funlockfile.c %/__lockfile.c %/ftrylockfile.c \
+ %/rename.c \
+ %/tmpnam.c %/tmpfile.c %/tempnam.c \
+ %/popen.c %/pclose.c \
+ %/remove.c \
+ %/gets.c, \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/*.c)) \
+ $(filter-out %/strsignal.c, \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/*.c)) \
+ $(filter-out %/dcngettext.c %/textdomain.c %/bind_textdomain_codeset.c, \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/locale/*.c)) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdlib/*.c) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/search/*.c) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/multibyte/*.c) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/regex/*.c) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/prng/*.c) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/conf/*.c) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/ctype/*.c) \
+ $(filter-out %/__signbit.c %/__signbitf.c %/__signbitl.c \
+ %/__fpclassify.c %/__fpclassifyf.c %/__fpclassifyl.c \
+ %/ceilf.c %/ceil.c \
+ %/floorf.c %/floor.c \
+ %/truncf.c %/trunc.c \
+ %/rintf.c %/rint.c \
+ %/nearbyintf.c %/nearbyint.c \
+ %/sqrtf.c %/sqrt.c \
+ %/fabsf.c %/fabs.c \
+ %/copysignf.c %/copysign.c \
+ %/fminf.c %/fmaxf.c \
+ %/fmin.c %/fmax.c, \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/math/*.c)) \
+ $(filter-out %/crealf.c %/creal.c %creall.c \
+ %/cimagf.c %/cimag.c %cimagl.c, \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \
+ $(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c)
+MUSL_PRINTSCAN_SOURCES = \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/floatscan.c \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfprintf.c \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfwprintf.c \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdio/vfscanf.c \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdlib/strtod.c \
+ $(LIBC_TOP_HALF_MUSL_SRC_DIR)/stdlib/wcstod.c
+LIBC_TOP_HALF_HEADERS_PRIVATE = $(LIBC_TOP_HALF_DIR)/headers/private
+LIBC_TOP_HALF_SOURCES = $(LIBC_TOP_HALF_DIR)/sources
+LIBC_TOP_HALF_ALL_SOURCES = \
+ $(LIBC_TOP_HALF_MUSL_SOURCES) \
+ $(shell find $(LIBC_TOP_HALF_SOURCES) -name \*.c)
+
+# Add any extra flags
+CFLAGS = $(EXTRA_CFLAGS)
+# Set the target.
+CFLAGS += --target=$(TARGET_TRIPLE)
+# WebAssembly floating-point match doesn't trap.
+# TODO: Add -fno-signaling-nans when the compiler supports it.
+CFLAGS += -fno-trapping-math
+# Add all warnings, but disable a few which occur in third-party code.
+CFLAGS += -Wall -Wextra -Werror \
+ -Wno-null-pointer-arithmetic \
+ -Wno-unused-parameter \
+ -Wno-sign-compare \
+ -Wno-unused-variable \
+ -Wno-unused-function \
+ -Wno-ignored-attributes \
+ -Wno-missing-braces \
+ -Wno-ignored-pragmas \
+ -Wno-unused-but-set-variable \
+ -Wno-unknown-warning-option
+
+# Configure support for threads.
+ifeq ($(THREAD_MODEL), single)
+CFLAGS += -mthread-model single
+endif
+ifeq ($(THREAD_MODEL), posix)
+CFLAGS += -mthread-model posix -pthread
+endif
+
+# Expose the public headers to the implementation. We use `-isystem` for
+# purpose for two reasons:
+#
+# 1. It only does `<...>` not `"...."` lookup. We are making a libc,
+# which is a system library, so all public headers should be
+# accessible via `<...>` and never also need `"..."`. `-isystem` main
+# purpose is to only effect `<...>` lookup.
+#
+# 2. The `-I` for private headers added for specific C files below
+# should come earlier in the search path, so they can "override"
+# and/or `#include_next` the public headers. `-isystem` (like
+# `-idirafter`) comes later in the search path than `-I`.
+CFLAGS += -isystem "$(SYSROOT_INC)"
+
+# These variables describe the locations of various files and directories in
+# the build tree.
+objs = $(patsubst $(CURDIR)/%.c,$(OBJDIR)/%.o,$(1))
+DLMALLOC_OBJS = $(call objs,$(DLMALLOC_SOURCES))
+LIBC_BOTTOM_HALF_ALL_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_ALL_SOURCES))
+LIBC_TOP_HALF_ALL_OBJS = $(call objs,$(LIBC_TOP_HALF_ALL_SOURCES))
+ifeq ($(MALLOC_IMPL),dlmalloc)
+LIBC_OBJS += $(DLMALLOC_OBJS)
+else ifeq ($(MALLOC_IMPL),none)
+# No object files to add.
+else
+$(error unknown malloc implementation $(MALLOC_IMPL))
+endif
+# Add libc-bottom-half's objects.
+LIBC_OBJS += $(LIBC_BOTTOM_HALF_ALL_OBJS)
+ifeq ($(BUILD_LIBC_TOP_HALF),yes)
+# libc-top-half is musl.
+LIBC_OBJS += $(LIBC_TOP_HALF_ALL_OBJS)
+endif
+MUSL_PRINTSCAN_OBJS = $(call objs,$(MUSL_PRINTSCAN_SOURCES))
+MUSL_PRINTSCAN_LONG_DOUBLE_OBJS = $(patsubst %.o,%.long-double.o,$(MUSL_PRINTSCAN_OBJS))
+MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS = $(patsubst %.o,%.no-floating-point.o,$(MUSL_PRINTSCAN_OBJS))
+LIBWASI_EMULATED_MMAN_OBJS = $(call objs,$(LIBWASI_EMULATED_MMAN_SOURCES))
+LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES))
+LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES))
+LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES))
+LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES))