# "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 if ${log}; then _cmd_build_header '-' 'Installed Packages' session_exec opkg list-installed || es=${?} fi ${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