[pacman-dev,1/1] Split prepare_buildenv() to libmakepkg scripts

Message ID 20181103165423.1414-1-quequotion@bugmenot.com
State Superseded, archived
Headers show
Series [pacman-dev,1/1] Split prepare_buildenv() to libmakepkg scripts | expand

Commit Message

Que Quotion Nov. 3, 2018, 4:54 p.m. UTC
From: Que Quotion <quequotion@gmail.com>

As Eli Schwartz has pointed out:
https://lists.archlinux.org/pipermail/pacman-dev/2018-May/022501.html

It would be beneficial to makepkg to have this function ported
to libmakepkg and split into individual scripts.

Supersedes: https://patchwork.archlinux.org/patch/540/

Signed-off-by: Que Quotion <quequotion@gmail.com>
---
 scripts/Makefile.am                          |  6 ++
 scripts/libmakepkg/buildenv.sh.in            | 55 ++++++++++++++++++
 scripts/libmakepkg/buildenv/buildflags.sh.in | 34 +++++++++++
 scripts/libmakepkg/buildenv/ccache.sh.in     | 45 +++++++++++++++
 scripts/libmakepkg/buildenv/distcc.sh.in     | 47 +++++++++++++++
 scripts/libmakepkg/buildenv/makeflags.sh.in  | 34 +++++++++++
 scripts/libmakepkg/buildenv/meson.build      | 20 +++++++
 scripts/libmakepkg/meson.build               |  1 +
 scripts/makepkg.sh.in                        | 60 +-------------------
 9 files changed, 243 insertions(+), 59 deletions(-)
 create mode 100644 scripts/libmakepkg/buildenv.sh.in
 create mode 100644 scripts/libmakepkg/buildenv/buildflags.sh.in
 create mode 100644 scripts/libmakepkg/buildenv/ccache.sh.in
 create mode 100644 scripts/libmakepkg/buildenv/distcc.sh.in
 create mode 100644 scripts/libmakepkg/buildenv/makeflags.sh.in
 create mode 100644 scripts/libmakepkg/buildenv/meson.build

Comments

Eli Schwartz Nov. 4, 2018, 12:15 a.m. UTC | #1
On 11/3/18 12:54 PM, Que Quotion wrote:
> From: Que Quotion <quequotion@gmail.com>
> 
> As Eli Schwartz has pointed out:
> https://lists.archlinux.org/pipermail/pacman-dev/2018-May/022501.html
> 
> It would be beneficial to makepkg to have this function ported
> to libmakepkg and split into individual scripts.
> 
> Supersedes: https://patchwork.archlinux.org/patch/540/

Thanks for putting in the work to (re)do this.

> Signed-off-by: Que Quotion <quequotion@gmail.com>
> ---
>  scripts/Makefile.am                          |  6 ++
>  scripts/libmakepkg/buildenv.sh.in            | 55 ++++++++++++++++++
>  scripts/libmakepkg/buildenv/buildflags.sh.in | 34 +++++++++++
>  scripts/libmakepkg/buildenv/ccache.sh.in     | 45 +++++++++++++++
>  scripts/libmakepkg/buildenv/distcc.sh.in     | 47 +++++++++++++++
>  scripts/libmakepkg/buildenv/makeflags.sh.in  | 34 +++++++++++
>  scripts/libmakepkg/buildenv/meson.build      | 20 +++++++
>  scripts/libmakepkg/meson.build               |  1 +
>  scripts/makepkg.sh.in                        | 60 +-------------------
>  9 files changed, 243 insertions(+), 59 deletions(-)
>  create mode 100644 scripts/libmakepkg/buildenv.sh.in
>  create mode 100644 scripts/libmakepkg/buildenv/buildflags.sh.in
>  create mode 100644 scripts/libmakepkg/buildenv/ccache.sh.in
>  create mode 100644 scripts/libmakepkg/buildenv/distcc.sh.in
>  create mode 100644 scripts/libmakepkg/buildenv/makeflags.sh.in
>  create mode 100644 scripts/libmakepkg/buildenv/meson.build
> 
> diff --git a/scripts/Makefile.am b/scripts/Makefile.am
> index c6b6220e..8e669f71 100644
> --- a/scripts/Makefile.am
> +++ b/scripts/Makefile.am
> @@ -41,6 +41,7 @@ LIBRARY = \
>  libmakepkgdir = $(datarootdir)/makepkg
>  
>  LIBMAKEPKGDIRS = \
> +	buildenv \
>  	integrity \
>  	lint_config \
>  	lint_package \
> @@ -50,6 +51,11 @@ LIBMAKEPKGDIRS = \
>  	util
>  
>  LIBMAKEPKG_IN = \
> +	libmakepkg/buildenv.sh \
> +	libmakepkg/buildenv/buildflags.sh \
> +	libmakepkg/buildenv/ccache.sh \
> +	libmakepkg/buildenv/distcc.sh \
> +	libmakepkg/buildenv/makeflags.sh \
>  	libmakepkg/integrity.sh \
>  	libmakepkg/integrity/generate_checksum.sh \
>  	libmakepkg/integrity/generate_signature.sh \
> diff --git a/scripts/libmakepkg/buildenv.sh.in b/scripts/libmakepkg/buildenv.sh.in
> new file mode 100644
> index 00000000..a14a3a9a
> --- /dev/null
> +++ b/scripts/libmakepkg/buildenv.sh.in
> @@ -0,0 +1,55 @@
> +#!/bin/bash
> +#
> +#   buildenv.sh - functions for altering the build environment before
> +#   compiliation
> +#
> +#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
> +#
> +#   This program 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 2 of the License, or
> +#   (at your option) any later version.
> +#
> +#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +
> +[[ -n "$LIBMAKEPKG_BUILDENV_SH" ]] && return
> +LIBMAKEPKG_BUILDENV_SH=1
> +
> +LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
> +
> +source "$LIBRARY/util/message.sh"
> +source "$LIBRARY/util/option.sh"
> +
> +
> +declare -a build_options
> +
> +for lib in "$LIBRARY/buildenv/"*.sh; do
> +	source "$lib"
> +done
> +
> +readonly -a build_options
> +
> +prepare_buildenv() {
> +	msg "$(gettext "Preparing build environment...")"
> +
> +	for func in ${build_options[@]}; do
> +		$func
> +	done
> +
> +	if check_option "debug" "y"; then
> +		DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
> +		DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
> +		CFLAGS+=" $DEBUG_CFLAGS"
> +		CXXFLAGS+=" $DEBUG_CXXFLAGS"
> +	fi
> +
> +	# ensure all necessary build variables are exported
> +	export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
> +}

Why is this on its own, not in a dropin?

> diff --git a/scripts/libmakepkg/buildenv/buildflags.sh.in b/scripts/libmakepkg/buildenv/buildflags.sh.in
> new file mode 100644
> index 00000000..fb49a85c
> --- /dev/null
> +++ b/scripts/libmakepkg/buildenv/buildflags.sh.in
> @@ -0,0 +1,34 @@
> +#!/usr/bin/bash
> +#
> +#   buildflags.sh - Clear user-specified buildflags if requested
> +#
> +#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
> +#
> +#   This program 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 2 of the License, or
> +#   (at your option) any later version.
> +#
> +#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +
> +[[ -n "$LIBMAKEPKG_BUILDENV_BUILDFLAGS_SH" ]] && return
> +LIBMAKEPKG_BUILDENV_BUILDFLAGS_SH=1
> +
> +LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
> +
> +source "$LIBRARY/util/option.sh"
> +
> +build_options+=('buildflags')

If you look at the way we do this in other sections, this should
probably be namespaced as buildenv_buildflags

> +buildflags() {
> +	if check_option "buildflags" "n"; then
> +		unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
> +	fi
> +}
> diff --git a/scripts/libmakepkg/buildenv/ccache.sh.in b/scripts/libmakepkg/buildenv/ccache.sh.in
> new file mode 100644
> index 00000000..122033a9
> --- /dev/null
> +++ b/scripts/libmakepkg/buildenv/ccache.sh.in
> @@ -0,0 +1,45 @@
> +#!/usr/bin/bash
> +#
> +#   ccache.sh - Cache compiliations and recycle them to save time on repititions
> +#
> +#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
> +#
> +#   This program 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 2 of the License, or
> +#   (at your option) any later version.
> +#
> +#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +
> +[[ -n "$LIBMAKEPKG_BUILDENV_CCACHE_SH" ]] && return
> +LIBMAKEPKG_BUILDENV_CCACHE_SH=1
> +
> +LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
> +
> +source "$LIBRARY/util/message.sh"
> +source "$LIBRARY/util/option.sh"
> +
> +build_options+=('ccache')
> +
> +local ccache=0
> +
> +ccache() {
> +	if check_buildoption "ccache" "y"; then
> +		if ! type -p ccache >/dev/null; then
> +			error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
> +			return 1
> +		fi
> +
> +		if [ -d /usr/lib/ccache/bin ]; then
> +			export PATH="/usr/lib/ccache/bin:$PATH"
> +			ccache=1
> +		fi
> +	fi
> +}

ccache is now both a function name and a variable name...

And the variable is declared as local, but outside of a function --
instead, it's relying on the fact that libmakepkg typically sources this
file while inside another function. I don't know whether we should be
doing this...

I'm inclined to think that at least ccache and distcc should be in the
same dropin file and parsed as the same buildenv function as a result.
Maybe buildenv_compiler.

> diff --git a/scripts/libmakepkg/buildenv/distcc.sh.in b/scripts/libmakepkg/buildenv/distcc.sh.in
> new file mode 100644
> index 00000000..f7580705
> --- /dev/null
> +++ b/scripts/libmakepkg/buildenv/distcc.sh.in
> @@ -0,0 +1,47 @@
> +#!/usr/bin/bash
> +#
> +#   distcc.sh - Distribute compliation to reduce compilation time
> +#
> +#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
> +#
> +#   This program 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 2 of the License, or
> +#   (at your option) any later version.
> +#
> +#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +
> +[[ -n "$LIBMAKEPKG_BUILDENV_DISTCC_SH" ]] && return
> +LIBMAKEPKG_BUILDENV_DISTCC_SH=1
> +
> +LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
> +
> +source "$LIBRARY/util/message.sh"
> +source "$LIBRARY/util/option.sh"
> +
> +build_options+=('distcc')
> +
> +distcc() {
> +	if check_buildoption "distcc" "y"; then
> +		if ! type -p distcc >/dev/null; then
> +			error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
> +			return 1
> +		fi
> +
> +		if (( ccache )); then
> +			export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc"
> +			export CCACHE_BASEDIR="$srcdir"
> +		elif [[ -d /usr/lib/distcc/bin ]]; then
> +			export PATH="/usr/lib/distcc/bin:$PATH"
> +		fi
> +
> +		export DISTCC_HOSTS
> +	fi
> +}
> diff --git a/scripts/libmakepkg/buildenv/makeflags.sh.in b/scripts/libmakepkg/buildenv/makeflags.sh.in
> new file mode 100644
> index 00000000..53ac1e4c
> --- /dev/null
> +++ b/scripts/libmakepkg/buildenv/makeflags.sh.in
> @@ -0,0 +1,34 @@
> +#!/usr/bin/bash
> +#
> +#   makeflags.sh - Clear user-specified makeflags if requested
> +#
> +#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
> +#
> +#   This program 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 2 of the License, or
> +#   (at your option) any later version.
> +#
> +#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +
> +[[ -n "$LIBMAKEPKG_BUILDENV_MAKEFLAGS_SH" ]] && return
> +LIBMAKEPKG_BUILDENV_MAKEFLAGS_SH=1
> +
> +LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
> +
> +source "$LIBRARY/util/option.sh"
> +
> +build_options+=('makeflags')
> +
> +makeflags() {
> +	if check_option "makeflags" "n"; then
> +		unset MAKEFLAGS
> +	fi
> +}
> diff --git a/scripts/libmakepkg/buildenv/meson.build b/scripts/libmakepkg/buildenv/meson.build
> new file mode 100644
> index 00000000..e0d07287
> --- /dev/null
> +++ b/scripts/libmakepkg/buildenv/meson.build
> @@ -0,0 +1,20 @@
> +libmakepkg_module = 'buildenv'
> +
> +sources = [
> +  'buildflags.sh.in',
> +  'ccache.sh.in',
> +  'distcc.sh.in',
> +  'makeflags.sh.in',
> +]
> +
> +foreach src : sources
> +  output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module)
> +
> +  custom_target(
> +    libmakepkg_module + '_' + src.underscorify(),
> +    command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
> +    input : src,
> +    output : '@BASENAME@',
> +    install : true,
> +    install_dir : output_dir)
> +endforeach
> diff --git a/scripts/libmakepkg/meson.build b/scripts/libmakepkg/meson.build
> index 07475b4d..3a487f0d 100644
> --- a/scripts/libmakepkg/meson.build
> +++ b/scripts/libmakepkg/meson.build
> @@ -1,4 +1,5 @@
>  libmakepkg_modules = [
> +  { 'name' : 'buildenv',      'has_subdir' : true },
>    { 'name' : 'integrity',     'has_subdir' : true },
>    { 'name' : 'lint_config',   'has_subdir' : true },
>    { 'name' : 'lint_package',  'has_subdir' : true },
> diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
> index 3ac03d11..8ce006fb 100644
> --- a/scripts/makepkg.sh.in
> +++ b/scripts/makepkg.sh.in
> @@ -48,11 +48,10 @@ declare -r startdir="$(pwd -P)"
>  
>  LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
>  
> -build_options=('ccache' 'distcc' 'buildflags' 'makeflags')
>  splitpkg_overrides=('pkgdesc' 'arch' 'url' 'license' 'groups' 'depends'
>                      'optdepends' 'provides' 'conflicts' 'replaces' 'backup'
>                      'options' 'install' 'changelog')
> -readonly -a build_options splitpkg_overrides
> +readonly -a splitpkg_overrides
>  
>  known_hash_algos=('md5' 'sha1' 'sha224' 'sha256' 'sha384' 'sha512')
>  
> @@ -380,47 +379,6 @@ source_buildfile() {
>  	source_safe "$@"
>  }
>  
> -prepare_buildenv() {
> -	# clear user-specified buildflags if requested
> -	if check_option "buildflags" "n"; then
> -		unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
> -	fi
> -
> -	if check_option "debug" "y"; then
> -		DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
> -		DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
> -		CFLAGS+=" $DEBUG_CFLAGS"
> -		CXXFLAGS+=" $DEBUG_CXXFLAGS"
> -	fi
> -
> -	# clear user-specified makeflags if requested
> -	if check_option "makeflags" "n"; then
> -		unset MAKEFLAGS
> -	fi
> -
> -	# ensure all necessary build variables are exported
> -	export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
> -
> -	local ccache=0
> -
> -	# use ccache if it is requested (check buildenv and PKGBUILD opts)
> -	if check_buildoption "ccache" "y" && [[ -d /usr/lib/ccache/bin ]]; then
> -		export PATH="/usr/lib/ccache/bin:$PATH"
> -		ccache=1
> -	fi
> -
> -	# use distcc if it is requested (check buildenv and PKGBUILD opts)
> -	if check_buildoption "distcc" "y"; then
> -		if (( ccache )); then
> -			export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc"
> -			export CCACHE_BASEDIR="$srcdir"
> -		elif [[ -d /usr/lib/distcc/bin ]]; then
> -			export PATH="/usr/lib/distcc/bin:$PATH"
> -		fi
> -		export DISTCC_HOSTS
> -	fi
> -}
> -
>  run_function_safe() {
>  	local restoretrap restoreshopt
>  
> @@ -1029,22 +987,6 @@ check_software() {
>  		done
>  	fi
>  
> -	# distcc - compilation with distcc
> -	if check_buildoption "distcc" "y"; then
> -		if ! type -p distcc >/dev/null; then
> -			error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
> -			ret=1
> -		fi
> -	fi
> -
> -	# ccache - compilation with ccache
> -	if check_buildoption "ccache" "y"; then
> -		if ! type -p ccache >/dev/null; then
> -			error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
> -			ret=1
> -		fi
> -	fi
> -
>  	# strip - strip symbols from binaries/libraries
>  	if check_option "strip" "y"; then
>  		if ! type -p strip >/dev/null; then
>
Que Quotion Nov. 4, 2018, 2:35 p.m. UTC | #2
>> +	if check_option "debug" "y"; then
>> +		DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
>> +		DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
>> +		CFLAGS+=" $DEBUG_CFLAGS"
>> +		CXXFLAGS+=" $DEBUG_CXXFLAGS"
>> +	fi
>> +
>> +	# ensure all necessary build variables are exported
>> +	export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
>> +}
>
>Why is this on its own, not in a dropin?

I needed feedback on this; since the debugflags don't have a corresponding build_option I wasn't sure what to do with them. Your feedback on the ccache/distcc section 
gave me an idea.

>> +build_options+=('buildflags')
>
>If you look at the way we do this in other sections, this should
>probably be namespaced as buildenv_buildflags

I've kept the name as it was in the original implementation to avoid upsetting anyone who might be using this flag in a PKGBUILD or makepkg.conf.

>> +ccache() {
>> +	if check_buildoption "ccache" "y"; then
>> +		if ! type -p ccache >/dev/null; then
>> +			error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
>> +			return 1
>> +		fi
>> +
>> +		if [ -d /usr/lib/ccache/bin ]; then
>> +			export PATH="/usr/lib/ccache/bin:$PATH"
>> +			ccache=1
>> +		fi
>> +	fi
>> +}
>
>ccache is now both a function name and a variable name...
>
>And the variable is declared as local, but outside of a function --
>instead, it's relying on the fact that libmakepkg typically sources this
>file while inside another function. I don't know whether we should be
>doing this...
>
>I'm inclined to think that at least ccache and distcc should be in the
>same dropin file and parsed as the same buildenv function as a result.
>Maybe buildenv_compiler.

I'd rather have them separate, as they may be used separately, but then I don't know how to ensure the ccache macro would be called before the distcc macro, so I put 
them into compiler.sh.in

Attached patch is succesive, and should be applied after the previous. I can resubmit if you want a single patch.

Patch

diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index c6b6220e..8e669f71 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -41,6 +41,7 @@  LIBRARY = \
 libmakepkgdir = $(datarootdir)/makepkg
 
 LIBMAKEPKGDIRS = \
+	buildenv \
 	integrity \
 	lint_config \
 	lint_package \
@@ -50,6 +51,11 @@  LIBMAKEPKGDIRS = \
 	util
 
 LIBMAKEPKG_IN = \
+	libmakepkg/buildenv.sh \
+	libmakepkg/buildenv/buildflags.sh \
+	libmakepkg/buildenv/ccache.sh \
+	libmakepkg/buildenv/distcc.sh \
+	libmakepkg/buildenv/makeflags.sh \
 	libmakepkg/integrity.sh \
 	libmakepkg/integrity/generate_checksum.sh \
 	libmakepkg/integrity/generate_signature.sh \
diff --git a/scripts/libmakepkg/buildenv.sh.in b/scripts/libmakepkg/buildenv.sh.in
new file mode 100644
index 00000000..a14a3a9a
--- /dev/null
+++ b/scripts/libmakepkg/buildenv.sh.in
@@ -0,0 +1,55 @@ 
+#!/bin/bash
+#
+#   buildenv.sh - functions for altering the build environment before
+#   compiliation
+#
+#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
+#
+#   This program 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 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_BUILDENV_SH" ]] && return
+LIBMAKEPKG_BUILDENV_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/option.sh"
+
+
+declare -a build_options
+
+for lib in "$LIBRARY/buildenv/"*.sh; do
+	source "$lib"
+done
+
+readonly -a build_options
+
+prepare_buildenv() {
+	msg "$(gettext "Preparing build environment...")"
+
+	for func in ${build_options[@]}; do
+		$func
+	done
+
+	if check_option "debug" "y"; then
+		DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
+		DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
+		CFLAGS+=" $DEBUG_CFLAGS"
+		CXXFLAGS+=" $DEBUG_CXXFLAGS"
+	fi
+
+	# ensure all necessary build variables are exported
+	export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
+}
diff --git a/scripts/libmakepkg/buildenv/buildflags.sh.in b/scripts/libmakepkg/buildenv/buildflags.sh.in
new file mode 100644
index 00000000..fb49a85c
--- /dev/null
+++ b/scripts/libmakepkg/buildenv/buildflags.sh.in
@@ -0,0 +1,34 @@ 
+#!/usr/bin/bash
+#
+#   buildflags.sh - Clear user-specified buildflags if requested
+#
+#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
+#
+#   This program 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 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_BUILDENV_BUILDFLAGS_SH" ]] && return
+LIBMAKEPKG_BUILDENV_BUILDFLAGS_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/option.sh"
+
+build_options+=('buildflags')
+
+buildflags() {
+	if check_option "buildflags" "n"; then
+		unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
+	fi
+}
diff --git a/scripts/libmakepkg/buildenv/ccache.sh.in b/scripts/libmakepkg/buildenv/ccache.sh.in
new file mode 100644
index 00000000..122033a9
--- /dev/null
+++ b/scripts/libmakepkg/buildenv/ccache.sh.in
@@ -0,0 +1,45 @@ 
+#!/usr/bin/bash
+#
+#   ccache.sh - Cache compiliations and recycle them to save time on repititions
+#
+#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
+#
+#   This program 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 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_BUILDENV_CCACHE_SH" ]] && return
+LIBMAKEPKG_BUILDENV_CCACHE_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/option.sh"
+
+build_options+=('ccache')
+
+local ccache=0
+
+ccache() {
+	if check_buildoption "ccache" "y"; then
+		if ! type -p ccache >/dev/null; then
+			error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
+			return 1
+		fi
+
+		if [ -d /usr/lib/ccache/bin ]; then
+			export PATH="/usr/lib/ccache/bin:$PATH"
+			ccache=1
+		fi
+	fi
+}
diff --git a/scripts/libmakepkg/buildenv/distcc.sh.in b/scripts/libmakepkg/buildenv/distcc.sh.in
new file mode 100644
index 00000000..f7580705
--- /dev/null
+++ b/scripts/libmakepkg/buildenv/distcc.sh.in
@@ -0,0 +1,47 @@ 
+#!/usr/bin/bash
+#
+#   distcc.sh - Distribute compliation to reduce compilation time
+#
+#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
+#
+#   This program 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 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_BUILDENV_DISTCC_SH" ]] && return
+LIBMAKEPKG_BUILDENV_DISTCC_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/message.sh"
+source "$LIBRARY/util/option.sh"
+
+build_options+=('distcc')
+
+distcc() {
+	if check_buildoption "distcc" "y"; then
+		if ! type -p distcc >/dev/null; then
+			error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
+			return 1
+		fi
+
+		if (( ccache )); then
+			export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc"
+			export CCACHE_BASEDIR="$srcdir"
+		elif [[ -d /usr/lib/distcc/bin ]]; then
+			export PATH="/usr/lib/distcc/bin:$PATH"
+		fi
+
+		export DISTCC_HOSTS
+	fi
+}
diff --git a/scripts/libmakepkg/buildenv/makeflags.sh.in b/scripts/libmakepkg/buildenv/makeflags.sh.in
new file mode 100644
index 00000000..53ac1e4c
--- /dev/null
+++ b/scripts/libmakepkg/buildenv/makeflags.sh.in
@@ -0,0 +1,34 @@ 
+#!/usr/bin/bash
+#
+#   makeflags.sh - Clear user-specified makeflags if requested
+#
+#   Copyright (c) 2018 Pacman Development Team <pacman-dev@archlinux.org>
+#
+#   This program 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 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_BUILDENV_MAKEFLAGS_SH" ]] && return
+LIBMAKEPKG_BUILDENV_MAKEFLAGS_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+source "$LIBRARY/util/option.sh"
+
+build_options+=('makeflags')
+
+makeflags() {
+	if check_option "makeflags" "n"; then
+		unset MAKEFLAGS
+	fi
+}
diff --git a/scripts/libmakepkg/buildenv/meson.build b/scripts/libmakepkg/buildenv/meson.build
new file mode 100644
index 00000000..e0d07287
--- /dev/null
+++ b/scripts/libmakepkg/buildenv/meson.build
@@ -0,0 +1,20 @@ 
+libmakepkg_module = 'buildenv'
+
+sources = [
+  'buildflags.sh.in',
+  'ccache.sh.in',
+  'distcc.sh.in',
+  'makeflags.sh.in',
+]
+
+foreach src : sources
+  output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module)
+
+  custom_target(
+    libmakepkg_module + '_' + src.underscorify(),
+    command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
+    input : src,
+    output : '@BASENAME@',
+    install : true,
+    install_dir : output_dir)
+endforeach
diff --git a/scripts/libmakepkg/meson.build b/scripts/libmakepkg/meson.build
index 07475b4d..3a487f0d 100644
--- a/scripts/libmakepkg/meson.build
+++ b/scripts/libmakepkg/meson.build
@@ -1,4 +1,5 @@ 
 libmakepkg_modules = [
+  { 'name' : 'buildenv',      'has_subdir' : true },
   { 'name' : 'integrity',     'has_subdir' : true },
   { 'name' : 'lint_config',   'has_subdir' : true },
   { 'name' : 'lint_package',  'has_subdir' : true },
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 3ac03d11..8ce006fb 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -48,11 +48,10 @@  declare -r startdir="$(pwd -P)"
 
 LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
 
-build_options=('ccache' 'distcc' 'buildflags' 'makeflags')
 splitpkg_overrides=('pkgdesc' 'arch' 'url' 'license' 'groups' 'depends'
                     'optdepends' 'provides' 'conflicts' 'replaces' 'backup'
                     'options' 'install' 'changelog')
-readonly -a build_options splitpkg_overrides
+readonly -a splitpkg_overrides
 
 known_hash_algos=('md5' 'sha1' 'sha224' 'sha256' 'sha384' 'sha512')
 
@@ -380,47 +379,6 @@  source_buildfile() {
 	source_safe "$@"
 }
 
-prepare_buildenv() {
-	# clear user-specified buildflags if requested
-	if check_option "buildflags" "n"; then
-		unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
-	fi
-
-	if check_option "debug" "y"; then
-		DEBUG_CFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
-		DEBUG_CXXFLAGS+=" -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug}"
-		CFLAGS+=" $DEBUG_CFLAGS"
-		CXXFLAGS+=" $DEBUG_CXXFLAGS"
-	fi
-
-	# clear user-specified makeflags if requested
-	if check_option "makeflags" "n"; then
-		unset MAKEFLAGS
-	fi
-
-	# ensure all necessary build variables are exported
-	export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
-
-	local ccache=0
-
-	# use ccache if it is requested (check buildenv and PKGBUILD opts)
-	if check_buildoption "ccache" "y" && [[ -d /usr/lib/ccache/bin ]]; then
-		export PATH="/usr/lib/ccache/bin:$PATH"
-		ccache=1
-	fi
-
-	# use distcc if it is requested (check buildenv and PKGBUILD opts)
-	if check_buildoption "distcc" "y"; then
-		if (( ccache )); then
-			export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc"
-			export CCACHE_BASEDIR="$srcdir"
-		elif [[ -d /usr/lib/distcc/bin ]]; then
-			export PATH="/usr/lib/distcc/bin:$PATH"
-		fi
-		export DISTCC_HOSTS
-	fi
-}
-
 run_function_safe() {
 	local restoretrap restoreshopt
 
@@ -1029,22 +987,6 @@  check_software() {
 		done
 	fi
 
-	# distcc - compilation with distcc
-	if check_buildoption "distcc" "y"; then
-		if ! type -p distcc >/dev/null; then
-			error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
-			ret=1
-		fi
-	fi
-
-	# ccache - compilation with ccache
-	if check_buildoption "ccache" "y"; then
-		if ! type -p ccache >/dev/null; then
-			error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
-			ret=1
-		fi
-	fi
-
 	# strip - strip symbols from binaries/libraries
 	if check_option "strip" "y"; then
 		if ! type -p strip >/dev/null; then