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