Add necessary Makefile.inc1 infrastructure for building on non-FreeBSD

The most awkward bit in this patch is the bootstrapping of m4:
We can't simply use the host version of m4 since that is not compatible
with the flags passed by lex (at least on macOS, possibly also on Linux).
Therefore we need to bootstrap m4, but lex needs m4 to build and m4 also
depends on lex (which needs m4 to generate any files). To work around this
cyclic dependency we can build a bootstrap version of m4 (with pre-generated
files) then use that to build the real m4.

This patch also changes the xz/unxz/dd tools to always use the host version
since the version in the source tree cannot easily be bootstrapped on macOS
or Linux.

Reviewed By:	brooks, imp (earlier version)
Differential Revision: https://reviews.freebsd.org/D25992
This commit is contained in:
Alex Richardson 2020-08-25 13:29:57 +00:00
parent 7ec1ec4fdb
commit 5bb9250e0a
8 changed files with 2059 additions and 49 deletions

View File

@ -167,6 +167,19 @@ _t= ${TARGET_ARCH}/${TARGET}
.endif
.endfor
.if ${.MAKE.OS} != "FreeBSD"
CROSSBUILD_HOST=${.MAKE.OS}
.if ${.MAKE.OS} != "Linux" && ${.MAKE.OS} != "Darwin"
.warning "Unsupported crossbuild system: ${.MAKE.OS}. Build will probably fail!"
.endif
# We need to force NO_ROOT/DB_FROM_SRC builds when building on other operating
# systems since the BSD.foo.dist specs contain users and groups that do not
# exist by default on a Linux/MacOS system.
NO_ROOT:= 1
DB_FROM_SRC:= 1
.export NO_ROOT
.endif
# If all targets are disabled for system llvm then don't expect it to work
# for cross-builds.
.if !defined(TOOLS_PREFIX) && ${MK_LLVM_TARGET_ALL} == "no" && \
@ -568,13 +581,16 @@ _CPUTYPE!= MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} -f /dev/null \
.endif
.if make(buildworld)
BUILD_ARCH!= uname -p
.if ${MACHINE_ARCH} != ${BUILD_ARCH}
# On some Linux systems uname -p returns "unknown" so skip this check there.
# This check only exists to tell people to use TARGET_ARCH instead of
# MACHINE_ARCH so skipping it when crossbuilding on non-FreeBSD should be fine.
.if ${MACHINE_ARCH} != ${BUILD_ARCH} && ${.MAKE.OS} == "FreeBSD"
.error To cross-build, set TARGET_ARCH.
.endif
.endif
WORLDTMP?= ${OBJTOP}/tmp
BPATH= ${CCACHE_WRAPPER_PATH_PFX}${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/bin:${WORLDTMP}/legacy/usr/libexec
XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin
XPATH= ${WORLDTMP}/bin:${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin
# When building we want to find the cross tools before the host tools in ${BPATH}.
# We also need to add UNIVERSE_TOOLCHAIN_PATH so that we can find the shared
@ -589,6 +605,13 @@ STRICTTMPPATH= ${XPATH}:${BPATH}:${UNIVERSE_TOOLCHAIN_PATH}
# USING_SYSTEM_LINKER/USING_SYSTEM_COMPILER. Once these issues have been
# resolved it will be turned on by default.
BUILD_WITH_STRICT_TMPPATH?=0
.if defined(CROSSBUILD_HOST)
# When building on non-FreeBSD we can't rely on the tools in /usr/bin being compatible
# with what FreeBSD expects. Therefore we only use tools from STRICTTMPPATH
# during the world build stage. We build most tools during the bootstrap-tools
# phase but symlink host tools that are known to work instead of building them
BUILD_WITH_STRICT_TMPPATH:=1
.endif
.if ${BUILD_WITH_STRICT_TMPPATH} != 0
TMPPATH= ${STRICTTMPPATH}
.else
@ -724,7 +747,9 @@ XMAKE= ${BMAKE} \
# kernel-tools stage
KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${BPATH}:${PATH} \
WORLDTMP=${WORLDTMP}
WORLDTMP=${WORLDTMP} \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}"
KTMAKE= \
TOOLS_PREFIX=${TOOLS_PREFIX_UNDEF:U${WORLDTMP}} \
${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
@ -845,7 +870,13 @@ NO_META_IGNORE_HOST_HEADERS= 1
# allows tracking the oldest osreldate to force rebuilds via
# META_MODE_BADABI_REVS above.
host-osreldate.h: # DO NOT ADD /usr/include/osreldate.h here
.if !defined(CROSSBUILD_HOST)
@cp -f /usr/include/osreldate.h ${.TARGET}
.else
@echo "#ifndef __FreeBSD_version" > ${.TARGET}
@echo "#define __FreeBSD_version ${OSRELDATE}" >> ${.TARGET}
@echo "#endif" >> ${.TARGET}
.endif
WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
BWPHASE=${.TARGET:C,^_,,} \
@ -1022,7 +1053,8 @@ _bootstrap-tools:
@echo ">>> stage 1.2: bootstrap tools"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${BMAKE} bootstrap-tools
mkdir -p ${WORLDTMP}/usr ${WORLDTMP}/lib/casper ${WORLDTMP}/lib/geom
mkdir -p ${WORLDTMP}/usr ${WORLDTMP}/lib/casper ${WORLDTMP}/lib/geom \
${WORLDTMP}/bin
${WORLDTMP_MTREE} -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${WORLDTMP}/usr >/dev/null
${WORLDTMP_MTREE} -f ${.CURDIR}/etc/mtree/BSD.include.dist \
@ -1277,11 +1309,15 @@ __installcheck_sh_check: .PHONY
_zoneinfo= zic tzsetup
.endif
.if !defined(CROSSBUILD_HOST)
_sysctl=sysctl
.endif
ITOOLS= [ awk cap_mkdb cat chflags chmod chown cmp cp \
date echo egrep find grep id install ${_install-info} \
ln make mkdir mtree mv pwd_mkdb \
rm sed services_mkdb sh sort strip sysctl test true uname wc ${_zoneinfo} \
${LOCAL_ITOOLS}
rm sed services_mkdb sh sort strip ${_sysctl} test true uname wc \
${_zoneinfo} ${LOCAL_ITOOLS}
# Needed for share/man
.if ${MK_MAN_UTILS} != "no"
@ -1317,13 +1353,14 @@ MTREE_MAGIC?= mtree 2.0
distributeworld installworld stageworld: _installcheck_world .PHONY
mkdir -p ${INSTALLTMP}
progs=$$(for prog in ${ITOOLS}; do \
if progpath=`which $$prog`; then \
if progpath=`env PATH=${TMPPATH} which $$prog`; then \
echo $$progpath; \
else \
echo "Required tool $$prog not found in PATH." >&2; \
echo "Required tool $$prog not found in PATH ($$PATH)." >&2; \
exit 1; \
fi; \
done); \
if [ -z "${CROSSBUILD_HOST}" ] ; then \
libs=$$(ldd -f "%o %p\n" -f "%o %p\n" $$progs 2>/dev/null | sort -u | \
while read line; do \
set -- $$line; \
@ -1334,6 +1371,7 @@ distributeworld installworld stageworld: _installcheck_world .PHONY
exit 1; \
fi; \
done); \
fi; \
cp $$libs $$progs ${INSTALLTMP}
cp -R $${PATH_LOCALE:-"/usr/share/locale"} ${INSTALLTMP}/locale
.if defined(NO_ROOT)
@ -2043,10 +2081,9 @@ update: .PHONY
# build-tools or cross-tools.
#
# libnv is a requirement for config(8), which is an unconditional
# libnv and libsbuf are requirements for config(8), which is an unconditional
# bootstrap-tool.
_config_deps= lib/libnv
_config_deps= lib/libnv lib/libsbuf
legacy: .PHONY
.if ${BOOTSTRAPPING} < ${MINIMUM_SUPPORTED_OSREL} && ${BOOTSTRAPPING} != 0
@ -2054,7 +2091,7 @@ legacy: .PHONY
false
.endif
.for _tool in tools/build ${_config_deps}
.for _tool in tools/build
${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,all,install)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
@ -2090,12 +2127,23 @@ _bt= _bootstrap-tools
# If BOOTSTRAP_ALL_TOOLS is set we will build all the required tools from the
# current source tree. Otherwise we create a symlink to the version found in
# $PATH during the bootstrap-tools stage.
# When building on non-FreeBSD systems we can't assume that the host binaries
# accept compatible flags or produce compatible output. Therefore we force
# BOOTSTRAP_ALL_TOOLS and just build the FreeBSD version of the binary.
.if defined(CROSSBUILD_HOST)
BOOTSTRAP_ALL_TOOLS:= 1
.endif
.if defined(BOOTSTRAP_ALL_TOOLS)
# BOOTSTRAPPING will be set on the command line so we can't override it here.
# Instead set BOOTSTRAPPING_OSRELDATE so that the value 0 is set ${BSARGS}
BOOTSTRAPPING_OSRELDATE:= 0
.endif
# libnv and libsbuf are requirements for config(8), which is an unconditional
# bootstrap-tool.
_config=usr.sbin/config lib/libnv lib/libsbuf
${_bt}-usr.sbin/config: ${_bt}-lib/libnv ${_bt}-lib/libsbuf
.if ${MK_GAMES} != "no"
_strfile= usr.bin/fortune/strfile
.endif
@ -2111,13 +2159,20 @@ _vtfontcvt= usr.bin/vtfontcvt
# please ensure that you also add a .else case where you add the tool to the
# _bootstrap_tools_links variable.
.if ${BOOTSTRAPPING} < 1000033
_m4= usr.bin/m4
# Note: lex needs m4 to build but m4 also depends on lex (which needs m4 to
# generate any files). To fix this cyclic dependency we can build a bootstrap
# version of m4 (with pre-generated files) then use that to build the real m4.
# We can't simply use the host m4 since e.g. the macOS version does not accept
# the flags that are passed by lex.
# For lex we also use the pre-gerated files since we would otherwise need to
# build awk and sed first (which need lex to build)
# TODO: add a _bootstrap_lex and then build the real lex afterwards
_lex= usr.bin/lex
# Note: lex needs m4 to build but m4 also depends on lex. However, lex can be
# bootstrapped so we build lex first.
${_bt}-usr.bin/m4: ${_bt}-lib/libopenbsd ${_bt}-usr.bin/yacc ${_bt}-${_lex}
_bt_m4_depend=${_bt}-${_m4}
_bt_lex_depend=${_bt}-${_lex} ${_bt_m4_depend}
_m4= tools/build/bootstrap-m4 usr.bin/m4
${_bt}-tools/build/bootstrap-m4: ${_bt}-usr.bin/lex ${_bt}-lib/libopenbsd ${_bt}-usr.bin/yacc
${_bt}-usr.bin/m4: ${_bt}-lib/libopenbsd ${_bt}-usr.bin/yacc ${_bt}-usr.bin/lex ${_bt}-tools/build/bootstrap-m4
_bt_m4_depend=${_bt}-usr.bin/m4
_bt_lex_depend=${_bt}-usr.bin/lex ${_bt_m4_depend}
.else
_bootstrap_tools_links+=m4 lex
.endif
@ -2183,12 +2238,15 @@ _bootstrap_tools_links+=crunchgen
.endif
# r296926 -P keymap search path, MFC to stable/10 in r298297
.if ${BOOTSTRAPPING} < 1003501 || \
(${BOOTSTRAPPING} >= 1100000 && ${BOOTSTRAPPING} < 1100103)
# Note: kbdcontrol can not be bootstrapped on non-FreeBSD systems
.if !defined(CROSSBUILD_HOST)
.if (${BOOTSTRAPPING} < 1003501 || \
(${BOOTSTRAPPING} >= 1100000 && ${BOOTSTRAPPING} < 1100103))
_kbdcontrol= usr.sbin/kbdcontrol
.else
_bootstrap_tools_links+=kbdcontrol
.endif
.endif
_yacc= usr.bin/yacc
@ -2215,6 +2273,7 @@ ${_bt}-usr.bin/clang/lldb-tblgen: ${_bt}-lib/clang/libllvmminimal
.if ${MK_LOCALES} != "no"
_localedef= usr.bin/localedef
${_bt}-usr.bin/localedef: ${_bt}-usr.bin/yacc ${_bt_lex_depend}
.endif
.if ${MK_KERBEROS} != "no"
@ -2244,8 +2303,8 @@ ${_bt}-usr.bin/mandoc: ${_bt}-lib/libopenbsd
_basic_bootstrap_tools_multilink=usr.bin/grep grep,egrep,fgrep
_basic_bootstrap_tools_multilink+=bin/test test,[
# bootstrap tools needed by buildworld:
_basic_bootstrap_tools=usr.bin/cut bin/expr usr.bin/gencat \
usr.bin/join usr.bin/mktemp bin/rmdir usr.bin/sed usr.bin/sort \
_basic_bootstrap_tools+=usr.bin/cut bin/expr usr.bin/gencat usr.bin/join \
usr.bin/mktemp bin/realpath bin/rmdir usr.bin/sed usr.bin/sort \
usr.bin/truncate usr.bin/tsort
# Some build scripts use nawk instead of awk (this happens at least in
# cddl/contrib/opensolaris/lib/libdtrace/common/mknames.sh) so we need both awk
@ -2259,24 +2318,29 @@ _basic_bootstrap_tools+=usr.bin/uuencode usr.bin/uudecode
_basic_bootstrap_tools+=usr.bin/xargs
# cap_mkdb is required for share/termcap:
_basic_bootstrap_tools+=usr.bin/cap_mkdb
# ldd is required for installcheck (TODO: just always use /usr/bin/ldd instead?)
_basic_bootstrap_tools+=usr.bin/ldd
# services_mkdb/pwd_mkdb are required for installworld:
_basic_bootstrap_tools+=usr.sbin/services_mkdb usr.sbin/pwd_mkdb
# ldd is required for installcheck (TODO: just always use /usr/bin/ldd instead?)
.if !defined(CROSSBUILD_HOST)
# ldd is only needed for updating the running system so we don't need to
# bootstrap ldd on non-FreeBSD systems
_basic_bootstrap_tools+=usr.bin/ldd
.endif
# sysctl/chflags are required for installkernel:
.if !defined(CROSSBUILD_HOST)
_basic_bootstrap_tools+=sbin/sysctl bin/chflags
.else
# When building on non-FreeBSD, install a fake chflags instead since the
# version from the source tree cannot work. We also don't need sysctl since we
# are install with -DNO_ROOT.
_other_bootstrap_tools+=tools/build/cross-build/fake_chflags
.endif
# mkfifo is used by sys/conf/newvers.sh
_basic_bootstrap_tools+=usr.bin/mkfifo
.if ${MK_BOOT} != "no"
_basic_bootstrap_tools+=bin/dd
# xz/unxz is used by EFI
_basic_bootstrap_tools_multilink+=usr.bin/xz xz,unxz
# md5 is used by boot/beri (and possibly others)
_basic_bootstrap_tools+=sbin/md5
.if defined(BOOTSTRAP_ALL_TOOLS)
${_bt}-sbin/md5: ${_bt}-lib/libmd
.endif
.endif
.if ${MK_ZONEINFO} != "no"
@ -2297,6 +2361,10 @@ ${_bt}-usr.sbin/config: ${_bt}-usr.bin/file2c ${_bt_lex_depend}
# `make legacy` step. Not adding a link to make is important on non-FreeBSD
# since "make" will usually point to GNU make there.
_other_bootstrap_tools+=usr.bin/bmake
# Avoid dependency on host bz2 headers:
_other_bootstrap_tools+=lib/libbz2
${_bt}-usr.bin/grep: ${_bt}-lib/libbz2
.else
# All tools in _basic_bootstrap_tools have the same name as the subdirectory
# so we can use :T to get the name of the symlinks that we need to create.
@ -2346,7 +2414,7 @@ bootstrap-tools: ${_bt}-links .PHONY
${_other_bootstrap_tools} \
usr.bin/xinstall \
${_gensnmptree} \
usr.sbin/config \
${_config} \
${_flua} \
${_crunchide} \
${_crunchgen} \
@ -2365,6 +2433,14 @@ ${_bt}-${_tool}: ${_bt}-links .PHONY .MAKE
bootstrap-tools: ${_bt}-${_tool}
.endfor
.if target(${_bt}-lib/libmd)
# If we are bootstrapping libmd (e.g. when building on macOS/Linux) add the
# necessary dependencies:
${_bt}-usr.bin/sort: ${_bt}-lib/libmd
${_bt}-usr.bin/xinstall: ${_bt}-lib/libmd
${_bt}-sbin/md5: ${_bt}-lib/libmd
.endif
#
# build-tools: Build special purpose build tools

View File

@ -395,7 +395,7 @@ kernel-install: .PHONY
exit 1 ; \
fi
.if exists(${DESTDIR}${KODIR})
-thiskernel=`sysctl -n kern.bootfile` ; \
-thiskernel=`sysctl -n kern.bootfile || echo /boot/kernel/kernel` ; \
if [ ! "`dirname "$$thiskernel"`" -ef ${DESTDIR}${KODIR} ] ; then \
chflags -R noschg ${DESTDIR}${KODIR} ; \
rm -rf ${DESTDIR}${KODIR} ; \

View File

@ -260,8 +260,8 @@ SYSINCS+= ${SRCTOP}/sys/sys/elf.h
# Linux/MacOS since we only use flags that are supported by all of them.
_host_tools_to_symlink= basename bzip2 bunzip2 chmod chown cmp comm cp date dd \
dirname echo env false find fmt gzip gunzip head hostname id ln ls \
mkdir mv nice patch rm realpath sh sleep stat tee touch tr true \
uname uniq wc which
mkdir mv nice patch rm sh sleep stat tee touch tr true uname uniq unxz \
wc which xz
# We also need a symlink to the absolute path to the make binary used for
# the toplevel makefile. This is not necessarily the same as `which make`
@ -285,9 +285,9 @@ _host_tools_to_symlink:=${_host_tools_to_symlink:Nsh}
host-symlinks:
@echo "Linking host tools into ${DESTDIR}/bin"
.for _tool in ${_host_tools_to_symlink}
@source_path=`which ${_tool}`; \
@export PATH=$${PATH}:/usr/local/bin; source_path=`which ${_tool}`; \
if [ ! -e "$${source_path}" ] ; then \
echo "Cannot find host tool '${_tool}'"; false; \
echo "Cannot find host tool '${_tool}' in PATH ($$PATH)." >&2; false; \
fi; \
rm -f "${DESTDIR}/bin/${_tool}"; \
cp -pf "$${source_path}" "${DESTDIR}/bin/${_tool}"
@ -330,7 +330,7 @@ installdirs:
.for _dir in sbin usr/sbin usr/bin
# delete existing directories from before r340157
@if [ ! -L ${DESTDIR}/${_dir} ]; then \
@if [ -e ${DESTDIR}/${_dir} ] && [ ! -L ${DESTDIR}/${_dir} ]; then \
echo "removing old non-symlink ${DESTDIR}/${_dir}"; \
rm -rf "${DESTDIR}/${_dir}"; \
fi

View File

@ -0,0 +1,27 @@
# $FreeBSD$
# Build a bootstrap version of m4 (needed in order to build libelf and lex)
.PATH: ${SRCTOP}/usr.bin/m4 ${.CURDIR}
# Avoid using lex or yacc to generate sources
LEX:=/this/should/not/be/used
tokenizer.c: bootstrap_m4_tokenizer
test -e ${.TARGET}
# This target is used as a marker in usr.bin/m4/Makefile to not add the
# lex and yacc includes. Therefore we must define it before including
# the other Makefile.
bootstrap_m4_tokenizer: inittokenizer.c
.for _f in tokenizer.c
@cmp -s ${.CURDIR}/init${_f} ${_f} || { \
echo "Bootstrapping ${_f}" ; \
${CP} ${.CURDIR}/init${_f} ${_f} ; \
}
.endfor
BINDIR= /usr/bin
.include "${SRCTOP}/usr.bin/m4/Makefile"
regen:
(cd ${SRCTOP}/usr.bin/m4 && lex -t ${SRCTOP}/usr.bin/m4/tokenizer.l) | grep -v '#line' > inittokenizer.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
# $FreeBSD$
NO_OBJ=
SCRIPTS= chflags
BINDIR= /usr/bin
.include <bsd.prog.mk>

View File

@ -0,0 +1,42 @@
#!/bin/sh -e
#
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
#
# This software was developed by SRI International and the University of
# Cambridge Computer Laboratory (Department of Computer Science and
# Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
# DARPA SSITH research programme.
#
# This software was developed by SRI International and the University of
# Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
# ("CTSRD"), as part of the DARPA CRASH research programme.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# chflags doesn't exist on Linux, just skip the calls for now
# TODO: we could also create a wrapper that calls `chattr +i` for `chflags schg`, etc
echo "WARNING: Ignoring chflags $@"
# TODO: exit 1

View File

@ -12,13 +12,21 @@ LIBADD= m openbsd
NO_WMISSING_VARIABLE_DECLARATIONS=
SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c parser.y tokenizer.l
SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c parser.y
.if target(bootstrap_m4_tokenizer)
# When crossbuilding on non-FreeBSD we need to first build m4 with pre-generated
# tokenizer files and the build the real m4 once we have lex+yacc.
SRCS+= tokenizer.c
.else
SRCS+= tokenizer.l
.endif
GENFILES= tokenizer.c parser.c parser.h
WARNS= 3
tokenizer.o: parser.h
CLEANFILES+= parser.c parser.h tokenizer.o
CLEANFILES+= parser.c parser.h tokenizer.o tokenizer.c
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests