From d8a07172f06f033be8880afc74d2ef3bf44e171f Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Wed, 28 Jun 2023 23:05:02 +0000
Subject: [PATCH 1/5] WIP: mk: Preliminary support for cross-OS compilation.

How it works:

1. Several variables are designated as CROSSVARS, currently:

        LOWER_OPSYS
        LOWER_OPSYS_VERSUFFIX
        LOWER_OS_VARIANT
        LOWER_VARIANT_VERSION
        LOWER_VENDOR
        MACHINE_ARCH
        OPSYS
        OPSYS_VERSION
        OS_VERSION

2. New variables like NATIVE_OPSYS, NATIVE_OS_VERSION, &c., reflect
   the system the build is running on, autodiscovered through uname
   and similar.

3. mk.conf must set CROSS_OPSYS, CROSS_MACHINE_ARCH, &c. -- all of
   the CROSSVARS.  For just cross-architecture compilation to the
   same OS version, you can set, e.g., CROSS_OPSYS=${NATIVE_OPSYS}
   for now.  It must also set USE_CROSS_COMPILE?=yes in order to
   trigger any cross-compilation logic, as before.

XXX TODO:

- Create boolean CROSS_ARCH to determine whether CROSS_MACHINE_ARCH
  overrides MACHINE_ARCH when cross-compiling.  If not set,
  CROSS_MACHINE_ARCH need not be set in mk.conf.

- Create boolean CROSS_OS to determine whether CROSS_OPSYS,
  CROSS_OS_VERSION, &c., override the unqualified ones when
  cross-compiling.  If not set, CROSS_OPSYS, CROSS_OS_VERSION, &c.,
  need not be set in mk.conf.

- Make USE_CROSS_COMPILE purely internal; replace it by CROSS_ARCH
  and CROSS_OS.

- Maybe make some of the more obscure CROSS_* variables optional like
  CROSS_LOWER_OPSYS_VERSUFFIX, or their optional/required nature
  depend on on what CROSS_OPSYS is set to.

- Extend TARGET_ARCH to other variables.
---
 doc/HOWTO-use-crosscompile |  33 ++--
 mk/bsd.prefs.mk            | 324 +++++++++++++++++++++----------------
 mk/tools/defaults.mk       |   9 +-
 3 files changed, 207 insertions(+), 159 deletions(-)

diff --git a/doc/HOWTO-use-crosscompile b/doc/HOWTO-use-crosscompile
index c95eec33b2d4..72c8cfe1318e 100644
--- a/doc/HOWTO-use-crosscompile
+++ b/doc/HOWTO-use-crosscompile
@@ -37,29 +37,27 @@ In addition to whatever else you want in your mk.conf for pkgsrc, add:
    # Cross-compile by default.
    #
    # XXX This currently can't be set to `yes' on the command line,
-   # which is a bug.
+   # which is a bug.  But it can be set to `no' to build native
+   # packages.
    USE_CROSS_COMPILE?=  yes
 
    # Point pkgsrc at the NetBSD tooldir and destdir.  These are used
    # only for cross-builds.
-   #
-   # XXX There is no obvious variable that is set to amd64 so that we
-   # could use
-   #
-   #    TOOLDIR=        /usr/obj/tooldir.${OPSYS}-${OS_VERSION}-${NATIVE_xyz}
-   #
-   # MACHINE is amd64 but, since it's not NATIVE_xyz, it's wrong.
-   # NATIVE_MACHINE_ARCH is x86_64, not amd64.
    TOOLDIR=             /usr/obj/tooldir.NetBSD-6.1-amd64
    CROSS_DESTDIR=       /usr/obj/destdir.evbppc
 
    # Specify the machine architecture of target packages.
-   #
-   # XXX This currently can't be set on the command line, which is a
-   # bug.
-   .if !empty(USE_CROSS_COMPILE:M[yY][eE][sS])
-   MACHINE_ARCH=        powerpc
-   .endif
+   CROSS_MACHINE_ARCH=  powerpc
+
+   # Specify the OS of target packages.
+   CROSS_OPSYS=		NetBSD
+   CROSS_OS_VERSION=	10.0
+   CROSS_OPSYS_VERSION=	100000
+   CROSS_LOWER_OPSYS=   netbsd
+   CROSS_LOWER_OPSYS_VERSUFFIX= # empty
+   CROSS_LOWER_OS_VARIANT=      # empty
+   CROSS_LOWER_VARIANT_VERSION= # empty
+   CROSS_LOWER_VENDOR=          # empty
 
 Optionally, you can set CROSS_LOCALBASE for cross-compiled packages
 separately from LOCALBASE for natively compiled packages.  For example,
@@ -69,6 +67,9 @@ will create packages which install to /opt/pkg:
    LOCALBASE=		/home/user/cross/pkg
    CROSS_LOCALBASE=	/opt/pkg
 
+By default, CROSS_LOCALBASE will be /usr/pkg, meaning packages that are
+being cross-compiled will see LOCALBASE=/usr/pkg.
+
 ** Bootstrapped pkgsrc
 
 You can bootstrap pkgsrc or not; it shouldn't make a difference for
@@ -83,7 +84,7 @@ cross-compilation.  If you do:
    be left empty or undefined for earmv7hf cross-builds.  So you might
    need:
 
-      .if empty(USE_CROSS_COMPILE:M[yY][eE][sS])
+      .if ${USE_CROSS_COMPILE:tl} != "yes"
       ABI=    64 # set for native amd64 build
       .else
       ABI=    # empty for earmv7hf cross-build
diff --git a/mk/bsd.prefs.mk b/mk/bsd.prefs.mk
index b3afb87288db..ae20829f7c01 100644
--- a/mk/bsd.prefs.mk
+++ b/mk/bsd.prefs.mk
@@ -87,23 +87,23 @@ UNAME=/run/current-system/sw/bin/uname
 UNAME=echo Unknown
 .endif
 
-.if !defined(OPSYS)
-OPSYS:=			${:!${UNAME} -s!:S/-//g:S/\///g:C/^CYGWIN_.*$/Cygwin/}
-MAKEFLAGS+=		OPSYS=${OPSYS:Q}
+.if !defined(NATIVE_OPSYS)
+NATIVE_OPSYS:=		${:!${UNAME} -s!:S/-//g:S/\///g:C/^CYGWIN_.*$/Cygwin/}
+MAKEFLAGS+=		NATIVE_OPSYS=${NATIVE_OPSYS:Q}
 .endif
 
 # OS_VARIANT is used to differentiate operating systems which have a common
 # basis but offer contrasting environments, for example Linux distributions
 # or illumos forks.
-OS_VARIANT?=		# empty
+NATIVE_OS_VARIANT?=	# empty
 
 # The _CMD indirection allows code below to modify these values
 # without executing the commands at all.  Later, recursed make
 # invocations will skip these blocks entirely thanks to MAKEFLAGS.
-.if !defined(OS_VERSION)
-_OS_VERSION_CMD=	${UNAME} -r
-OS_VERSION=		${_OS_VERSION_CMD:sh}
-MAKEFLAGS+=		OS_VERSION=${OS_VERSION:Q}
+.if !defined(NATIVE_OS_VERSION)
+_NATIVE_OS_VERSION_CMD=	${UNAME} -r
+NATIVE_OS_VERSION=	${_NATIVE_OS_VERSION_CMD:sh}
+MAKEFLAGS+=		NATIVE_OS_VERSION=${NATIVE_OS_VERSION:Q}
 .endif
 
 #
@@ -112,11 +112,11 @@ MAKEFLAGS+=		OS_VERSION=${OS_VERSION:Q}
 # default command is likely correct for most OS, those that need to can set
 # it to a custom command in the later OPSYS-specific section.
 #
-.if !defined(OPSYS_VERSION)
-_OPSYS_VERSION_CMD=	${UNAME} -r | \
+.if !defined(NATIVE_OPSYS_VERSION)
+_NATIVE_OPSYS_VERSION_CMD=	${UNAME} -r | \
 			awk -F. '{major=int($$1); minor=int($$2); if (minor>=100) minor=99; patch=int($$3); if (patch>=100) patch=99; printf "%02d%02d%02d", major, minor, patch}'
-OPSYS_VERSION=		${_OPSYS_VERSION_CMD:sh}
-MAKEFLAGS+=		OPSYS_VERSION=${OPSYS_VERSION:Q}
+NATIVE_OPSYS_VERSION=	${_NATIVE_OPSYS_VERSION_CMD:sh}
+MAKEFLAGS+=		NATIVE_OPSYS_VERSION=${NATIVE_OPSYS_VERSION:Q}
 .endif
 
 # Preload these for architectures not in all variations of bsd.own.mk,
@@ -155,190 +155,225 @@ MACHINE_GNU_ARCH?=		${GNU_ARCH.${MACHINE_ARCH}:U${MACHINE_ARCH}}
 
 ## If changes are made to how OS_VERSION is set below please keep
 ## "pkgsrc/pkgtools/osabi/INSTALL" in-sync.
-.if ${OPSYS} == "NetBSD"
-LOWER_OPSYS?=		netbsd
+.if ${NATIVE_OPSYS} == "NetBSD"
+NATIVE_LOWER_OPSYS?=	netbsd
 
-.elif ${OPSYS} == "AIX"
+.elif ${NATIVE_OPSYS} == "AIX"
 .  if exists(/usr/bin/oslevel)
-_OS_VERSION!=		/usr/bin/oslevel
+_NATIVE_OS_VERSION!=	/usr/bin/oslevel
 .  else
-_OS_VERSION!=		echo `${UNAME} -v`.`${UNAME} -r`
+_NATIVE_OS_VERSION!=	echo `${UNAME} -v`.`${UNAME} -r`
 .  endif
-OS_VERSION=		${_OS_VERSION:C/([0-9]*\.[0-9]*).*/\1/}
-LOWER_OPSYS_VERSUFFIX=	${_OS_VERSION}
-LOWER_OPSYS?=		aix
-LOWER_VENDOR?=		ibm
-
-.elif ${OPSYS} == "BSDOS"
-LOWER_OPSYS?=		bsdi
-
-.elif ${OPSYS} == "Cygwin"
-LOWER_OPSYS?=		cygwin
-LOWER_VENDOR?=		pc
-_OS_VERSION!=		${UNAME} -r
-OS_VERSION=		${_OS_VERSION:C/\(.*\)//}
-OS_VARIANT!=		${UNAME} -s
-
-.elif ${OPSYS} == "Darwin"
-LOWER_OPSYS?=		darwin
-LOWER_OPSYS_VERSUFFIX=	${OS_VERSION:C/([0-9]*).*/\1/}
-LOWER_VENDOR?=		apple
-_OPSYS_VERSION_CMD=	sw_vers -productVersion | \
+NATIVE_OS_VERSION=		${_NATIVE_OS_VERSION:C/([0-9]*\.[0-9]*).*/\1/}
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${_NATIVE_OS_VERSION}
+NATIVE_LOWER_OPSYS?=		aix
+NATIVE_LOWER_VENDOR?=		ibm
+
+.elif ${NATIVE_OPSYS} == "BSDOS"
+NATIVE_LOWER_OPSYS?=	bsdi
+
+.elif ${NATIVE_OPSYS} == "Cygwin"
+NATIVE_LOWER_OPSYS?=	cygwin
+NATIVE_LOWER_VENDOR?=	pc
+_NATIVE_OS_VERSION!=	${UNAME} -r
+NATIVE_OS_VERSION=	${_NATIVE_OS_VERSION:C/\(.*\)//}
+NATIVE_OS_VARIANT!=	${UNAME} -s
+
+.elif ${NATIVE_OPSYS} == "Darwin"
+NATIVE_LOWER_OPSYS?=		darwin
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${NATIVE_OS_VERSION:C/([0-9]*).*/\1/}
+NATIVE_LOWER_VENDOR?=		apple
+_NATIVE_OPSYS_VERSION_CMD=	sw_vers -productVersion | \
 			awk -F. '{major=int($$1); minor=int($$2); if (minor>=100) minor=99; patch=int($$3); if (patch>=100) patch=99; printf "%02d%02d%02d", major, minor, patch}'
 
-.elif ${OPSYS} == "DragonFly"
-OS_VERSION:=		${OS_VERSION:C/-.*$//}
-LOWER_OPSYS?=		dragonfly
-LOWER_VENDOR?=		pc
+.elif ${NATIVE_OPSYS} == "DragonFly"
+NATIVE_OS_VERSION:=	${NATIVE_OS_VERSION:C/-.*$//}
+NATIVE_LOWER_OPSYS?=	dragonfly
+NATIVE_LOWER_VENDOR?=	pc
 
-.elif ${OPSYS} == "FreeBSD"
-OS_VERSION:=		${OS_VERSION:C/-.*$//}
-LOWER_OPSYS?=		freebsd
-LOWER_OPSYS_VERSUFFIX=	${OS_VERSION:C/([0-9]*).*/\1/}
+.elif ${NATIVE_OPSYS} == "FreeBSD"
+NATIVE_OS_VERSION:=		${OS_VERSION:C/-.*$//}
+NATIVE_LOWER_OPSYS?=		freebsd
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${OS_VERSION:C/([0-9]*).*/\1/}
 .  if ${MACHINE_ARCH} == "i386"
-LOWER_VENDOR?=		pc
+NATIVE_LOWER_VENDOR?=		pc
 .  endif
-LOWER_VENDOR?=		unknown
+NATIVE_LOWER_VENDOR?=		unknown
 
-.elif ${OPSYS} == "Haiku"
-LOWER_OPSYS?=		haiku
-.  if ${MACHINE_ARCH} == "i386"
-LOWER_VENDOR?=		pc
+.elif ${NATIVE_OPSYS} == "Haiku"
+NATIVE_LOWER_OPSYS?=		haiku
+.  if ${NATIVE_MACHINE_ARCH} == "i386"
+NATIVE_LOWER_VENDOR?=		pc
 .  endif
 
-.elif ${OPSYS} == "Interix"
-LOWER_OPSYS?=		interix
-LOWER_VENDOR?=		pc
+.elif ${NATIVE_OPSYS} == "Interix"
+NATIVE_LOWER_OPSYS?=		interix
+NATIVE_LOWER_VENDOR?=		pc
 .  if exists(/usr/lib/libc.so.5.2) || exists(/usr/lib/x86/libc.so.5.2)
-LOWER_OPSYS_VERSUFFIX=	${OS_VERSION:C/([0-9]*).*/\1/}
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${NATIVE_OS_VERSION:C/([0-9]*).*/\1/}
 .  else
-LOWER_OPSYS_VERSUFFIX?=	3
+NATIVE_LOWER_OPSYS_VERSUFFIX?=	3
 .    if exists(/usr/lib/libc.so.3.5)
-OS_VERSION=		3.5
+NATIVE_OS_VERSION=		3.5
 .    elif exists(/usr/lib/libc.so.3.1)
-OS_VERSION=		3.1
+NATIVE_OS_VERSION=		3.1
 .    else
-OS_VERSION=		3.0
+NATIVE_OS_VERSION=		3.0
 .    endif
 .  endif
 
 .elif ${OPSYS} == "MirBSD"
-LOWER_OPSYS?=		mirbsd
-LOWER_OPSYS_VERSUFFIX=	${OS_VERSION}
-LOWER_VENDOR?=		unknown
-
-.elif !empty(OPSYS:MIRIX*)
-LOWER_OPSYS?=		irix
-LOWER_OPSYS_VERSUFFIX?=	${OS_VERSION}
-LOWER_VENDOR?=		sgi
-
-.elif ${OPSYS} == "Linux"
-OS_VERSION:=		${OS_VERSION:C/-.*$//}
-LOWER_OPSYS?=		linux
+NATIVE_LOWER_OPSYS?=		mirbsd
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${NATIVE_OS_VERSION}
+NATIVE_LOWER_VENDOR?=		unknown
+
+.elif !empty(NATIVE_OPSYS:MIRIX*)
+NATIVE_LOWER_OPSYS?=		irix
+NATIVE_LOWER_OPSYS_VERSUFFIX?=	${NATIVE_OS_VERSION}
+NATIVE_LOWER_VENDOR?=		sgi
+
+.elif ${NATIVE_OPSYS} == "Linux"
+NATIVE_OS_VERSION:=		${NATIVE_OS_VERSION:C/-.*$//}
+NATIVE_LOWER_OPSYS?=		linux
 .  if exists(/etc/lsb-release)
 CHROMEOS_RELEASE_NAME!=	awk -F = '$$1 == "CHROMEOS_RELEASE_NAME" { print $$2 }' /etc/lsb-release
 .  endif
 .  if exists(/etc/debian_version)
-LOWER_VENDOR?=		debian
+NATIVE_LOWER_VENDOR?=		debian
 .  elif exists(/etc/mandrake-release)
-LOWER_VENDOR?=		mandrake
+NATIVE_LOWER_VENDOR?=		mandrake
 .  elif exists(/etc/redhat-version) || exists(/etc/redhat-release)
-LOWER_VENDOR?=		redhat
+NATIVE_LOWER_VENDOR?=		redhat
 .  elif exists(/etc/slackware-version)
-LOWER_VENDOR?=		slackware
+NATIVE_LOWER_VENDOR?=		slackware
 .  elif exists(/etc/ssdlinux_version)
-LOWER_VENDOR?=		ssd
+NATIVE_LOWER_VENDOR?=		ssd
 .  elif !empty(CHROMEOS_RELEASE_NAME)
-LOWER_VENDOR?=		chromeos
-.  elif ${MACHINE_ARCH} == "i386"
-LOWER_VENDOR?=          pc
+NATIVE_LOWER_VENDOR?=		chromeos
+.  elif ${NATIVE_MACHINE_ARCH} == "i386"
+NATIVE_LOWER_VENDOR?=          pc
 .  endif
-LOWER_VENDOR?=          unknown
-OS_VARIANT!=		${UNAME} -r
-OS_VARIANT:=		${OS_VARIANT:C/^.*-//}
-.  if ${OS_VARIANT} != "Microsoft"
-OS_VARIANT=		${LOWER_VENDOR}
+NATIVE_LOWER_VENDOR?=          unknown
+NATIVE_OS_VARIANT!=		${UNAME} -r
+NATIVE_OS_VARIANT:=		${NATIVE_OS_VARIANT:C/^.*-//}
+.  if ${NATIVE_OS_VARIANT} != "Microsoft"
+NATIVE_OS_VARIANT=		${NATIVE_LOWER_VENDOR}
 .  endif
+# XXX NATIVE_HOST_MACHINE_ARCH?  ???
 .  if !defined(HOST_MACHINE_ARCH)
 HOST_MACHINE_ARCH!=	${UNAME} -m
 MAKEFLAGS+=		HOST_MACHINE_ARCH=${HOST_MACHINE_ARCH:Q}
 .  endif
 
-.elif ${OPSYS} == "OpenBSD"
-LOWER_OPSYS?= 		openbsd
-
-.elif ${OPSYS} == "OSF1"
-OS_VERSION:=		${OS_VERSION:C/^V//}
-LOWER_OPSYS?=		osf1
-LOWER_OPSYS_VERSUFFIX?=	${OS_VERSION}
-LOWER_VENDOR?=		dec
-
-.elif ${OPSYS} == "HPUX"
-OS_VERSION:=		${OS_VERSION:C/^B.//}
-LOWER_OPSYS?=		hpux
-LOWER_OPSYS_VERSUFFIX?=	${OS_VERSION}
-LOWER_VENDOR?=		hp
-
-.elif ${OPSYS} == "SunOS"
-LOWER_VENDOR?=		sun
-LOWER_OPSYS?=		solaris
-LOWER_OPSYS_VERSUFFIX=	2.${OS_VERSION:C/5.//}
+.elif ${NATIVE_OPSYS} == "OpenBSD"
+NATIVE_LOWER_OPSYS?= 		openbsd
+
+.elif ${NATIVE_OPSYS} == "OSF1"
+NATIVE_OS_VERSION:=		${NATIVE_OS_VERSION:C/^V//}
+NATIVE_LOWER_OPSYS?=		osf1
+NATIVE_LOWER_OPSYS_VERSUFFIX?=	${NATIVE_OS_VERSION}
+NATIVE_LOWER_VENDOR?=		dec
+
+.elif ${NATIVE_OPSYS} == "HPUX"
+NATIVE_OS_VERSION:=		${NATIVE_OS_VERSION:C/^B.//}
+NATIVE_LOWER_OPSYS?=		hpux
+NATIVE_LOWER_OPSYS_VERSUFFIX?=	${NATIVE_OS_VERSION}
+NATIVE_LOWER_VENDOR?=		hp
+
+.elif ${NATIVE_OPSYS} == "SunOS"
+NATIVE_LOWER_VENDOR?=		sun
+NATIVE_LOWER_OPSYS?=		solaris
+NATIVE_LOWER_OPSYS_VERSUFFIX=	2.${NATIVE_OS_VERSION:C/5.//}
 .  if !defined(_UNAME_V)
 _UNAME_V!=		${UNAME} -v
 MAKEFLAGS+=		_UNAME_V=${_UNAME_V:Q}
 .  endif
 .  if !empty(_UNAME_V:Mjoyent_*)
-OS_VARIANT=		SmartOS
-LOWER_VARIANT_VERSION=	${_UNAME_V:C/joyent_//}
+NATIVE_OS_VARIANT=		SmartOS
+NATIVE_LOWER_VARIANT_VERSION=	${_UNAME_V:C/joyent_//}
 .  elif !empty(_UNAME_V:Momnios-*)
-OS_VARIANT=		OmniOS
-LOWER_VARIANT_VERSION!=	/usr/bin/awk '{ print $$3; exit 0; }' /etc/release
+NATIVE_OS_VARIANT=		OmniOS
+NATIVE_LOWER_VARIANT_VERSION!=	/usr/bin/awk '{ print $$3; exit 0; }' /etc/release
 .  elif !empty(_UNAME_V:Mtribblix-*)
-OS_VARIANT=		Tribblix
-LOWER_VARIANT_VERSION!=	/usr/bin/awk '{ print $$2; exit 0; }' /etc/release
+NATIVE_OS_VARIANT=		Tribblix
+NATIVE_LOWER_VARIANT_VERSION!=	/usr/bin/awk '{ print $$2; exit 0; }' /etc/release
 .  else
-OS_VARIANT=		Solaris
-LOWER_VARIANT_VERSION=	${_UNAME_V}
+NATIVE_OS_VARIANT=		Solaris
+NATIVE_LOWER_VARIANT_VERSION=	${_UNAME_V}
 .  endif
 
 .elif ${OPSYS} == "SCO_SV"
-SCO_RELEASE!=		${UNAME} -r
-SCO_VERSION!=		${UNAME} -v
-LOWER_VENDOR?=		pc
-LOWER_OPSYS?=		sco
-LOWER_OPSYS_VERSUFFIX=	${SCO_RELEASE}v${SCO_VERSION}
-_UNAME_V!=		${UNAME} -v
+SCO_RELEASE!=			${UNAME} -r
+SCO_VERSION!=			${UNAME} -v
+NATIVE_LOWER_VENDOR?=		pc
+NATIVE_LOWER_OPSYS?=		sco
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${SCO_RELEASE}v${SCO_VERSION}
+_UNAME_V!=			${UNAME} -v
 .  if !empty(_UNAME_V:M5.0*)
-OS_VARIANT=		SCOOSR5
+NATIVE_OS_VARIANT=		SCOOSR5
 .  elif !empty(_UNAME_V:M6.0*)
-OS_VARIANT=		SCOOSR6
+NATIVE_OS_VARIANT=		SCOOSR6
 .  endif
 
-.elif ${OPSYS} == "UnixWare"
-SCO_RELEASE?=		sysv5${OPSYS}
-SCO_VERSION!=		${UNAME} -v
-LOWER_VENDOR?=		unknown
-LOWER_OPSYS_VERSUFFIX=	${SCO_RELEASE}${SCO_VERSION}
+.elif ${NATIVE_OPSYS} == "UnixWare"
+SCO_RELEASE?=			sysv5${NATIVE_OPSYS}
+SCO_VERSION!=			${UNAME} -v
+NATIVE_LOWER_VENDOR?=		unknown
+NATIVE_LOWER_OPSYS_VERSUFFIX=	${SCO_RELEASE}${SCO_VERSION}
 
-.elif ${OPSYS} == "Minix"
-LOWER_VENDOR?=		unknown
-LOWER_OPSYS:=		${OPSYS:tl}
+.elif ${NATIVE_OPSYS} == "Minix"
+NATIVE_LOWER_VENDOR?=		unknown
+NATIVE_LOWER_OPSYS:=		${NATIVE_OPSYS:tl}
 
-.elif !defined(LOWER_OPSYS)
-LOWER_OPSYS:=		${OPSYS:tl}
+.elif !defined(NATIVE_LOWER_OPSYS)
+NATIVE_LOWER_OPSYS:=		${NATIVE_OPSYS:tl}
 .endif
 
 # Now commit the version values computed above, eliding the :sh
-OS_VERSION:=		${OS_VERSION}
-
-MAKEFLAGS+=		LOWER_OPSYS=${LOWER_OPSYS:Q}
-
-LOWER_VENDOR?=			# empty ("arch--opsys")
-
+NATIVE_OS_VERSION:=	${NATIVE_OS_VERSION}
+
+MAKEFLAGS+=		NATIVE_LOWER_OPSYS=${NATIVE_LOWER_OPSYS:Q}
+
+NATIVE_LOWER_VENDOR?=	# empty ("arch--opsys")
+
+# List of variables that must be set to determine a cross-compilation
+# target.
+CROSSVARS?=	# empty
+
+# Cross-compilation target settings.
+CROSSVARS+=	OPSYS
+OPSYS=			\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_OPSYS}:${NATIVE_OPSYS}}
+CROSSVARS+=	OS_VERSION
+OS_VERSION=		\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_OS_VERSION}:${NATIVE_OS_VERSION}}
+CROSSVARS+=	OPSYS_VERSION
+OPSYS_VERSION=		\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_OPSYS_VERSION}:${NATIVE_OPSYS_VERSION}}
+CROSSVARS+=	LOWER_OPSYS
+LOWER_OPSYS=		\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_LOWER_OPSYS}:${NATIVE_LOWER_OPSYS}}
+CROSSVARS+=	LOWER_OPSYS_VERSUFFIX
+LOWER_OPSYS_VERSUFFIX=	\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_LOWER_OPSYS_VERSUFFIX}:${NATIVE_LOWER_OPSYS_VERSUFFIX}}
+CROSSVARS+=	LOWER_VARIANT_VERSION
+LOWER_VARIANT_VERSION=	\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_LOWER_VARIANT_VERSION}:${NATIVE_LOWER_VARIANT_VERSION}}
+CROSSVARS+=	LOWER_VENDOR
+LOWER_VENDOR=		\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_LOWER_VENDOR}:${NATIVE_LOWER_VENDOR}}
+CROSSVARS+=	LOWER_OS_VARIANT
+OS_VARIANT=		\
+	${"${USE_CROSS_COMPILE:U:tl}" == "yes":?${CROSS_OS_VARIANT}:${NATIVE_OS_VARIANT}}
+
+# Remember the MACHINE_ARCH that make was built with before we override
+# it with CROSS_MACHINE_ARCH if USE_CROSS_COMPILE is enabled.
+CROSSVARS+=	MACHINE_ARCH
 NATIVE_MACHINE_ARCH:=		${MACHINE_ARCH}
+
 NATIVE_MACHINE_PLATFORM?=	${OPSYS}-${OS_VERSION}-${NATIVE_MACHINE_ARCH}
 MACHINE_PLATFORM?=		${OPSYS}-${OS_VERSION}-${MACHINE_ARCH}
-NATIVE_MACHINE_GNU_PLATFORM?=	${NATIVE_MACHINE_GNU_ARCH}-${LOWER_VENDOR}-${LOWER_OPSYS:C/[0-9]//g}${NATIVE_APPEND_ELF}${LOWER_OPSYS_VERSUFFIX}${NATIVE_APPEND_ABI}
+NATIVE_MACHINE_GNU_PLATFORM?=	${NATIVE_MACHINE_GNU_ARCH}-${NATIVE_LOWER_VENDOR}-${NATIVE_LOWER_OPSYS:C/[0-9]//g}${NATIVE_APPEND_ELF}${NATIVE_LOWER_OPSYS_VERSUFFIX}${NATIVE_APPEND_ABI}
 MACHINE_GNU_PLATFORM?=		${MACHINE_GNU_ARCH}-${LOWER_VENDOR}-${LOWER_OPSYS:C/[0-9]//g}${APPEND_ELF}${LOWER_OPSYS_VERSUFFIX}${APPEND_ABI}
 
 #
@@ -377,6 +412,8 @@ USETOOLS=		no
 MAKE_ENV+=		USETOOLS=no
 
 # Set this before <bsd.own.mk> does, since it doesn't know about Darwin
+# XXX Won't work for cross-compilation -- why don't we just teach
+# bsd.own.mk about OBJECT_FMT for Darwin?
 .if ${OPSYS} == "Darwin"
 OBJECT_FMT?=		Mach-O
 .endif
@@ -452,7 +489,7 @@ SHAREMODE?=		${DOCMODE}
 
 # When cross-compilation support is requested, the following options
 # must be specified as well or guessable:
-# - MACHINE_ARCH is set to TARGET_ARCH if set.
+# - Variables like MACHINE_ARCH are set to CROSS_MACHINE_ARCH.
 # - CROSS_DESTDIR is guessed from MAKEOBJDIR and MACHINE_ARCH.
 # - PKG_DBDIR is expanded and prefixed with CROSS_DESTDIR
 # - DESTDIR support is required
@@ -460,9 +497,16 @@ SHAREMODE?=		${DOCMODE}
 # _CROSS_DESTDIR is set for internal use to avoid conditionalising
 # the use.
 
-.if !empty(USE_CROSS_COMPILE:M[yY][eE][sS])
-.  if defined(TARGET_ARCH)
-MACHINE_ARCH=	${TARGET_ARCH}
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+.  for _v_ in ${CROSSVARS}
+.    ifndef CROSS_${_v_}
+MISSING_CROSSVARS=	yes
+.      warning Missing CROSS_${_v_} setting
+.    endif
+${_v_}:=	${CROSS_${_v_}}
+.  endfor
+.  ifdef MISSING_CROSSVARS
+.    error USE_CROSS_COMPILE=yes but missing cross variable settings
 .  endif
 CROSS_DESTDIR?=	${MAKEOBJDIR}/destdir.${MACHINE_ARCH}
 .  if !exists(${CROSS_DESTDIR}/usr/include/stddef.h)
diff --git a/mk/tools/defaults.mk b/mk/tools/defaults.mk
index 5b49c4224d72..b08d65166582 100644
--- a/mk/tools/defaults.mk
+++ b/mk/tools/defaults.mk
@@ -34,10 +34,13 @@ TOOLS_DEFAULTS_MK=	defined
 # These are the platform-specific lists of system-supplied tools.
 #
 # XXX These should eventually just migrate over to the appropriate
-# XXX pkgsrc/mk/platform/${OPSYS}.mk file.
+# XXX pkgsrc/mk/platform/${NATIVE_OPSYS}.mk file.
 #
-.if exists(${_PKGSRC_TOPDIR}/mk/tools/tools.${OPSYS}.mk)
-.  include "${_PKGSRC_TOPDIR}/mk/tools/tools.${OPSYS}.mk"
+# XXX Use ${OPSYS} for :run tools, but ${NATIVE_OPSYS} for :build and
+# XXX :bootstrap tools.
+#
+.if exists(${_PKGSRC_TOPDIR}/mk/tools/tools.${NATIVE_OPSYS}.mk)
+.  include "${_PKGSRC_TOPDIR}/mk/tools/tools.${NATIVE_OPSYS}.mk"
 .endif
 
 ######################################################################

From 28284fcc8f7da25541c36e93188e193193aa1bcf Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Wed, 28 Jun 2023 23:53:26 +0000
Subject: [PATCH 2/5] WIP: mk: Pass through all CROSSVARS as TARGET_* for tool
 depends.

Use this for cross-libtool-base.

Name it cross-libtool-base-${MACHINE_PLATFORM} instead of
cross-libtool-base-${MACHINE_ARCH}.  MACHINE_GNU_PLATFORM isn't quite
enough, because it doesn't reflect OS versions (e.g., aarch64--netbsd
covers both NetBSD 9 and NetBSD 10).

XXX MACHINE_PLATFORM doesn't cover all the other little exotic OS
knobs like LOWER_OPSYS_VERSUFFIX.  Do we care?
---
 cross/cross-libtool-base/Makefile |  13 ++--
 cross/cross-libtool-base/PLIST    | 108 +++++++++++++++---------------
 doc/HOWTO-dev-crosscompile        |  46 +++++++------
 mk/bsd.pkg.use.mk                 |   6 +-
 mk/bsd.prefs.mk                   |  42 ++++++++++--
 mk/pkgformat/pkg/depends.mk       |  18 +++--
 6 files changed, 138 insertions(+), 95 deletions(-)

diff --git a/cross/cross-libtool-base/Makefile b/cross/cross-libtool-base/Makefile
index c2b4abedd693..4fbeb7a2c165 100644
--- a/cross/cross-libtool-base/Makefile
+++ b/cross/cross-libtool-base/Makefile
@@ -37,7 +37,7 @@ LIBTOOL_CROSS_COMPILE=	yes
 
 # XXX Tweaked for cross-compilation.
 #PKGNAME=	${DISTNAME:S/-/-base-/}
-PKGNAME=	${DISTNAME:S/^libtool-/cross-libtool-base-${MACHINE_ARCH}-/}
+PKGNAME=	${DISTNAME:S/^libtool-/cross-libtool-base-${MACHINE_PLATFORM}-/}
 PKGREVISION=	8
 
 COMMENT=	Generic shared library support script (the script itself)
@@ -64,10 +64,11 @@ CFLAGS.SunOS+=	${_COMPILER_ABI_FLAG.${ABI}}
 # and Fortran compilers.
 #
 USE_LANGUAGES=		c c++
-# XXX Added for cross-compilation.  XXX Should be ${TARGET_ARCH}, but
-# currently we have to fake-cross-compile libtool because it's broken
-# upstream.
-GNU_CONFIGURE_PREFIX=	${PREFIX}/cross-${MACHINE_ARCH}
+# XXX Added for cross-compilation.  XXX Should be
+# ${TARGET_MACHINE_PLATFORM}, but currently we have to
+# fake-cross-compile libtool because it's broken upstream.
+GNU_CONFIGURE_PREFIX=	${PREFIX}/cross-${MACHINE_PLATFORM}
+PLIST_SUBST+=		MACHINE_PLATFORM=${MACHINE_PLATFORM:Q}
 CONFIGURE_ARGS+=	--disable-ltdl-install
 CONFIGURE_ARGS+=	F77=no FC=no
 
@@ -96,7 +97,7 @@ post-build:
 		${FILESDIR}/shlibtool.in > ${WRKSRC}/shlibtool
 
 post-install:
-	${INSTALL_SCRIPT} ${WRKSRC}/shlibtool ${DESTDIR}${PREFIX}/cross-${MACHINE_ARCH}/bin/shlibtool
+	${INSTALL_SCRIPT} ${WRKSRC}/shlibtool ${DESTDIR}${PREFIX}/cross-${MACHINE_PLATFORM}/bin/shlibtool
 
 BUILDLINK_DEPMETHOD.dlcompat=	build
 
diff --git a/cross/cross-libtool-base/PLIST b/cross/cross-libtool-base/PLIST
index a1db9768dde3..c78dfac0fcb5 100644
--- a/cross/cross-libtool-base/PLIST
+++ b/cross/cross-libtool-base/PLIST
@@ -1,55 +1,55 @@
 @comment $NetBSD: PLIST,v 1.3 2019/07/09 15:45:25 riastradh Exp $
-cross-${MACHINE_ARCH}/bin/libtool
-cross-${MACHINE_ARCH}/bin/libtoolize
-cross-${MACHINE_ARCH}/bin/shlibtool
-cross-${MACHINE_ARCH}/man/man1/libtool.1
-cross-${MACHINE_ARCH}/man/man1/libtoolize.1
-cross-${MACHINE_ARCH}/share/aclocal/libtool.m4
-cross-${MACHINE_ARCH}/share/aclocal/ltargz.m4
-cross-${MACHINE_ARCH}/share/aclocal/ltdl.m4
-cross-${MACHINE_ARCH}/share/aclocal/ltoptions.m4
-cross-${MACHINE_ARCH}/share/aclocal/ltsugar.m4
-cross-${MACHINE_ARCH}/share/aclocal/ltversion.m4
-cross-${MACHINE_ARCH}/share/aclocal/lt~obsolete.m4
-cross-${MACHINE_ARCH}/share/libtool/COPYING.LIB
-cross-${MACHINE_ARCH}/share/libtool/Makefile.am
-cross-${MACHINE_ARCH}/share/libtool/Makefile.in
-cross-${MACHINE_ARCH}/share/libtool/README
-cross-${MACHINE_ARCH}/share/libtool/aclocal.m4
-cross-${MACHINE_ARCH}/share/libtool/build-aux/compile
-cross-${MACHINE_ARCH}/share/libtool/build-aux/config.guess
-cross-${MACHINE_ARCH}/share/libtool/build-aux/config.sub
-cross-${MACHINE_ARCH}/share/libtool/build-aux/depcomp
-cross-${MACHINE_ARCH}/share/libtool/build-aux/install-sh
-cross-${MACHINE_ARCH}/share/libtool/build-aux/ltmain.sh
-cross-${MACHINE_ARCH}/share/libtool/build-aux/missing
-cross-${MACHINE_ARCH}/share/libtool/config-h.in
-cross-${MACHINE_ARCH}/share/libtool/configure
-cross-${MACHINE_ARCH}/share/libtool/configure.ac
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt__alloc.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt__argz_.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt__dirent.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt__glibc.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt__private.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt__strl.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt_dlloader.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt_error.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/lt_system.h
-cross-${MACHINE_ARCH}/share/libtool/libltdl/slist.h
-cross-${MACHINE_ARCH}/share/libtool/loaders/dld_link.c
-cross-${MACHINE_ARCH}/share/libtool/loaders/dlopen.c
-cross-${MACHINE_ARCH}/share/libtool/loaders/dyld.c
-cross-${MACHINE_ARCH}/share/libtool/loaders/load_add_on.c
-cross-${MACHINE_ARCH}/share/libtool/loaders/loadlibrary.c
-cross-${MACHINE_ARCH}/share/libtool/loaders/preopen.c
-cross-${MACHINE_ARCH}/share/libtool/loaders/shl_load.c
-cross-${MACHINE_ARCH}/share/libtool/lt__alloc.c
-cross-${MACHINE_ARCH}/share/libtool/lt__argz.c
-cross-${MACHINE_ARCH}/share/libtool/lt__dirent.c
-cross-${MACHINE_ARCH}/share/libtool/lt__strl.c
-cross-${MACHINE_ARCH}/share/libtool/lt_dlloader.c
-cross-${MACHINE_ARCH}/share/libtool/lt_error.c
-cross-${MACHINE_ARCH}/share/libtool/ltdl.c
-cross-${MACHINE_ARCH}/share/libtool/ltdl.h
-cross-${MACHINE_ARCH}/share/libtool/ltdl.mk
-cross-${MACHINE_ARCH}/share/libtool/slist.c
+cross-${MACHINE_PLATFORM}/bin/libtool
+cross-${MACHINE_PLATFORM}/bin/libtoolize
+cross-${MACHINE_PLATFORM}/bin/shlibtool
+cross-${MACHINE_PLATFORM}/man/man1/libtool.1
+cross-${MACHINE_PLATFORM}/man/man1/libtoolize.1
+cross-${MACHINE_PLATFORM}/share/aclocal/libtool.m4
+cross-${MACHINE_PLATFORM}/share/aclocal/ltargz.m4
+cross-${MACHINE_PLATFORM}/share/aclocal/ltdl.m4
+cross-${MACHINE_PLATFORM}/share/aclocal/ltoptions.m4
+cross-${MACHINE_PLATFORM}/share/aclocal/ltsugar.m4
+cross-${MACHINE_PLATFORM}/share/aclocal/ltversion.m4
+cross-${MACHINE_PLATFORM}/share/aclocal/lt~obsolete.m4
+cross-${MACHINE_PLATFORM}/share/libtool/COPYING.LIB
+cross-${MACHINE_PLATFORM}/share/libtool/Makefile.am
+cross-${MACHINE_PLATFORM}/share/libtool/Makefile.in
+cross-${MACHINE_PLATFORM}/share/libtool/README
+cross-${MACHINE_PLATFORM}/share/libtool/aclocal.m4
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/compile
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/config.guess
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/config.sub
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/depcomp
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/install-sh
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/ltmain.sh
+cross-${MACHINE_PLATFORM}/share/libtool/build-aux/missing
+cross-${MACHINE_PLATFORM}/share/libtool/config-h.in
+cross-${MACHINE_PLATFORM}/share/libtool/configure
+cross-${MACHINE_PLATFORM}/share/libtool/configure.ac
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt__alloc.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt__argz_.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt__dirent.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt__glibc.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt__private.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt__strl.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt_dlloader.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt_error.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/lt_system.h
+cross-${MACHINE_PLATFORM}/share/libtool/libltdl/slist.h
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/dld_link.c
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/dlopen.c
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/dyld.c
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/load_add_on.c
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/loadlibrary.c
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/preopen.c
+cross-${MACHINE_PLATFORM}/share/libtool/loaders/shl_load.c
+cross-${MACHINE_PLATFORM}/share/libtool/lt__alloc.c
+cross-${MACHINE_PLATFORM}/share/libtool/lt__argz.c
+cross-${MACHINE_PLATFORM}/share/libtool/lt__dirent.c
+cross-${MACHINE_PLATFORM}/share/libtool/lt__strl.c
+cross-${MACHINE_PLATFORM}/share/libtool/lt_dlloader.c
+cross-${MACHINE_PLATFORM}/share/libtool/lt_error.c
+cross-${MACHINE_PLATFORM}/share/libtool/ltdl.c
+cross-${MACHINE_PLATFORM}/share/libtool/ltdl.h
+cross-${MACHINE_PLATFORM}/share/libtool/ltdl.mk
+cross-${MACHINE_PLATFORM}/share/libtool/slist.c
diff --git a/doc/HOWTO-dev-crosscompile b/doc/HOWTO-dev-crosscompile
index bc4827802308..2b9990ad518a 100644
--- a/doc/HOWTO-dev-crosscompile
+++ b/doc/HOWTO-dev-crosscompile
@@ -11,34 +11,42 @@ have ever thought of cross-compilation.
 
 * Native and target platform
 
-When building a package, MACHINE_ARCH, MACHINE_GNU_PLATFORM, &c.,
-describe the platform for which the package is being built.  If
+When building a package, MACHINE_ARCH, OPSYS, &c., describe the
+platform for which the package is being built.  If
 USE_CROSS_COMPILE=no, this is the native platform; otherwise, if
-USE_CROSS_COMPILE=yes, it is the target platform, and the additional
-variables NATIVE_MACHINE_ARCH, NATIVE_MACHINE_GNU_PLATFORM, &c.,
-describe the native platform.
+USE_CROSS_COMPILE=yes, it is the target platform.  The additional
+variables NATIVE_MACHINE_ARCH, NATIVE_OPSYS, &c., always describe the
+native platform.
 
 When building a native package for cross-compilation, such as a
-compiler for the target, the variable TARGET_ARCH describes the target
-platform like MACHINE_ARCH.  If the build product varies with the
-choice of target, then TARGET_ARCH should be embedded into the PKGNAME
+compiler for the target, the variables TARGET_MACHINE_ARCH,
+TARGET_OPSYS, &c., describe the target platform.  If the build product
+varies with the choice of target, then TARGET_MACHINE_ARCH or
+TARGET_OPSYS or whatever affects it should be embedded into the PKGNAME
 somewhere so that the different build products are distinguished by
 having different package names.
 
-XXX This pattern is incompletely realized.  We should probably replace
-TARGET_ARCH by TARGET_MACHINE_ARCH, TARGET_MACHINE_GNU_PLATFORM, &c.,
-and perhaps decide which of those is the main switch that you set when
-you want to select cross-compilation.  Ideally, this switch should
-also support cross-compilation to other operating systems.
+XXX Missing:
+XXX - TARGET_MACHINE_GNU_PLATFORM
+XXX - TARGET_MACHINE_GNU_ARCH
+XXX - probably other variables defined in terms of the CROSSVARS
 
 * Specifying the toolchain
 
-Software built following GNU conventions can set GNU_CONFIGURE=yes so
-that pkgsrc will automatically specify the right --build, --host, and
---target options for cross-compilation and point everything at the
-right toolchain.
+The following build systems should automagically handle
+cross-compilation by passing through the architecture and OS
+information:
 
-XXX And software not built following GNU conventions...?
+- GNU_CONFIGURE=yes
+- .include "../../devel/meson/build.mk" (sets
+- .include "../../devel/cmake/build.mk" (and legacy USE_CMAKE=yes)
+
+Additional tweaks are sometimes needed (but not always), conditional on
+${USE_CROSS_COMPILE:tl} == "yes" (after including bsd.prefs.mk):
+
+- (pkg-config) ALL_ENV+= PKG_CONFIG_SYSROOT_DIR=${CROSS_DESTDIR:Q}
+- (pkg-config) ALL_ENV+= PKG_CONFIG_FDO_SYSROOT_RULES=1
+- (cmake) CMAKE_ARGS+= -DCMAKE_SYSROOT:STRING=${CROSS_DESTDIR:Q}
 
 * Tool dependencies
 
@@ -107,7 +115,7 @@ pre-answer the tests for autoconf:
 
 .include "../../bsd.prefs.mk"
 
-.if ${USE_CROSS_COMPILE:U:tl} == "yes"
+.if ${USE_CROSS_COMPILE:tl} == "yes"
 # Configure wants to check for /dev/random but can't.  We know NetBSD
 # always has a /dev/random, so inform autoconf of the fact.
 CONFIGURE_ENV.NetBSD+=	ac_cv_file__dev_random=yes
diff --git a/mk/bsd.pkg.use.mk b/mk/bsd.pkg.use.mk
index 5e1adc1adb2b..27fb648a6f6c 100644
--- a/mk/bsd.pkg.use.mk
+++ b/mk/bsd.pkg.use.mk
@@ -91,8 +91,8 @@ TOOL_DEPENDS+=		libtool-fortran>=${_OPSYS_LIBTOOL_REQD:U${LIBTOOL_REQD}}:../../d
 .  endif
 .else
 .  if !empty(USE_CROSS_COMPILE:M[yY][eE][sS])
-PKG_LIBTOOL?=		${TOOLBASE}/cross-${TARGET_ARCH:U${MACHINE_ARCH}}/bin/libtool
-PKG_SHLIBTOOL?=		${TOOLBASE}/cross-${TARGET_ARCH:U${MACHINE_ARCH}}/bin/shlibtool
+PKG_LIBTOOL?=		${TOOLBASE}/cross-${TARGET_MACHINE_PLATFORM:U${MACHINE_PLATFORM}}/bin/libtool
+PKG_SHLIBTOOL?=		${TOOLBASE}/cross-${TARGET_MACHINE_PLATFORM:U${MACHINE_PLATFORM}}/bin/shlibtool
 .  else
 PKG_LIBTOOL?=		${TOOLBASE}/bin/libtool
 PKG_SHLIBTOOL?=		${TOOLBASE}/bin/shlibtool
@@ -103,7 +103,7 @@ SHLIBTOOL?=		${WRAPPER_BINDIR}/shlibtool
 .if defined(USE_LIBTOOL)
 LIBTOOL_REQD?=		2.4.2nb9
 .if !empty(USE_CROSS_COMPILE:M[yY][eE][sS])
-TOOL_DEPENDS+=		cross-libtool-base-${MACHINE_ARCH}>=${_OPSYS_LIBTOOL_REQD:U${LIBTOOL_REQD}}:../../cross/cross-libtool-base
+TOOL_DEPENDS+=		cross-libtool-base-${MACHINE_PLATFORM}>=${_OPSYS_LIBTOOL_REQD:U${LIBTOOL_REQD}}:../../cross/cross-libtool-base
 .else
 TOOL_DEPENDS+=		libtool-base>=${_OPSYS_LIBTOOL_REQD:U${LIBTOOL_REQD}}:../../devel/libtool-base
 .endif
diff --git a/mk/bsd.prefs.mk b/mk/bsd.prefs.mk
index ae20829f7c01..2468a458f03f 100644
--- a/mk/bsd.prefs.mk
+++ b/mk/bsd.prefs.mk
@@ -376,6 +376,12 @@ MACHINE_PLATFORM?=		${OPSYS}-${OS_VERSION}-${MACHINE_ARCH}
 NATIVE_MACHINE_GNU_PLATFORM?=	${NATIVE_MACHINE_GNU_ARCH}-${NATIVE_LOWER_VENDOR}-${NATIVE_LOWER_OPSYS:C/[0-9]//g}${NATIVE_APPEND_ELF}${NATIVE_LOWER_OPSYS_VERSUFFIX}${NATIVE_APPEND_ABI}
 MACHINE_GNU_PLATFORM?=		${MACHINE_GNU_ARCH}-${LOWER_VENDOR}-${LOWER_OPSYS:C/[0-9]//g}${APPEND_ELF}${LOWER_OPSYS_VERSUFFIX}${APPEND_ABI}
 
+.ifdef TARGET_MACHINE_ARCH
+TARGET_MACHINE_GNU_ARCH=	${GNU_ARCH.${TARGET_MACHINE_ARCH}:U${TARGET_MACHINE_ARCH}}
+TARGET_MACHINE_GNU_PLATFORM=	${TARGET_MACHINE_GNU_ARCH}-${TARGET_LOWER_VENDOR}-${TARGET_LOWER_OPSYS:C/[0-9]//g}${TARGET_APPEND_ELF}${TARGET_LOWER_OPSYS_VERSUFFIX}${TARGET_APPEND_ABI}
+TARGET_MACHINE_PLATFORM=	${TARGET_OPSYS}-${TARGET_OS_VERSION}-${TARGET_MACHINE_ARCH}
+.endif
+
 #
 # cross-libtool is special -- it is built as a native package, but it
 # needs tools set up as if for a cross-compiled package because it
@@ -387,15 +393,18 @@ MACHINE_GNU_PLATFORM?=		${MACHINE_GNU_ARCH}-${LOWER_VENDOR}-${LOWER_OPSYS:C/[0-9
 # the rest of the native package build with USE_CROSS_COMPILE=no.
 #
 # This can't live inside the cross-libtool makefile because the
-# TARGET_ARCH / MACHINE_ARCH / NATIVE_MACHINE_ARCH switcheroo has to
-# happen in the middle of this file -- after NATIVE_MACHINE_ARCH is
-# determined, before MACHINE_ARCH is used for anything else.
+# TARGET_MACHINE_ARCH / MACHINE_ARCH / NATIVE_MACHINE_ARCH switcheroo
+# has to happen in the middle of this file -- after NATIVE_MACHINE_ARCH
+# is determined, before MACHINE_ARCH is used for anything else.
 #
-.if !empty(LIBTOOL_CROSS_COMPILE:M[yY][eE][sS])
-.  if !defined(TARGET_ARCH)
-PKG_FAIL_REASON+=	"Must set TARGET_ARCH for cross-libtool."
+.if ${LIBTOOL_CROSS_COMPILE:U:tl} == "yes"
+.  if !defined(TARGET_MACHINE_ARCH)
+PKG_FAIL_REASON+=	"Must set TARGET_MACHINE_ARCH for cross-libtool."
 .  endif
-MACHINE_ARCH:=			${TARGET_ARCH}
+.  for _v_ in ${CROSSVARS}
+${_v_}=				${TARGET_${_v_}}
+.  endfor
+# XXX Other CROSSVARS for _BUILD_DEFS?
 _BUILD_DEFS.MACHINE_ARCH=	${NATIVE_MACHINE_ARCH}
 _BUILD_DEFS.MACHINE_GNU_ARCH=	${NATIVE_MACHINE_GNU_ARCH}
 TOOLS_USE_CROSS_COMPILE=	yes
@@ -605,6 +614,9 @@ TOOLS_CROSS_DESTDIR=		${CROSS_DESTDIR}
 # XXX NATIVE_OBJECT_FMT is a cop-out -- but seriously, who is going to
 # do cross-builds on a NetBSD host that still uses a.out?
 NATIVE_OBJECT_FMT?=	${OBJECT_FMT}
+.  ifdef TARGET_MACHINE_ARCH
+TARGET_OBJECT_FMT?=	${OBJECT_FMT} # XXX
+.  endif
 .  if ${NATIVE_OBJECT_FMT} == "ELF" && \
    (!empty(NATIVE_MACHINE_ARCH:Mearm*) || \
     ${NATIVE_MACHINE_GNU_ARCH} == "arm" || \
@@ -629,12 +641,28 @@ NATIVE_APPEND_ELF=	elf
     ${MACHINE_ARCH} == "vax")
 APPEND_ELF=		elf
 .  endif
+.  if defined(TARGET_MACHINE_ARCH) && \
+   ${TARGET_OBJECT_FMT} == "ELF" && \
+   (!empty(TARGET_MACHINE_ARCH:Mearm*) || \
+    ${TARGET_MACHINE_GNU_ARCH} == "arm" || \
+    ${TARGET_MACHINE_ARCH} == "i386" || \
+    ${TARGET_MACHINE_ARCH} == "m68k" || \
+    ${TARGET_MACHINE_ARCH} == "m68000" || \
+    ${TARGET_MACHINE_GNU_ARCH} == "sh" || \
+    ${TARGET_MACHINE_GNU_ARCH} == "shle" || \
+    ${TARGET_MACHINE_ARCH} == "sparc" || \
+    ${TARGET_MACHINE_ARCH} == "vax")
+TARGET_APPEND_ELF=	elf
+.  endif
 .  if !empty(NATIVE_MACHINE_ARCH:Mearm*)
 NATIVE_APPEND_ABI=	-${NATIVE_MACHINE_ARCH:C/eb//:C/v[4-7]//:S/earm/eabi/}
 .  endif
 .  if !empty(MACHINE_ARCH:Mearm*)
 APPEND_ABI=		-${MACHINE_ARCH:C/eb//:C/v[4-7]//:S/earm/eabi/}
 .  endif
+.  if !empty(TARGET_MACHINE_ARCH:Mearm*)
+TARGET_APPEND_ABI=	-${TARGET_MACHINE_ARCH:C/eb//:C/v[4-7]//:S/earm/eabi/}
+.  endif
 .endif
 
 # if the system is IPv6-ready, compile with IPv6 support turned on.
diff --git a/mk/pkgformat/pkg/depends.mk b/mk/pkgformat/pkg/depends.mk
index ed4674e63279..57b873186116 100644
--- a/mk/pkgformat/pkg/depends.mk
+++ b/mk/pkgformat/pkg/depends.mk
@@ -90,6 +90,8 @@ _RESOLVE_DEPENDS_CMD=	\
 			" "${BUILD_DEPENDS:Q} \
 			" "${DEPENDS:Q}
 
+CROSSTARGETSETTINGS=	${CROSSVARS:@_v_@TARGET_${_v_}=${${_v_}}@}
+
 # _DEPENDS_INSTALL_CMD checks whether the package $pattern is installed,
 #	and installs it if necessary.
 #
@@ -110,17 +112,20 @@ _DEPENDS_INSTALL_CMD=							\
 	case $$type in							\
 	bootstrap|tool)							\
 		case "${USE_CROSS_COMPILE:Uno:tl}" in			\
-		yes) extradep="" ;;					\
-		*) extradep=" ${PKGNAME}" ;;				\
+		yes)	extradep="";					\
+			crosstargetsettings=${CROSSTARGETSETTINGS:Q};	\
+			;;						\
+		*)	extradep=" ${PKGNAME}";				\
+			crosstargetsettings=;				\
+			;;						\
 		esac;							\
 		cross=no;						\
-		archopt=TARGET_ARCH=${MACHINE_ARCH};			\
 		pkg=`${_HOST_PKG_BEST_EXISTS} "$$pattern" || ${TRUE}`;	\
 		;;							\
-	build|test|full)							\
+	build|test|full)						\
 		extradep=" ${PKGNAME}";					\
+		crosstargetsettings=;					\
 		cross=${USE_CROSS_COMPILE:Uno};				\
-		archopt=;						\
 		pkg=`${_PKG_BEST_EXISTS} "$$pattern" || ${TRUE}`;	\
 		;;							\
 	esac;								\
@@ -133,11 +138,12 @@ _DEPENDS_INSTALL_CMD=							\
 		cd $$dir;						\
 		unset _PKGSRC_BARRIER;					\
 		unset MAKEFLAGS;					\
+		unset ${CROSSVARS:@_v_@TARGET_${_v_}@};			\
 		${PKGSRC_SETENV} ${PKGSRC_MAKE_ENV} PATH=${_PATH_ORIG:Q}\
 			_PKGSRC_DEPS="$$extradep${_PKGSRC_DEPS}"	\
 			PKGNAME_REQD="$$pattern"			\
 			USE_CROSS_COMPILE=$$cross			\
-			$$archopt					\
+			$$crosstargetsettings				\
 		    ${MAKE} ${MAKEFLAGS} _AUTOMATIC=yes $$target;	\
 		case $$type in						\
 		bootstrap|tool)						\

From e208dba99e8ef3e2b13c16ea43edc973deb9b4cf Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Thu, 29 Jun 2023 00:38:40 +0000
Subject: [PATCH 3/5] mk/configure/gnu-configure.mk: Set --target too if
 requested.

---
 mk/configure/gnu-configure.mk | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/mk/configure/gnu-configure.mk b/mk/configure/gnu-configure.mk
index 46be4a13eac8..9410e26e0e76 100644
--- a/mk/configure/gnu-configure.mk
+++ b/mk/configure/gnu-configure.mk
@@ -40,7 +40,7 @@ _PKG_VARS.gnu-configure=	\
 	GNU_CONFIGURE_LIBDIR GNU_CONFIGURE_INFODIR GNU_CONFIGURE_MANDIR \
 	CONFIGURE_HAS_LIBDIR CONFIGURE_HAS_MANDIR CONFIGURE_HAS_INFODIR \
 	OVERRIDE_DIRDEPTH.configure \
-	USE_GNU_CONFIGURE_HOST
+	USE_GNU_CONFIGURE_HOST USE_GNU_CONFIGURE_TARGET
 
 HAS_CONFIGURE=			defined
 OVERRIDE_GNU_CONFIG_SCRIPTS=	defined
@@ -79,6 +79,7 @@ CONFIGURE_ARGS+=	--libdir=${GNU_CONFIGURE_LIBDIR}
 .endif
 
 USE_GNU_CONFIGURE_HOST?=	yes
+USE_GNU_CONFIGURE_TARGET?=	no # enable for toolchain packages
 .if !empty(USE_GNU_CONFIGURE_HOST:M[yY][eE][sS])
 .  if !empty(TOOLS_USE_CROSS_COMPILE:M[yY][eE][sS])
 CONFIGURE_ARGS+=	--build=${NATIVE_MACHINE_GNU_PLATFORM:Q}
@@ -86,6 +87,9 @@ CONFIGURE_ARGS+=	--build=${NATIVE_MACHINE_GNU_PLATFORM:Q}
 CONFIGURE_ARGS+=	--build=${MACHINE_GNU_PLATFORM:Q}
 .  endif
 CONFIGURE_ARGS+=	--host=${MACHINE_GNU_PLATFORM:Q}
+.  if ${USE_GNU_CONFIGURE_TARGET:tl} == "yes"
+CONFIGURE_ARGS+=	--target=${TARGET_MACHINE_GNU_PLATFORM:Q}
+.  endif
 .endif
 
 # PKGINFODIR is the subdirectory of ${PREFIX} into which the info

From bc4a7864289ec245b2223525ee02c81dabbec6e2 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Thu, 29 Jun 2023 01:24:05 +0000
Subject: [PATCH 4/5] mk: Use MACHINE_PLATFORM, not MACHINE_ARCH, for
 work/packages.

Fix bogus default PACKAGES setting -- this was shadowed by the one in
mk/defaults/mk.conf, so it never took effect.
---
 mk/bsd.prefs.mk     | 6 ++----
 mk/defaults/mk.conf | 5 +++--
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/mk/bsd.prefs.mk b/mk/bsd.prefs.mk
index 2468a458f03f..1e736687d14e 100644
--- a/mk/bsd.prefs.mk
+++ b/mk/bsd.prefs.mk
@@ -799,12 +799,10 @@ MAKEFLAGS+=		_PKGSRCDIR=${_PKGSRCDIR:Q}
 .endif
 PKGSRCDIR=		${_PKGSRCDIR}
 
-.if !empty(USE_CROSS_COMPILE:M[yY][eE][sS])
-_CROSSDIR_SUFFIX=	.${MACHINE_ARCH}
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+_CROSSDIR_SUFFIX=	.${MACHINE_PLATFORM}
 .endif
 
-DISTDIR?=		${PKGSRCDIR}/distfiles
-PACKAGES?=		${PKGSRCDIR}/packages${_CROSSDIR_SUFFIX}
 TEMPLATES?=		${PKGSRCDIR}/templates
 
 PATCHDIR?=		${.CURDIR}/patches
diff --git a/mk/defaults/mk.conf b/mk/defaults/mk.conf
index ffb691133ff6..e64a86ae9177 100644
--- a/mk/defaults/mk.conf
+++ b/mk/defaults/mk.conf
@@ -524,10 +524,11 @@ RCD_SCRIPTS_DIR?= ${SYSCONFBASE}/rc.d
 # Possible: any path you like
 # Default: ${SYSCONFBASE}/rc.d
 
-PACKAGES?=	${PKGSRCDIR}/packages
+PACKAGES?=	${PKGSRCDIR}/packages${${USE_CROSS_COMPILE:tl} == "yes":?.${MACHINE_PLATFORM}:}
 # Stores generated packages
 # Possible: any path you like
-# Default: ${PKGSRCDIR}/packages
+# Default: ${PKGSRCDIR}/packages, or ${PKGSRCDIR}/packages.${MACHINE_PLATFORM}
+# if cross-compiling.
 
 #PASSIVE_FETCH=
 # Use ftp(1) in passive mode, for use behind filtering firewalls.

From 9135d458559e9901b9265140dd31b99f000e6200 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Thu, 29 Jun 2023 01:25:01 +0000
Subject: [PATCH 5/5] doc/TODO.crosscompile: Note OBJECT_FMT issue.

Mostly a matter of copying a table in bsd.prefs.mk, which is annoying
and a bit of a maintenance burden if it gets out of sync but not in
principle a difficult problem.
---
 doc/TODO.crosscompile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/TODO.crosscompile b/doc/TODO.crosscompile
index f358fa6164bb..9f0b486e019d 100644
--- a/doc/TODO.crosscompile
+++ b/doc/TODO.crosscompile
@@ -15,3 +15,4 @@ $NetBSD: TODO.crosscompile,v 1.9 2023/06/03 15:01:05 riastradh Exp $
 * Make sure cross-builds DTRT with INSTALL scripts.
 * Fix cmake.
 * Handle BUILD_DEPENDS/TOOL_DEPENDS split in bsd.pkg.readme.mk.
+* Handle OBJECT_FMT, e.g. making NetBSD packages (elf) on macOS (mach-o).