Subject: WIP: USE_NEW_TOOLCHAIN for i386 Build from an Alpha Running OpenBSD
To: None <tech-toolchain@netbsd.org>
From: Chris Jepeway <jepeway@blasted-heath.com>
List: tech-toolchain
Date: 09/10/2001 19:38:33
Well...don't shoot me, but I've made decent progress with
USE_NEW_TOOLCHAIN for an i386 -current build hosted on an
Alpha running OpenBSD-2.9.

I figured using a different O/S and a different processor
would uncover all sorta problems with the new toolchain that
might otherwise stay hidden.  Too, I only have clunky
133MHz i386 boxes for native builds, so I thought compiling
on my clunky 233MHz Alpha might save me some time.

Well, I was right on the first count :)

I started out intending to write up a cookbook-type document
for me and some colleagues that'd be helpful to anyone
working with USE_NEW_TOOLCHAIN.  That was a mistake--I should
have just logged every change I made as I made it.  Nevertheless,
having begun in a "do this first, do that next" format, I tried
to stick to it.  Since I've iterated over a few "make dependall"
runs, correcting whatever crops up, though, it's less of a
cookbook and more of a list of problems and how I fixed them.

By "decent progress," I mean I've got most userland binaries compiled.
For example, the Alpha builds a /bin/cat executable that runs on a
386 running NetBSD-1.5.1.  The execs that don't build yet are
hpftodit, most of the DHCP stuff, and a few RPC servers.  The
other "dependall" targets compiles.

I've not tried any kernel builds.  I'm just now starting on
wrestling with "make release".

I'm not totally sure that diffs to everything I've changed
would be helpful, since I doubt the changes I've made are
stylish enough.  However, I'll put one up tomorrow at
http://www.blasted-heath.com/netbsd/tc1.diff.

Lessee, what else?  I synced to -current as of Wed/Thu of last week.

Oh, and I hope I understand the ${MACHINE} vs. ${MACHINE_ARCH}
distinction properly. ${MACHINE} is the hosting architecture,
and ${MACHINE_ARCH} is the target architecture, right?  If I've
got that screwed up, well, this doc is just wrong.

If you Emacs, the doc's in outline format.

Chris <jepeway@blasted-heath.com>.




* cd to the src dir

  % cd /export/netbsd-1.5/src
  % set p = $PWD

* MAKECONF

  __TOP			= /export/netbsd-1.5
  __SRC			= $(__TOP)/src
  __OBJ			= $(__TOP)/obj
  __TOOLARCH		= obsd-alpha
  __TARGARCH		= i386
  MACHINE_ARCH		= $(__TARGARCH)
  USE_NEW_TOOLCHAIN	= yes
  TOOLDIR		= $(__OBJ)/$(__TOOLARCH)
  MKTOOLS		= yes
  MKOBJDIRS		= yes
  BSDOBJDIR		= $(__OBJ)/$(MACHINE_ARCH)
  BSDSRCDIR		= $(__SRC)
  DESTDIR		= $(BSDOBJDIR)/Root
  MKINFO		= no

* Build bmake

  % ( cd usr.bin/make ; make -f Makefile.boot MACHINE=alpha MACHINE_ARCH=alpha )

* Put bmake somewhere it can be found via PATH

  % cp usr.bin/make/bmake ~/bin

  Ideally, bmake would go in $(TOOLDIR)/bin

* Create obj dirs

  Even though Open and Net are similar, you can't just start on a build,
  because, eg, you need an "install" that groks "-r".

  % bmake -k -m $p/share/mk MAKECONF=$p/mk.conf do-make-obj \
    MKLINT=no MKCRYPTO=no MKMAN=no

* Add some macros that the toolchain .c files want

  Add these to tools/compat/compat_netbsd.h

	#ifndef __RCSID   
	#define __RCSID(x)
	#endif

	#ifndef __COPYRIGHT   
	#define __COPYRIGHT(x)
	#endif

* Fix mkdep

  mkdep won't use the C compiler from the new toolchain.
  Instead, it'll use the native compiler, which, of course,
  wrecks everything.

  First, fix the mkdep source to define the macro DEFAULT_CC only
  if it hasn't been already defined.

  In the file usr.sbin/mkdep.c, protect the #define of DEFAULT_CC
  by wrapping it in a #ifndef.  Change

	#define DEFAULT_CC		"cc"

  to

	#ifndef DEFAULT_CC
	#define DEFAULT_CC		"cc"
	#endif

  Next, change the file tools/mkdep/Makefile so it sets DEFAULT_CC
  by adding the line

	HOST_CFLAGS += '-DDEFAULT_CC="$(TOOLDIR)/bin/$(MACHINE_GNU_PLATFORM)-gcc"'

	
  before the .include line.

* Make obj dirs for tools

  % ( cd tools ; bmake -m $p/share/mk 'BSDOBJDIR=$(TOOLDIR)' \
				      MAKECONF=$p/mk.conf obj )

* Fix usr.sbin/config/Makefile

  Protect .include of bsd.prog.mk:

	.ifndef HOSTPROG
	.include <bsd.prog.mk>
	.endif

* Fix configure.host files for gdb

  The configure.host files that come with NetBSD don't know
  about OpenBSD.  Fixing them consists of adding lines that
  look like

	alpha*-*-openbsd*)      gdb_host=obsd ;;

  to the case statements that set the gdb_host variable in the
  files gnu/dist/{toolchain,}/gdb/configure.host

* Add config files for OpenBSD/Alpha to tools/toolchain/gdb/config

  You'll need all the files from OpenBSD that match the glob *obsd*
  found in the directories /usr/src/gnu/usr.bin/binutils/gdb/config{,/alpha}.
  They should be copied to gnu/dist/toolchain/gdb/config{,/alpha}.

* Change tools/Makefile so it doesn't build texinfo

  texinfo won't build, since its configure writes to a file not in obj/.
  So, change the line

                toolchain .WAIT texinfo

  in tools/Makefile to		

                toolchain #.WAIT texinfo

* Fix tools/Makefile so it creates includes for gcc

  This one is ugly.  tools/Makefile changes the Makefile for gcc
  so that some targets like libgcc.a aren't made.  However, when
  those targets don't get made, then (some of) their dependencies
  don't get made either.  In particular, some of the include files
  gcc wants don't get made, and so not all of gcc is built.  The
  fix is ugly, and it might be overkill.  Nevertheless...

  For the target toolchain.configure in the file tools/Makefile,
  change the line that looks like

		Makefile.orig >Makefile

  to

		Makefile.orig | \
		sed 's/^STMP_FIXPROTO =$$/STMP_FIXPROTO = stmp-int-hdrs/' \
			>Makefile

* Make tools

  % ( cd tools ; bmake -m $p/share/mk MAKECONF=$p/mk.conf \
				      BSDOBJDIR='$(TOOLDIR)' build )

* Fix Makefile.tools

  As it turns out, the install part of the gcc build isn't smart enough
  to figure out that it's building a cross-compiling version of cpp.
  As a consequence, you'll need to change the definition of CPP in
  tools/Makefile.tools from

	CPP=		${TOOLDIR}/bin/${MACHINE_GNU_PLATFORM}-cpp

  to		

	CPP=		${TOOLDIR}/bin/cpp

* mtree wants the user games to exist

  % sudo user add games

* make the distrib-dirs

  % su
  # bmake -m $PWD/share/mk MAKECONF=$PWD/mk.conf beforeinstall

* Fix some MACHINE vs. MACHINE_ARCH make variable problems

  MACHINE_ARCH is the architecture of the target machine.
  MACHINE is the arch of the building (aka host) machine.
  Some *.mk files use MACHINE instead of MACHINE_ARCH.  Fix them.

  In share/mk/bsd.kmod.mk, change the commands that update
  machine-links: target from

      machine-links:
	    -rm -f machine && \
		ln -s $S/arch/${MACHINE}/include machine
	    -rm -f ${MACHINE_ARCH} && \
		ln -s $S/arch/${MACHINE_ARCH}/include ${MACHINE_ARCH}
	    CLEANFILES+=machine ${MACHINE_ARCH}

  to

      machine-links:
	    -rm -f machine && \
		ln -s $S/arch/${MACHINE_ARCH}/include machine
    #	-rm -f ${MACHINE_ARCH} && \
    #	    ln -s $S/arch/${MACHINE_ARCH}/include ${MACHINE_ARCH}
	    CLEANFILES+=machine #${MACHINE_ARCH}


  In the file share/mk/bsd.kernobj.mk, change
  
	KERNARCHDIR?=   arch/${MACHINE}
	
  to

	KERNARCHDIR?=   arch/${MACHINE_ARCH}

  In the file sys/arch/Makefile, change all occurrences of
  ${MACHINE} to ${MACHINE_ARCH}.

* Fix gnu/lib/libstdc++/config/Makefile to use MACHINE_ARCH

  In gnu/lib/libstdc++/config/Makefile, change

	INCSDIR=	/usr/include/${MACHINE}

  to	

	INCSDIR=	/usr/include/${MACHINE_ARCH}

* Make includes

  The includes target doesn't pick up Makefile.tools, so you
  must set INSTALL to get the includes into $DESTDIR/usr/include,
  where the rest of the build system expects them to be.

  # bmake -k -m $PWD/share/mk MAKECONF=$PWD/mk.conf includes \
			      INSTALL='$(TOOLDIR)/bin/binstall' \
			      MKCRYPTO=no
  # exit			 

  You need MKCRYPTO=no here.  Without it, you'll try to build
  compile_et, a binary which is needed to generate Kerberos .h
  files.  compile_et isn't part of the new toolchain, yet, so it
  bombs trying to link in setprogname().

  Ignore any errors about usr.bin/dbsym and in usr.sbin/pvctxctl,
  gnu/usr.bin/gcc/, and src/regress/lib/libc/arch/i386.

* Build the C startup libs

  % ( cd lib/csu ; bmake -m $PWD/share/mk MAKECONF=$PWD/mk.conf dependall )

* Add MKCRYPT=no to mk.conf

* Set some make variables in the environment

  % setenv MAKECONF $p/mk.conf
  % setenv MACHINE_ARCH i386

  I should have begun with these set, but better late than never.
  I'm not sure MACHINE_ARCH is necessary, but I (think I)
  encountered some problem that was fixed by setting it.

* Build the system libs

  % ( cd lib ; bmake -e -m $p/share/mk -k dependall MKSHARE=no )

  You need the -k so the missing include file <machine/ecoff_machdep.h>
  and a missing y.tab.h won't cause the depending to fail.

* Install the csu & system libs

  % su
  # set p = $PWD
  # cd lib && bmake -e -m $p/share/mk install
  # exit

* Build the GNU libs

  % ( cd gnu/lib ; bmake -e -m $p/share/mk dependall MKSHARE=no )

* Install the GNU libs

  # cd gnu/lib && bmake -e -m $p/share/mk install MKSHARE=no
  # exit

* Fix usr.bin/file/ so that mkmagic can built for the hosting machine

  Change the lines in usr.bin/file/apprentice.c that look like

	#else
	__RCSID("$NetBSD: ... ")
	#endif

  to

	#elsif defined(__NetBSD__)
	__RCSID("$NetBSD: ... ")
	#endif

  Do the same for usr.bin/file/print.c.  Ideally, I suppose, the
  HOST_CC make variable could be set to drag in the compat parts
  of the tools/ directory.

  Next, change the fmttime() function in usr.bin/file/print.c
  so that it can be compiled & run on machines that don't
  support the USG/Unix-98/XSH5 daylight global variable.
  Change the line

		if (daylight)
  
  to

		time_t tt = time(0);
		tm = localtime(&tt);
		if (tm->tm_isdst > 0)

  I'm not entirely sure this is equivalent to using the daylight global.
  If it is, though, I wonder if something like the following should go
  the tools compat library:

		#ifdef IDUNNOdaylight
		#define daylight __daylight__()
		int __daylight__(void)
		{
			static int __daylight;
			static int initialized = 0;
			if (!initialized) {
			   time_t t = time(0);
			   tm = localtime(&t);
			   __daylight = tm->tm_isdst > 0;
			}
			return __daylight;
		}
		#endif

* Fix usr.bin/kdump/Makefile.ioctl-c to use $(DESTDIR) includes

  By default, the list of ioctls that kdump knows how to decode
  is built using the shell script usr.bin/kdump/mkioctls.  mkioctls
  isn't being invoked correctly: it will use the native cc and it won't
  see DESTDIR.  So, change the first line of the commands updating
  ioctl.c in Makefile.ioctl-c from

      /bin/sh ${.CURDIR}/../kdump/mkioctls ${DESTDIR}/usr/include/sys/ioctl.h \
	    ${DESTDIR}/usr/include/sys/ioctl_compat.h > ioctl.c

  to

      CC=$(CC) DESTDIR=$(DESTDIR) /bin/sh ${.CURDIR}/../kdump/mkioctls ${DESTDIR}/usr/include/sys/ioctl.h \


* Add HOST_CFLAGS to mk.conf to fix some incompatibilities w/ NetBSD

  Add the lines

      HOST_CFLAGS             += '-D__RCSID(x)='
      HOST_CFLAGS             += '-D__COPYRIGHT(x)='

  to mk.conf.  Ideally, we'd get these straight from the compat
  part of tools/, which could perhaps get put into bsd.hostprog.mk.

  These changes make one set of previous mods to src in usr.bin/file/
  unnecessary (though those mods don't hurt anything).

  Perhaps these mods should instead be made to HOST_CPPFLAGS.

* Fix more MACHINE vs. MACHINE_ARCH in sys/lkm/

  The references to MACHINE should really be MACHINE_ARCH.  Oddly,
  there are proper uses of MACHINE_ARCH scattered throughout the
  Makefiles in this hierarchy.

  The files that need fixing, named relative to sys/lkm/:

	compat/Makefile
	compat/linux/Makefile
	exec/Makefile
	exec/linux_elf/Makefile

  Change all occurrences of {MACHINE} to {MACHINE_ARCH}.

* Fix some trickier MACHINE vs. MACHINE_ARCH in sys/lkm/

** sys/lkm compat/linux/Makefile.inc 

   This file contains a conditional that looks like it's trying to
   compensate for (historical?) problems when MACHINE_ARCH doesn't
   necessarily get set.  If sys/$(MACHINE)/$(MACHINE)/genassym.cf exists,
   that's used to build assym.h.  Otherwise, it does the same check
   using $(MACHINE_ARCH).  This should change either to try $(MACHINE_ARCH)
   first, or to never try $(MACHINE).

   So, in the file sys/lkm/compat/linux/Makefile.inc, change the lines

      .if exists($S/arch/${MACHINE}/${MACHINE}/genassym.cf)
      GENASSYM_DIR?= $S/arch/${MACHINE}/${MACHINE}
      .elif exists($S/arch/${MACHINE_ARCH}/${MACHINE_ARCH}/genassym.cf)
      GENASSYM_DIR?= $S/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
      .else
      GENASSYM_DIR?=
      .endif

   to

      .if exists($S/arch/${MACHINE_ARCH}/${MACHINE_ARCH}/genassym.cf)
      GENASSYM_DIR?= $S/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
      .else
      GENASSYM_DIR?=
      .endif

   to ignore $(MACHINE) altogether.

** sys/lkm/exec/linux_elf/Makefile

   This file unconditionally sets -DEXEC_ELF64.  It seems to me
   that it should be changed to only set that for 64bit architectures.
   So, two changes:

   Change

	CPPFLAGS+=	-nostdinc -I$S -D_KERNEL -DEXEC_ELF32 -DEXEC_ELF64

   to
	CPPFLAGS+=	-nostdinc -I$S -D_KERNEL -DEXEC_ELF32

   and change

	SRCS+=  linux_exec_elf64.c
	
   to

	SRCS+=  linux_exec_elf64.c
	CPPFLAGS+=      -DEXEC_ELF64

   I haven't tried the build without this change to see if it's necessary,
   so somebody who knows the code should comment.  Also, it may be that
   -DEXEC_ELF32 should be defined *only* for 32-bit archs, I dunno.

* Delete reference to dbsym

  The dbsym executable doesn't seem to exist any longer.
  However, usr.sbin/Makefile thinks that it does.  Convince
  it otherwise by removing its use of the word "dbsym".

* Build it all

  % bmake -k -e -m $p/share/mk dependall

* Some builds fail

** The Don't Cares

*** Man pages are made with native nroff

    nroff should get into the tools dir so that man pages
    are built properly.  Some macros don't necessarily work
    on non-NetBSD systems.  Here's an example from make's
    man page:

        .SUFFIXES   Each source specifies a suffix to .

    Maybe using a shell script that points the native
    nroff at the NetBSD macros would work.

*** DHCP won't compile

    usr.sbin/dhcp/Makefile.inc sets DIST to point to dist/dhcp, which hoses
    redefinitions in some include files in usr.sbin/dhcp, eg, in the file
    usr.sbin/dhcp/includes/omapip/alloc.h.

   The problem is with DIST set, includes first from $(DIST) and the
   .h files in the usr.sbin/dhcp hierarchy are skipped.

*** rpc.* servers from OpenBSD won't compile

    rpc.bootparamd, rpc.statd

    The problem here is that warnings are being treated as errors
    and __RCSID() magic isn't being used to squelch gcc's complaint
    about an unused "rcsid" variable.

*** usr.bin/groff/hpftodit/../../../dist/groff/src/utils/htpftodit/hpftodit.cc

    Hm.  The assembler doesn't like some comparisons generated from this file:

	 Error: Value of 4294967296 too large for field of 4 bytes at 1724

** The Do Cares

*** gnu/usr.bin/gcc won't compile

**** gnu/usr.bin/gcc/backend/Makefile needs help

     There's a bootstrapping problem in this Makefile.  It tries
     build .depend, but it can't do that until it first generates
     some .h and .c files from .md files.  The fix is to add the
     generated files to the DPSRCS variable.

     However, there's also trouble with building the native object
     files used by the programs that generate the .[ch] files.
     The fix I've got for this problem is hairy, so I won't
     go into it any great detail.  Basically, I've never had
     make let me down whenever every last underlying dependency
     is expressed in some rule.  So, the fix changes the .for loop
     to say that each gen* program depends on the .lo files, and
     each file built from an .md file depends on the gen* prog.

     See the patch in the Patches section, below.

*** gnu/usr.bin/gcc/f771/Makefile needs help

    The problem here is similar to the previous one.  This time,
    the fix is structured a bit better.  See the patch in the Patches
    section.

** The Might Cares

*** Assembly warnings

    I have not idea whether these warnings matter.

**** libc: indirect jmp without `*'

   Building libc generates warnings from the assembler like this

	{standard input}:950: Warning: indirect jmp without `*'
	
    in the following files

	   	lib/libc/arch/i386/gen/alloca.S
		lib/libc/arch/i386/sys/Ovfork.S
		lib/libc/arch/i386/sys/__semctl.S
		lib/libc/arch/i386/sys/__sigreturn14.S
		lib/libc/arch/i386/sys/__syscall.S
		lib/libc/arch/i386/sys/__vfork14.S
		lib/libc/arch/i386/sys/brk.S
		lib/libc/arch/i386/sys/exect.S
		lib/libc/arch/i386/sys/fork.S
		lib/libc/arch/i386/sys/msgctl.S
		lib/libc/arch/i386/sys/pipe.S
		lib/libc/arch/i386/sys/ptrace.S
		lib/libc/arch/i386/sys/sbrk.S
		lib/libc/arch/i386/sys/setlogin.S
		lib/libc/arch/i386/sys/shmat.S
		lib/libc/arch/i386/sys/shmctl.S
		lib/libc/arch/i386/sys/sigaction.S
		lib/libc/arch/i386/sys/sigpending.S
		lib/libc/arch/i386/sys/sigprocmask.S
		lib/libc/arch/i386/sys/sigreturn.S
		lib/libc/arch/i386/sys/sigsuspend.S
			lib/libc/arch/i386/sys/syscall.S

*** libc: using %pishfoo instead of %posh due to `b' suffix

    Assembling lib/libc/arch/i386/string/memcmp.S generates
    warnings like these:

	     Warning: using `%al' instead of `%eax' due to `b' suffix
	     Warning: using `%dl' instead of `%edx' due to `b' suffix



* Install it all

  I haven't made it this far.

  % su
  # bmake -e -m $p/share/mk _BUILD= install

* Patches

** gnu/usr.bin/gcc/backend/Makefile

Index: Makefile
===================================================================
RCS file: /cvsroot/gnusrc/gnu/usr.bin/gcc/backend/Makefile,v
retrieving revision 1.1
diff -u -r1.1 Makefile
--- Makefile	2001/06/18 16:18:34	1.1
+++ Makefile	2001/09/10 16:50:07
@@ -12,12 +12,16 @@
 		-DTARGET_NAME=\"${MACHINE_GNU_ARCH}-netbsd\"
 HOST_CPPFLAGS+=	-I. -I${GCCARCH} ${G_ALL_CFLAGS:M-D*} ${G_INCLUDES:M-I*:N-I.*}
 
-.include <bsd.lib.mk>
-
 # Independent generation programs.
+
+CLEANFILES+=	gengenrtl gencheck
+#
+# Force these sources to be built b/4 .depend
+#
+DPSRCS+=	genrtl.c genrtl.h tree-check.h
+DPSRCS+=	insn-attr.h insn-codes.h insn-config.h insn-flags.h tree-check.h
 
-CLEANFILES+=	gengenrtl genrtl.c genrtl.h \
-		gencheck tree-check.h
+.include <bsd.lib.mk>
 
 genrtl.c genrtl.h: gengenrtl.c
 	${HOST_LINK.c} -o gengenrtl $>
@@ -26,32 +30,36 @@
 tree-check.h: gencheck.c
 	${HOST_LINK.c} -o gencheck $>
 	./gencheck >$@
-
-# Programs which depend on common sources.  The ${MAKE} dance
-# ensures that these programs regen their object files
-# whenever they are needed (so a build can be restarted on
-# another platform if desired).
 
+# The host progs use these libs
 LOFILES=	obstack.lo ${G_HOST_RTL:.o=.lo} ${G_HOST_PRINT:.o=.lo}
-lofiles: ${LOFILES}
 
-.if !target(.BEGIN) && !make(lofiles)
-.BEGIN:
-	@rm -f ${LOFILES}
-.endif
+# Progs which need to link w/ ${G_HOST_RTLANAL}
+NEEDRTLANAL=	genattr genattrtab
 
 .for f in attr.h attrtab.c codes.h config.h emit.c extract.c \
 	flags.h opinit.c peep.c output.c recog.c
-CLEANFILES+=	gen${f:R} insn-${f}
 
-insn-${f}: genrtl.h gen${f:R}.c
-	@cd ${.CURDIR} && ${MAKE} lofiles
-	${HOST_LINK.c} -o gen${f:R} ${>:M*.c} ${LOFILES}
+GENPROG = gen${f:R}
+CLEANFILES+=	${GENPROG} insn-${f}
+
+insn-${f}: ${GENPROG} ${G_md_file}
 	./gen${f:R} ${G_md_file} >$@
+
+.if ${NEEDRTLANAL:M*${GENPROG}*} == ${GENPROG}
+${GENPROG}: ${GENPROG}.o ${LOFILES} ${G_HOST_RTLANAL:.o=.lo}
+.else
+${GENPROG}: ${GENPROG}.o ${LOFILES}
+.endif
+	${HOST_LINK.c} -o $@ $>
+
+${GENPROG}.o: gen${f:R}.c rtl.h genrtl.h
+	${HOST_CC} ${HOST_CFLAGS} ${HOST_CPPFLAGS} -c ${>:M*.c}
+
 .endfor
+
+genextract.o genattrtab.o: insn-config.h
 
-insn-attrtab.c: ${G_HOST_RTLANAL:.o=.c}
-insn-extract.c: insn-config.h
 ${OBJS}: insn-attr.h insn-codes.h insn-config.h insn-flags.h tree-check.h
 
 .PATH: ${DIST}/gcc ${DIST}/libiberty ${G_out_file:H}

** gnu/usr.bin/gcc/f771/Makefile

Index: Makefile
===================================================================
RCS file: /cvsroot/gnusrc/gnu/usr.bin/gcc/f771/Makefile,v
retrieving revision 1.1
diff -u -r1.1 Makefile
--- Makefile	2001/06/18 16:18:35	1.1
+++ Makefile	2001/09/10 17:25:40
@@ -7,27 +7,21 @@
 HOST_CPPFLAGS+=	-I${GCCARCH} -DUSE_HCONFIG= \
 		${G_ALL_CFLAGS:M-D*} ${G_INCLUDES:M-I*:N-I.*}
 
-.include "../Makefile.backend"
-
-# See comment in ../backend/Makefile for the reason for
-# this ${MAKE} dance.
-
-fini: fini.c proj.c
-	${HOST_LINK.c} -o $@ $>
-
-.if !target(.BEGIN) && !make(fini)
-.BEGIN:
-	@rm -f fini
-.endif
+GENFILES=	1t 2t fo io nq op ot
+.for f in $(GENFILES)
+DPSRCS+=	str-${f}.h str-${f}.j
+.endfor
 
-.for f in 1t 2t fo io nq op ot
-CLEANFILES+=	str-${f}.h str-${f}.j
+.include "../Makefile.backend"
 
-str-${f}.h str-${f}.j: str-${f}.fin fini.c proj.c
-	@cd ${.CURDIR} && ${MAKE} fini
+.for f in $(GENFILES)
+str-${f}.h str-${f}.j: str-${f}.fin fini
 	./fini ${>:M*.fin} str-${f}.j str-${f}.h
 
 ${OBJS}: str-${f}.h
 .endfor
+
+fini: fini.c proj.c
+	${HOST_LINK.c} -o $@ $>
 
 .PATH: ${DIST}/gcc/f