diff --git a/share/mk/dirdeps.mk b/share/mk/dirdeps.mk index 83b620044aa5..aafa5ab47557 100644 --- a/share/mk/dirdeps.mk +++ b/share/mk/dirdeps.mk @@ -1,955 +1,959 @@ -# $Id: dirdeps.mk,v 1.158 2023/05/04 18:26:17 sjg Exp $ +# $Id: dirdeps.mk,v 1.160 2023/05/10 20:44:58 sjg Exp $ # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2010-2023, Simon J. Gerraty # Copyright (c) 2010-2018, Juniper Networks, Inc. # All rights reserved. # # 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 COPYRIGHT HOLDERS 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 COPYRIGHT # OWNER 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. # Much of the complexity here is for supporting cross-building. # If a tree does not support that, simply using plain Makefile.depend # should provide sufficient clue. # Otherwise the recommendation is to use Makefile.depend.${MACHINE} # as expected below. # Note: this file gets multiply included. # This is what we do with DIRDEPS # DIRDEPS: # This is a list of directories - relative to SRCTOP, it is # normally only of interest to .MAKE.LEVEL 0. # In some cases the entry may be qualified with a . # or . suffix (see TARGET_SPEC_VARS below), # for example to force building something for the pseudo # machines "host" or "common" regardless of current ${MACHINE}. # # All unqualified entries end up being qualified with .${TARGET_SPEC} # and partially qualified (if TARGET_SPEC_VARS has multiple # entries) are also expanded to a full .. # The _DIRDEP_USE target uses the suffix to set TARGET_SPEC # correctly when visiting each entry. # # The fully qualified directory entries are used to construct a # dependency graph that will drive the build later. # # Also, for each fully qualified directory target, we will search # using ${.MAKE.DEPENDFILE_PREFERENCE} to find additional # dependencies. We use Makefile.depend (default value for # .MAKE.DEPENDFILE_PREFIX) to refer to these makefiles to # distinguish them from others. # # Before each Makefile.depend file is read, we set # DEP_RELDIR to be the RELDIR (path relative to SRCTOP) for # its directory, and DEP_MACHINE etc according to the . # represented by the suffix of the corresponding target. # # Since each Makefile.depend file includes dirdeps.mk, this # processing is recursive and results in .MAKE.LEVEL 0 learning the # dependencies of the tree wrt the initial directory (_DEP_RELDIR). # # NOTE: given the extent of processing that DIRDEPS undergoes it # is important that any variables in entries use :U to guard # against surprises when undefined. # # TARGET_SPEC_VARS # The default value is just MACHINE, and for most environments # this is sufficient. The _DIRDEP_USE target actually sets # both MACHINE and TARGET_SPEC to the suffix of the current # target so that in the general case TARGET_SPEC can be ignored. # # If more than MACHINE is needed then sys.mk needs to decompose # TARGET_SPEC and set the relevant variables accordingly. # It is important that MACHINE be included in and actually be # the first member of TARGET_SPEC_VARS. This allows other # variables to be considered optional, and some of the treatment # below relies on MACHINE being the first entry. # Note: TARGET_SPEC cannot contain any '.'s so the target # triple used by compiler folk won't work (directly anyway). # # For example: # # # Always list MACHINE first, # # other variables might be optional. # TARGET_SPEC_VARS = MACHINE TARGET_OS # .if ${TARGET_SPEC:Uno:M*,*} != "" # _tspec := ${TARGET_SPEC:S/,/ /g} # MACHINE := ${_tspec:[1]} # TARGET_OS := ${_tspec:[2]} # # etc. # # We need to stop that TARGET_SPEC affecting any submakes # # and deal with MACHINE=${TARGET_SPEC} in the environment. # TARGET_SPEC = # # export but do not track # .export-env TARGET_SPEC # .export ${TARGET_SPEC_VARS} # .for v in ${TARGET_SPEC_VARS:O:u} # .if empty($v) # .undef $v # .endif # .endfor # .endif # # make sure we know what TARGET_SPEC is # # as we may need it to find Makefile.depend* # TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} # # The following variables can influence the initial DIRDEPS # computation with regard to the TARGET_SPECs that will be # built. # Most should also be considered by init.mk # # ONLY_TARGET_SPEC_LIST # Defines a list of TARGET_SPECs for which the current # directory can be built. # If ALL_MACHINES is defined, we build for all the # TARGET_SPECs listed. # # ONLY_MACHINE_LIST # As for ONLY_TARGET_SPEC_LIST but only specifies # MACHINEs. # # NOT_TARGET_SPEC_LIST # A list of TARGET_SPECs for which the current # directory should not be built. # # NOT_MACHINE_LIST # A list of MACHINEs the current directory should not be # built for. # # DIRDEPS_EXPORT_VARS (DEP_EXPORT_VARS) # It is discouraged, but sometimes necessary for a # Makefile.depend file to influence the environment. # Doing this is correctly (especially if using DIRDEPS_CACHE) is # tricky so a Makefile.depend file can set DIRDEPS_EXPORT_VARS # and dirdeps.mk will do the deed: # # MK_UEFI = yes # DIRDEPS_EXPORT_VARS = MK_UEFI # # _build_xtra_dirs # local.dirdeps.mk can add targets to this variable. # They will be hooked into the build, but independent of # any other DIRDEP. # # This allows for adding TESTS to the build, such that the build # if any test fails, but without the risk of introducing # circular dependencies. now_utc ?= ${%s:L:gmtime} .if !defined(start_utc) start_utc := ${now_utc} .endif .if !target(bootstrap) && (make(bootstrap) || \ make(bootstrap-this) || \ make(bootstrap-recurse) || \ make(bootstrap-empty)) # disable most of below .MAKE.LEVEL = 1 .endif # touch this at your peril _DIRDEP_USE_LEVEL?= 0 .if ${.MAKE.LEVEL} == ${_DIRDEP_USE_LEVEL} # only the first instance is interested in all this # the first time we are included the _DIRDEP_USE target will not be defined # we can use this as a clue to do initialization and other one time things. .if !target(_DIRDEP_USE) # do some setup we only need once _CURDIR ?= ${.CURDIR} _OBJDIR ?= ${.OBJDIR} .if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*[/.]*} != "" # This little trick let's us do # # mk -f dirdeps.mk some/dir.${TARGET_SPEC} # all: ${.TARGETS:Nall}: all DIRDEPS := ${.TARGETS:M*[/.]*} # so that -DNO_DIRDEPS works DEP_RELDIR := ${DIRDEPS:[1]:R} # this will become DEP_MACHINE below TARGET_MACHINE := ${DIRDEPS:[1]:E:C/,.*//} .if ${TARGET_MACHINE:N*/*} == "" TARGET_MACHINE := ${MACHINE} .endif # disable DIRDEPS_CACHE as it does not like this trick MK_DIRDEPS_CACHE = no # incase anyone needs to know _dirdeps_cmdline: .endif # make sure we get the behavior we expect .MAKE.SAVE_DOLLARS = no # make sure these are empty to start with _DEP_TARGET_SPEC = # If TARGET_SPEC_VARS is other than just MACHINE # it should be set by sys.mk or similar by now. # TARGET_SPEC must not contain any '.'s. TARGET_SPEC_VARS ?= MACHINE # this is what we started with TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} # this is what we mostly use below DEP_TARGET_SPEC = ${TARGET_SPEC_VARS:S,^,DEP_,:@v@${$v:U}@:ts,} # make sure we have defaults .for v in ${TARGET_SPEC_VARS} DEP_$v ?= ${$v} .endfor .if ${TARGET_SPEC_VARS:[#]} > 1 # Ok, this gets more complex (putting it mildly). # In order to stay sane, we need to ensure that all the build_dirs # we compute below are fully qualified wrt DEP_TARGET_SPEC. # The makefiles may only partially specify (eg. MACHINE only), # so we need to construct a set of modifiers to fill in the gaps. .if ${MAKE_VERSION} >= 20170130 _tspec_x := ${TARGET_SPEC_VARS:range} .else # do it the hard way _tspec_x := ${TARGET_SPEC_VARS:[#]:@x@i=1;while [ $$i -le $x ]; do echo $$i; i=$$((i + 1)); done;@:sh} .endif # this handles unqualified entries M_dep_qual_fixes = C;(/[^/.,]+)$$;\1.$${DEP_TARGET_SPEC}; # there needs to be at least one item missing for these to make sense .for i in ${_tspec_x:[2..-1]} _tspec_m$i := ${TARGET_SPEC_VARS:[2..$i]:@w@[^,]+@:ts,} _tspec_a$i := ,${TARGET_SPEC_VARS:[$i..-1]:@v@$$$${DEP_$v}@:ts,} M_dep_qual_fixes += C;(\.${_tspec_m$i})$$;\1${_tspec_a$i}; .endfor TARGET_SPEC_VARSr := ${TARGET_SPEC_VARS:[-1..1]} .else # A harmless? default. M_dep_qual_fixes = U .endif .if !defined(.MAKE.DEPENDFILE_PREFERENCE) # .MAKE.DEPENDFILE_PREFERENCE makes the logic below neater? # you really want this set by sys.mk or similar .MAKE.DEPENDFILE_PREFERENCE = ${_CURDIR}/${.MAKE.DEPENDFILE:T} .if ${.MAKE.DEPENDFILE:E} == "${TARGET_SPEC}" .if ${TARGET_SPEC} != ${MACHINE} .MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}.$${MACHINE} .endif .MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R} .endif .endif _default_dependfile := ${.MAKE.DEPENDFILE_PREFERENCE:[1]:T} _machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:T:M*${MACHINE}*} # for machine specific dependfiles we require ${MACHINE} to be at the end # also for the sake of sanity we require a common prefix .if !defined(.MAKE.DEPENDFILE_PREFIX) # knowing .MAKE.DEPENDFILE_PREFIX helps .if !empty(_machine_dependfiles) .MAKE.DEPENDFILE_PREFIX := ${_machine_dependfiles:[1]:T:R} .else .MAKE.DEPENDFILE_PREFIX := ${_default_dependfile:T} .endif .endif +# turn a list into a set of :N modifiers +# NskipFoo = ${Foo:${M_ListToSkip}} +M_ListToSkip ?= O:u:S,^,N,:ts: + # this is how we identify non-machine specific dependfiles N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N*${MACHINE}*:${M_ListToSkip}} # this gets reset for each dirdep we check DEP_RELDIR ?= ${RELDIR} # remember the initial value of DEP_RELDIR - we test for it below. _DEP_RELDIR := ${DEP_RELDIR} # this can cause lots of output! # set to a set of glob expressions that might match RELDIR DEBUG_DIRDEPS ?= no # make sure this target exists dirdeps: beforedirdeps .WAIT beforedirdeps: .endif # !target(_DIRDEP_USE) .if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@} != "" _debug_reldir = 1 .else _debug_reldir = 0 .endif .if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend depend:L:M$x}@} != "" _debug_search = 1 .else _debug_search = 0 .endif # First off, we want to know what ${MACHINE} to build for. # This can be complicated if we are using a mixture of ${MACHINE} specific # and non-specific Makefile.depend* # if we were included recursively _DEP_TARGET_SPEC should be valid. .if empty(_DEP_TARGET_SPEC) DEP_MACHINE = ${TARGET_MACHINE:U${MACHINE}} _DEP_TARGET_SPEC := ${DEP_TARGET_SPEC} .if ${.INCLUDEDFROMFILE:U:M${.MAKE.DEPENDFILE_PREFIX}*} != "" # record that we've read dependfile for this _dirdeps_checked.${_CURDIR}.${TARGET_SPEC}: .endif .endif # by now _DEP_TARGET_SPEC should be set, parse it. .if ${TARGET_SPEC_VARS:[#]} > 1 # we need to parse DEP_MACHINE may or may not contain more info _tspec := ${_DEP_TARGET_SPEC:S/,/ /g} .for i in ${_tspec_x} DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]} .endfor .for v in ${TARGET_SPEC_VARS:O:u} .if empty(DEP_$v) .undef DEP_$v .endif .endfor .else DEP_MACHINE := ${_DEP_TARGET_SPEC} .endif # host is special .if ${DEP_MACHINE:Mhost*} != "" DEP_TARGET_SPEC = ${DEP_MACHINE} .for v in ${TARGET_SPEC_VARS:O:u:NMACHINE} .undef DEP_$v .endfor .endif # reset each time through _build_all_dirs = _build_xtra_dirs = # DIRDEPS_CACHE can be very handy for debugging. # Also if repeatedly building the same target, # we can avoid the overhead of re-computing the tree dependencies. MK_DIRDEPS_CACHE ?= no BUILD_DIRDEPS_CACHE ?= no BUILD_DIRDEPS ?= yes .if ${MK_DIRDEPS_CACHE} == "yes" # this is where we will cache all our work DIRDEPS_CACHE ?= ${_OBJDIR:tA}/dirdeps.cache${_TARGETS:U${.TARGETS}:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.} .endif # sanity check: Makefile.depend.options should *not* include us .if ${.INCLUDEDFROMFILE:U:M${.MAKE.DEPENDFILE_PREFIX}.options} != "" .error ${DEP_RELDIR}/${.MAKE.DEPENDFILE_PREFIX}.options: should include dirdeps-options.mk .endif # pickup customizations # as below you can use !target(_DIRDEP_USE) to protect things # which should only be done once. .-include .if !target(_DIRDEP_USE) # things we skip for host tools SKIP_HOSTDIR ?= NSkipHostDir = ${SKIP_HOSTDIR:N*.host*:S,$,.host*,:N.host*:S,^,${SRCTOP}/,:${M_ListToSkip}} # things we always skip # SKIP_DIRDEPS allows for adding entries on command line. SKIP_DIR += .host *.WAIT ${SKIP_DIRDEPS} SKIP_DIR.host += ${SKIP_HOSTDIR} DEP_SKIP_DIR = ${SKIP_DIR} \ ${SKIP_DIR.${DEP_TARGET_SPEC}:U} \ ${TARGET_SPEC_VARS:@v@${SKIP_DIR.${DEP_$v}:U}@} \ ${SKIP_DIRDEPS.${DEP_TARGET_SPEC}:U} \ ${TARGET_SPEC_VARS:@v@${SKIP_DIRDEPS.${DEP_$v}:U}@} NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}} .if defined(NODIRDEPS) || defined(WITHOUT_DIRDEPS) NO_DIRDEPS = .elif defined(WITHOUT_DIRDEPS_BELOW) NO_DIRDEPS_BELOW = .endif .if defined(NO_DIRDEPS) # confine ourselves to the original dir and below. DIRDEPS_FILTER += M${_DEP_RELDIR}* .elif defined(NO_DIRDEPS_BELOW) DIRDEPS_FILTER += M${_DEP_RELDIR} .endif # this is what we run below DIRDEP_MAKE ?= ${.MAKE} DIRDEP_DIR ?= ${.TARGET:R} # if you want us to report load averages during build # DIRDEP_USE_PRELUDE += ${DIRDEP_LOADAVG_REPORT}; DIRDEP_LOADAVG_CMD ?= ${UPTIME:Uuptime} | sed 's,.*\(load\),\1,' DIRDEP_LOADAVG_LAST = 0 # yes the expression here is a bit complicated, # the trick is to only eval ${DIRDEP_LOADAVG_LAST::=${now_utc}} # when we want to report. # Note: expr(1) will exit 1 if the expression evaluates to 0 # hence the || true DIRDEP_LOADAVG_REPORT = \ test -z "${"${expr ${now_utc} - ${DIRDEP_LOADAVG_INTERVAL:U60} - ${DIRDEP_LOADAVG_LAST} || true:L:sh:N-*}":?yes${DIRDEP_LOADAVG_LAST::=${now_utc}}:}" || \ echo "${TRACER}`${DIRDEP_LOADAVG_CMD}`" # we suppress SUBDIR when visiting the leaves # we assume sys.mk will set MACHINE_ARCH # you can add extras to DIRDEP_USE_ENV # if there is no makefile in the target directory, we skip it. _DIRDEP_USE: .USE .MAKE @for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \ test -s ${.TARGET:R}/$$m || continue; \ echo "${TRACER}Checking ${.TARGET:S,^${SRCTOP}/,,} for ${.TARGET:E} ..."; \ ${DIRDEP_USE_PRELUDE} \ MACHINE_ARCH= NO_SUBDIR=1 ${DIRDEP_USE_ENV} \ TARGET_SPEC=${.TARGET:E} \ MACHINE=${.TARGET:E} \ ${DIRDEP_MAKE} -C ${DIRDEP_DIR} || exit 1; \ break; \ done .ifdef ALL_MACHINES .if empty(ONLY_TARGET_SPEC_LIST) && empty(ONLY_MACHINE_LIST) # we start with everything _machine_list != echo; 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX}* 2> /dev/null # some things we know we want to ignore DIRDEPS_TARGETS_SKIP_LIST += \ *~ \ *.bak \ *.inc \ *.old \ *.options \ *.orig \ *.rej \ # first trim things we know we want to skip # and provide canonical form _machine_list := ${_machine_list:${DIRDEPS_TARGETS_SKIP_LIST:${M_ListToSkip}}:T:E} # cater for local complexities # local.dirdeps.mk can set # DIRDEPS_ALL_MACHINES_FILTER and # DIRDEPS_ALL_MACHINES_FILTER_XTRAS for final tweaks .if !empty(ALL_TARGET_SPEC_LIST) .if ${_debug_reldir} .info ALL_TARGET_SPEC_LIST=${ALL_TARGET_SPEC_LIST} .endif DIRDEPS_ALL_MACHINES_FILTER += \ @x@$${ALL_TARGET_SPEC_LIST:@s@$${x:M$$s}@}@ .elif !empty(ALL_MACHINE_LIST) .if ${_debug_reldir} .info ALL_MACHINE_LIST=${ALL_MACHINE_LIST} .endif .if ${TARGET_SPEC_VARS:[#]} > 1 # the space below can result in extraneous ':' DIRDEPS_ALL_MACHINES_FILTER += \ @x@$${ALL_MACHINE_LIST:@m@$${x:M$$m,*} $${x:M$$m}@}@ .else DIRDEPS_ALL_MACHINES_FILTER += \ @x@$${ALL_MACHINE_LIST:@m@$${x:M$$m}@}@ .endif .endif # add local XTRAS - default to something benign DIRDEPS_ALL_MACHINES_FILTER += \ ${DIRDEPS_ALL_MACHINES_FILTER_XTRAS:UNbak} .if ${_debug_reldir} .info _machine_list=${_machine_list} .info DIRDEPS_ALL_MACHINES_FILTER=${DIRDEPS_ALL_MACHINES_FILTER} .endif _only_machines := ${_machine_list:${DIRDEPS_ALL_MACHINES_FILTER:ts:}:S,:, ,g} .else _only_machines := ${ONLY_TARGET_SPEC_LIST:U} ${ONLY_MACHINE_LIST:U} .endif .if empty(_only_machines) # we must be boot-strapping _only_machines := ${TARGET_MACHINE:U${ALL_TARGET_SPEC_LIST:U${ALL_MACHINE_LIST:U${DEP_MACHINE}}}} .endif # cleanup the result _only_machines := ${_only_machines:O:u} .if ${_debug_reldir} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: ALL_MACHINES _only_machines=${_only_machines} .endif .else # ! ALL_MACHINES # if ONLY_TARGET_SPEC_LIST or ONLY_MACHINE_LIST is set, we are limited to that. # Note that ONLY_TARGET_SPEC_LIST should be fully qualified. # if TARGET_MACHINE is set - it is really the same as ONLY_MACHINE_LIST # otherwise DEP_MACHINE is it - so DEP_MACHINE will match. _only_machines := ${ONLY_TARGET_SPEC_LIST:U:M${DEP_MACHINE},*} .if empty(_only_machines) _only_machines := ${ONLY_MACHINE_LIST:U${TARGET_MACHINE:U${DEP_MACHINE}}:M${DEP_MACHINE}} .endif .endif .if !empty(NOT_MACHINE_LIST) _only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}} .endif .if !empty(NOT_TARGET_SPEC_LIST) # we must first qualify _dm := ${DEP_MACHINE} _only_machines := ${_only_machines:M*,*} ${_only_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,} DEP_MACHINE := ${_dm} _only_machines := ${_only_machines:${NOT_TARGET_SPEC_LIST:${M_ListToSkip}}} .endif # clean up _only_machines := ${_only_machines:O:u} .if ${_debug_reldir} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _only_machines=${_only_machines} .endif # make sure we have a starting place? DIRDEPS ?= ${RELDIR} .endif # target .if !defined(NO_DIRDEPS) && !defined(NO_DIRDEPS_BELOW) .if ${MK_DIRDEPS_CACHE} == "yes" # just ensure this exists build-dirdeps: M_oneperline = @x@\\${.newline} $$x@ .if ${BUILD_DIRDEPS_CACHE} == "no" .if !target(dirdeps-cached) # we do this via sub-make BUILD_DIRDEPS = no # ignore anything but these .MAKE.META.IGNORE_FILTER = M*/${.MAKE.DEPENDFILE_PREFIX}* dirdeps: dirdeps-cached dirdeps-cached: ${DIRDEPS_CACHE} .MAKE @echo "${TRACER}Using ${DIRDEPS_CACHE}" @MAKELEVEL=${.MAKE.LEVEL} \ TARGET_SPEC=${TARGET_SPEC} \ ${TARGET_SPEC_VARS:@v@$v=${$v}@} \ ${.MAKE} -C ${_CURDIR} -f ${DIRDEPS_CACHE} \ dirdeps MK_DIRDEPS_CACHE=no BUILD_DIRDEPS=no # leaf makefiles rarely work for building DIRDEPS_CACHE .if ${RELDIR} != "." BUILD_DIRDEPS_MAKEFILE ?= -f dirdeps.mk .endif # these should generally do BUILD_DIRDEPS_MAKEFILE ?= BUILD_DIRDEPS_TARGETS ?= ${.TARGETS} .if ${DIRDEPS_CACHE} != ${STATIC_DIRDEPS_CACHE:Uno} && ${DIRDEPS_CACHE:M${SRCTOP}/*} == "" # export this for dirdeps-cache-update.mk DYNAMIC_DIRDEPS_CACHE := ${DIRDEPS_CACHE} .export DYNAMIC_DIRDEPS_CACHE # we need the .meta file to ensure we update if # any of the Makefile.depend* changed. # We do not want to compare the command line though. ${DIRDEPS_CACHE}: .META .NOMETA_CMP +@{ echo '# Autogenerated - do NOT edit!'; echo; \ echo 'BUILD_DIRDEPS=no'; echo; \ echo '.include '; echo; \ } > ${.TARGET}.new +@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \ DIRDEPS="${DIRDEPS}" \ TARGET_SPEC=${TARGET_SPEC} \ MAKEFLAGS= ${DIRDEP_CACHE_MAKE:U${.MAKE}} -C ${_CURDIR} \ ${BUILD_DIRDEPS_MAKEFILE} \ ${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \ .MAKE.DEPENDFILE=.none \ ${"${DEBUG_DIRDEPS:Nno}":?DEBUG_DIRDEPS='${DEBUG_DIRDEPS}':} \ ${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \ ${.MAKEFLAGS:tW:S,-d ,-d,g:tw:M-d*} \ 3>&1 1>&2 | sed 's,${SRCTOP},_{SRCTOP},g;s,_{SRCTOP}/_{SRCTOP},_{SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \ mv ${.TARGET}.new ${.TARGET} .endif .endif .elif !target(_count_dirdeps) # we want to capture the dirdeps count in the cache .END: _count_dirdeps _count_dirdeps: .NOMETA @{ echo; echo '.info $${.newline}$${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} ${DIRDEP_INFO_XTRAS}'; } >&3 .endif .elif !make(dirdeps) && !target(_count_dirdeps) beforedirdeps: _count_dirdeps _count_dirdeps: .NOMETA @echo "${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} ${DIRDEP_INFO_XTRAS} seconds=`expr ${now_utc} - ${start_utc}`" .endif .endif .if ${BUILD_DIRDEPS} == "yes" # the rest is done repeatedly for every Makefile.depend we read. # if we are anything but the original dir we care only about the # machine type we were included for.. .if ${DEP_RELDIR} == "." _this_dir := ${SRCTOP} .else _this_dir := ${SRCTOP}/${DEP_RELDIR} .endif # on rare occasions, there can be a need for extra help _dep_hack := ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX}.inc .-include <${_dep_hack}> .-include <${_dep_hack:R}.options> .if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_TARGET_SPEC} != ${TARGET_SPEC} # this should be all _machines := ${DEP_MACHINE} .else # this is the machine list we actually use below _machines := ${_only_machines} .if defined(HOSTPROG) || ${DEP_MACHINE:Nhost*} == "" # we need to build this guy's dependencies for host as well. .if ${DEP_MACHINE:Nhost*} == "" _machines += ${DEP_MACHINE} .else _machines += host .endif .endif _machines := ${_machines:O:u} .endif .if ${TARGET_SPEC_VARS:[#]} > 1 # we need to tweak _machines _dm := ${DEP_MACHINE} # apply the same filtering that we do when qualifying DIRDEPS. # M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.' # Again we expect that any already qualified machines are fully qualified. _machines := ${_machines:M*,*} ${_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:S,^.,,} DEP_MACHINE := ${_dm} _machines := ${_machines:${M_dep_qual_fixes:ts:}:O:u} .endif # reset each time through _build_dirs = -.if ${DEP_RELDIR} == ${_DEP_RELDIR} +.if ${DEP_RELDIR} == ${_DEP_RELDIR} && ${_CURDIR} != ${SRCTOP} # pickup other machines for this dir if necessary _build_dirs += ${_machines:@m@${_CURDIR}.$m@} .endif .if ${_debug_reldir} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: nDIRDEPS=${DIRDEPS:[#]} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}' .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}' .endif .if !empty(DIRDEPS) # these we reset each time through as they can depend on DEP_MACHINE DEP_DIRDEPS_FILTER = \ ${DIRDEPS_FILTER.${DEP_TARGET_SPEC}:U} \ ${TARGET_SPEC_VARS:@v@${DIRDEPS_FILTER.${DEP_$v}:U}@} \ ${DIRDEPS_FILTER:U} .if empty(DEP_DIRDEPS_FILTER) # something harmless DEP_DIRDEPS_FILTER = U .endif # this is what we start with __depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:O:u:@d@${SRCTOP}/$d@} # some entries may be qualified with . or . # we can tell the unqualified ones easily - because they exist __unqual_depdirs := ${__depdirs:@d@${exists($d):?$d:}@} __qual_depdirs := ${__depdirs:${__unqual_depdirs:Uno:${M_ListToSkip}}} .if ${DEP_RELDIR} == ${_DEP_RELDIR} # if it was called out - we likely need it. __hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host,:N.*:@d@${SRCTOP}/$d@} \ ${DPADD:U.:M${HOST_OBJTOP32:Uno}/*:S,${HOST_OBJTOP32:Uno}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host32,:N.*:@d@${SRCTOP}/$d@} __qual_depdirs += ${__hostdpadd} .endif .if ${_debug_reldir} .info DEP_DIRDEPS_FILTER=${DEP_DIRDEPS_FILTER:ts:} .info depdirs=${__depdirs:S,^${SRCTOP}/,,} .info qualified=${__qual_depdirs:S,^${SRCTOP}/,,} .info unqualified=${__unqual_depdirs:S,^${SRCTOP}/,,} .endif # _build_dirs is what we will feed to _DIRDEP_USE _build_dirs += \ ${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \ ${__qual_depdirs:N*.host} \ ${_machines:Mhost*:@m@${__unqual_depdirs:@d@$d.$m@}@:${NSkipHostDir}:N.host} \ ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@} # qualify everything now _build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u} .endif # empty DIRDEPS _build_all_dirs += ${_build_dirs} ${_build_xtra_dirs} _build_all_dirs := ${_build_all_dirs:O:u} # Normally if doing make -V something, # we do not want to waste time chasing DIRDEPS # but if we want to count the number of Makefile.depend* read, we do. .if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS:U}} == "" .if !empty(_build_all_dirs) .if ${BUILD_DIRDEPS_CACHE} == "yes" # we use _cache_script to minimize the number of times we fork the shell _cache_script = echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; # guard against _new_dirdeps being too big for a single command line _new_dirdeps := ${_build_all_dirs:@x@${target($x):?:$x}@:S,^${SRCTOP}/,,} _cache_xtra_deps := ${_build_xtra_dirs:S,^${SRCTOP}/,,} .export _cache_xtra_deps _new_dirdeps .if !empty(DIRDEPS_EXPORT_VARS) || !empty(DEP_EXPORT_VARS) # Discouraged, but there are always exceptions. # Handle it here rather than explain how. DIRDEPS_EXPORT_VARS ?= ${DEP_EXPORT_VARS} _cache_xvars := echo; ${DIRDEPS_EXPORT_VARS:@v@echo '$v = ${$v}';@} echo '.export ${DIRDEPS_EXPORT_VARS}'; echo; _cache_script += ${_cache_xvars} .endif .else # this makes it all happen dirdeps: ${_build_all_dirs} .endif ${_build_all_dirs}: _DIRDEP_USE .if ${_debug_reldir} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs:S,^${SRCTOP}/,,} .endif .if !empty(DIRDEPS_EXPORT_VARS) || !empty(DEP_EXPORT_VARS) .export ${DIRDEPS_EXPORT_VARS} ${DEP_EXPORT_VARS} DIRDEPS_EXPORT_VARS = DEP_EXPORT_VARS = .endif # this builds the dependency graph .for m in ${_machines} .if ${BUILD_DIRDEPS_CACHE} == "yes" && !empty(_build_dirs) _cache_deps = _cache_script += echo; echo 'DIRDEPS.${_this_dir}.$m = \'; .endif # it would be nice to do :N${.TARGET} .if !empty(__qual_depdirs) .for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m} .if ${_debug_reldir} || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != "" .info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q:S,^${SRCTOP}/,,} .endif .if ${BUILD_DIRDEPS_CACHE} == "yes" _cache_deps += ${_build_dirs:M*.$q:S,^${SRCTOP}/,,} .else ${_this_dir}.$m: ${_build_dirs:M*.$q} .endif .endfor .endif .if ${_debug_reldir} .info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m:S,^${SRCTOP}/,,} .endif .if ${BUILD_DIRDEPS_CACHE} == "yes" .if !empty(_build_dirs) _cache_deps += ${_build_dirs:M*.$m:N${_this_dir}.$m:S,^${SRCTOP}/,,} .if !empty(_cache_deps) .export _cache_deps _cache_script += for x in $$_cache_deps; do echo " _{SRCTOP}/$$x \\"; done; .endif # anything in _{build,env}_xtra_dirs is hooked to dirdeps: only x!= echo; { echo; ${_cache_script} echo; echo '${_this_dir}.$m: $${DIRDEPS.${_this_dir}.$m}'; \ echo; echo 'dirdeps: ${_this_dir}.$m \'; \ for x in $$_cache_xtra_deps; do echo " _{SRCTOP}/$$x \\"; done; \ echo; for x in $$_new_dirdeps; do echo "_{SRCTOP}/$$x: _DIRDEP_USE"; done; } >&3 .endif .else ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m} .endif .endfor .endif # Now find more dependencies - and recurse. .for d in ${_build_all_dirs} .if !target(_dirdeps_checked.$d) # once only _dirdeps_checked.$d: _dr := ${d:S,^${SRCTOP}/,,} .if ${_debug_search} .info checking ${_dr} .endif # Note: _build_all_dirs is fully qualifed so d:R is always the directory .if exists(${d:R}) # we pass _DEP_TARGET_SPEC to tell the next step what we want _DEP_TARGET_SPEC := ${d:E} # some makefiles may still look at this _DEP_MACHINE := ${d:E:C/,.*//} # set these too in case Makefile.depend* uses them .if ${TARGET_SPEC_VARS:[#]} > 1 _dtspec := ${_DEP_TARGET_SPEC:S/,/ /g} .for i in ${_tspec_x} DEP_${TARGET_SPEC_VARS:[$i]} := ${_dtspec:[$i]} .endfor .else DEP_MACHINE := ${_DEP_MACHINE} .endif # Warning: there is an assumption here that MACHINE is always # the first entry in TARGET_SPEC_VARS. # If TARGET_SPEC and MACHINE are insufficient, you have a problem. _m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:C;${MACHINE}((,.+)?)$;${d:E:C/,.*//}\1;:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]} .if !empty(_m) # M_dep_qual_fixes isn't geared to Makefile.depend _qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}} .if ${_debug_search} .info Looking for ${_qm} .endif # set this "just in case" # we can skip :tA since we computed the path above DEP_RELDIR := ${_m:H:S,^${SRCTOP}/,,} # and reset this DIRDEPS = .if ${_debug_reldir} && ${_qm} != ${_m} .info loading ${_m:S,${SRCTOP}/,,} for ${_dr} .endif .include <${_m}> .else # set these as if we found Makefile.depend* DEP_RELDIR := ${_dr:R} DIRDEPS = .if ${_debug_reldir} .info loading local.dirdeps-missing.mk for ${_dr} .endif .-include .endif .endif .endif .endfor .endif # -V .endif # BUILD_DIRDEPS .elif ${.MAKE.LEVEL} > 42 .error You should have stopped recursing by now. .else # we are building something DEP_RELDIR := ${RELDIR} _DEP_RELDIR := ${RELDIR} # Since we are/should be included by .MAKE.DEPENDFILE # This is a final opportunity to add/hook global rules. .-include # skip _reldir_{finish,failed} if not included from Makefile.depend* # or not in meta mode .if !defined(WITHOUT_META_STATS) && ${.INCLUDEDFROMFILE:U:M${.MAKE.DEPENDFILE_PREFIX}*} != "" && ${.MAKE.MODE:Mmeta} != "" meta_stats= meta=${empty(.MAKE.META.FILES):?0:${.MAKE.META.FILES:[#]}} \ created=${empty(.MAKE.META.CREATED):?0:${.MAKE.META.CREATED:[#]}} .if !target(_reldir_finish) .END: _reldir_finish _reldir_finish: .NOMETA @echo "${TRACER}Finished ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}" .endif .if !target(_reldir_failed) .ERROR: _reldir_failed _reldir_failed: .NOMETA @echo "${TRACER}Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}" .endif .endif # pickup local dependencies .if ${MAKE_VERSION} < 20160220 .-include <.depend> .else .dinclude <.depend> .endif .endif # bootstrapping new dependencies made easy? .if !target(bootstrap-empty) .if !target(bootstrap) && (make(bootstrap) || \ make(bootstrap-this) || \ make(bootstrap-recurse) || \ make(bootstrap-empty)) # if we are bootstrapping create the default _want = ${.CURDIR}/${.MAKE.DEPENDFILE_DEFAULT:T} .if exists(${_want}) # stop here ${.TARGETS:Mboot*}: .elif !make(bootstrap-empty) # find a Makefile.depend to use as _src _src != cd ${.CURDIR} && for m in ${.MAKE.DEPENDFILE_PREFERENCE:T:S,${MACHINE},*,}; do test -s $$m || continue; echo $$m; break; done; echo .if empty(_src) .error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T}${.newline}Use: bootstrap-empty .endif _src?= ${.MAKE.DEPENDFILE} .MAKE.DEPENDFILE_BOOTSTRAP_SED+= -e 's/${_src:E:C/,.*//}/${MACHINE}/g' # just create Makefile.depend* for this dir bootstrap-this: .NOTMAIN @echo Bootstrapping ${RELDIR}/${_want:T} from ${_src:T}; \ echo You need to build ${RELDIR} to correctly populate it. .if ${_src:T} != ${.MAKE.DEPENDFILE_PREFIX:T} (cd ${.CURDIR} && sed ${.MAKE.DEPENDFILE_BOOTSTRAP_SED} ${_src} > ${_want:T}) .else cp ${.CURDIR}/${_src:T} ${_want} .endif # create Makefile.depend* for this dir and its dependencies bootstrap: bootstrap-recurse bootstrap-recurse: bootstrap-this _mf := ${.PARSEFILE} bootstrap-recurse: .NOTMAIN .MAKE @cd ${SRCTOP} && \ for d in `cd ${RELDIR} && ${.MAKE} -B -f ${"${.MAKEFLAGS:M-n}":?${_src}:${.MAKE.DEPENDFILE:T}} -V DIRDEPS`; do \ test -d $$d || d=$${d%.*}; \ test -d $$d || continue; \ echo "Checking $$d for bootstrap ..."; \ (cd $$d && ${.MAKE} -f ${_mf} bootstrap-recurse); \ done .endif # create an empty Makefile.depend* to get the ball rolling. bootstrap-empty: .NOTMAIN .NOMETA @echo Creating empty ${RELDIR}/${_want:T}; \ echo You need to build ${RELDIR} to correctly populate it. @{ echo DIRDEPS=; echo ".include "; } > ${_want} .endif .endif diff --git a/share/mk/local.meta.sys.env.mk b/share/mk/local.meta.sys.env.mk index 6d0d493f1047..f109da4f39dd 100644 --- a/share/mk/local.meta.sys.env.mk +++ b/share/mk/local.meta.sys.env.mk @@ -1,102 +1,87 @@ # $FreeBSD$ # local configuration specific to meta mode # before we process TARGET_SPEC # we assume that MK_DIRDEPS_BUILD=yes -.if !defined(HOST_TARGET) || !defined(HOST_MACHINE) -# we need HOST_TARGET etc below. -.include -.export HOST_TARGET -.endif - # from src/Makefile (for universe) TARGET_ARCHES_arm?= arm armv6 armv7 TARGET_ARCHES_arm64?= aarch64 TARGET_ARCHES_powerpc?= powerpc powerpc64 powerpc64le powerpcspe TARGET_ARCHES_riscv?= riscv64 # some corner cases BOOT_MACHINE_DIR.amd64 = boot/i386 MACHINE_ARCH.host = ${_HOST_ARCH} # the list of machines we support ALL_MACHINE_LIST?= amd64 arm arm64 i386 powerpc riscv .-include .for m in ${ALL_MACHINE_LIST:O:u} MACHINE_ARCH_LIST.$m?= ${TARGET_ARCHES_${m}:U$m} MACHINE_ARCH.$m?= ${MACHINE_ARCH_LIST.$m:[1]} BOOT_MACHINE_DIR.$m ?= boot/$m .endfor .if empty(MACHINE_ARCH) .if !empty(TARGET_ARCH) MACHINE_ARCH= ${TARGET_ARCH} .else MACHINE_ARCH= ${MACHINE_ARCH.${MACHINE}} .endif .endif MACHINE_ARCH?= ${MACHINE_ARCH.${MACHINE}} MACHINE_ARCH:= ${MACHINE_ARCH} -# For universe we want to potentially -# build for multiple MACHINE_ARCH per MACHINE -# so we need more than MACHINE in TARGET_SPEC -TARGET_SPEC_VARS?= MACHINE MACHINE_ARCH - HOST_OBJTOP ?= ${OBJROOT}${HOST_TARGET} .if ${REQUESTED_MACHINE:U${MACHINE}} == "host" MACHINE= host .if ${TARGET_MACHINE:Uno} == ${HOST_TARGET} # not what we want TARGET_MACHINE= host .endif .endif .if ${MACHINE} == "host" OBJTOP := ${HOST_OBJTOP} MACHINE_ARCH= ${MACHINE_ARCH.${MACHINE}} .endif .if ${.MAKE.LEVEL} == 0 || empty(PYTHON) PYTHON ?= /usr/local/bin/python .export PYTHON # _SKIP_BUILD is not 100% as it requires wrapping all 'all:' targets to avoid # building in MAKELEVEL0. Just prohibit 'all' entirely in this case to avoid # problems. .if ${MK_DIRDEPS_BUILD} == "yes" && ${.MAKE.LEVEL} == 0 .MAIN: dirdeps .if make(all) .error DIRDEPS_BUILD: Please run '${MAKE}' instead of '${MAKE} all'. .endif .endif .endif -# this is sufficient for most of the tree. -.MAKE.DEPENDFILE_DEFAULT = ${.MAKE.DEPENDFILE_PREFIX} - -# but if we have a machine qualified file it should be used in preference -.MAKE.DEPENDFILE_PREFERENCE = \ - ${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \ - ${.MAKE.DEPENDFILE_PREFIX} - -.undef .MAKE.DEPENDFILE - -META_MODE+= missing-meta=yes +.if !defined(NO_META_MISSING) +META_MODE+= missing-meta=yes +.endif +# silent will hide command output if a .meta file is created. +.if !defined(NO_SILENT) +META_MODE+= silent=yes +.endif .if empty(META_MODE:Mnofilemon) META_MODE+= missing-filemon=yes .endif .if make(showconfig) # this does not need/want filemon UPDATE_DEPENDFILE= NO .endif .if ${MK_DIRDEPS_BUILD} == "yes" .if ${.MAKE.OS} != "FreeBSD" || ${_HOST_OSREL:R} < ${OS_REVISION:R} # a pseudo option to indicate we need libegacy for host MK_host_egacy= yes .endif .endif diff --git a/share/mk/local.sys.dirdeps.env.mk b/share/mk/local.sys.dirdeps.env.mk new file mode 100644 index 000000000000..ab22f4c9e7d9 --- /dev/null +++ b/share/mk/local.sys.dirdeps.env.mk @@ -0,0 +1,14 @@ + +# For universe we want to potentially +# build for multiple MACHINE_ARCH per MACHINE +# so we need more than MACHINE in TARGET_SPEC +TARGET_SPEC_VARS?= MACHINE MACHINE_ARCH + +# this is sufficient for most of the tree. +.MAKE.DEPENDFILE_DEFAULT = ${.MAKE.DEPENDFILE_PREFIX} + +# but if we have a machine qualified file it should be used in preference +.MAKE.DEPENDFILE_PREFERENCE = \ + ${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \ + ${.MAKE.DEPENDFILE_PREFIX} + diff --git a/share/mk/local.meta.sys.mk b/share/mk/local.sys.dirdeps.mk similarity index 85% rename from share/mk/local.meta.sys.mk rename to share/mk/local.sys.dirdeps.mk index 9d66e7295a0a..00030cb247bb 100644 --- a/share/mk/local.meta.sys.mk +++ b/share/mk/local.sys.dirdeps.mk @@ -1,189 +1,160 @@ # $FreeBSD$ # local configuration specific to meta mode # we assume that MK_DIRDEPS_BUILD=yes # we need this until there is an alternative MK_INSTALL_AS_USER= yes +.-include +# previously only included for DIRDEPS_BUILD anyway .-include -# to be consistent with src/Makefile just concatenate with '.'s -TARGET_OBJ_SPEC:= ${TARGET_SPEC:S;,;.;g} -.if ${MACHINE} != "host" -OBJTOP:= ${OBJROOT}${TARGET_OBJ_SPEC} -.endif - -.if defined(MAKEOBJDIR) -.if ${MAKEOBJDIR:M/*} == "" -.error Cannot use MAKEOBJDIR=${MAKEOBJDIR}${.newline}Unset MAKEOBJDIR to get default: MAKEOBJDIR='${_default_makeobjdir}' -.endif -.endif - - -# we want to end up with a singe stage tree for all machines .if ${MK_STAGING} == "yes" -.if empty(STAGE_ROOT) -STAGE_ROOT?= ${OBJROOT}stage -.export STAGE_ROOT -.endif -.endif -.if ${MK_STAGING} == "yes" -.if ${MACHINE} == "host" -STAGE_MACHINE= ${HOST_TARGET} -.else -STAGE_MACHINE:= ${TARGET_OBJ_SPEC} -.endif -STAGE_OBJTOP:= ${STAGE_ROOT}/${STAGE_MACHINE} -STAGE_COMMON_OBJTOP:= ${STAGE_ROOT}/common STAGE_TARGET_OBJTOP:= ${STAGE_ROOT}/${TARGET_OBJ_SPEC} -STAGE_HOST_OBJTOP:= ${STAGE_ROOT}/${HOST_TARGET} # These are exported for hooking in out-of-tree builds. They will always # be overridden in sub-makes above when building in-tree. .if ${.MAKE.LEVEL} > 0 .export STAGE_OBJTOP STAGE_TARGET_OBJTOP STAGE_HOST_OBJTOP .endif # Use tools/install.sh which can avoid the need for xinstall for simple cases. INSTALL?= sh ${SRCTOP}/tools/install.sh # This is for stage-install to pickup from the environment. REAL_INSTALL:= ${INSTALL} .export REAL_INSTALL STAGE_INSTALL= sh ${.PARSEDIR:tA}/stage-install.sh OBJDIR=${.OBJDIR:tA} STAGE_LIBDIR= ${STAGE_OBJTOP}${_LIBDIR:U${LIBDIR:U/lib}} STAGE_INCLUDEDIR= ${STAGE_OBJTOP}${INCLUDEDIR:U/usr/include} # this is not the same as INCLUDEDIR STAGE_INCSDIR= ${STAGE_OBJTOP}${INCSDIR:U/include} # the target is usually an absolute path STAGE_SYMLINKS_DIR= ${STAGE_OBJTOP} #LDFLAGS_LAST+= -Wl,-rpath-link,${STAGE_LIBDIR} .if ${MK_SYSROOT} == "yes" SYSROOT?= ${STAGE_OBJTOP} .else LDFLAGS_LAST+= -L${STAGE_LIBDIR} .endif .endif # MK_STAGING .-include "local.toolchain.mk" .if ${.MAKE.LEVEL} > 0 && ${MACHINE} == "host" && ${.MAKE.DEPENDFILE:E} != "host" # we can use this but should not update it. UPDATE_DEPENDFILE?= NO .endif # define the list of places that contain files we are responsible for .MAKE.META.BAILIWICK = ${SB} ${OBJROOT} ${STAGE_ROOT} CSU_DIR.${MACHINE_ARCH} ?= csu/${MACHINE_ARCH} CSU_DIR := ${CSU_DIR.${MACHINE_ARCH}} .if !empty(TIME_STAMP) TRACER= ${TIME_STAMP} ${:U} .endif .if !defined(_RECURSING_PROGS) && !defined(_RECURSING_CRUNCH) && \ !make(print-dir) WITH_META_STATS= t .endif # toolchains can be a pain - especially bootstrappping them .if ${MACHINE} == "host" MK_SHARED_TOOLCHAIN= no .endif TOOLCHAIN_VARS= AS AR CC CLANG_TBLGEN CXX CPP LD NM OBJCOPY RANLIB \ STRINGS SIZE LLVM_TBLGEN _toolchain_bin_CLANG_TBLGEN= /usr/bin/clang-tblgen _toolchain_bin_LLVM_TBLGEN= /usr/bin/llvm-tblgen _toolchain_bin_CXX= /usr/bin/c++ .ifdef WITH_TOOLSDIR TOOLSDIR?= ${HOST_OBJTOP}/tools .elif defined(STAGE_HOST_OBJTOP) TOOLSDIR?= ${STAGE_HOST_OBJTOP} .endif .if ${MK_DIRDEPS_BUILD} == "yes" && ${MACHINE} != "host" # ideally tools needed by makefiles like sh,csh,tinfo # would be built in their own directories but for now # this works well enough. BTOOLSPATH= ${HOST_OBJTOP}/${RELDIR} .else # Only define if it exists in case user didn't run bootstrap-tools. Otherwise # the tool will be built during the build. Building it assumes it is # TARGET==MACHINE. .if exists(${HOST_OBJTOP}/tools${.CURDIR}) BTOOLSPATH= ${HOST_OBJTOP}/tools${.CURDIR} .endif .endif # Don't use the bootstrap tools logic on itself. .if ${.TARGETS:Mbootstrap-tools} == "" && \ !make(test-system-*) && !make(showconfig) && !make(print-dir) && \ !defined(BOOTSTRAPPING_TOOLS) && !empty(TOOLSDIR) && ${.MAKE.LEVEL} == 0 .for dir in /sbin /bin /usr/sbin /usr/bin PATH:= ${TOOLSDIR}${dir}:${PATH} .endfor .export PATH # Prefer the TOOLSDIR version of the toolchain if present vs the host version. .for var in ${TOOLCHAIN_VARS} _toolchain_bin.${var}= ${TOOLSDIR}${_toolchain_bin_${var}:U/usr/bin/${var:tl}} .if exists(${_toolchain_bin.${var}}) HOST_${var}?= ${_toolchain_bin.${var}} .export HOST_${var} .endif .endfor .endif .for var in ${TOOLCHAIN_VARS} HOST_${var}?= ${_toolchain_bin_${var}:U/usr/bin/${var:tl}} .endfor .if ${MACHINE} == "host" .for var in ${TOOLCHAIN_VARS} ${var}= ${HOST_${var}} .endfor .endif .if ${MACHINE:Nhost:Ncommon} != "" && ${MACHINE} != ${HOST_MACHINE} # cross-building .if !defined(FREEBSD_REVISION) FREEBSD_REVISION!= sed -n '/^REVISION=/{s,.*=,,;s,",,g;p; }' ${SRCTOP}/sys/conf/newvers.sh .export FREEBSD_REVISION .endif CROSS_TARGET_FLAGS= -target ${MACHINE_ARCH}-unknown-freebsd${FREEBSD_REVISION} CFLAGS+= ${CROSS_TARGET_FLAGS} ACFLAGS+= ${CROSS_TARGET_FLAGS} .endif -.if ${MK_DIRDEPS_BUILD} == "yes" # we set these here, rather than local.gendirdeps.mk # so we can ensure any DEP_* values that might be used in # conditionals do not cause syntax errors when Makefile.depend # is included at level 1+ # order of this list matters! GENDIRDEPS_FILTER_DIR_VARS+= \ CSU_DIR \ BOOT_MACHINE_DIR # order of this list matters! GENDIRDEPS_FILTER_VARS+= \ KERNEL_NAME \ DEP_MACHINE_CPUARCH \ DEP_MACHINE_ARCH \ DEP_MACHINE .if ${.MAKE.LEVEL} > 0 .for V in ${GENDIRDEPS_FILTER_DIR_VARS:MDEP_*:O:u} \ ${GENDIRDEPS_FILTER_VARS:MDEP_*:O:u} $V?= ${${V:S,DEP_,,}} .endfor .endif .if ${MACHINE} == "host" && ${.MAKE.OS} != "FreeBSD" # some makefiles expect this BOOTSTRAPPING= 0 .endif - -.endif diff --git a/share/mk/local.sys.env.mk b/share/mk/local.sys.env.mk index e3348537db41..e10bf58e14e8 100644 --- a/share/mk/local.sys.env.mk +++ b/share/mk/local.sys.env.mk @@ -1,52 +1,58 @@ # $FreeBSD$ # This makefile is for customizations that should be done early .if !defined(_TARGETS) # some things we do only once _TARGETS:= ${.TARGETS} .export _TARGETS .endif # some handy macros _this = ${.PARSEDIR:tA}/${.PARSEFILE} # some useful modifiers # A useful trick for testing multiple :M's against something # :L says to use the variable's name as its value - ie. literal # got = ${clean* destroy:${M_ListToMatch:S,V,.TARGETS,}} M_ListToMatch = L:@m@$${V:M$$m}@ # match against our initial targets (see above) M_L_TARGETS = ${M_ListToMatch:S,V,_TARGETS,} # turn a list into a set of :N modifiers # NskipFoo = ${Foo:${M_ListToSkip}} M_ListToSkip= O:u:ts::S,:,:N,g:S,^,N, # type should be a builtin in any sh since about 1980, # AUTOCONF := ${autoconf:L:${M_whence}} M_type = @x@(type $$x 2> /dev/null); echo;@:sh:[0]:N* found*:[@]:C,[()],,g M_whence = ${M_type}:M/*:[1] # convert a path to a valid shell variable M_P2V = tu:C,[./-],_,g # these are handy # we can use this for a cheap timestamp at the start of a target's script, # but not at the end - since make will expand both at the same time. TIME_STAMP_FMT = @ %s [%Y-%m-%d %T] TIME_STAMP = ${TIME_STAMP_FMT:localtime} # this will produce the same output but as of when date(1) is run. TIME_STAMP_DATE = `date '+${TIME_STAMP_FMT}'` TIME_STAMP_END?= ${TIME_STAMP_DATE} # Simplify auto.obj.mk mkdir -p handling and avoid unneeded/redundant # error spam and show a proper error. Mkdirs= Mkdirs() { mkdir -p $$* || :; } .if !empty(.MAKEFLAGS:M-s) ECHO_TRACE?= true .endif .include "src.sys.env.mk" .-include + +.if !defined(HOST_TARGET) || !defined(HOST_MACHINE) +# we need HOST_TARGET etc below. +.include +.export HOST_TARGET +.endif diff --git a/share/mk/meta.sys.mk b/share/mk/meta.sys.mk index f580f4962be8..ba213dd49da4 100644 --- a/share/mk/meta.sys.mk +++ b/share/mk/meta.sys.mk @@ -1,227 +1,153 @@ -# $Id: meta.sys.mk,v 1.48 2023/05/04 16:41:10 sjg Exp $ +# $Id: meta.sys.mk,v 1.51 2023/05/11 20:05:32 sjg Exp $ # -# @(#) Copyright (c) 2010-2021, Simon J. Gerraty +# @(#) Copyright (c) 2010-2023, Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. # Permission to copy, redistribute or otherwise # use this file is hereby granted provided that # the above copyright notice and this notice are # left intact. # # Please send copies of changes and bug-fixes to: # sjg@crufty.net # # include this if you want to enable meta mode # for maximum benefit, requires filemon(4) driver. -.if ${MAKE_VERSION:U0} > 20100901 -.if !target(.ERROR) +# absolute path to what we are reading. +_PARSEDIR ?= ${.PARSEDIR:tA} .-include -# If TARGET_SPEC_VARS is other than just MACHINE -# it should be set by now. -# TARGET_SPEC must not contain any '.'s. -TARGET_SPEC_VARS ?= MACHINE - -.if !target(_meta_tspec_env_done_) -_meta_tspec_env_done_: .NOTMAIN -# Allow for local.meta.sys.env.mk to have done this - -.if ${TARGET_SPEC:Uno:M*,*} != "" -# deal with TARGET_SPEC from env -_tspec := ${TARGET_SPEC:S/,/ /g} -.for i in ${TARGET_SPEC_VARS:${M_RANGE:Urange}} -${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]} -.endfor -# We need to stop that TARGET_SPEC affecting any submakes -TARGET_SPEC= -# so export but do not track -.export-env TARGET_SPEC -.export ${TARGET_SPEC_VARS} -.for v in ${TARGET_SPEC_VARS:O:u} -.if empty($v) -.undef $v -.endif -.endfor -.endif -.endif - -# Now make sure we know what TARGET_SPEC is -# as we may need it to find Makefile.depend* -.if ${MACHINE:Mhost*} != "" -# host is special -TARGET_SPEC = ${MACHINE} -.else -TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} -.endif - -# absolute path to what we are reading. -_PARSEDIR = ${.PARSEDIR:tA} - .if !defined(SYS_MK_DIR) SYS_MK_DIR := ${_PARSEDIR} .endif -META_MODE += meta verbose +.if !target(.ERROR) + +META_MODE += meta +.if empty(.MAKEFLAGS:M-s) +META_MODE += verbose +.endif .if ${MAKE_VERSION:U0} > 20130323 && empty(.MAKE.PATH_FILEMON) # we do not support filemon META_MODE += nofilemon MKDEP_MK ?= auto.dep.mk .endif .MAKE.MODE ?= ${META_MODE} _filemon := ${.MAKE.PATH_FILEMON:U/dev/filemon} .if empty(UPDATE_DEPENDFILE) _make_mode := ${.MAKE.MODE} ${META_MODE} .if ${_make_mode:M*read*} != "" || ${_make_mode:M*nofilemon*} != "" # tell everyone we are not updating Makefile.depend* UPDATE_DEPENDFILE = NO .export UPDATE_DEPENDFILE .endif .if ${_filemon:T:Mfilemon} == "filemon" .if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(${_filemon}) # we should not get upset META_MODE += nofilemon .export META_MODE .endif .endif .endif .if !defined(NO_SILENT) .if ${MAKE_VERSION} > 20110818 # only be silent when we have a .meta file META_MODE += silent=yes .else .SILENT: .endif .endif -# we use the pseudo machine "host" for the build host. -# this should be taken care of before we get here -.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub} -MACHINE = host -.endif - -.if !defined(MACHINE0) -# it can be handy to know which MACHINE kicked off the build -# for example, if using Makefild.depend for multiple machines, -# allowing only MACHINE0 to update can keep things simple. -MACHINE0 := ${MACHINE} -.export MACHINE0 -.endif +.if ${MK_DIRDEPS_BUILD:Uno} == "yes" .if !defined(META2DEPS) .if defined(PYTHON) && exists(${PYTHON}) # we prefer the python version of this - it is much faster META2DEPS ?= ${.PARSEDIR}/meta2deps.py .else META2DEPS ?= ${.PARSEDIR}/meta2deps.sh .endif META2DEPS := ${META2DEPS} .export META2DEPS .endif MAKE_PRINT_VAR_ON_ERROR += \ .ERROR_TARGET \ .ERROR_META_FILE \ .MAKE.LEVEL \ MAKEFILE \ .MAKE.MODE +MK_META_ERROR_TARGET = yes +.endif + +.if ${MK_META_ERROR_TARGET:Uno} == "yes" + .if !defined(SB) && defined(SRCTOP) SB = ${SRCTOP:H} .endif ERROR_LOGDIR ?= ${SB}/error meta_error_log = ${ERROR_LOGDIR}/meta-${.MAKE.PID}.log # we are not interested in make telling us a failure happened elsewhere .ERROR: _metaError _metaError: .NOMETA .NOTMAIN -@[ "${.ERROR_META_FILE}" ] && { \ grep -q 'failure has been detected in another branch' ${.ERROR_META_FILE} && exit 0; \ mkdir -p ${meta_error_log:H}; \ cp ${.ERROR_META_FILE} ${meta_error_log}; \ echo "ERROR: log ${meta_error_log}" >&2; }; : .endif +.endif # Are we, after all, in meta mode? .if ${.MAKE.MODE:Uno:Mmeta*} != "" MKDEP_MK ?= meta.autodep.mk -.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == "" -# this does all the smarts of setting .MAKE.DEPENDFILE -.-include -# check if we got anything sane -.if ${.MAKE.DEPENDFILE} == ".depend" -.undef .MAKE.DEPENDFILE -.endif -.MAKE.DEPENDFILE ?= Makefile.depend -.endif - # we can afford to use cookies to prevent some targets # re-running needlessly META_COOKIE_TOUCH?= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}} META_NOPHONY= META_NOECHO= : # some targets involve old pre-built targets # ignore mtime of shell # and mtime of makefiles does not matter in meta mode .MAKE.META.IGNORE_PATHS += \ ${MAKEFILE} \ ${MAKE_SHELL} \ ${SHELL} \ ${SYS_MK_DIR} \ .if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" .if ${.MAKEFLAGS:Uno:M-k} != "" # make this more obvious .warning Setting UPDATE_DEPENDFILE=NO due to -k UPDATE_DEPENDFILE= NO .export UPDATE_DEPENDFILE .elif ${_filemon:T} == "filemon" && !exists(${_filemon}) .error ${.newline}ERROR: The filemon module (${_filemon}) is not loaded. .endif .endif -.if ${.MAKE.LEVEL} == 0 -.if ${MK_DIRDEPS_BUILD:Uyes} == "yes" -# make sure dirdeps target exists and do it first -all: dirdeps .WAIT -dirdeps: -.NOPATH: dirdeps - -.if defined(ALL_MACHINES) -# the first .MAIN: is what counts -# by default dirdeps is all we want at level0 -.MAIN: dirdeps -.endif -.endif +.else # in meta mode? -.else # level > 0 - -# Makefile.depend* get read at level 1+ -# and often refer to DEP_MACHINE etc, -# so ensure DEP_* (for TARGET_SPEC_VARS anyway) are set -.for V in ${TARGET_SPEC_VARS} -DEP_$V = ${$V} -.endfor - -.endif -.else META_COOKIE_TOUCH= # some targets need to be .PHONY in non-meta mode META_NOPHONY= .PHONY META_NOECHO= echo -.endif -.endif + +.endif # in meta mode? .-include diff --git a/share/mk/src.sys.obj.mk b/share/mk/src.sys.obj.mk index 3b48fc3c5514..3d2cf7043c96 100644 --- a/share/mk/src.sys.obj.mk +++ b/share/mk/src.sys.obj.mk @@ -1,230 +1,225 @@ # $FreeBSD$ # # Early setup of MAKEOBJDIR # # Default format is: /usr/obj/usr/src/[${TARGET}.${TARGET_ARCH}/]bin/sh # MAKEOBJDIRPREFIX is /usr/obj # OBJROOT is /usr/obj/usr/src/ # OBJTOP is /usr/obj/usr/src/[${TARGET}.${TARGET_ARCH}/] # MAKEOBJDIR is /usr/obj/usr/src/[${TARGET}.${TARGET_ARCH}/]bin/sh # # MAKEOBJDIRPREFIX will override the default pattern above and internally # set MAKEOBJDIR. If OBJROOT is set then MAKEOBJDIRPREFIX is rooted inside # of there. # # If MK_UNIFIED_OBJDIR is no then OBJROOT will always match OBJTOP. # # If .MAKE.LEVEL == 0 then the TARGET.TARGET_ARCH is potentially added on. # If .MAKE.LEVEL > 0 and MAKEOBJDIRPREFIX is set then it will not get # TARGET.TARGET_ARCH added in as it assumes that MAKEOBJDIRPREFIX is # nested in the existing OBJTOP with TARGET.TARGET_ARCH in it. # # The expected OBJDIR is stored in __objdir for auto.obj.mk to use. # # AUTO_OBJ is opportunistically enabled if the computed .OBJDIR is writable # by the current user. Some top-level targets disable this behavior in # Makefile.sys.inc. # _default_makeobjdirprefix?= /usr/obj _default_makeobjdir= $${.CURDIR:S,^$${SRCTOP},$${OBJTOP},} .include .if ${.MAKE.LEVEL} == 0 || empty(OBJROOT) .if ${MK_UNIFIED_OBJDIR} == "no" && ${MK_DIRDEPS_BUILD} == "no" # Fall back to historical behavior. # We always want to set a default MAKEOBJDIRPREFIX... MAKEOBJDIRPREFIX?= ${_default_makeobjdirprefix} # but don't enforce TARGET.TARGET_ARCH unless we're at the top-level directory. .if ${.CURDIR} == ${SRCTOP} && \ !(defined(TARGET) && defined(TARGET_ARCH) && \ ${MACHINE} == ${TARGET} && ${MACHINE_ARCH} == ${TARGET_ARCH} && \ !defined(CROSS_BUILD_TESTING)) MAKEOBJDIRPREFIX:= ${MAKEOBJDIRPREFIX}${TARGET:D/${TARGET}.${TARGET_ARCH}} .endif .endif # ${MK_UNIFIED_OBJDIR} == "no" .if !empty(MAKEOBJDIRPREFIX) # put things approximately where they want OBJROOT:= ${MAKEOBJDIRPREFIX}${SRCTOP}/ MAKEOBJDIRPREFIX= # export but do not track .export-env MAKEOBJDIRPREFIX .endif .if empty(MAKEOBJDIR) # OBJTOP set below MAKEOBJDIR= ${_default_makeobjdir} # export but do not track .export-env MAKEOBJDIR # Expand for our own use MAKEOBJDIR:= ${MAKEOBJDIR} .endif # SB documented at http://www.crufty.net/sjg/docs/sb-tools.htm .if !empty(SB) SB_OBJROOT?= ${SB}/obj/ # this is what we use below OBJROOT?= ${SB_OBJROOT} .endif OBJROOT?= ${_default_makeobjdirprefix}${SRCTOP}/ .if ${OBJROOT:M*/} != "" OBJROOT:= ${OBJROOT:H:tA}/ .else OBJROOT:= ${OBJROOT:H:tA}/${OBJROOT:T} .endif # Must export since OBJDIR will dynamically be based on it .export OBJROOT SRCTOP .endif .if ${MK_DIRDEPS_BUILD} == "no" .if empty(OBJTOP) # SRCTOP == OBJROOT only happens with clever MAKEOBJDIRPREFIX=/. Don't # append TARGET.TARGET_ARCH for that case since the user wants to build # in the source tree. .if ${MK_UNIFIED_OBJDIR} == "yes" && ${SRCTOP} != ${OBJROOT:tA} .if defined(TARGET) && defined(TARGET_ARCH) OBJTOP:= ${OBJROOT}${TARGET}.${TARGET_ARCH} .elif defined(TARGET) && ${.CURDIR} == ${SRCTOP} # Not enough information, just use basic OBJDIR. This can happen with some # 'make universe' targets or if TARGET is not being used as expected. OBJTOP:= ${OBJROOT:H} .else OBJTOP:= ${OBJROOT}${MACHINE}.${MACHINE_ARCH} .endif .else # TARGET.TARGET_ARCH handled in OBJROOT already. OBJTOP:= ${OBJROOT:H} .endif # ${MK_UNIFIED_OBJDIR} == "yes" .endif # empty(OBJTOP) # Fixup OBJROOT/OBJTOP if using MAKEOBJDIRPREFIX. # This intenionally comes after adding TARGET.TARGET_ARCH so that is truncated # away for nested objdirs. This logic also will not trigger if the OBJROOT # block above unsets MAKEOBJDIRPREFIX. .if !empty(MAKEOBJDIRPREFIX) OBJTOP:= ${MAKEOBJDIRPREFIX}${SRCTOP} OBJROOT:= ${OBJTOP}/ .endif # Wait to validate MAKEOBJDIR until OBJTOP is set. .if defined(MAKEOBJDIR) .if ${MAKEOBJDIR:M/*} == "" .error Cannot use MAKEOBJDIR=${MAKEOBJDIR}${.newline}Unset MAKEOBJDIR to get default: MAKEOBJDIR='${_default_makeobjdir}' .endif .endif # __objdir is the expected .OBJDIR we want to use and that auto.obj.mk will # try to create. .if !empty(MAKEOBJDIRPREFIX) .if ${.CURDIR:M${MAKEOBJDIRPREFIX}/*} != "" # we are already in obj tree! __objdir= ${.CURDIR} .else __objdir:= ${MAKEOBJDIRPREFIX}${.CURDIR} .endif .elif !empty(MAKEOBJDIR) __objdir:= ${MAKEOBJDIR} .endif # Try to enable MK_AUTO_OBJ by default if we can write to the __objdir. Only # do this if AUTO_OBJ is not disabled by the user, and this is the first make # ran. .if ${.MAKE.LEVEL} == 0 && \ ${MK_AUTO_OBJ} == "no" && empty(.MAKEOVERRIDES:MMK_AUTO_OBJ) && \ !defined(WITHOUT_AUTO_OBJ) && !make(showconfig) && !make(print-dir) && \ !make(test-system-*) && \ !defined(NO_OBJ) && \ empty(RELDIR:Msys/*/compile/*) # Find the last existing directory component and check if we can write to it. # If the last component is a symlink then recurse on the new path. CheckAutoObj= \ DirIsCreatable() { \ if [ -w "$${1}" ]; then \ [ -d "$${1}" ] || return 1; \ return 0; \ fi; \ d="$${1}"; \ IFS=/; \ set -- $${d}; \ unset dir; \ while [ $$\# -gt 0 ]; do \ d="$${1}"; \ shift; \ if [ ! -d "$${dir}$${d}/" ]; then \ if [ -L "$${dir}$${d}" ]; then \ dir="$$(readlink "$${dir}$${d}")/"; \ for d in "$${@}"; do \ dir="$${dir}$${d}/"; \ done; \ ret=0; \ DirIsCreatable "$${dir%/}" || ret=$$?; \ return $${ret}; \ elif [ -e "/$${dir}$${d}" ]; then \ return 1; \ else \ break; \ fi; \ fi; \ dir="$${dir}$${d}/"; \ done; \ [ -w "$${dir}" ] && [ -d "$${dir}" ] && return 0; \ return 1; \ }; \ CheckAutoObj() { \ if DirIsCreatable "$${1}"; then \ echo yes; \ else \ echo no; \ fi; \ } .if !empty(__objdir) .if ${.CURDIR} == ${__objdir} || \ (exists(${__objdir}) && ${.TARGETS:M*install*} == ${.TARGETS}) __objdir_writable?= yes .elif empty(__objdir_writable) __objdir_writable!= \ ${CheckAutoObj}; CheckAutoObj "${__objdir}" || echo no .endif .endif __objdir_writable?= no # Export the decision to sub-makes. MK_AUTO_OBJ:= ${__objdir_writable} .export MK_AUTO_OBJ .elif make(showconfig) # Need to export for showconfig internally running make -dg1. It is enabled # in sys.mk by default. .export MK_AUTO_OBJ .endif # ${MK_AUTO_OBJ} == "no" && ... # Assign this directory as .OBJDIR if possible. # # The expected OBJDIR already exists, set it as .OBJDIR. .if !empty(__objdir) && exists(${__objdir}) .OBJDIR: ${__objdir} .else # The OBJDIR we wanted does not yet exist, ensure we default to safe .CURDIR # in case make started with a bogus MAKEOBJDIR, that expanded before OBJTOP # was set, that happened to match some unexpected directory. Either # auto.obj.mk or bsd.obj.mk will create the directory and fix .OBJDIR later. .OBJDIR: ${.CURDIR} .endif # Ensure .OBJDIR=.CURDIR cases have a proper OBJTOP and .OBJDIR .if defined(NO_OBJ) || ${__objdir_writable:Uunknown} == "no" || \ ${__objdir} == ${.CURDIR} OBJTOP= ${SRCTOP} OBJROOT= ${SRCTOP}/ # Compare only to avoid an unneeded chdir(2), :tA purposely left out. .if ${.OBJDIR} != ${.CURDIR} .OBJDIR: ${.CURDIR} .endif .endif # defined(NO_OBJ) -.if !defined(HOST_TARGET) -# we need HOST_TARGET etc below. -.include -.export HOST_TARGET -.endif HOST_OBJTOP?= ${OBJROOT}${HOST_TARGET} .endif # ${MK_DIRDEPS_BUILD} == "no" diff --git a/share/mk/sys.dependfile.mk b/share/mk/sys.dependfile.mk index 745873f6bfeb..49232646d569 100644 --- a/share/mk/sys.dependfile.mk +++ b/share/mk/sys.dependfile.mk @@ -1,60 +1,64 @@ -# $FreeBSD$ -# $Id: sys.dependfile.mk,v 1.7 2016/02/20 01:57:39 sjg Exp $ +# $Id: sys.dependfile.mk,v 1.10 2023/05/10 19:23:26 sjg Exp $ # -# @(#) Copyright (c) 2012, Simon J. Gerraty +# @(#) Copyright (c) 2012-2023, Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. # Permission to copy, redistribute or otherwise -# use this file is hereby granted provided that +# use this file is hereby granted provided that # the above copyright notice and this notice are -# left intact. -# +# left intact. +# # Please send copies of changes and bug-fixes to: # sjg@crufty.net # -# This only makes sense in meta mode. +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: .NOTMAIN + +# This only makes sense for DIRDEPS_BUILD. # This allows a mixture of auto generated as well as manually edited # dependency files, which can be differentiated by their names. # As per dirdeps.mk we only require: # 1. a common prefix # 2. that machine specific files end in .${MACHINE} # # The .MAKE.DEPENDFILE_PREFERENCE below is an example. # All depend file names should start with this .MAKE.DEPENDFILE_PREFIX ?= Makefile.depend .if !empty(.MAKE.DEPENDFILE) && \ ${.MAKE.DEPENDFILE:M${.MAKE.DEPENDFILE_PREFIX}*} == "" # let us do our thing below... .undef .MAKE.DEPENDFILE .endif # The order of preference: we will use the first one of these we find. # It usually makes sense to order from most specific to least. .MAKE.DEPENDFILE_PREFERENCE ?= \ ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \ ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX} # Normally the 1st entry is our default choice # Another useful default is ${.MAKE.DEPENDFILE_PREFIX} .MAKE.DEPENDFILE_DEFAULT ?= ${.MAKE.DEPENDFILE_PREFERENCE:[1]} _e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@} .if !empty(_e) .MAKE.DEPENDFILE := ${_e:[1]} .elif ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}} != "" && ${.MAKE.DEPENDFILE_DEFAULT:E} != ${MACHINE} # MACHINE specific depend files are supported, but *not* default. # If any already exist, we should follow suit. _aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE} # make sure we restore MACHINE _m := ${MACHINE} _e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@} MACHINE := ${_m} .if !empty(_e) .MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]} .endif .endif .MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT} + +.endif diff --git a/share/mk/sys.dirdeps.mk b/share/mk/sys.dirdeps.mk new file mode 100644 index 000000000000..845eda181b90 --- /dev/null +++ b/share/mk/sys.dirdeps.mk @@ -0,0 +1,183 @@ +# $Id: sys.dirdeps.mk,v 1.9 2023/05/11 20:05:42 sjg Exp $ +# +# @(#) Copyright (c) 2012-2023, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# Originally DIRDEPS_BUILD and META_MODE were the same thing. +# So, much of this was done in *meta.sys.mk and local*mk +# but properly belongs here. + +# Include from [local.]sys.mk - if doing DIRDEPS_BUILD +# we should not be here otherwise +MK_DIRDEPS_BUILD ?= yes +# these are all implied +MK_AUTO_OBJ ?= yes +MK_META_MODE ?= yes +MK_STAGING ?= yes + +_PARSEDIR ?= ${.PARSEDIR:tA} + +.-include + +.if ${.MAKE.LEVEL} == 0 +# make sure dirdeps target exists and do it first +dirdeps: +# first .MAIN is what counts +.MAIN: dirdeps +.NOPATH: dirdeps +all: dirdeps .WAIT +.endif + +.if empty(SRCTOP) +# fallback assumes share/mk! +SRCTOP := ${SB_SRC:U${.PARSEDIR:tA:H:H}} +.export SRCTOP +.endif + +# fake SB if not using mk wrapper +.if !defined(SB) +SB := ${SRCTOP:H} +.export SB +.endif + +.if empty(OBJROOT) +OBJROOT := ${SB_OBJROOT:U${MAKEOBJDIRPREFIX:U${SB}/obj}/} +.export OBJROOT +.endif + +.if empty(STAGE_ROOT) +STAGE_ROOT ?= ${OBJROOT}stage +.export STAGE_ROOT +.endif + +# We should be included before meta.sys.mk +# If TARGET_SPEC_VARS is other than just MACHINE +# it should be set by now. +# TARGET_SPEC must not contain any '.'s. +TARGET_SPEC_VARS ?= MACHINE + +.if !target(_tspec_env_done_) +_tspec_env_done_: .NOTMAIN + +.if ${TARGET_SPEC:Uno:M*,*} != "" +# deal with TARGET_SPEC from env +_tspec := ${TARGET_SPEC:S/,/ /g} +.for i in ${TARGET_SPEC_VARS:${M_RANGE:Urange}} +${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]} +.endfor +# We need to stop that TARGET_SPEC affecting any submakes +TARGET_SPEC= +# so export but do not track +.export-env TARGET_SPEC +.export ${TARGET_SPEC_VARS} +.for v in ${TARGET_SPEC_VARS:O:u} +.if empty($v) +.undef $v +.endif +.endfor +.endif +.endif + +# Now make sure we know what TARGET_SPEC is +# as we may need it to find Makefile.depend* +.if ${MACHINE:Mhost*} != "" +# host is special +TARGET_SPEC = ${MACHINE} +.else +TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} +.endif + +.if ${TARGET_SPEC_VARS:[#]} > 1 +TARGET_OBJ_SPEC ?= ${TARGET_SPEC_VARS:@v@${$v:U}@:ts.} +.else +TARGET_OBJ_SPEC ?= ${MACHINE} +.endif + +MAKE_PRINT_VAR_ON_ERROR += ${TARGET_SPEC_VARS} + +.if !defined(MACHINE0) +# it can be handy to know which MACHINE kicked off the build +# for example, if using Makefild.depend for multiple machines, +# allowing only MACHINE0 to update can keep things simple. +MACHINE0 := ${MACHINE} +.export MACHINE0 +.endif + +.if ${MACHINE} == "host" +OBJTOP = ${HOST_OBJTOP} +.elif ${MACHINE} == "host32" +OBJTOP = ${HOST_OBJTOP32} +.endif + +MACHINE_OBJ.host = ${HOST_TARGET} +MACHINE_OBJ.host32 = ${HOST_TARGET32} +MACHINE_OBJ.${MACHINE} ?= ${TARGET_OBJ_SPEC} +MACHINE_OBJDIR = ${MACHINE_OBJ.${MACHINE}} +OBJTOP = ${OBJROOT}/${MACHINE_OBJDIR} + +# we do not use MAKEOBJDIRPREFIX +.undef MAKEOBJDIRPREFIX +# we use this +MAKEOBJDIR ?= ${.CURDIR:S,${SRCTOP},${OBJTOP},} + +STAGE_MACHINE ?= ${MACHINE_OBJDIR} +STAGE_OBJTOP ?= ${STAGE_ROOT}/${STAGE_MACHINE} +STAGE_COMMON_OBJTOP ?= ${STAGE_ROOT}/common +STAGE_HOST_OBJTOP ?= ${STAGE_ROOT}/${HOST_TARGET} +STAGE_HOST_OBJTOP32 ?= ${STAGE_ROOT}/${HOST_TARGET32} + +STAGE_INCLUDEDIR ?= ${STAGE_OBJTOP}${INCLUDEDIR:U/usr/include} +STAGE_LIBDIR ?= ${STAGE_OBJTOP}${LIBDIR:U/lib} + +TIME_STAMP_FMT ?= @ %s [%Y-%m-%d %T] ${:U} +DATE_TIME_STAMP ?= `date '+${TIME_STAMP_FMT}'` +TIME_STAMP ?= ${TIME_STAMP_FMT:localtime} + +.if ${MK_TIME_STAMPS:Uyes} == "yes" +TRACER = ${TIME_STAMP} +ECHO_DIR = echo ${TIME_STAMP} +ECHO_TRACE = echo ${TIME_STAMP} +.endif + +.if ${.CURDIR} == ${SRCTOP} +RELDIR= . +RELTOP= . +.elif ${.CURDIR:M${SRCTOP}/*} +RELDIR:= ${.CURDIR:S,${SRCTOP}/,,} +.else +RELDIR:= ${.OBJDIR:S,${OBJTOP}/,,} +.endif +RELTOP?= ${RELDIR:C,[^/]+,..,g} +RELOBJTOP?= ${RELTOP} +RELSRCTOP?= ${RELTOP} + +# this does all the smarts of setting .MAKE.DEPENDFILE +.-include + +.-include + +# check if we got anything sane +.if ${.MAKE.DEPENDFILE} == ".depend" +.undef .MAKE.DEPENDFILE +.endif +# just in case +.MAKE.DEPENDFILE ?= Makefile.depend + +.if ${.MAKE.LEVEL} > 0 +# Makefile.depend* also get read at level 1+ +# and often refer to DEP_MACHINE etc, +# so ensure DEP_* (for TARGET_SPEC_VARS anyway) are set +.for V in ${TARGET_SPEC_VARS} +DEP_$V = ${$V} +.endfor +.endif diff --git a/share/mk/sys.mk b/share/mk/sys.mk index 1ab0022ddc21..d585444a485f 100644 --- a/share/mk/sys.mk +++ b/share/mk/sys.mk @@ -1,347 +1,334 @@ # from: @(#)sys.mk 8.2 (Berkeley) 3/21/94 # $FreeBSD$ unix ?= We run FreeBSD, not UNIX. .FreeBSD ?= true .if !defined(%POSIX) # # MACHINE_CPUARCH defines a collection of MACHINE_ARCH. Machines with # the same MACHINE_ARCH can run each other's binaries, so it necessarily # has word size and endian swizzled in. However, the source files for # these machines often are shared amongst all combinations of size # and/or endian. This is called MACHINE_CPU in NetBSD, but that's used # for something different in FreeBSD. # __TO_CPUARCH=C/arm(v[67])?/arm/:C/powerpc(64|64le|spe)/powerpc/:C/riscv64/riscv/ MACHINE_CPUARCH=${MACHINE_ARCH:${__TO_CPUARCH}} .endif __DEFAULT_YES_OPTIONS+= \ UNIFIED_OBJDIR # src.sys.obj.mk enables AUTO_OBJ by default if possible but it is otherwise # disabled. Ensure src.conf.5 shows it as default on. .if make(showconfig) __DEFAULT_YES_OPTIONS+= AUTO_OBJ .endif # Some options we need now __DEFAULT_NO_OPTIONS= \ DIRDEPS_BUILD \ DIRDEPS_CACHE __DEFAULT_DEPENDENT_OPTIONS= \ AUTO_OBJ/DIRDEPS_BUILD \ + META_ERROR_TARGET/DIRDEPS_BUILD \ META_MODE/DIRDEPS_BUILD \ STAGING/DIRDEPS_BUILD \ SYSROOT/DIRDEPS_BUILD __ENV_ONLY_OPTIONS:= \ ${__DEFAULT_NO_OPTIONS} \ ${__DEFAULT_YES_OPTIONS} \ ${__DEFAULT_DEPENDENT_OPTIONS:H} # early include for customization # see local.sys.mk below # Not included when building in fmake compatibility mode (still needed # for older system support) .if defined(.PARSEDIR) .sinclude .include # Disable MK_META_MODE with make -B .if ${MK_META_MODE} == "yes" && defined(.MAKEFLAGS) && ${.MAKEFLAGS:M-B} MK_META_MODE= no .endif .if ${MK_DIRDEPS_BUILD} == "yes" -.sinclude -.elif ${MK_META_MODE} == "yes" -META_MODE+= meta -.if empty(.MAKEFLAGS:M-s) -# verbose will show .MAKE.META.PREFIX for each target. -META_MODE+= verbose -.endif -.if !defined(NO_META_MISSING) -META_MODE+= missing-meta=yes -.endif -# silent will hide command output if a .meta file is created. -.if !defined(NO_SILENT) -META_MODE+= silent=yes +.-include .endif +.if ${MK_META_MODE} == "yes" .if !exists(/dev/filemon) || defined(NO_FILEMON) META_MODE+= nofilemon .endif -# Require filemon data with bmake -.if empty(META_MODE:Mnofilemon) -META_MODE+= missing-filemon=yes -.endif +.-include .endif META_MODE?= normal .export META_MODE .MAKE.MODE?= ${META_MODE} .if !empty(.MAKE.MODE:Mmeta) .if !defined(NO_META_IGNORE_HOST) # Ignore host file changes that will otherwise cause # buildworld -> installworld -> buildworld to rebuild everything. # Since the build is self-reliant and bootstraps everything it needs, # this should not be a real problem for incremental builds. # XXX: This relies on the existing host tools retaining ABI compatibility # through upgrades since they won't be rebuilt on header/library changes. # This is mitigated by Makefile.inc1 for known-ABI-breaking revisions. # Note that these are prefix matching, so /lib matches /libexec. .MAKE.META.IGNORE_PATHS+= \ ${__MAKE_SHELL} \ /bin \ /lib \ /rescue \ /sbin \ /usr/bin \ /usr/lib \ /usr/sbin \ /usr/share \ .else NO_META_IGNORE_HOST_HEADERS= 1 .endif .if !defined(NO_META_IGNORE_HOST_HEADERS) .MAKE.META.IGNORE_PATHS+= /usr/include .endif # We do not want everything out-of-date just because # some unrelated shared lib updated this. .MAKE.META.IGNORE_PATHS+= /usr/local/etc/libmap.d .endif # !empty(.MAKE.MODE:Mmeta) .if ${MK_AUTO_OBJ} == "yes" # This needs to be done early - before .PATH is computed # Don't do this for 'make showconfig' as it enables all options where meta mode # is not expected. .if !make(showconfig) && !make(print-dir) && !make(test-system-*) && \ empty(.MAKEFLAGS:M-[nN]) .sinclude .endif .endif # ${MK_AUTO_OBJ} == "yes" .else # bmake .include .endif # If the special target .POSIX appears (without prerequisites or # commands) before the first noncomment line in the makefile, make shall # process the makefile as specified by the Posix 1003.2 specification. # make(1) sets the special macro %POSIX in this case (to the actual # value "1003.2", for what it's worth). # # The rules below use this macro to distinguish between Posix-compliant # and default behaviour. # # This functionality is currently broken, since make(1) processes sys.mk # before reading any other files, and consequently has no opportunity to # set the %POSIX macro before we read this point. .if defined(%POSIX) .SUFFIXES: .o .c .y .l .a .sh .f .else .SUFFIXES: .out .a .o .bco .llo .c .cc .cpp .cxx .C .m .F .f .e .r .y .l .S .asm .s .cl .p .h .sh .endif AR ?= ar .if defined(%POSIX) ARFLAGS ?= -rv .else ARFLAGS ?= -crsD .endif RANLIB ?= ranlib .if !defined(%POSIX) RANLIBFLAGS ?= -D .endif AS ?= as AFLAGS ?= ACFLAGS ?= .if defined(%POSIX) CC ?= c89 CFLAGS ?= -O .else CC ?= cc CFLAGS ?= -O2 -pipe .if defined(NO_STRICT_ALIASING) CFLAGS += -fno-strict-aliasing .endif .endif IR_CFLAGS ?= ${STATIC_CFLAGS:N-O*} ${CFLAGS:N-O*} PO_CFLAGS ?= ${CFLAGS} # cp(1) is used to copy source files to ${.OBJDIR}, make sure it can handle # read-only files as non-root by passing -f. CP ?= cp -f CPP ?= cpp # C Type Format data is required for DTrace CTFFLAGS ?= -L VERSION CTFCONVERT ?= ctfconvert CTFMERGE ?= ctfmerge .if defined(CFLAGS) && (${CFLAGS:M-g} != "") CTFFLAGS += -g .endif CXX ?= c++ CXXFLAGS ?= ${CFLAGS:N-std=*:N-Wnested-externs:N-W*-prototypes:N-Wno-pointer-sign:N-Wold-style-definition} IR_CXXFLAGS ?= ${STATIC_CXXFLAGS:N-O*} ${CXXFLAGS:N-O*} PO_CXXFLAGS ?= ${CXXFLAGS} DTRACE ?= dtrace DTRACEFLAGS ?= -C -x nolibs .if empty(.MAKEFLAGS:M-s) ECHO ?= echo ECHODIR ?= echo .else ECHO ?= true .if ${.MAKEFLAGS:M-s} == "-s" ECHODIR ?= echo .else ECHODIR ?= true .endif .endif ELFCTL ?= elfctl .if ${.MAKEFLAGS:M-N} # bmake -N is supposed to skip executing anything but it does not skip # exeucting '+' commands. The '+' feature is used where .MAKE # is not safe for the entire target. -N is intended to skip building sub-makes # so it executing '+' commands is not right. Work around the bug by not # setting '+' when -N is used. _+_ ?= .else _+_ ?= + .endif .if defined(%POSIX) FC ?= fort77 FFLAGS ?= -O 1 .else FC ?= f77 FFLAGS ?= -O .endif EFLAGS ?= INSTALL ?= ${INSTALL_CMD:Uinstall} LEX ?= lex LFLAGS ?= # LDFLAGS is for CC, _LDFLAGS is for LD. Generate _LDFLAGS from # LDFLAGS by stripping -Wl, from pass-through arguments and dropping # compiler driver flags (e.g. -mabi=*) that conflict with flags to LD. LD ?= ld LDFLAGS ?= _LDFLAGS = ${LDFLAGS:S/-Wl,//g:N-mabi=*:N-fuse-ld=*:N--ld-path=*:N-fsanitize=*:N-fno-sanitize=*} MAKE ?= make .if !defined(%POSIX) LLVM_LINK ?= llvm-link LORDER ?= lorder NM ?= nm NMFLAGS ?= OBJC ?= cc OBJCFLAGS ?= ${OBJCINCLUDES} ${CFLAGS} -Wno-import OBJCOPY ?= objcopy PC ?= pc PFLAGS ?= RC ?= f77 RFLAGS ?= TSORT ?= tsort TSORTFLAGS ?= -q .endif SHELL ?= sh .if !defined(%POSIX) SIZE ?= size STRIPBIN ?= strip .endif YACC ?= yacc .if defined(%POSIX) YFLAGS ?= .else YFLAGS ?= -d .endif .if defined(%POSIX) .include "bsd.suffixes-posix.mk" .else # non-Posix rule set .include "bsd.suffixes.mk" # Pull in global settings. __MAKE_CONF?=/etc/make.conf .if exists(${__MAKE_CONF}) .include "${__MAKE_CONF}" .endif # late include for customization .sinclude .if defined(META_MODE) META_MODE:= ${META_MODE:O:u} .endif .if defined(__MAKE_SHELL) && !empty(__MAKE_SHELL) SHELL= ${__MAKE_SHELL} .SHELL: path=${__MAKE_SHELL} .endif # Tell bmake to expand -V VAR by default .MAKE.EXPAND_VARIABLES= yes # Tell bmake the makefile preference MAKEFILE_PREFERENCE?= BSDmakefile makefile Makefile .MAKE.MAKEFILE_PREFERENCE= ${MAKEFILE_PREFERENCE} # Tell bmake to always pass job tokens, regardless of target depending on # .MAKE or looking like ${MAKE}/${.MAKE}/$(MAKE)/$(.MAKE)/make. .MAKE.ALWAYS_PASS_JOB_QUEUE= yes # By default bmake does *not* use set -e # when running target scripts, this is a problem for many makefiles here. # So define a shell that will do what FreeBSD expects. .ifndef WITHOUT_SHELL_ERRCTL __MAKE_SHELL?=/bin/sh .SHELL: name=sh \ quiet="set -" echo="set -v" filter="set -" \ hasErrCtl=yes check="set -e" ignore="set +e" \ echoFlag=v errFlag=e \ path=${__MAKE_SHELL} .endif # Hack for ports compatibility. Historically, ports makefiles have # assumed they can examine MACHINE_CPU without including anything # because this was automatically included in sys.mk. For /usr/src, # this file has moved to being included from bsd.opts.mk. Until all # the ports files are modernized, and a reasonable transition # period has passed, include it while we're in a ports tree here # to preserve historic behavior. .if exists(${.CURDIR}/../../Mk/bsd.port.mk) .include .endif .endif # ! Posix