xref: /freebsd/share/mk/bsd.pkg.mk (revision bb75b0d581f74e22a68d7868ad1f5da1146a8de0)
1*bb75b0d5SLexi Winter# SPDX-License-Identifier: ISC
2*bb75b0d5SLexi Winter#
3*bb75b0d5SLexi Winter# Copyright (c) 2026 Lexi Winter <ivy@FreeBSD.org>
4*bb75b0d5SLexi Winter#
5*bb75b0d5SLexi Winter# Permission to use, copy, modify, and distribute this software for any
6*bb75b0d5SLexi Winter# purpose with or without fee is hereby granted, provided that the above
7*bb75b0d5SLexi Winter# copyright notice and this permission notice appear in all copies.
8*bb75b0d5SLexi Winter#
9*bb75b0d5SLexi Winter# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*bb75b0d5SLexi Winter# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*bb75b0d5SLexi Winter# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*bb75b0d5SLexi Winter# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*bb75b0d5SLexi Winter# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*bb75b0d5SLexi Winter# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*bb75b0d5SLexi Winter# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*bb75b0d5SLexi Winter
17*bb75b0d5SLexi Winter# bsd.pkg.mk: Create a package based on an existing plist and the template
18*bb75b0d5SLexi Winter# UCL files.  This is intended for use by packages/* during the build, and
19*bb75b0d5SLexi Winter# cannot be used to generate standalone packages.
20*bb75b0d5SLexi Winter
21*bb75b0d5SLexi Winter.if !defined(REPODIR)
22*bb75b0d5SLexi Winter. error REPODIR must be set
23*bb75b0d5SLexi Winter.endif
24*bb75b0d5SLexi Winter
25*bb75b0d5SLexi Winter.if !defined(PKG_VERSION)
26*bb75b0d5SLexi Winter. error PKG_VERSION must be set
27*bb75b0d5SLexi Winter.endif
28*bb75b0d5SLexi Winter
29*bb75b0d5SLexi Winter_PKG_NEED_ABI=
30*bb75b0d5SLexi Winter.include <bsd.pkg.pre.mk>
31*bb75b0d5SLexi Winter.include <bsd.compat.pre.mk>
32*bb75b0d5SLexi Winter.include <src.opts.mk>
33*bb75b0d5SLexi Winter
34*bb75b0d5SLexi Winter# Allow flua to be overridden; the world build does this to use the
35*bb75b0d5SLexi Winter# bootstrap version.
36*bb75b0d5SLexi WinterFLUA?=	/usr/libexec/flua
37*bb75b0d5SLexi Winter
38*bb75b0d5SLexi Winter# The directory that files to be packaged have been staged into.
39*bb75b0d5SLexi Winter# If ${WSTAGEDIR} is set from Makefile.inc1, use that, otherwise
40*bb75b0d5SLexi Winter# use the default location.
41*bb75b0d5SLexi Winter.if defined(WSTAGEDIR)
42*bb75b0d5SLexi Winter_PKG_WORLDSTAGE=	${WSTAGEDIR}
43*bb75b0d5SLexi Winter.else
44*bb75b0d5SLexi Winter_PKG_WORLDSTAGE=	${OBJTOP}/worldstage
45*bb75b0d5SLexi Winter.endif
46*bb75b0d5SLexi Winter
47*bb75b0d5SLexi Winter_PKGDIR=	${SRCTOP}/packages
48*bb75b0d5SLexi Winter_STAGEDIR=	${REPODIR}/${PKG_ABI}/${PKG_VERSION}
49*bb75b0d5SLexi Winter
50*bb75b0d5SLexi Winter# These are the default UCL variables we pass to generate-ucl.lua.
51*bb75b0d5SLexi Winter# Allow the caller to add additional variables via PKG_UCLVARS.
52*bb75b0d5SLexi Winter_UCLVARS= \
53*bb75b0d5SLexi Winter	VERSION "${PKG_VERSION}" \
54*bb75b0d5SLexi Winter	PKG_NAME_PREFIX "${PKG_NAME_PREFIX}" \
55*bb75b0d5SLexi Winter	PKG_WWW "${PKG_WWW}" \
56*bb75b0d5SLexi Winter	PKG_MAINTAINER "${PKG_MAINTAINER}" \
57*bb75b0d5SLexi Winter	${PKG_UCLVARS}
58*bb75b0d5SLexi Winter
59*bb75b0d5SLexi Winter# Global pkg(8) arguments.
60*bb75b0d5SLexi Winter_PKG_ARGS= \
61*bb75b0d5SLexi Winter	-o ABI=${PKG_ABI} \
62*bb75b0d5SLexi Winter	-o OSVERSION=${PKG_OSVERSION} \
63*bb75b0d5SLexi Winter	-o ALLOW_BASE_SHLIBS=yes \
64*bb75b0d5SLexi Winter	-o SHLIB_PROVIDE_PATHS_NATIVE=/lib,/usr/lib \
65*bb75b0d5SLexi Winter	${_ALL_LIBCOMPATS:range:@i@-o SHLIB_PROVIDE_PATHS_COMPAT_${_ALL_LIBCOMPATS:[$i]}=/usr/lib${_ALL_libcompats:[$i]}@} \
66*bb75b0d5SLexi Winter
67*bb75b0d5SLexi Winter# Arguments to pkg-create(8).
68*bb75b0d5SLexi Winter_PKG_CREATE_ARGS= \
69*bb75b0d5SLexi Winter	-f ${PKG_FORMAT} \
70*bb75b0d5SLexi Winter	${PKG_CLEVEL} \
71*bb75b0d5SLexi Winter	-T ${PKG_CTHREADS} \
72*bb75b0d5SLexi Winter	-r ${_PKG_WORLDSTAGE} \
73*bb75b0d5SLexi Winter	-o ${.OBJDIR}
74*bb75b0d5SLexi Winter
75*bb75b0d5SLexi Winter_PKG_CREATE=		${PKG_CMD} ${_PKG_ARGS} create ${_PKG_CREATE_ARGS}
76*bb75b0d5SLexi Winter
77*bb75b0d5SLexi Winter# If WORLDPACKAGE is set, we're building a world package.
78*bb75b0d5SLexi Winter.if defined(WORLDPACKAGE)
79*bb75b0d5SLexi Winter
80*bb75b0d5SLexi Winter# Default to using the same UCL file for all subpackages, since the vast
81*bb75b0d5SLexi Winter# majority of packages are built this way.
82*bb75b0d5SLexi WinterUCLSRC?=	${WORLDPACKAGE}.ucl
83*bb75b0d5SLexi Winter
84*bb75b0d5SLexi Winter# Nearly all packages have a dbg and man subpackage, so enable that by default.
85*bb75b0d5SLexi WinterSUBPACKAGES?=	dbg man
86*bb75b0d5SLexi Winter
87*bb75b0d5SLexi Winter# This lets the caller use constructs like SUBPACKAGES.${MK_FOO}+= foo
88*bb75b0d5SLexi Winter_SUBPACKAGES=	${SUBPACKAGES} ${SUBPACKAGES.yes} ${SUBPACKAGES.yes.yes}
89*bb75b0d5SLexi Winter
90*bb75b0d5SLexi Winter# Remove the dbg subpackage if debug files are disabled.
91*bb75b0d5SLexi Winter.if ${MK_DEBUG_FILES} == "no"
92*bb75b0d5SLexi Winter_SUBPACKAGES:=	${_SUBPACKAGES:Ndbg}
93*bb75b0d5SLexi Winter. if defined(COMPAT_PKGS)
94*bb75b0d5SLexi WinterCOMPAT_PKGS:=	${COMPAT_PKGS:Ndbg}
95*bb75b0d5SLexi Winter. endif	# defined(COMPAT_PKGS)
96*bb75b0d5SLexi Winter.endif	# ${MK_DEBUG_FILES} == "no"
97*bb75b0d5SLexi Winter
98*bb75b0d5SLexi Winter# Remove the man subpackage if split man packages are disabled.
99*bb75b0d5SLexi Winter.if ${MK_MANSPLITPKG} == "no"
100*bb75b0d5SLexi Winter_SUBPACKAGES:=	${_SUBPACKAGES:Nman}
101*bb75b0d5SLexi Winter.endif	# ${MK_MANSPLITPKG} == "no"
102*bb75b0d5SLexi Winter
103*bb75b0d5SLexi Winter# Add the base package, unless there isn't one, which can happen with
104*bb75b0d5SLexi Winter# static library packages.
105*bb75b0d5SLexi Winter.if !defined(PKG_NO_BASE)
106*bb75b0d5SLexi Winter_ALLPACKAGES=	${WORLDPACKAGE}
107*bb75b0d5SLexi Winter.endif
108*bb75b0d5SLexi Winter
109*bb75b0d5SLexi Winter# Add basic subpackages.
110*bb75b0d5SLexi Winter.for _subpackage in ${_SUBPACKAGES}
111*bb75b0d5SLexi Winter_ALLPACKAGES+=	${_subpackage:S/^/${WORLDPACKAGE}-/}
112*bb75b0d5SLexi Winter.endfor	# _subpackage in ${_SUBPACKAGES}
113*bb75b0d5SLexi Winter
114*bb75b0d5SLexi Winter# Add libcompat subpackages.
115*bb75b0d5SLexi Winter.for LIBCOMPAT libcompat in ${_ALL_LIBCOMPATS_libcompats}
116*bb75b0d5SLexi Winter. if ${MK_LIB${LIBCOMPAT}} != "no"
117*bb75b0d5SLexi Winter
118*bb75b0d5SLexi Winter# For the base package...
119*bb75b0d5SLexi Winter.  if ${COMPAT_PKG:Uno} != "no"
120*bb75b0d5SLexi Winter_ALLPACKAGES+=	${WORLDPACKAGE}-lib${libcompat}
121*bb75b0d5SLexi Winter.  endif
122*bb75b0d5SLexi Winter
123*bb75b0d5SLexi Winter# And for subpackages.
124*bb75b0d5SLexi Winter.  for _pkg in ${COMPAT_PKGS}
125*bb75b0d5SLexi Winter# lib is special, because it gets -lib32, not -lib-lib32.
126*bb75b0d5SLexi Winter.   if ${_pkg} == "lib"
127*bb75b0d5SLexi Winter_ALLPACKAGES+=	${WORLDPACKAGE}-lib${libcompat}
128*bb75b0d5SLexi Winter.   else
129*bb75b0d5SLexi Winter_ALLPACKAGES+=	${WORLDPACKAGE}-${_pkg}-lib${libcompat}
130*bb75b0d5SLexi Winter.   endif
131*bb75b0d5SLexi Winter.  endfor
132*bb75b0d5SLexi Winter
133*bb75b0d5SLexi Winter. endif	# ${MK_LIB${LIBCOMPAT}} != "no"
134*bb75b0d5SLexi Winter.endfor
135*bb75b0d5SLexi Winter
136*bb75b0d5SLexi WinterCLEANFILES+=	*.pkgucl *.ucl.in *.plist *.pkg
137*bb75b0d5SLexi Winter
138*bb75b0d5SLexi Winterall: .PHONY
139*bb75b0d5SLexi Winter
140*bb75b0d5SLexi Winter. for _pkg in ${_ALLPACKAGES}
141*bb75b0d5SLexi Winter_pkgfullname:=	${PKG_NAME_PREFIX}-${_pkg}
142*bb75b0d5SLexi Winter_pkgfilename:=	${_pkgfullname}-${PKG_VERSION}.pkg
143*bb75b0d5SLexi Winter
144*bb75b0d5SLexi Winterall: ${_pkgfilename}
145*bb75b0d5SLexi Winter
146*bb75b0d5SLexi Winter${_pkgfilename}: ${_pkgfullname}.pkgucl ${_pkg}.plist
147*bb75b0d5SLexi Winter	# We should never create an empty package; this means we intended to
148*bb75b0d5SLexi Winter	# build the package, but we didn't build the things which are supposed
149*bb75b0d5SLexi Winter	# to be in the package, which means something went wrong somewhere.
150*bb75b0d5SLexi Winter	# If you hit this check when building, it probably means a package is
151*bb75b0d5SLexi Winter	# not properly excluded in packages/Makefile based on src.conf options.
152*bb75b0d5SLexi Winter	@if [ "$$(grep -vc '^@dir' "${.ALLSRC:M*.plist}")" -eq 0 ]; \
153*bb75b0d5SLexi Winter	then \
154*bb75b0d5SLexi Winter		printf >&2 'ERROR: Refusing to build empty package %s from %s\n' \
155*bb75b0d5SLexi Winter			"${.TARGET}" "${.ALLSRC:M*.plist}"; \
156*bb75b0d5SLexi Winter		exit 1; \
157*bb75b0d5SLexi Winter	fi
158*bb75b0d5SLexi Winter	${_PKG_CREATE} -M ${.ALLSRC:M*.pkgucl} -p ${.ALLSRC:M*.plist}
159*bb75b0d5SLexi Winter
160*bb75b0d5SLexi Winter${_pkgfullname}.ucl.in: ${UCLSRC.${_pkg}:U${UCLSRC:U${_pkg}.ucl}}
161*bb75b0d5SLexi Winter	@echo 'Generating ${.TARGET} from ${.ALLSRC}'
162*bb75b0d5SLexi Winter	@cp ${.ALLSRC} ${.TARGET}
163*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'name = "${PKG_NAME_PREFIX}-${_pkg}"'
164*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'origin = "base/${PKG_NAME_PREFIX}-${_pkg}"'
165*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'categories [ "base" ]'
166*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'prefix = "/"'
167*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'version = "${PKG_VERSION}"'
168*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'maintainer = "${PKG_MAINTAINER}"'
169*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'www = "${PKG_WWW}"'
170*bb75b0d5SLexi Winter.if defined(PKG_VITAL.${_pkg})
171*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'vital = true'
172*bb75b0d5SLexi Winter.endif
173*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'licenselogic = "${PKG_LICENSELOGIC}"'
174*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'licenses ['
175*bb75b0d5SLexi Winter.for _license in ${PKG_LICENSES}
176*bb75b0d5SLexi Winter	# When a value contains spaces and is quoted (e.g., "X WITH Y"),
177*bb75b0d5SLexi Winter	# make preserves the quotes in the value, so we need to strip them.
178*bb75b0d5SLexi Winter	@echo >>${.TARGET} '    "${_license:S/"//g}",'
179*bb75b0d5SLexi Winter.endfor
180*bb75b0d5SLexi Winter	@echo >>${.TARGET} ']'
181*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'annotations {'
182*bb75b0d5SLexi Winter.for _annotation in ${PKG_ANNOTATIONS}
183*bb75b0d5SLexi Winter	@echo >>${.TARGET} '    ${_annotation} = "${PKG_ANNOTATIONS.${_annotation}}"'
184*bb75b0d5SLexi Winter.endfor
185*bb75b0d5SLexi Winter	@echo >>${.TARGET} '}'
186*bb75b0d5SLexi Winter.if defined(PKG_DEPS.${_pkg})
187*bb75b0d5SLexi Winter	@echo >>${.TARGET} 'deps {'
188*bb75b0d5SLexi Winter. for _dep in ${PKG_DEPS.${_pkg}}
189*bb75b0d5SLexi Winter	@echo >>${.TARGET} '    "${_dep}" {'
190*bb75b0d5SLexi Winter	@echo >>${.TARGET} '        "origin" = "base/${PKG_NAME_PREFIX}-${_dep}"'
191*bb75b0d5SLexi Winter	@echo >>${.TARGET} '        "version" = "${PKG_VERSION}"'
192*bb75b0d5SLexi Winter	@echo >>${.TARGET} '    },'
193*bb75b0d5SLexi Winter. endfor
194*bb75b0d5SLexi Winter	@echo >>${.TARGET} '}'
195*bb75b0d5SLexi Winter.endif
196*bb75b0d5SLexi Winter
197*bb75b0d5SLexi Winter${_pkgfullname}.pkgucl: ${_pkgfullname}.ucl.in
198*bb75b0d5SLexi Winter	${FLUA} ${SRCTOP}/release/packages/generate-ucl.lua \
199*bb75b0d5SLexi Winter		${_UCLVARS} \
200*bb75b0d5SLexi Winter		PKGNAME "${_pkg}" \
201*bb75b0d5SLexi Winter		PKGGENNAME "${WORLDPACKAGE}" \
202*bb75b0d5SLexi Winter		SRCDIR "${.CURDIR}" \
203*bb75b0d5SLexi Winter		"${.ALLSRC:M*.ucl.in}" ${.TARGET}
204*bb75b0d5SLexi Winter
205*bb75b0d5SLexi Winter. endfor	# _pkg in ${_ALLPACKAGES}
206*bb75b0d5SLexi Winter.endif		# defined(WORLDPACKAGE)
207*bb75b0d5SLexi Winter
208*bb75b0d5SLexi Winter# Stage the packages from objdir into repodir.
209*bb75b0d5SLexi Winter
210*bb75b0d5SLexi Winterstagepackages: .PHONY
211*bb75b0d5SLexi Winter	mkdir -p ${_STAGEDIR}
212*bb75b0d5SLexi Winter	cp ${_ALLPACKAGES:S/^/${PKG_NAME_PREFIX}-/:S/$/-${PKG_VERSION}.pkg/} \
213*bb75b0d5SLexi Winter		${_STAGEDIR}
214*bb75b0d5SLexi Winter
215*bb75b0d5SLexi Winter.SUFFIXES:	.plist .ucl .pkg
216*bb75b0d5SLexi Winter.PATH:		${_PKG_WORLDSTAGE}
217*bb75b0d5SLexi Winter
218*bb75b0d5SLexi Winter.include <bsd.obj.mk>
219