CC ?= cc CPPFLAGS ?= CFLAGS ?= LDFLAGS ?= TMPDIR ?= /tmp VROOT ?= . VC ?= ./vc VEXE ?= ./v V1_FALLBACK_EXE = $(dir $(VEXE))v1_fallback$(EXE_EXT) # Portable VC snapshots do not embed the default compiler. Keep their v1 executable on the full # compatibility compiler path even when the generated C is built on a V3 host. VC_BOOTSTRAP_DEFINE := -DCUSTOM_DEFINE_v1_fallback VCREPO ?= https://github.com/vlang/vc TCCREPO ?= https://github.com/vlang/tccbin LEGACYREPO ?= https://github.com/macports/macports-legacy-support GIT ?= git # Command-line variables are exported automatically. Keep GIT as literal data # until platform detection decides whether the Linux selector will consume it. override V_GIT_LITERAL := $(value GIT) unexport GIT VCFILE := v.c TMPTCC := $(VROOT)/thirdparty/tcc LEGACYLIBS := $(VROOT)/thirdparty/legacy TMPLEGACY := $(LEGACYLIBS)/source TCCOS := unknown TCCARCH := unknown LINUX_TCC_SELECTOR := $(VROOT)/cmd/tools/select_linux_tcc.sh GIT_ARGV_RUNNER := $(VROOT)/cmd/tools/git_argv.sh #### Platform detections and overrides: _SYS := $(shell uname 2>/dev/null || echo Unknown) _SYS := $(patsubst MSYS%,MSYS,$(_SYS)) _SYS := $(patsubst MINGW%,MinGW,$(_SYS)) ifneq ($(filter $(_SYS),MSYS MinGW),) WIN32 := 1 EXE_EXT := .exe # vc/v.c is generated with `-cross` targeting the host OS that ran gen_vc_ci.yml # (Linux), so it only guards *nix headers/APIs, not Windows. The dedicated # `-os windows` snapshot lives in vc/v_win.c; that is the one Windows needs. VCFILE := v_win.c # GNU make defaults CC to `cc`, but mingw32-make installations often only # provide `gcc`. Switch only the implicit default and preserve explicit CC=... ifneq ($(filter $(origin CC),default file),) ifeq ($(CC),cc) CC := gcc endif endif endif ifeq ($(_SYS),Linux) LINUX := 1 TCCOS := linux ifneq ($(shell ldd --version 2>&1 | grep -i musl),) TCCOS := linuxmusl endif endif ifeq ($(_SYS),Darwin) MAC := 1 TCCOS := macos ifeq ($(shell expr $(shell uname -r | cut -d. -f1) \<= 16), 1) LEGACY := 1 CPPFLAGS += -I$(LEGACYLIBS)/include/LegacySupport LDFLAGS += -L$(LEGACYLIBS)/lib LDFLAGS += -lMacportsLegacySupport VFLAGS += -cc $(CC) VFLAGS += -cflags "$(strip $(CPPFLAGS) $(CFLAGS))" VFLAGS += -ldflags -L$(LEGACYLIBS)/lib VFLAGS += -cflags $(LEGACYLIBS)/lib/libMacportsLegacySupport.a endif endif ifeq ($(_SYS),FreeBSD) TCCOS := freebsd LDFLAGS += -lexecinfo endif ifeq ($(_SYS),NetBSD) NETBSD := 1 TCCOS := netbsd LDFLAGS += -lexecinfo endif ifeq ($(_SYS),OpenBSD) OPENBSD := 1 TCCOS := openbsd LDFLAGS += -lexecinfo endif ifdef ANDROID_ROOT ANDROID := 1 undefine LINUX TCCOS := android ifneq ($(wildcard $(PREFIX)/lib/libexecinfo.*),) LDFLAGS += -lexecinfo endif endif ##### ifdef WIN32 TCCOS := windows endif TCCARCH := $(shell uname -m 2>/dev/null || echo unknown) # A 32-bit userland can run on a 64-bit kernel (Raspberry Pi OS 32-bit on a Pi 4/5, # an armhf or i386 container), where `uname -m` names the kernel's architecture. # The C compiler, the TCC bundle and the bootstrap follow the userland, whose word # size `getconf LONG_BIT` reports. ifeq ($(shell getconf LONG_BIT 2>/dev/null),32) ifneq ($(filter aarch64 arm64 armv8%,$(TCCARCH)),) TCCARCH := armv7l endif ifeq ($(TCCARCH),x86_64) TCCARCH := i686 endif endif ifeq ($(TCCARCH),x86_64) TCCARCH := amd64 else ifneq ($(filter x86%,$(TCCARCH)),) TCCARCH := i386 else ifeq ($(TCCARCH),arm64) TCCARCH := arm64 else ifneq ($(filter arm%,$(TCCARCH)),) TCCARCH := arm # otherwise, just use the arch name endif endif endif endif ifeq ($(TCCOS),linux) override GIT := $(V_GIT_LITERAL) export GIT # GNU Make before 4.4 does not export make variables to $(shell ...). # Linux recipes validate and execute custom GIT argv at recipe execution time. else export GIT HAS_GIT := $(shell command -v $(GIT) >/dev/null 2>&1 && echo 1 || echo 0) endif GITCLEANPULL := $(GIT) clean -xf && $(GIT) pull --rebase --quiet GITFASTCLONE := $(GIT) clone --filter=blob:none --quiet TCCBUILDSCRIPT = $(VROOT)/thirdparty/build_scripts/thirdparty-$(TCCOS)-$(TCCARCH)_tcc.sh .PHONY: all v1 cache-basic-modules clean rebuild check fresh_vc fresh_tcc fresh_legacy latest_tcc_source check_for_working_tcc etags ctags ifdef prod VFLAGS+=-prod endif # The compiler can be optimized with Clang while its users compile ordinary # programs and tests with another C compiler, such as TCC in Linux CI. CACHE_VFLAGS ?= $(VFLAGS) # Optional optimized sidecar compiler; leave the bootstrap executable available # for the self-hosting checks, and warm caches with the compiler used by tests. VPROD ?= CACHE_VEXE = $(if $(strip $(VPROD)),$(VPROD),$(VEXE)) # Keep bootstrap C compiler/linker flags aligned with the initial `v1` build. BOOTSTRAP_CC_CFLAGS := $(strip $(CFLAGS)) BOOTSTRAP_CFLAGS := $(strip $(CPPFLAGS) $(CFLAGS)) BOOTSTRAP_VC_CC_CFLAGS := $(BOOTSTRAP_CC_CFLAGS) BOOTSTRAP_VC_CFLAGS := $(BOOTSTRAP_CFLAGS) BOOTSTRAP_LDFLAGS := $(strip $(LDFLAGS)) ifeq ($(LINUX),1) ifeq ($(TCCARCH),arm) BOOTSTRAP_LDFLAGS := $(strip $(BOOTSTRAP_LDFLAGS) -latomic) endif ifneq ($(filter $(TCCARCH),arm64 aarch64),) BOOTSTRAP_VC_UNSAFE_OPTFLAGS := $(filter-out -O -O0 -O1,$(filter -O%,$(BOOTSTRAP_CC_CFLAGS))) ifneq ($(BOOTSTRAP_VC_UNSAFE_OPTFLAGS),) # Some Linux ARM64 system compilers miscompile the external vc bootstrap # snapshot at -O2/-O3, making `v1` segfault before it can build `v2`. # Keep the bootstrap stages at -O1, but preserve the requested flags for # the final `v` build. BOOTSTRAP_VC_SAFE_CFLAGS := $(strip $(filter-out -O%,$(BOOTSTRAP_CC_CFLAGS)) -O1) BOOTSTRAP_VC_CC_CFLAGS := $(BOOTSTRAP_VC_SAFE_CFLAGS) BOOTSTRAP_VC_CFLAGS := $(strip $(CPPFLAGS) $(BOOTSTRAP_VC_SAFE_CFLAGS)) endif endif endif # A vc snapshot may use the lean compiler dispatcher when its generated C is built # on a Unix-like host. Keep the temporary v1 on the full compatibility path so # it can create v2 before either the compiler driver or v1_fallback exists. BOOTSTRAP_VC_CC_CFLAGS += -DCUSTOM_DEFINE_v1_fallback BOOTSTRAP_VC_EXTRA_SOURCES := # Portable vc snapshots generated before the OpenBSD entropy and semaphore guards # still reference two libc symbols that OpenBSD does not provide. Supply the small # bootstrap-only compatibility implementations until vc is regenerated. ifdef OPENBSD BOOTSTRAP_VC_CC_CFLAGS += -DSYS_getrandom=0 BOOTSTRAP_VC_EXTRA_SOURCES += $(VROOT)/cmd/tools/openbsd_vc_compat.c endif # Portable vc snapshots guard android_print with `defined(__ANDROID__) && !defined(__TERMUX__)`. # Termux's compiler does not predefine __TERMUX__, so a native Termux bootstrap must define it; # otherwise v1 references android_print, which only the android target links (#30279). ifdef ANDROID ifneq ($(or $(TERMUX_VERSION),$(findstring com.termux,$(PREFIX))),) BOOTSTRAP_VC_CC_CFLAGS += -D__TERMUX__ endif endif BOOTSTRAP_TCC_REQUESTED := $(or $(findstring -cc tcc,$(strip $(VFLAGS))),$(findstring -cc=tcc,$(strip $(VFLAGS)))) BOOTSTRAP_CCOMPILER_VFLAG := BOOTSTRAP_VC_CCOMPILER_VFLAG := POST_BOOTSTRAP_CCOMPILER_VFLAG := BOOTSTRAP_GC_VFLAG := ifeq ($(filter -gc -gc=%,$(VFLAGS)),) BOOTSTRAP_GC_VFLAG := -gc none endif ifneq ($(filter $(_SYS),Linux FreeBSD NetBSD OpenBSD DragonFly),) ifneq ($(filter $(TCCARCH),arm64 aarch64 arm),) ifeq ($(filter -cc,$(VFLAGS)),) ifeq ($(findstring -cc=,$(VFLAGS)),) # Bundled TCC can hang, fail, or miscompile V while bootstrapping on ARM64, # so keep both `v1 -> v2` and `v2 -> v` on the same system compiler # unless the user overrode it explicitly. On 32-bit ARM, TCC cannot link V # itself: the Thumb-2 C startup code of armhf distributions calls into libc # with a branch that cannot reach across V's text, and TCC adds no veneer. BOOTSTRAP_CCOMPILER_VFLAG := -cc "$(CC)" BOOTSTRAP_VC_CCOMPILER_VFLAG := $(BOOTSTRAP_CCOMPILER_VFLAG) endif endif endif endif ifeq ($(LINUX),1) ifneq ($(BOOTSTRAP_TCC_REQUESTED),) ifneq ($(CC),tcc) # The external vc bootstrap snapshot may still emit Windows-only stdio # declarations for non-Windows TCC. Use the system compiler just for v1 -> v2. BOOTSTRAP_VC_CCOMPILER_VFLAG := -cc "$(CC)" endif endif endif ifdef ANDROID ifneq ($(BOOTSTRAP_TCC_REQUESTED),) ifneq ($(CC),tcc) # There is no Android TCC bundle yet. If `-cc tcc` was requested anyway, # keep both bootstrap stages on the system compiler. BOOTSTRAP_VC_CCOMPILER_VFLAG := -cc "$(CC)" BOOTSTRAP_CCOMPILER_VFLAG := -cc "$(CC)" POST_BOOTSTRAP_CCOMPILER_VFLAG := -cc "$(CC)" endif endif endif BOOTSTRAP_VC_VFLAGS := $(BOOTSTRAP_VC_CCOMPILER_VFLAG) $(if $(strip $(BOOTSTRAP_VC_CFLAGS)),-cflags "$(BOOTSTRAP_VC_CFLAGS)") $(if $(strip $(BOOTSTRAP_LDFLAGS)),-ldflags "$(BOOTSTRAP_LDFLAGS)") BOOTSTRAP_VFLAGS := $(BOOTSTRAP_CCOMPILER_VFLAG) $(if $(strip $(BOOTSTRAP_CFLAGS)),-cflags "$(BOOTSTRAP_CFLAGS)") $(if $(strip $(BOOTSTRAP_LDFLAGS)),-ldflags "$(BOOTSTRAP_LDFLAGS)") all: latest_vc latest_tcc latest_legacy ifdef WIN32 powershell -NoProfile -ExecutionPolicy Bypass -File "$(VROOT)/cmd/tools/vc_compat_uint.ps1" -Source "$(VC)/$(VCFILE)" -Destination "$(VC)/v_win_compat.c" $(CC) $(CPPFLAGS) $(BOOTSTRAP_VC_CC_CFLAGS) $(VC_BOOTSTRAP_DEFINE) -std=c99 -municode -w -o v1$(EXE_EXT) "$(VC)/v_win_compat.c" $(LDFLAGS) -lws2_32 -lbcrypt || cmd/tools/cc_compilation_failed_windows.sh $(RM) "$(VC)/v_win_compat.c" ./v1$(EXE_EXT) -no-parallel -o v2$(EXE_EXT) $(BOOTSTRAP_GC_VFLAG) $(VFLAGS) $(BOOTSTRAP_VC_VFLAGS) cmd/v ./v2$(EXE_EXT) -o $(VEXE)$(EXE_EXT) $(BOOTSTRAP_GC_VFLAG) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v $(RM) v1$(EXE_EXT) $(RM) v2$(EXE_EXT) else ifdef LEGACY '$(MAKE)' -C $(TMPLEGACY) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' '$(MAKE)' -C $(TMPLEGACY) PREFIX=$(realpath $(LEGACYLIBS)) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' install rm -rf $(TMPLEGACY) $(eval override LDFLAGS+=-L$(realpath $(LEGACYLIBS))/lib -lMacportsLegacySupport) endif # Stream compatibility fixes for stale snapshots to the compiler, keeping one v.c. sh "$(VROOT)/cmd/tools/vc_compat.sh" "$(VC)/$(VCFILE)" $(CC) $(CPPFLAGS) $(BOOTSTRAP_VC_CC_CFLAGS) $(VC_BOOTSTRAP_DEFINE) -std=c99 -w -o v1$(EXE_EXT) -- $(BOOTSTRAP_VC_EXTRA_SOURCES) -lm -lpthread $(BOOTSTRAP_LDFLAGS) || sh cmd/tools/cc_compilation_failed_non_windows.sh ifdef NETBSD paxctl +m v1$(EXE_EXT) endif ./v1$(EXE_EXT) -no-parallel -o v2$(EXE_EXT) $(BOOTSTRAP_GC_VFLAG) $(VFLAGS) $(BOOTSTRAP_VC_VFLAGS) cmd/v ifdef NETBSD paxctl +m v2$(EXE_EXT) endif ./v2$(EXE_EXT) -nocache -o $(VEXE)$(EXE_EXT) $(BOOTSTRAP_GC_VFLAG) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v ifdef NETBSD paxctl +m $(VEXE)$(EXE_EXT) endif rm -rf v1$(EXE_EXT) v2$(EXE_EXT) endif @$(VEXE)$(EXE_EXT) $(POST_BOOTSTRAP_CCOMPILER_VFLAG) -new-compiler -gc none run cmd/tools/detect_tcc.v @echo "V has been successfully built" @$(VEXE)$(EXE_EXT) -version @$(VEXE)$(EXE_EXT) $(POST_BOOTSTRAP_CCOMPILER_VFLAG) -new-compiler -gc none run .github/problem-matchers/register_all.vsh ifneq ($(strip $(VPROD)),) # A failed self-build may bootstrap through make; that fallback must not # inherit this optional production build and recursively start another one. @VPROD= MAKEFLAGS= MFLAGS= VFLAGS= sh "$(VROOT)/cmd/tools/build_vprod.sh" "$(VEXE)$(EXE_EXT)" "$(VPROD)$(EXE_EXT)" "$(CC)" @"$(VPROD)$(EXE_EXT)" -version endif @$(MAKE) --no-print-directory cache-basic-modules cache-basic-modules: @set -e; \ cache_gcflags=; \ if [ ! -f "$(TMPTCC)/lib/libgc.a" ] && [ ! -f "$(TMPTCC)/lib/libgc.dylib" ]; then \ cache_gcflags='-gc none'; \ fi; \ VFLAGS= $(CACHE_VEXE)$(EXE_EXT) $$cache_gcflags $(CACHE_VFLAGS) $(POST_BOOTSTRAP_CCOMPILER_VFLAG) -new-compiler run cmd/tools/cache_basic_modules.v; \ VFLAGS= $(CACHE_VEXE)$(EXE_EXT) $$cache_gcflags $(CACHE_VFLAGS) $(POST_BOOTSTRAP_CCOMPILER_VFLAG) -new-compiler cmd/tools/cache_basic_modules_test.v v1: ifdef LEGACY @set -e; \ if [ ! -f "$(LEGACYLIBS)/lib/libMacportsLegacySupport.a" ]; then \ '$(MAKE)' latest_legacy; \ '$(MAKE)' -C "$(TMPLEGACY)" CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)'; \ '$(MAKE)' -C "$(TMPLEGACY)" PREFIX="$(abspath $(LEGACYLIBS))" CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' install; \ rm -rf "$(TMPLEGACY)"; \ fi endif @set -e; \ CC='$(CC)' OLDV_CCOPTIONS='$(CPPFLAGS) $(BOOTSTRAP_VC_CC_CFLAGS)' \ OLDV_LDFLAGS='$(BOOTSTRAP_LDFLAGS)' \ cmd/tools/install_v1_fallback.sh '$(VEXE)$(EXE_EXT)' '$(V1_FALLBACK_EXE)' ifdef NETBSD paxctl +m "$${V1_FALLBACK_OUTPUT:-$(V1_FALLBACK_EXE)}" endif @echo "Built V1 compatibility compiler: $(V1_FALLBACK_EXE)" clean: rm -rf $(TMPTCC) rm -rf $(LEGACYLIBS) rm -rf $(VC) rebuild: clean all ifndef local latest_vc: $(VC)/.git/config ifeq ($(TCCOS),linux) @if bash '$(GIT_ARGV_RUNNER)' check > /dev/null 2>&1; then \ bash '$(GIT_ARGV_RUNNER)' run -C '$(VC)' clean -xf \ && bash '$(GIT_ARGV_RUNNER)' run -C '$(VC)' pull --rebase --quiet; \ else \ echo "git not found; using existing $(VC)/$(VCFILE)"; \ fi else ifeq ($(HAS_GIT),1) cd $(VC) && $(GITCLEANPULL) else @echo "git not found; using existing $(VC)/$(VCFILE)" endif endif else latest_vc: @echo "Using local vc" endif check_for_working_tcc: @$(TMPTCC)/tcc.exe --version > /dev/null 2> /dev/null || echo "The executable '$(TMPTCC)/tcc.exe' does not work." fresh_vc: ifeq ($(TCCOS),linux) @bash '$(GIT_ARGV_RUNNER)' check rm -rf $(VC) @bash '$(GIT_ARGV_RUNNER)' run clone --filter=blob:none --quiet '$(VCREPO)' '$(VC)' else rm -rf $(VC) ifeq ($(HAS_GIT),1) $(GITFASTCLONE) $(VCREPO) $(VC) else @echo "git is required to clone $(VCREPO) into $(VC)" @exit 1 endif endif ifndef local ifeq ($(TCCOS),linux) latest_tcc: else latest_tcc: $(TMPTCC)/.git/config endif ifeq ($(TCCOS),linux) @TMPDIR='$(TMPDIR)' VFLAGS='$(VFLAGS)' \ bash '$(LINUX_TCC_SELECTOR)' latest '$(TMPTCC)' '$(TCCREPO)' '$(TCCARCH)' '$(VROOT)' else ifeq ($(HAS_GIT),1) ifdef WIN32 @if [ -f "$(TMPTCC)/lib/advapi32.def" ]; then \ cd "$(TMPTCC)" && $(GIT) checkout -- lib/advapi32.def > /dev/null 2> /dev/null || true; \ fi endif # A pull fetches every platform branch, so skip it while the upstream that the pull would # follow has not moved. `clean` keeps changed tracked files; leave those to the pull to report, # as well as a missing or local upstream. @set -e; cd $(TMPTCC); $(GIT) clean -xf; \ tcc_branch="$$($(GIT) symbolic-ref --quiet --short HEAD || true)"; \ tcc_upstream_remote=; \ tcc_upstream_ref=; \ if [ -n "$$tcc_branch" ]; then \ tcc_upstream_remote="$$($(GIT) config --get "branch.$$tcc_branch.remote" || true)"; \ tcc_upstream_ref="$$($(GIT) config --get "branch.$$tcc_branch.merge" || true)"; \ fi; \ tcc_remote_sha=; \ if [ -n "$$tcc_upstream_remote" ] && [ "$$tcc_upstream_remote" != . ] && [ -n "$$tcc_upstream_ref" ] \ && [ -z "$$($(GIT) status --porcelain --untracked-files=no)" ]; then \ tcc_remote_sha="$$($(GIT) ls-remote "$$tcc_upstream_remote" "$$tcc_upstream_ref" 2> /dev/null | cut -f1)"; \ fi; \ if [ -n "$$tcc_remote_sha" ] && [ "$$tcc_remote_sha" = "$$($(GIT) rev-parse HEAD)" ]; then \ echo "TCC $$tcc_branch is already up to date."; \ else \ $(GIT) pull --rebase --quiet; \ fi ifdef WIN32 @if [ -f "$(TMPTCC)/lib/advapi32.def" ]; then \ for sym in RegEnumKeyExW RegEnumValueW RegQueryInfoKeyW; do \ grep -qx "$$sym" "$(TMPTCC)/lib/advapi32.def" || printf '%s\n' "$$sym" >> "$(TMPTCC)/lib/advapi32.def"; \ done; \ fi endif else @echo "git not found; skipping update of $(TMPTCC)" endif endif ifneq (,$(wildcard ./tcc.exe)) @'$(MAKE)' --quiet check_for_working_tcc 2> /dev/null endif else latest_tcc: @echo "Using local tcc" @'$(MAKE)' --quiet check_for_working_tcc 2> /dev/null endif # Rebuild the bundled TCC in-place from upstream tinycc, while preserving the # V-specific libgc/openlibm files already stored in $(TMPTCC). latest_tcc_source: $(TMPTCC)/.git/config ifeq ($(TCCOS),linux) @bash '$(GIT_ARGV_RUNNER)' check else ifneq ($(HAS_GIT),1) @echo "git is required to bootstrap $(TMPTCC) before rebuilding it from source" @exit 1 endif endif ifneq (,$(wildcard $(TCCBUILDSCRIPT))) ifeq ($(TCCOS),linux) @GIT_ARGV_RUNNER='$(GIT_ARGV_RUNNER)' TCC_FOLDER='$(TMPTCC)' $(if $(strip $(TCC_COMMIT)),TCC_COMMIT='$(TCC_COMMIT)') CC='$(CC)' bash '$(TCCBUILDSCRIPT)' else @TCC_FOLDER='$(TMPTCC)' $(if $(strip $(TCC_COMMIT)),TCC_COMMIT='$(TCC_COMMIT)') CC='$(CC)' bash '$(TCCBUILDSCRIPT)' endif @'$(MAKE)' --quiet check_for_working_tcc 2> /dev/null else @echo 'No upstream TinyCC build script is available for thirdparty-$(TCCOS)-$(TCCARCH).' @echo 'Use `make latest_tcc` to refresh the prebuilt bundle from $(TCCREPO).' @exit 1 endif fresh_tcc: rm -rf $(TMPTCC) ifndef local ifeq ($(TCCOS),linux) @TMPDIR='$(TMPDIR)' VFLAGS='$(VFLAGS)' \ bash '$(LINUX_TCC_SELECTOR)' fresh '$(TMPTCC)' '$(TCCREPO)' '$(TCCARCH)' '$(VROOT)' else ifeq ($(HAS_GIT),1) @set -e; \ branches="$$( $(GIT) ls-remote --heads $(TCCREPO) 2> /dev/null | awk '{sub("refs/heads/","",$$2); print $$2}' || true )"; \ preferred_branch='thirdparty-$(TCCOS)-$(TCCARCH)'; \ fallback_branch=''; \ if [ "$(LINUX)" = "1" ]; then \ fallback_branch='thirdparty-linuxmusl-$(TCCARCH)'; \ fi; \ selected_branch=''; \ if printf '%s\n' "$$branches" | grep -Fx "$$preferred_branch" > /dev/null; then \ selected_branch="$$preferred_branch"; \ elif [ "$$fallback_branch" != '' ] && [ "$$fallback_branch" != "$$preferred_branch" ] \ && printf '%s\n' "$$branches" | grep -Fx "$$fallback_branch" > /dev/null; then \ selected_branch="$$fallback_branch"; \ fi; \ if [ "$$selected_branch" = '' ]; then \ echo "Pre-built TCC not available for $$preferred_branch at $(TCCREPO), will use the system compiler: $(CC)"; \ $(GITFASTCLONE) --branch thirdparty-unknown-unknown $(TCCREPO) "$(TMPTCC)"; \ else \ $(GITFASTCLONE) --branch "$$selected_branch" $(TCCREPO) "$(TMPTCC)"; \ if [ -f "$(TMPTCC)/lib/advapi32.def" ]; then \ for sym in RegEnumKeyExW RegEnumValueW RegQueryInfoKeyW; do \ grep -qx "$$sym" "$(TMPTCC)/lib/advapi32.def" || printf '%s\n' "$$sym" >> "$(TMPTCC)/lib/advapi32.def"; \ done; \ fi; \ if ! "$(TMPTCC)/tcc.exe" --version > /dev/null 2> /dev/null; then \ echo "Pre-built TCC bundle $$selected_branch did not run; V will use the system compiler: $(CC)"; \ '$(MAKE)' --quiet check_for_working_tcc 2> /dev/null; \ else \ '$(MAKE)' --quiet check_for_working_tcc 2> /dev/null; \ fi; \ fi else @echo "git is required to clone $(TCCREPO)" @exit 1 endif endif else @echo "Using local tccbin" @'$(MAKE)' --quiet check_for_working_tcc 2> /dev/null endif ifndef local latest_legacy: $(TMPLEGACY)/.git/config ifdef LEGACY ifeq ($(TCCOS),linux) @if bash '$(GIT_ARGV_RUNNER)' check > /dev/null 2>&1; then \ bash '$(GIT_ARGV_RUNNER)' run -C '$(TMPLEGACY)' clean -xf \ && bash '$(GIT_ARGV_RUNNER)' run -C '$(TMPLEGACY)' pull --rebase --quiet; \ else \ echo "git not found; using existing $(TMPLEGACY)"; \ fi else ifeq ($(HAS_GIT),1) cd $(TMPLEGACY) && $(GITCLEANPULL) else @echo "git not found; using existing $(TMPLEGACY)" endif endif endif else latest_legacy: ifdef LEGACY @echo "Using local legacysupport" endif endif fresh_legacy: ifeq ($(TCCOS),linux) @bash '$(GIT_ARGV_RUNNER)' check rm -rf $(LEGACYLIBS) @bash '$(GIT_ARGV_RUNNER)' run clone --filter=blob:none --quiet '$(LEGACYREPO)' '$(TMPLEGACY)' else rm -rf $(LEGACYLIBS) ifeq ($(HAS_GIT),1) $(GITFASTCLONE) $(LEGACYREPO) $(TMPLEGACY) else @echo "git is required to download legacy support sources ($(LEGACYREPO))" @exit 1 endif endif $(TMPTCC)/.git/config: ifeq ($(TCCOS),linux) @bash '$(GIT_ARGV_RUNNER)' check '$(MAKE)' fresh_tcc else ifeq ($(HAS_GIT),1) '$(MAKE)' fresh_tcc else @echo "git not found; skipping bootstrap of $(TMPTCC), system compiler $(CC) will be used" endif endif $(VC)/.git/config: ifeq ($(TCCOS),linux) @if bash '$(GIT_ARGV_RUNNER)' check > /dev/null 2>&1; then \ '$(MAKE)' fresh_vc; \ elif [ -f "$(VC)/$(VCFILE)" ]; then \ echo "git not found; using existing $(VC)/$(VCFILE)"; \ else \ echo "git is required to download $(VC)/$(VCFILE). Install git or provide the file manually."; \ exit 1; \ fi else ifeq ($(HAS_GIT),1) '$(MAKE)' fresh_vc else @if [ -f "$(VC)/$(VCFILE)" ]; then \ echo "git not found; using existing $(VC)/$(VCFILE)"; \ else \ echo "git is required to download $(VC)/$(VCFILE). Install git or provide the file manually."; \ exit 1; \ fi endif endif $(TMPLEGACY)/.git/config: ifdef LEGACY ifeq ($(TCCOS),linux) @if bash '$(GIT_ARGV_RUNNER)' check > /dev/null 2>&1; then \ '$(MAKE)' fresh_legacy; \ elif [ -d "$(TMPLEGACY)" ]; then \ echo "git not found; using existing $(TMPLEGACY)"; \ else \ echo "git is required to download legacy support sources ($(LEGACYREPO))"; \ exit 1; \ fi else ifeq ($(HAS_GIT),1) '$(MAKE)' fresh_legacy else @if [ -d "$(TMPLEGACY)" ]; then \ echo "git not found; using existing $(TMPLEGACY)"; \ else \ echo "git is required to download legacy support sources ($(LEGACYREPO))"; \ exit 1; \ fi endif endif endif asan: '$(MAKE)' all CFLAGS='-fsanitize=address,undefined' selfcompile: $(VEXE)$(EXE_EXT) -cg -o v cmd/v selfcompile-static: $(VEXE)$(EXE_EXT) -cg -cflags '--static' -o v-static cmd/v ### NB: Please keep this Makefile and makev.bat simple. install: @echo 'Please use `sudo ./v symlink` instead, or manually add the current directory to your PATH.' check: $(VEXE)$(EXE_EXT) test-all etags: ./v$(EXE_EXT) -print-v-files cmd/v | grep -v :parse_text| etags -L - ctags: ./v$(EXE_EXT) -print-v-files cmd/v | grep -v :parse_text| ctags -L -