1/*
2 * source and binary package support
3 *
4 * @(#)package.mk (AT&T Research) 2011-02-02
5 *
6 * usage:
7 *
8 *	cd $INSTALLROOT/lib/package
9 *	nmake -f name [closure] [cyg|exp|lcl|pkg|rpm|tgz] [base|delta] type
10 *
11 * where:
12 *
13 *	name	package description file or component
14 *
15 *	type	source	build source archive, generates
16 *			$(PACKAGEDIR)/name.version.release.suffix
17 *		binary	build binary archive, generates
18 *			$(PACKAGEDIR)/name.version.hosttype.release.suffix
19 *		runtime	build binary archive, generates
20 *			$(PACKAGEDIR)/name-run.version.hosttype.release.suffix
21 *
22 * NOTE: $(PACKAGEDIR) is in the lowest view and is shared among all views
23 *
24 * generated archive member files are $(PACKAGEROOT) relative
25 *
26 * main assertions:
27 *
28 *	NAME [ name=value ] :PACKAGE: component ...
29 *	:OMIT: component ...
30 *	:LICENSE: license-class-pattern
31 *	:CATEGORY: category-id ...
32 *	:COVERS: package ...
33 *	:REQURES: package ...
34 *	:INDEX: index description line
35 *	:DESCRIPTION:
36 *		[ verbose description ]
37 *	:DETAILS: style
38 *		:README:
39 *			readme lines
40 *		:EXPORT:
41 *			name=value
42 *		target :INSTALL: [ source ]
43 *
44 * option variables, shown with default values
45 *
46 *	format=tgz
47 *		archive format
48 *
49 *	version=YYYY-MM-DD
50 *		package base version (overrides current date)
51 *
52 *	release=YYYY-MM-DD
53 *		package delta release (overrides current date)
54 *
55 *	license=type.class
56 *		:LICENSE: type.class pattern override
57 *
58 *	notice=1
59 *		include the conspicuous empty notice file
60 *
61 *	copyright=0
62 *		do not prepend source file copyright notice
63 *
64 *	strip=0
65 *		don't strip non-lcl binary package members
66 *
67 *	variants=pattern
68 *		include variants matching pattern in binary packages
69 *
70 *	incremental=[source:1 binary:0]
71 *		if a base archive is generated then also generate an
72 *		incremental delta archive from the previous base
73 *
74 * NOTE: the Makerules.mk :PACKAGE: operator defers to :package: when
75 *	 a target is specified
76 */
77
78/* these are ast centric -- we'll parameterize another day */
79
80org = ast
81url = http://www.research.att.com/sw/download
82
83/* generic defaults */
84
85base =
86category = utils
87checksum = md5
88closure =
89copyright = 1
90delta =
91format = tgz
92incremental =
93index =
94init = INIT
95license =
96licenses = $(org)
97mamfile = 1
98opt =
99name =
100notice =
101release =
102strip = 0
103style = tgz
104suffix = tgz
105type =
106variants = !(cc-g)
107vendor =
108version = $("":T=R%Y-%m-%d)
109
110SUM = sum
111
112package.notice = ------------ NOTICE -- LICENSED SOFTWARE -- SEE README FOR DETAILS ------------
113
114package.readme = $(@.package.readme.)
115
116.package.readme. :
117	This is a package root directory $PACKAGEROOT. Source and binary
118	packages in this directory tree are controlled by the command
119	$()
120		bin/package
121	$()
122	Binary files may be in this directory or in the install root directory
123	$()
124		INSTALLROOT=$PACKAGEROOT/arch/`bin/package`
125	$()
126	For more information run
127	$()
128		bin/package help
129	$()
130	Many of the packaged commands self-document via the --man and --html
131	options; those that do have no separate man page.
132	$()
133	Each package has its own license file
134	$()
135		$(PACKAGELIB)/LICENSES/<prefix>
136	$()
137	where <prefix> is the longest matching prefix of the package name.
138	At the top of each license file is a URL; the license covers all
139	software referring to this URL. For details run
140	$()
141		bin/package license [<package>]
142	$()
143	A component within a package may have its own license file
144	$()
145		$(PACKAGELIB)/LICENSES/<prefix>-<component>
146	$()
147	or it may have a separate license detailed in the component
148	source directory.
149	$()
150	Many of the commands self-document via the --man and --html
151	options; those that do have no separate man page.
152	$()
153	Any archives, distributions or packages made from source or
154	binaries covered by license(s) must contain the corresponding
155	license file(s)$(notice:?, this README file, and the empty file$$("\n")$$(package.notice)?.?)
156
157.package.licenses. : .FUNCTION
158	local I F L R all text
159	L := $(%)
160	while L == "--*"
161		I := $(L:O=1)
162		if I == "--all"
163			all = 1
164		elif I == "--text"
165			text = 1
166		end
167		L := $(L:O>1)
168	end
169	if "$(L)" == "*-*"
170		L += $(L:/[^-]*-//) $(L:/-.*//)
171	end
172	L += $(licenses)
173	for I $(L:U)
174		if I == "gpl"
175			I = gnu
176			all =
177		end
178		if F = "$(I:D=$(PACKAGESRC):B:S=.lic:T=F)"
179			R += $(F)
180			if text
181				R += $(I:D=$(PACKAGESRC)/LICENSES:B)
182			end
183			if ! all
184				break
185			end
186		end
187	end
188	return $(R)
189
190/*
191 * glob(3) doesn't handle / in alternation -- should it?
192 */
193
194.package.glob. : .FUNCTION
195	local A D I P S
196	for I $(%)
197		if I == "*/*"
198			D := $(I:C,/.*,,)
199			if ! "$(A:N=$(D))"
200				local S.$(D)
201				A += $(D)
202			end
203			S.$(D) += $(I:C,[^/]*/,,)
204		else
205			P := $(P)$(S)$(I)
206		end
207		S = |
208	end
209	if P == "*\|*"
210		P := ($(P))
211	end
212	for I $(A)
213		P += $(I)/$(.package.glob. $(S.$(I)))
214	end
215	return $(P)
216
217
218.MAKEINIT : .package.init
219
220.package.init : .MAKE .VIRTUAL .FORCE
221	local V
222	V := $(VROOT:T=F:P=L*)
223	if ! PACKAGEROOT
224	PACKAGEROOT := $(V:N!=*/arch/+([!/]):O=1)
225	end
226	if V == "$(PACKAGEROOT)"
227		V :=
228	end
229	V += $(INSTALLROOT) $(PACKAGEROOT)
230	PACKAGEVIEW := $(V:H=RU)
231	INSTALLOFFSET := $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
232	if license
233		license := $(license)|none.none
234	end
235
236PACKAGELIB = lib/package
237PACKAGESRC = $(PACKAGEROOT)/$(PACKAGELIB)
238PACKAGEBIN = $(INSTALLROOT)/$(PACKAGELIB)
239PACKAGEDIR = $(PACKAGESRC)/$(style)
240INSTALLOFFSET = $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
241
242package.omit = -|*/$(init)
243package.glob.all = $(INSTALLROOT)/src/*/*/($(MAKEFILES:/:/|/G))
244package.all = $(package.glob.all:P=G:W=O=$(?$(name):A=.VIRTUAL):N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
245package.glob.pkg = $(.package.glob. $(~$(name):P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%) $(~$(name):P=U:N=$(name):?$$(INSTALLROOT)/src/$$(name)/($$(MAKEFILES:/:/|/G))??)
246package.pkg = $(package.glob.pkg:P=G:D:N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
247package.closure = $(closure:?$$(package.all)?$$(package.pkg)?)
248
249package.init = $(.package.glob. $("$(init)$(name)":P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%:P=G:T=F:D::B)
250package.ini = ignore mamprobe manmake package silent
251package.src.pat = $(PACKAGESRC)/($(name).(ini|lic|pkg))
252package.src = $(package.src.pat:P=G)
253package.bin = $(PACKAGEBIN)/$(name).ini
254
255op = current
256stamp = [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
257source = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(suffix)
258binary = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
259runtime = $(PACKAGEDIR)/$(name)-run.$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
260old.new.source = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(suffix)
261old.new.binary = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
262old.new.runtime = $(PACKAGEDIR)/$(name)-run.$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
263
264source.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(suffix)":P=G:H=R)
265binary.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H=R)
266runtime.list = $("$(PACKAGEDIR)/$(name)-run.*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H>)
267
268source.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz.c":T=F)
269binary.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz":T=F)
270
271$(init) : .VIRTUAL $(init)
272
273package.requires = 0
274
275":package:" : .MAKE .OPERATOR
276	local P I R V
277	P := $(<:O=1)
278	$(P) : $(>:V)
279	if ! package.requires
280		if ! name
281			name := $(P)
282			.PACKAGE. := $(P)
283			if name == "$(init)"
284				package.omit = -
285				package.src += $(package.ini:C,^,$(PACKAGEROOT)/bin/,) $(PACKAGESRC)/package.mk
286			else
287				$(P) : $(package.init)
288			end
289			for I $(<:O>1)
290				if I == "*=*"
291					eval
292					$(I)
293					end
294				else
295					version := $(I)
296				end
297			end
298			LICENSEFILE := $(.package.licenses. $(name):@/ /:/G)
299			export LICENSEFILE
300		end
301		if "$(>)"
302			for I $(>:V)
303				$(I) : .VIRTUAL
304				if I == "/*"
305					package.dir += $(I:V)
306				end
307			end
308		end
309		if "$(@)"
310			$(P).README := $(@)
311		else
312			$(P).README := This is the $(P) package.
313		end
314	end
315
316":AUXILIARY:" : .MAKE .OPERATOR
317	package.auxiliary.$(style) += $(>:N=/*:T=F) $(>:N!=/*:C%^%$(INSTALLROOT)/%:T=F)
318
319":CATEGORY:" : .MAKE .OPERATOR
320	if ! package.requires
321		category := $(>)
322	end
323
324.covers. : .FUNCTION
325	local I C D F K=0 L
326	for I $(%)
327		if ! "$(~covers:N=$(I:B))"
328			if F = "$(I:D:B:S=.pkg:T=F)"
329				if D = "$(F:T=I)"
330					covers : $(I:B)
331					for L $(D)
332						if L == ":COVERS:"
333							K = 1
334						elif L == ":*:"
335							if K
336								break
337							end
338						elif K
339							: $(.covers. $(L))
340						end
341					end
342				end
343			else
344				error $(--exec:?3?1?) $(I): unknown package $(I)
345			end
346		end
347	end
348
349":COVERS:" : .MAKE .OPERATOR
350	if ! package.requires
351		: $(.covers. $(>))
352	end
353
354":DESCRIPTION:" : .MAKE .OPERATOR
355	if ! package.requires
356		$(name).README := $(@:V)
357	end
358
359":DETAILS:" : .MAKE .OPERATOR
360	if ! package.requires
361		details.$(>:O=1) := $(@:V)
362	end
363
364":EXPORT:" : .MAKE .OPERATOR
365	if ! package.requires
366		export.$(style) := $(@:/$$("\n")/ /G)
367	end
368
369":INDEX:" : .MAKE .OPERATOR
370	if ! package.requires
371		index := $(>)
372	end
373
374":INSTALL:" : .MAKE .OPERATOR
375	if ! package.requires
376		local T S F X
377		S := $(>)
378		T := $(<)
379		if "$(exe.$(style))" && "$(T)" == "bin/*([!./])"
380			T := $(T).exe
381		end
382		if ! "$(S)"
383			S := $(T)
384		elif "$(exe.$(style))" && "$(S)" == "bin/*([!./])"
385			S := $(S).exe
386		end
387		install.$(style) := $(install.$(style):V)$("\n")install : $$(ROOT)/$(T)$("\n")$$(ROOT)/$(T) : $$(ARCH)/$(S)$("\n\t")cp $< $@
388		if strip && "$(T:N=*.exe)"
389			install.$(style) := $(install.$(style):V)$("\n\t")strip $@ 2>/dev/null
390		end
391		X := $(PACKAGEROOT)/arch/$(CC.HOSTTYPE)/$(S)
392		if strip && "$(X:T=Y)" == "*/?(x-)(dll|exe)"
393			F := filter $(STRIP) $(STRIPFLAGS) $(X)
394		end
395		if "$(filter.$(style):V)"
396			filter.$(style) := $(filter.$(style):V)$$("\n")
397		end
398		filter.$(style) := $(filter.$(style):V);;$(F);$(X);usr/$(T)
399	end
400
401":LICENSE:" : .MAKE .OPERATOR
402	if ! package.requires && ! license
403		license := $(>)
404	end
405
406":OMIT:" : .MAKE .OPERATOR
407	if ! package.requires
408		package.omit := $(package.omit)|$(>:C,^,*/,:/ /|/G)
409	end
410
411":POSTINSTALL:" : .MAKE .OPERATOR
412	if ! package.requires
413		postinstall.$(style) := $(@:V)
414	end
415
416":README:" : .MAKE .OPERATOR
417	if ! package.requires
418		readme.$(style) := $(@:V)
419	end
420
421.requires. : .FUNCTION
422	local I C D F K=0 L V T M=0
423	for I $(%)
424		if ! "$(~requires:N=$(I:B))"
425			if F = "$(I:D:B:S=.pkg:T=F)"
426				if I == "$(init)"
427					package.omit = -
428				else
429					requires : $(I:B)
430				end
431				if V = "$(I:D:B=gen/$(I:B):S=.ver:T=F)"
432					req : $(I:B)
433				else
434					error 1 $(I): package should be written before $(P)
435				end
436				let package.requires = package.requires + 1
437				include "$(F)"
438				let package.requires = package.requires - 1
439			else
440				error 1 $(I): package not found
441			end
442		end
443	end
444
445":REQUIRES:" : .MAKE .OPERATOR
446	: $(.requires. $(>))
447
448":TEST:" : .MAKE .OPERATOR
449	if ! package.requires
450		local T
451		T := $(>)
452		if "$(T)" == "bin/*([!./])"
453			if "$(exe.$(style))"
454				T := $(T).exe
455			end
456			T := $$(PWD)/$$(ARCH)/$(T)
457		end
458		test.$(style) := $(test.$(style):V)$("\n")test : $(T:V)$("\n\t")$(@)
459	end
460
461base delta : .MAKE .VIRTUAL .FORCE
462	op := $(<)
463
464closure : .MAKE .VIRTUAL .FORCE
465	$(<) := 1
466
467cyg exp lcl pkg rpm tgz : .MAKE .VIRTUAL .FORCE
468	style := $(<)
469
470source : .source.init .source.gen .source.$$(style)
471
472.source.init : .MAKE
473	local A B D P V I
474	type := source
475	if ! "$(incremental)"
476		incremental = 1
477	end
478	if "$(source.$(name))"
479		suffix = c
480	end
481	: $(.init.$(style))
482	: $(details.$(style):V:R) :
483	A := $(source.list)
484	B := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
485	P := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
486	D := $(A:N=*.$(stamp).$(stamp).$(suffix):O=1:T=F)
487	if op == "delta"
488		if ! B
489			error 3 delta requires a base archive
490		end
491		base := -z $(B)
492		deltaversion := $(B:B:/$(name).//)
493		let deltasince = $(deltaversion:/.*-//) + 1
494		deltasince := $(deltaversion:/[^-]*$/$(deltasince:F=%02d)/)
495		if "$(release)" != "$(stamp)"
496			release := $("":T=R%Y-%m-%d)
497		end
498		source := $(B:D:B:S=.$(release).$(suffix))
499		version := $(source:B:B:/$(name).//)
500	elif B || op == "base"
501		if op == "base"
502			for I $(B) $(P)
503				V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
504				if V == "$(stamp)" && V != "$(version)"
505					old.version := $(V)
506					old.source := $(I)
507					if "$(old.version)" >= "$(version)"
508						error 3 $(name): previous base $(old.version) is newer than $(version)
509					end
510					break
511				end
512			end
513		else
514			source := $(B)
515		end
516		if B == "$(source)"
517			if "$(B:D:B:B)" == "$(D:D:B:B)" && "$(B:B::S)" != "$(D:B::S)"
518				error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
519			end
520			error 1 $(B:B:S): replacing current base
521		end
522		version := $(source:B:S:/^$(name).\(.*\).$(suffix)$/\1/)
523	end
524	PACKAGEGEN := $(PACKAGESRC)/gen
525
526.source.gen : $$(PACKAGEDIR) $$(PACKAGEGEN) $$(PACKAGEGEN)/SOURCE.html $$(PACKAGEGEN)/BINARY.html $$(PACKAGEGEN)/DETAILS.html
527
528BINPACKAGE := $(PATH:/:/ /G:X=package:T=F:O=1)
529
530$$(PACKAGEDIR) $$(PACKAGEGEN) : .IGNORE
531	[[ -d $(<) ]] || mkdir $(<)
532
533$$(PACKAGEGEN)/SOURCE.html : $(BINPACKAGE)
534	$(*) html source > $(<)
535
536$$(PACKAGEGEN)/BINARY.html : $(BINPACKAGE)
537	$(*) html binary > $(<)
538
539$$(PACKAGEGEN)/DETAILS.html : $(BINPACKAGE)
540	$(*) html intro > $(<)
541
542.source.exp .source.pkg .source.rpm : .MAKE
543	error 3 $(style): source package style not supported yet
544
545exe.cyg = .exe
546vendor.cyg = gnu
547
548.name.cyg : .FUNCTION
549	local N
550	N := $(%)
551	if N == "*-*"
552		vendor := $(N:/-.*//)
553		if vendor == "$(vendor.cyg)"
554			vendor :=
555			N := $(N:/[^-]*-//)
556		end
557		N := $(N:/-//G)
558	end
559	return $(N)
560
561.init.cyg : .FUNCTION
562	local N O
563	closure = 1
564	init = .
565	strip = 1
566	suffix = tar.bz2
567	format = tbz
568	vendor := $(licenses:N!=$(vendor.cyg):O=1)
569	package.ini := $(package.ini)
570	package.src.pat := $(package.src.pat)
571	package.src := $(package.src)
572	package.bin := $(package.bin)
573	.source.gen : .CLEAR $(*.source.gen:V:N!=*.html)
574	name.original := $(name)
575	name := $(.name.cyg $(name))
576	if name != "$(name.original)"
577		$(name) : $(~$(name.original))
578		O := $(~covers)
579		covers : .CLEAR
580		for N $(O)
581			covers : $(.name.cyg $(N))
582		end
583	end
584	stamp = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]
585	version.original := $(version)
586	version := $(version:/-//G)-1
587	if opt
588		opt := $(opt)/$(vendor)/
589	else
590		opt := $(name)-$(version)/
591	end
592	if type == "source"
593		version := $(version)-src
594		source = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
595	else
596		binary = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
597	end
598
599.source.cyg :
600	if	[[ '$(~$(name))' ]]
601	then	tmp=/tmp/pkg$(tmp)
602		mkdir $tmp
603		{
604			integer m=0 o
605			cat > $tmp/configure <<'!'
606	echo "you didn't have to do that"
607	!
608			chmod +x $tmp/configure
609			echo ";;;$tmp/configure;configure"
610			cat > $tmp/Makefile0 <<'!'
611	HOSTTYPE := $$(shell bin/package)
612	ROOT = ../..
613	ARCH = arch/$$(HOSTTYPE)
614	all :
615		PACKAGEROOT= CYGWIN="$$CYGWIN ntsec binmode" bin/package make $(export.$(style))
616	install : all
617	$(install.$(style):V)
618	$(test.$(style):V)
619	!
620			echo ";;;$tmp/Makefile0;Makefile"
621			cat > $tmp/CYGWIN-README <<'!'
622	$(readme.$(style):@?$$(readme.$$(style))$$("\n\n")??)To build binaries from source into the ./arch/`bin/package` tree run:
623	$()
624		make
625	$()
626	$(test.$(style):@?To test the binaries after building/installing run:$$("\n\n\t")make test$$("\n\n")??)To build and/or install the binaries run:
627	$()
628		make install
629	$()
630	The bin/package command provides a command line interface for all package
631	operations. The $(opt:/.$//) source and binary packages were generated by:
632	$()
633		package write cyg base source version=$(version.original) $(name.original)
634		package write cyg base binary version=$(version.original) $(name.original)
635	$()
636	using the $(org)-base package. To download and install the latest
637	$(org)-base source package in /opt/$(org) run:
638	$()
639		PATH=/opt/$(org)/bin:$PATH
640		cd /opt/$(org)
641		package authorize "NAME" password "PASSWORD" setup flat source $("\\")
642			$(url) $("\\")
643			$(org)-base
644		package make
645	$()
646	and export /opt/$(org)/bin in PATH to use. The NAME and PASSWORD signify your
647	agreement to the software license(s). All users get the same NAME and PASSWORD.
648	See $(url) for details. If multiple architectures may be built under
649	/opt/$(org) then drop "flat" and export /opt/$(org)/arch/`package`/bin in PATH
650	to use. To update previously downloaded packages from the same url simply run:
651	$()
652		cd /opt/$(org)
653		package setup
654		package make
655	$()
656	To download and install the latest $(org)-base binary package in
657	/opt/$(org) change "source" to "binary" and omit "package make".
658	!
659			echo ";;;$tmp/CYGWIN-README;CYGWIN-PATCHES/README"
660			cat > $(source:/-src.$(suffix)//).setup.hint <<'!'
661	category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
662	requires: cygwin
663	sdesc: "$(index)"
664	ldesc: "$($(name.original).README)"
665	!
666			echo ";;;$(source:/-src.$(suffix)//).setup.hint;CYGWIN-PATCHES/setup.hint"
667			echo ";;;$(BINPACKAGE);bin/package"
668			cat > $tmp/Makefile <<'!'
669	:MAKE:
670	!
671			echo ";;;$tmp/Makefile;src/Makefile"
672			echo ";;;$tmp/Makefile;src/cmd/Makefile"
673			echo ";;;$tmp/Makefile;src/lib/Makefile"
674			if	[[ '$(mamfile)' == 1 ]]
675			then	cat > $tmp/Mamfile1 <<'!'
676	info mam static
677	note source level :MAKE: equivalent
678	make install
679	make all
680	exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
681	done all virtual
682	done install virtual
683	!
684				echo ";;;$tmp/Mamfile1;src/Mamfile"
685				cat > $tmp/Mamfile2 <<'!'
686	info mam static
687	note component level :MAKE: equivalent
688	make install
689	make all
690	exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
691	done all virtual
692	done install virtual
693	!
694				echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
695				echo ";;;$tmp/Mamfile2;src/lib/Mamfile"
696			fi
697			$(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
698			echo ";;;$(PACKAGEGEN)/$(name.original).req"
699			set -- $(package.closure)
700			for i
701			do	cd $(INSTALLROOT)/$i
702				if	[[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
703				then	if	[[ '$(mamfile)' == 1 ]]
704					then	(( o=m ))
705						s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
706						if	[[ $s ]]
707						then	for j in $s
708							do	if	[[ -d $j ]]
709								then	cd $j
710									if	[[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
711									then	(( m++ ))
712										$(MAKE) --never --force --mam=static --corrupt=accept CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test $(export.$(style):Q) > $tmp/$m.mam
713										echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
714									fi
715									cd $(INSTALLROOT)/$i
716								fi
717							done
718							if	(( o != m ))
719							then	(( m++ ))
720								cat > $tmp/$m.mam <<'!'
721	info mam static
722	note subcomponent level :MAKE: equivalent
723	make install
724	make all
725	exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
726	done all virtual
727	done install virtual
728	!
729								echo ";;;$tmp/$m.mam;$i/Mamfile"
730							fi
731						else	(( m++ ))
732							$(MAKE) --never --force --mam=static --corrupt=accept CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test $(export.$(style):Q) > $tmp/$m.mam
733							echo ";;;$tmp/$m.mam;$i/Mamfile"
734						fi
735					fi
736					$(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q)
737				fi
738			done
739			set -- $(package.dir:P=G)
740			for i
741			do	tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
742			done
743		} |
744		{
745			: > $tmp/HEAD
746			cat > $tmp/README <<'!'
747	$(package.readme)
748	!
749			echo ";;;$tmp/README;README"
750			sort -t';' -k5,5 -u
751			: > $tmp/TAIL
752			[[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
753		} |
754		$(PAX)	--filter=- \
755			--to=ascii \
756			--format=$(format) \
757			--local \
758			-wvf $(source) $(base) \
759			$(PACKAGEVIEW:C%.*%-s",^&/,,"%) \
760			$(vendor:?-s",^[^/],$(opt)&,"??)
761		$(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
762		rm -rf $tmp
763	fi
764
765.source.lcl :
766	if	[[ '$(~$(name))' ]]
767	then	tmp=/tmp/pkg$(tmp)
768		mkdir $tmp
769		{
770			integer m=0 o
771			$(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
772			set -- $(package.closure)
773			for i
774			do	cd $(INSTALLROOT)/$i
775				$(MAKE) --noexec $(-) $(=) .FILES.+=Mamfile recurse list.package.local
776			done
777			set -- $(package.dir:P=G)
778			for i
779			do	tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
780			done
781		} |
782		$(PAX)	--filter=- \
783			--to=ascii \
784			$(op:N=delta:??--format=$(format)?) \
785			--local \
786			-wvf $(source) $(base) \
787			$(op:N=delta:?--format=gzip??) \
788			$(PACKAGEVIEW:C%.*%-s",^&/,,"%)
789		rm -rf $tmp
790	fi
791
792.source.tgz :
793	if	[[ '$(~$(name))' ]]
794	then	tmp=/tmp/pkg$(tmp)
795		mkdir $tmp
796		{
797			integer m=0 o
798			if	[[ '$(init)' == '$(name)' ]]
799			then	cat > $tmp/Makefile <<'!'
800	:MAKE:
801	!
802				$(CMP) $(CMPFLAGS) $tmp/Makefile $(PACKAGEROOT)/src/Makefile && touch -r $(PACKAGEROOT)/src/Makefile $tmp/Makefile
803				echo ";;;$tmp/Makefile;src/Makefile"
804				cp $tmp/Makefile $tmp/Makefile1
805				$(CMP) $(CMPFLAGS) $tmp/Makefile1 $(PACKAGEROOT)/src/cmd/Makefile && touch -r $(PACKAGEROOT)/src/cmd/Makefile $tmp/Makefile1
806				echo ";;;$tmp/Makefile1;src/cmd/Makefile"
807				cp $tmp/Makefile $tmp/Makefile2
808				$(CMP) $(CMPFLAGS) $tmp/Makefile2 $(PACKAGEROOT)/src/lib/Makefile && touch -r $(PACKAGEROOT)/src/lib/Makefile $tmp/Makefile2
809				echo ";;;$tmp/Makefile2;src/lib/Makefile"
810				if	[[ '$(mamfile)' == 1 ]]
811				then	cat > $tmp/Mamfile1 <<'!'
812	info mam static
813	note source level :MAKE: equivalent
814	make install
815	make all
816	exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
817	done all virtual
818	done install virtual
819	!
820					$(CMP) $(CMPFLAGS) $tmp/Mamfile1 $(PACKAGEROOT)/src/Mamfile && touch -r $(PACKAGEROOT)/src/Mamfile $tmp/Mamfile1
821					echo ";;;$tmp/Mamfile1;src/Mamfile"
822					cat > $tmp/Mamfile2 <<'!'
823	info mam static
824	note component level :MAKE: equivalent
825	make install
826	make all
827	exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
828	done all virtual
829	done install virtual
830	!
831					$(CMP) $(CMPFLAGS) $tmp/Mamfile2 $(PACKAGEROOT)/src/cmd/Mamfile && touch -r $(PACKAGEROOT)/src/cmd/Mamfile $tmp/Mamfile2
832					echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
833					cp $tmp/Mamfile2 $tmp/Mamfile3
834					$(CMP) $(CMPFLAGS) $tmp/Mamfile3 $(PACKAGEROOT)/src/lib/Mamfile && touch -r $(PACKAGEROOT)/src/lib/Mamfile $tmp/Mamfile3
835					echo ";;;$tmp/Mamfile3;src/lib/Mamfile"
836				fi
837			fi
838			$(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
839			if	[[ '$(~covers)' ]]
840			then	for i in $(~covers)
841				do	for j in pkg lic
842					do	if	[[ -f $(PACKAGESRC)/$i.$j ]]
843						then	echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
844						fi
845					done
846					for j in ver req
847					do	if	[[ -f $(PACKAGEGEN)/$i.$j ]]
848						then	echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
849						fi
850					done
851				done
852			fi
853			if	[[ '$(PACKAGEDIR:B)' == '$(style)' ]]
854			then	echo $(name) $(version) $(release|version) 1 > $tmp/t
855				$(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).ver || cp $tmp/t $(PACKAGEGEN)/$(name).ver
856				echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
857				sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $tmp/t
858				$(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).req || cp $tmp/t $(PACKAGEGEN)/$(name).req
859				echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
860				{
861					echo "name='$(name)'"
862					echo "index='$(index)'"
863					echo "covers='$(~covers)'"
864					echo "requires='$(~req)'"
865				} > $tmp/t
866				$(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).inx || cp $tmp/t $(PACKAGEGEN)/$(name).inx
867				{
868					{
869					echo '$($(name).README)'
870					if	[[ '$(~covers)' ]]
871					then	echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
872					fi
873					if	[[ '$(~requires)' ]]
874					then	echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
875					fi
876					} | fmt
877					package help source
878					package release $(name)
879				} > $tmp/t
880				$(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).README || cp $tmp/t $(PACKAGEGEN)/$(name).README
881				echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
882				{
883					echo '.xx title="$(name) package"'
884					echo '.xx meta.description="$(name) package"'
885					echo '.xx meta.keywords="software, package"'
886					echo '.MT 4'
887					echo '.TL'
888					echo '$(name) package'
889					echo '.H 1 "$(name) package"'
890					echo '$($(name).README)'
891					set -- $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F:D::B)
892					hot=
893					for i
894					do	hot="$hot -e s/\\(\\<$i\\>\\)/\\\\h'0*1'\\1\\\\h'0'/"
895					done
896					set -- $(package.closure:B)
897					if	(( $# ))
898					then	echo 'Components in this package:'
899						echo '.P'
900						echo '.TS'
901						echo 'center expand;'
902						echo 'l l l l l l.'
903						if	[[ $hot ]]
904						then	hot="sed $hot"
905						else	hot=cat
906						fi
907						for i
908						do	echo $i
909						done |
910						pr -6 -t -s'	' |
911						$hot
912						echo '.TE'
913					fi
914					echo '.P'
915					if	[[ '$(~covers)' ]]
916					then	echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
917					fi
918					if	[[ '$(~requires)' ]]
919					then	echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
920					fi
921					set -- $(.package.licenses. --all $(name))
922					case $# in
923					0)	;;
924					*)	case $# in
925						1)	echo 'The software is covered by this license:' ;;
926						*)	echo 'The software is covered by these licenses:' ;;
927						esac
928						echo .BL
929						for j
930						do	i=$( $(PROTO) -l $j -p -h -o type=usage /dev/null | sed -e 's,.*\[-license?\([^]]*\).*,\1,' )
931							echo .LI
932							echo ".xx link=\"$i\""
933						done
934						echo .LE
935						echo 'Individual components may be covered by separate licenses;'
936						echo 'refer to the component source and/or binaries for more information.'
937						echo .P
938						;;
939					esac
940					echo 'A recent'
941					echo '.xx link="release change log"'
942					echo 'is also included.'
943					cat $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F) < /dev/null
944					echo '.H 1 "release change log"'
945					echo '.xx index'
946					echo '.nf'
947					package release $(name) |
948					sed -e 's/:::::::: \(.*\) ::::::::/.fi\$("\n").H 1 "\1 changes"\$("\n").nf/'
949					echo '.fi'
950				} |
951				$(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
952				$(STDED) $(STDEDFLAGS) $tmp/t <<'!'
953	/^<!--LABELS-->$/,/^<!--\/LABELS-->$/s/ changes</</
954	/^<!--LABELS-->$/,/^<!--\/LABELS-->$/m/<A name="release change log">/
955	w
956	q
957	!
958				$(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).html || cp $tmp/t $(PACKAGEGEN)/$(name).html
959				echo ";;;$(PACKAGEGEN)/$(name).html;$(PACKAGELIB)/$(name).html"
960				if	[[ '$(deltasince)' ]]
961				then	{
962					echo '.xx title="$(name) package"'
963					echo '.xx meta.description="$(name) package $(version) delta $(release)"'
964					echo '.xx meta.keywords="software, package, delta"'
965					echo '.MT 4'
966					echo '.TL'
967					echo '$(name) package $(deltaversion) delta $(release)'
968					echo '.H 1 "$(name) package $(deltaversion) delta $(release) changes"'
969					echo '.nf'
970					package release $(deltasince) $(name) |
971					sed -e 's/:::::::: \(.*\) ::::::::/.H 2 \1/'
972					echo '.fi'
973					} |
974					$(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
975					$(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).$(release).html || cp $tmp/t $(PACKAGEGEN)/$(name).$(release).html
976					echo ";;;$(PACKAGEGEN)/$(name).$(release).html;$(PACKAGELIB)/$(name).$(release).html"
977				fi
978			fi
979			set -- $(package.closure)
980			for i
981			do	cd $(INSTALLROOT)/$i
982				if	[[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
983				then	if	[[ '$(mamfile)' == 1 ]]
984					then	(( o=m ))
985						s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
986						if	[[ $s ]]
987						then	for j in $s
988							do	if	[[ -d $j ]]
989								then	cd $j
990									if	[[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
991									then	(( m++ ))
992										$(MAKE) --never --force --mam=static --corrupt=accept CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test > $tmp/$m.mam
993										$(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/$j/Mamfile && touch -r $(PACKAGEROOT)/$i/$j/Mamfile $tmp/$m.mam
994										echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
995									fi
996									cd $(INSTALLROOT)/$i
997								fi
998							done
999							if	(( o != m ))
1000							then	(( m++ ))
1001								cat > $tmp/$m.mam <<'!'
1002	info mam static
1003	note subcomponent level :MAKE: equivalent
1004	make install
1005	make all
1006	exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
1007	done all virtual
1008	done install virtual
1009	!
1010								$(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
1011								echo ";;;$tmp/$m.mam;$i/Mamfile"
1012							fi
1013						else	(( m++ ))
1014							$(MAKE) --never --force --mam=static --corrupt=accept CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test > $tmp/$m.mam
1015							$(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
1016							echo ";;;$tmp/$m.mam;$i/Mamfile"
1017						fi
1018					fi
1019					$(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q) $(copyright:N=1:??LICENSE=?)
1020				fi
1021			done
1022			set -- $(package.dir:P=G)
1023			for i
1024			do	tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
1025			done
1026		} |
1027		{
1028			: > $tmp/HEAD
1029			[[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
1030			cat > $tmp/README <<'!'
1031	$(package.readme)
1032	!
1033			echo ";;;$tmp/README;README"
1034			$(CMP) $(CMPFLAGS) $tmp/README $(PACKAGEROOT)/README && touch -r $(PACKAGEROOT)/README $tmp/README
1035			sort -t';' -k5,5 -u
1036			: > $tmp/TAIL
1037			[[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
1038		} |
1039		$(PAX)	--filter=- \
1040			--to=ascii \
1041			$(op:N=delta:??--format=$(format)?) \
1042			--local \
1043			-wvf $(source) $(base) \
1044			$(op:N=delta:?--format=gzip??) \
1045			$(PACKAGEVIEW:C%.*%-s",^&/,,"%)
1046		$(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
1047		echo local > $(source:D:B=$(name):S=.tim)
1048		if	[[ '$(incremental)' == 1 && '$(old.source)' ]]
1049		then	$(PAX) -rf $(source) -wvf $(old.new.source) -z $(old.source)
1050			$(SUM) -x $(checksum) < $(old.new.source) > $(old.new.source:D:B:S=.$(checksum))
1051		fi
1052		rm -rf $tmp
1053	else	if	[[ '$(old.source)' ]] && $(CMP) $(CMPFLAGS) $(source.$(name)) $(source)
1054		then	: $(name) is up to date
1055		else	echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
1056			: > $(PACKAGEGEN)/$(name).req
1057			{
1058				echo "name='$(name)'"
1059				echo "index='$(index)'"
1060				echo "covers='$(~covers)'"
1061				echo "requires='$(~req)'"
1062			} > $(PACKAGEGEN)/$(name).inx
1063			{
1064				echo '.xx title="$(name) package"'
1065				echo '.xx meta.description="$(name) package"'
1066				echo '.xx meta.keywords="software, package"'
1067				echo '.MT 4'
1068				echo '.TL'
1069				echo '$(name) package'
1070				echo '.H 1'
1071				echo '$($(name).README)'
1072			} |
1073			$(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $(PACKAGEGEN)/$(name).html
1074			if	[[ '$(source.$(name))' ]]
1075			then	{
1076					echo '$($(name).README)'
1077					package help source
1078				} > $(PACKAGEGEN)/$(name).README
1079				cp $(source.$(name)) $(source)
1080				$(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
1081			fi
1082			echo local > $(source:D:B=$(name):S=.tim)
1083		fi
1084	fi
1085
1086binary : .binary.init .binary.gen .binary.$$(style)
1087
1088.binary.init : .MAKE
1089	local A B D I P V
1090	type := binary
1091	if ! "$(incremental)"
1092		incremental = 0
1093	end
1094	if ! "$(~$(name))"
1095		if name == "ratz"
1096			suffix = exe
1097		else
1098			suffix = gz
1099		end
1100	end
1101	: $(.init.$(style)) :
1102	: $(details.$(style):V:R) :
1103	A := $(binary.list)
1104	B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
1105	P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
1106	D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
1107	if op == "delta"
1108		if ! B
1109			error 3 delta requires a base archive
1110		end
1111		base := -z $(B)
1112		if "$(release)" != "$(stamp)"
1113			release := $("":T=R%Y-%m-%d)
1114		end
1115		binary := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
1116		version := $(binary:B:B:/$(name).//)
1117	elif B || op == "base"
1118		if op == "base"
1119			for I $(B) $(P)
1120				V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
1121				if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
1122					old.version := $(V)
1123					old.binary := $(I)
1124					if "$(old.version)" >= "$(version)"
1125						error 3 $(name): previous base $(old.version) is newer than $(version)
1126					end
1127					break
1128				end
1129			end
1130		else
1131			binary := $(B)
1132		end
1133		if B == "$(binary)"
1134			if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
1135				error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
1136			end
1137			error 1 $(B:B:S): replacing current base
1138		end
1139		version := $(binary:B:/$(name).//:/\..*//)
1140	end
1141	PACKAGEGEN := $(PACKAGEBIN)/gen
1142
1143.binary.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
1144
1145.binary.exp .binary.pkg .binary.rpm : .MAKE
1146	error 3 $(style): binary package style not supported yet
1147
1148.binary.cyg :
1149	if	[[ '$(~$(name))' ]]
1150	then	tmp=/tmp/pkg$(tmp)
1151		mkdir $tmp
1152		{
1153			integer m=0 o
1154			{
1155				echo '$($(name.original).README)' | fmt
1156				cat <<'!'
1157	$(readme.$(style):@?$$("\n")$$(readme.$$(style))??)
1158	!
1159			} > $tmp/README1
1160			echo ";;;$tmp/README1;usr/share/doc/Cygwin/$(opt:/.$//).README"
1161			{
1162				echo '$($(name.original).README)' | fmt
1163				cat <<'!'
1164	$()
1165	The remainder of this file is the README from the source package
1166	that was used to generate this binary package. It describes
1167	the source build hierarchy, not the current directory.
1168	$()
1169	$(package.readme)
1170	!
1171			} > $tmp/README2
1172			echo ";;;$tmp/README2;usr/share/doc/$(opt)README"
1173			package release $(name.original) > $tmp/RELEASE
1174			echo ";;;$tmp/RELEASE;usr/share/doc/$(opt)RELEASE"
1175			cat > $(binary:/.$(suffix)//).setup.hint <<'!'
1176	category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
1177	requires: cygwin
1178	sdesc: "$(index)"
1179	ldesc: "$($(name.original).README)"
1180	!
1181			set -- $(.package.licenses. --text $(name.original):N!=*.lic)
1182			for i
1183			do	echo ";;;${i};usr/share/doc/$(opt)LICENSE-${i##*/}"
1184			done
1185			cat <<'!'
1186	$(filter.$(style))
1187	!
1188			if	[[ '$(postinstall.$(style):V:O=1:?1??)' ]]
1189			then	cat >$tmp/postinstall <<'!'
1190	$("#")!/bin/sh
1191	$(postinstall.$(style))
1192	!
1193				echo ";;;$tmp/postinstall;etc/postinstall/$(name).sh"
1194			fi
1195		} |
1196		{
1197			: > $tmp/HEAD
1198			[[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
1199			sort -t';' -k5,5 -u
1200			: > $tmp/TAIL
1201			[[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
1202		} |
1203		$(PAX)	--filter=- \
1204			--to=ascii \
1205			--format=$(format) \
1206			--local \
1207			-wvf $(binary)
1208		$(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
1209		rm -rf $tmp
1210	fi
1211
1212.binary.lcl :
1213	if	[[ '$(~$(name))' ]]
1214	then	tmp=/tmp/pkg$(tmp)
1215		mkdir $tmp
1216		{
1217			$(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
1218			$(package.bin:U:T=F:/.*/echo ";;;&"$("\n")/)
1219			set -- $(package.closure)
1220			for i
1221			do	cd $(INSTALLROOT)/$i
1222				$(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) recurse list.package.$(type) package.license.class=$(license:Q) cc-
1223			done
1224		} |
1225		$(PAX)	--filter=- \
1226			--to=ascii \
1227			$(op:N=delta:??--format=$(format)?) \
1228			--local \
1229			--checksum=md5:$(PACKAGEGEN)/$(name).sum \
1230			--install=$(PACKAGEGEN)/$(name).ins \
1231			-wvf $(binary) $(base) \
1232			$(op:N=delta:?--format=gzip??) \
1233			-s",^$tmp/,$(INSTALLOFFSET)/," \
1234			$(PACKAGEROOT:C%.*%-s",^&/,,"%)
1235		$(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
1236		echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
1237		rm -rf $tmp
1238	fi
1239
1240.binary.tgz :
1241	if	[[ '$(~$(name))' ]]
1242	then	tmp=/tmp/pkg$(tmp)
1243		mkdir $tmp
1244		{
1245			if	[[ '$(init)' == '$(name)' ]]
1246			then	for i in lib32 lib64
1247				do	if	[[ -d $(INSTALLROOT)/$i ]]
1248					then	echo ";physical;;$(INSTALLROOT)/$i"
1249					fi
1250				done
1251			fi
1252			$(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
1253			$(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
1254			$(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
1255			if	[[ '$(PACKAGEDIR:B)' == '$(style)' ]]
1256			then	echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
1257				echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
1258				if	[[ '$(~covers)' ]]
1259				then	for i in $(~covers)
1260					do	for j in pkg lic
1261						do	if	[[ -f $(PACKAGESRC)/$i.$j ]]
1262							then	echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
1263							fi
1264						done
1265						for j in ver req
1266						do	if	[[ -f $(PACKAGEGEN)/$i.$j ]]
1267							then	echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
1268							fi
1269						done
1270					done
1271				fi
1272				sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
1273				echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
1274				{
1275					echo "name='$(name)'"
1276					echo "index='$(index)'"
1277					echo "covers='$(~covers)'"
1278					echo "requires='$(~req)'"
1279				} > $(PACKAGEGEN)/$(name).inx
1280				{
1281					{
1282					echo '$($(name).README)'
1283					if	[[ '$(~covers)' ]]
1284					then	echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
1285					fi
1286					if	[[ '$(~requires)' ]]
1287					then	echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
1288					fi
1289					} | fmt
1290					package help binary
1291					package release $(name)
1292				} > $(PACKAGEGEN)/$(name).README
1293				echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
1294			fi
1295			set -- $(package.closure)
1296			for i
1297			do	cd $(INSTALLROOT)/$i
1298				$(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
1299			done
1300		} |
1301		{
1302			: > $tmp/HEAD
1303			[[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
1304			cat > $tmp/README <<'!'
1305	$(package.readme)
1306	!
1307			echo ";;;$tmp/README;README"
1308			sort -t';' -k5,5 -u
1309			: > $tmp/TAIL
1310			[[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
1311		} |
1312		$(PAX)	--filter=- \
1313			--to=ascii \
1314			$(op:N=delta:??--format=$(format)?) \
1315			--local \
1316			--checksum=md5:$(PACKAGEGEN)/$(name).sum \
1317			--install=$(PACKAGEGEN)/$(name).ins \
1318			-wvf $(binary) $(base) \
1319			$(op:N=delta:?--format=gzip??) \
1320			-s",^$tmp/,$(INSTALLOFFSET)/," \
1321			$(PACKAGEROOT:C%.*%-s",^&/,,"%)
1322		echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1323		$(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
1324		echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1325		echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
1326		if	[[ '$(incremental)' == 1 && '$(old.binary)' ]]
1327		then	$(PAX) -rf $(binary) -wvf $(old.new.binary) -z $(old.binary)
1328			echo $(old.new.binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1329			$(SUM) -x $(checksum) < $(old.new.binary) > $(old.new.binary:D:B:S=.$(checksum))
1330			echo $(old.new.binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1331		fi
1332		rm -rf $tmp
1333	else	if	[[ '$(binary.$(name))' ]]
1334		then	exe=$(binary.$(name))
1335		else	exe=$(INSTALLROOT)/bin/$(name)
1336		fi
1337		if	[[ '$(old.binary)' ]] && $(CMP) $(CMPFLAGS) $exe $(binary)
1338		then	: $(name) is up to date
1339		else	echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
1340			: > $(PACKAGEGEN)/$(name).req
1341			{
1342				echo "name='$(name)'"
1343				echo "index='$(index)'"
1344				echo "covers='$(~covers)'"
1345				echo "requires='$(~req)'"
1346			} > $(PACKAGEGEN)/$(name).inx
1347			{
1348				echo '$($(name).README)'
1349				package help binary
1350			} > $(PACKAGEGEN)/$(name).README
1351			case "$(binary)" in
1352			*.gz)	gzip < $exe > $(binary) ;;
1353			*)	cp $exe $(binary) ;;
1354			esac
1355			$(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
1356			echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
1357		fi
1358		echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1359		echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1360	fi
1361
1362runtime : .runtime.init .runtime.gen .runtime.$$(style)
1363
1364.runtime.init : .MAKE
1365	local A B D I P V
1366	type := runtime
1367	if ! "$(incremental)"
1368		incremental = 0
1369	end
1370	if ! "$(~$(name))"
1371		if name == "ratz"
1372			suffix = exe
1373		else
1374			suffix = gz
1375		end
1376	end
1377	: $(.init.$(style)) :
1378	: $(details.$(style):V:R) :
1379	A := $(runtime.list)
1380	B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
1381	P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
1382	D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
1383	if op == "delta"
1384		if ! B
1385			error 3 delta requires a base archive
1386		end
1387		base := -z $(B)
1388		if "$(release)" != "$(stamp)"
1389			release := $("":T=R%Y-%m-%d)
1390		end
1391		runtime := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
1392		version := $(runtime:B:B:/$(name).//)
1393	elif B || op == "base"
1394		if op == "base"
1395			for I $(B) $(P)
1396				V := $(I:B:/$(name)-run\.\([^.]*\).*/\1/)
1397				if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
1398					old.version := $(V)
1399					old.runtime := $(I)
1400					if "$(old.version)" >= "$(version)"
1401						error 3 $(name): previous base $(old.version) is newer than $(version)
1402					end
1403					break
1404				end
1405			end
1406		else
1407			runtime := $(B)
1408		end
1409		if B == "$(runtime)"
1410			if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
1411				error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
1412			end
1413			error 1 $(B:B:S): replacing current base
1414		end
1415		version := $(runtime:B:/$(name)-run.//:/\..*//)
1416	end
1417	PACKAGEGEN := $(PACKAGESRC)/gen
1418
1419.runtime.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
1420
1421.runtime.cyg .runtime.exp .runtime.lcl .runtime.pkg .runtime.rpm : .MAKE
1422	error 3 $(style): runtime package style not supported yet
1423
1424.runtime.tgz :
1425	if	[[ '$(~$(name))' ]]
1426	then	tmp=/tmp/pkg$(tmp)
1427		mkdir $tmp
1428		{
1429			if	[[ '$(init)' == '$(name)' ]]
1430			then	for i in lib32 lib64
1431				do	if	[[ -d $(INSTALLROOT)/$i ]]
1432					then	echo ";physical;;$(INSTALLROOT)/$i"
1433					fi
1434				done
1435			fi
1436			$(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
1437			$(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
1438			$(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
1439			echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
1440			echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
1441			if	[[ '$(~covers)' ]]
1442			then	for i in $(~covers)
1443				do	for j in pkg lic
1444					do	if	[[ -f $(PACKAGESRC)/$i.$j ]]
1445						then	echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
1446						fi
1447					done
1448					for j in ver req
1449					do	if	[[ -f $(PACKAGEGEN)/$i.$j ]]
1450						then	echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
1451						fi
1452					done
1453				done
1454			fi
1455			sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
1456			echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
1457			{
1458				echo "name='$(name)'"
1459				echo "index='$(index)'"
1460				echo "covers='$(~covers)'"
1461				echo "requires='$(~req)'"
1462			} > $(PACKAGEGEN)/$(name).inx
1463			{
1464				{
1465				echo '$($(name).README)'
1466				if	[[ '$(~covers)' ]]
1467				then	echo
1468					echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
1469				fi
1470				if	[[ '$(~requires)' ]]
1471				then	echo
1472					echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
1473				fi
1474				echo
1475				echo "To install this $(type) package read the tarball into a directory"
1476				echo "suitable for containing bin and lib subdirectories, and run the"
1477				echo "$(PACKAGELIB)/gen/$(name)-run.ins script to fix up permissions."
1478				echo
1479				echo "To use the package export the bin directory in PATH. The commands and"
1480				echo "libraries use \$PATH to locate dynamic libraries and related data files."
1481				echo
1482				} | fmt
1483			} > $(PACKAGEGEN)/$(name)-run.README
1484			echo ";;;$(PACKAGEGEN)/$(name)-run.README;$(PACKAGELIB)/$(name)-run.README"
1485			set -- $(package.closure)
1486			for i
1487			do	cd $(INSTALLROOT)/$i
1488				$(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
1489			done
1490		} |
1491		{
1492			: > $tmp/HEAD
1493			[[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
1494			cat > $tmp/README <<'!'
1495	$(package.readme)
1496	!
1497			echo ";;;$tmp/README;README"
1498			sort -t';' -k5,5 -u
1499			: > $tmp/TAIL
1500			[[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
1501		} |
1502		$(PAX)	--filter=- \
1503			--to=ascii \
1504			$(op:N=delta:??--format=$(format)?) \
1505			--local \
1506			--checksum=md5:$(PACKAGEGEN)/$(name)-run.sum \
1507			--install=$(PACKAGEGEN)/$(name)-run.ins \
1508			-wvf $(runtime) $(base) \
1509			$(op:N=delta:?--format=gzip??) \
1510			-s",^$tmp/,$(INSTALLOFFSET)/," \
1511			$(PACKAGEROOT:C%.*%-s",^&/,,"%)
1512		echo $(runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1513		$(SUM) -x $(checksum) < $(runtime) > $(runtime:D:B:S=.$(checksum))
1514		echo $(runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1515		echo local > $(runtime:D:B=$(name)-run:S=.$(CC.HOSTTYPE).tim)
1516		if	[[ '$(incremental)' == 1 && '$(old.runtime)' ]]
1517		then	$(PAX) -rf $(runtime) -wvf $(old.new.runtime) -z $(old.runtime)
1518			echo $(old.new.runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1519			$(SUM) -x $(checksum) < $(old.new.runtime) > $(old.new.runtime:D:B:S=.$(checksum))
1520			echo $(old.new.runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
1521		fi
1522		rm -rf $tmp
1523	fi
1524
1525list.installed list.manifest :
1526	set -- $(package.closure)
1527	for i
1528	do	cd $(INSTALLROOT)/$i
1529		ignore $(MAKE) --noexec $(-) $(=) $(<)
1530	done
1531