# "build" command
#
# Copyright (C) 2014, 2015 Patrick McDermott
#
# This file is part of the ProteanOS Development Kit.
#
# The ProteanOS Development Kit is free software: you can redistribute
# it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# The ProteanOS Development Kit is distributed in the hope that it
# will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with the ProteanOS Development Kit. If not, see
# .
_cmd_build_root=
_cmd_build_pkg_dir=
_cmd_build_build_deps=
_cmd_build_header()
{
local underline="${1}"
local fmt="${2}"
shift 2
printf "\\n${fmt}\\n" "${@}"
printf "${fmt}\\n\\n" "${@}" | sed "s|.|${underline}|g"
return 0
}
_cmd_build_time()
{
# Based on code from by Rich
# Felker, with whitespace added for readability.
printf '%d' $(($(TZ=UTC0 date "+
(
(%Y - 1600) * 365
+ (%Y - 1600) / 4
- (%Y - 1600) / 100
+ (%Y - 1600) / 400
+ 1%j - 1000
- 135140
) * 86400
+ (1%H - 100) * 3600
+ (1%M - 100) * 60
+ (1%S - 100)")))
return 0
}
_cmd_build_make_deps_pkg()
{
local pkg_dir=
pkg_dir="${_cmd_build_root}$(session_dir)/builddeps"
mkdir -p -- "${pkg_dir}/control" "${pkg_dir}/data"
printf '2.0\n' >"${pkg_dir}/debian-binary"
cat >"${pkg_dir}/control/control" <<-EOF
Package: prokit-builddeps-$(session_id)
Source: prokit
Version: 1.0
Architecture: all
Platform: all
Depends: ${_cmd_build_build_deps}
Description: Build dependencies metapackage generated by prokit
EOF
(cd -- "${pkg_dir}/data"; tar -czf ../data.tar.gz .)
(cd -- "${pkg_dir}/control"; tar -czf ../control.tar.gz .)
(cd -- "${pkg_dir}"; tar -czf ../builddeps.opk \
'debian-binary' 'data.tar.gz' 'control.tar.gz')
rm -Rf -- "${pkg_dir}"
}
_cmd_build_fini()
{
local session_dir=
local f=
session_dir="$(session_dir)"
if [ "x${_cmd_build_build_deps}" != 'x' ]; then
session_exec opkg --autoremove remove \
prokit-builddeps-$(session_id)
rm -f -- "${_cmd_build_root}${session_dir}/builddeps.opk"
# Hack to avoid this code branch if the function is called again
# in response to a signal.
_cmd_build_build_deps=''
fi
for f in "${_cmd_build_root}${session_dir}/"*; do
[ -e "${f}" ] || continue
[ "x${f##*/}" = 'xwd' ] && continue
mv "${f}" "${_cmd_build_pkg_dir}/.."
done
}
_cmd_build_build()
{
local log="${1}"
local build_arch="${2}"
local build_plat="${3}"
local host_arch="${4}"
local host_plat="${5}"
local dist="${6}"
shift 6
local build_date=
local es=
local changes=
local opks=
local opk=
local build_time=
if ${log}; then
build_date="$(LC_ALL='C' date '+%a, %d %b %Y %H:%M:%S %z')"
build_time=$(_cmd_build_time)
printf '%s (%s) %s\n' \
"${0##*/}" "${PACKAGE_NAME}" "${PACKAGE_VERSION}"
_cmd_build_header '=' '%-47s %31s' \
"${source} (${version})" "${build_date}"
cat <<-EOF
Source: ${source}
Version: ${version}
Build-Architecture: ${build_arch}
Host-Architecture: ${host_arch}
Host-Platform: ${host_plat}
Distribution: ${dist}
Build-Date: ${build_date}
Filter: Replacing "$(session_dir)" with "<>"
Filter: Replacing "$(session_id)" with "<>"
EOF
fi
es=0
${log} && _cmd_build_header '-' 'Install Build Dependencies'
_cmd_build_build_deps="$(package_get_build_deps \
"${host_arch}" "${host_plat}")"
if [ "x${_cmd_build_build_deps}" != 'x' ]; then
_cmd_build_make_deps_pkg
if session_exec opkg -a "${host_arch}" print-architecture \
1>/dev/null 2>&1; then
session_exec opkg -a "${host_arch}" \
install ../builddeps.opk || es=${?}
else
session_exec opkg install ../builddeps.opk || es=${?}
fi
fi
${log} && _cmd_build_header '-' 'Installed Packages'
session_exec opkg list-installed || es=${?}
${log} && _cmd_build_header '-' 'Build'
if [ ${es} -eq 0 ]; then
session_exec opkbuild "${@}" || es=${?}
fi
${log} && _cmd_build_header '-' 'Remove Build Dependencies'
_cmd_build_fini
if ! ${log}; then
return ${es}
fi
changes="${_cmd_build_pkg_dir}/../$(: \
)${source}_${version}_${host_arch}_${host_plat}.changes"
if [ -r "${changes}" ]; then
opks="$(sed -n '/^Files:/,${ s/^ [0-9][0-9]* ..* //p; };' \
"${changes}")"
_cmd_build_header '-' 'Build Results'
printf '%s\n' "${changes##*/}" ${opks}
_cmd_build_header '~' "${changes##*/}"
cat "${changes}"
for opk in ${opks}; do
_cmd_build_header '~' "${opk}"
opk="${_cmd_build_pkg_dir}/../${opk}"
tar -xzOf "${opk}" control.tar.gz | tar -xzO ./control
printf '\n'
tar -xzOf "${opk}" data.tar.gz | tar -tvz
done
fi
_cmd_build_header '-' 'Summary'
build_time=$(($(_cmd_build_time) - ${build_time}))
cat <<-EOF
Source: ${source}
Version: ${version}
Build-Architecture: ${build_arch}
Host-Architecture: ${host_arch}
Host-Platform: ${host_plat}
Distribution: ${dist}
Build-Date: ${build_date}
Finished: $(LC_ALL='C' date '+%a, %d %b %Y %H:%M:%S %z')
Build-Time: ${build_time}
Build-Time-Human: $(printf '%02d:%02d:%02d' \
$((${build_time} / 60 / 60)) \
$((${build_time} / 60 % 60)) \
$((${build_time} % 60)))
Status: $([ ${es} -eq 0 ] \
&& printf 'successful' || printf 'failed')
EOF
return ${es}
}
cmd_build_main()
{
local root=
local dev=
local opkbuild_optstring=
local build_arch=
local build_plat=
local host_arch=
local host_plat=
local log=
local opts=
local opt=
local source=
local version=
local dist=
local es=
if [ ${#} -lt 2 ]; then
print_cmd_usage 'build' >&2
return 1
fi
root="${1}"
shift 1
dev=''
if is_block "${root}"; then
dev="${root}"
if ! root="$(block_mount "${dev}")"; then
return 2
fi
fi
_cmd_build_root="${root}"
opkbuild_optstring="$(cat -- "${root}/usr/share/opkbuild/optstring")"
build_arch="$(cat -- "${root}/etc/proteanos_arch")"
build_plat="$(cat -- "${root}/etc/proteanos_plat")"
host_arch="${build_arch}"
host_plat="${build_plat}"
log=true
opts=''
while getopts "l${opkbuild_optstring}" opt 2>/dev/null; do
case "${opt}" in
a) host_arch="${OPTARG}";;
p) host_plat="${OPTARG}";;
l) log=false;;
*)
opts="${opts}${opt} "
eval "opt_${opt}_set=\"\${OPTARG:+set}\""
eval "opt_${opt}=\"\${OPTARG:-}\""
;;
?)
print_cmd_usage 'build' >&2
[ "x${dev}" != 'x' ] && block_umount "${root}"
return 1
;;
esac
done
shift $((${OPTIND} - 1))
if [ ${#} -ne 1 ]; then
print_cmd_usage 'build' >&2
[ "x${dev}" != 'x' ] && block_umount "${root}"
return 1
fi
_cmd_build_pkg_dir="${1}"
set -- -a "${host_arch}" -p "${host_plat}"
for opt in ${opts}; do
set -- "${@}" "-${opt}"
if eval "[ x\"\${opt_${opt}_set}\" = x'set' ]"; then
eval "set -- \"\${@}\" \"\${opt_${opt}}\""
fi
done
if ! profile_detect "${root}"; then
[ "x${dev}" != 'x' ] && block_umount "${root}"
return 2
fi
if ! [ -d "${_cmd_build_pkg_dir}" ]; then
error "$(get_msg 'cmd_build_not_a_dir')" "${_cmd_build_pkg_dir}"
[ "x${dev}" != 'x' ] && block_umount "${root}"
return 2
fi
if ! package_init "${_cmd_build_pkg_dir}"; then
[ "x${dev}" != 'x' ] && block_umount "${root}"
return 2
fi
package_set_substvars "${host_arch}" "${host_plat}"
if ! session_begin "${root}" "${_cmd_build_pkg_dir}" false; then
_cmd_build_fini
[ "x${dev}" != 'x' ] && block_umount "${root}"
return 2
fi
es=0
if ${log}; then
read -r source version dist <<-EOF
$(package_get_name_version_dist)
EOF
log="${_cmd_build_pkg_dir}/../$(: \
)${source}_${version}_${host_arch}_${host_plat}.log"
{
{
{
set +e
_cmd_build_build true \
"${build_arch}" "${build_plat}"\
"${host_arch}" "${host_plat}" \
"${dist}" "${@}" 2>&1
printf '%d' ${?} 1>&3
} | sed "/^Filter: /!{
s|$(session_dir)|<>|;
s|$(session_id)|<>|;
};" | tee "${log}" 1>&2
} 3>&1 | {
read es
exit ${es}
}
} 2>&1 || es=${?}
else
_cmd_build_build false \
"${build_arch}" "${build_plat}" \
"${host_arch}" "${host_plat}" \
"${dist}" "${@}"
fi
session_end
[ "x${dev}" != 'x' ] && block_umount "${root}"
return ${es}
}
cmd_build_register()
{
register_cmd 'build'
}
__init cmd_build_register