Files
blis/configure
Field G. Van Zee 9804adfd40 Added option to disable pack buffer memory pools.
Details:
- Added a new configure option, --[en|dis]able-packbuf-pools, which will
  enable or disable the use of internal memory pools for managing buffers
  used for packing. When disabled, the function specified by the cpp
  macro BLIS_MALLOC_POOL is called whenever a packing buffer is needed
  (and BLIS_FREE_POOL is called when the buffer is ready to be released,
  usually at the end of a loop). When enabled, which was the status quo
  prior to this commit, a memory pool data structure is created and
  managed to provide threads with packing buffers. The memory pool
  minimizes calls to bli_malloc_pool() (i.e., the wrapper that calls
  BLIS_MALLOC_POOL), but does so through a somewhat more complex
  mechanism that may incur additional overhead in some (but not all)
  situations. The new option defaults to --enable-packbuf-pools.
- Removed the reinitialization of the memory pools from the level-3
  front-ends and replaced it with automatic reinitialization within the
  pool API's implementation. This required an extra argument to
  bli_pool_checkout_block() in the form of a requested size, but hides
  the complexity entirely from BLIS. And since bli_pool_checkout_block()
  is only ever called within a critical section, this change fixes a
  potential race condition in which threads using contexts with different
  cache blocksizes--most likely a heterogeneous environment--can check
  out pool blocks that are too small for the submatrices it wishes to
  pack. Thanks to Nisanth Padinharepatt for reporting this potential
  issue.
- Removed several functions in light of the relocation of pool reinit,
  including bli_membrk_reinit_pools(), bli_memsys_reinit(),
  bli_pool_reinit_if(), and bli_check_requested_block_size_for_pool().
- Updated the testsuite to print whether the memory pools are enabled or
  disabled.
2017-12-21 19:22:57 -06:00

1411 lines
43 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# BLIS
# An object-based framework for developing high-performance BLAS-like
# libraries.
#
# Copyright (C) 2014, The University of Texas at Austin
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - Neither the name of The University of Texas at Austin nor the names
# of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
#
# -- Helper functions ----------------------------------------------------------
#
print_usage()
{
# Echo usage info.
echo " "
echo " ${script_name} (BLIS ${version})"
#echo " "
#echo " BLIS ${version}"
echo " "
echo " Field G. Van Zee"
echo " "
echo " Configure BLIS's build system for compilation using a specified"
echo " configuration directory."
echo " "
echo " Usage:"
echo " "
echo " ${script_name} [options] [env. vars.] confname"
echo " "
echo " Arguments:"
echo " "
echo " confname The name of the sub-directory inside of the 'config'"
echo " directory containing the desired BLIS configuration."
echo " Note that confname MUST be specified; if it is not,"
echo " configure will complain. To build a completely generic"
echo " implementation, use the 'generic' configuration"
echo " "
echo " Options:"
echo " "
echo " -p PREFIX, --prefix=PREFIX"
echo " "
echo " The path to which make will install buid products."
echo " If not given, PREFIX defaults to \$(HOME)/blis. If"
echo " the path refers to a directory that does not exist,"
echo " it will be created."
echo " "
echo " -d DEBUG, --enable-debug[=DEBUG]"
echo " "
echo " Enable debugging symbols in the library. If argument"
echo " DEBUG is given as 'opt', then optimization flags are"
echo " kept in the framework, otherwise optimization is"
echo " turned off."
echo " "
echo " --enable-verbose-make, --disable-verbose-make"
echo " "
echo " Enable (disabled by default) verbose compilation"
echo " output during make."
echo " "
echo " --disable-static, --enable-static"
echo " "
echo " Disable (enabled by default) building BLIS as a static"
echo " library. May be combined with --enable-shared."
echo " "
echo " --enable-shared, --disable-static"
echo " "
echo " Enable (disabled by default) building BLIS as a shared"
echo " library. May be combined with --enable-static."
echo " "
echo " -t MODEL, --enable-threading[=MODEL], --disable-threading"
echo " "
echo " Enable threading in the library, using threading model"
echo " MODEL={openmp,pthreads,no}. If MODEL=no or "
echo " --disable-threading is specified, threading will be"
echo " disabled. The default is 'no'."
echo " "
echo " --disable-packbuf-pools, --enable-packbuf-pools"
echo " "
echo " Disable (enabled by default) use of internal memory"
echo " pools for managing packing buffers. When disabled,"
echo " the function specified by BLIS_MALLOC_POOL is called"
echo " on-demand, whenever a packing buffer is needed, and"
echo " the buffer is released via the function specified by"
echo " BLIS_FREE_POOL() when the loop in which it was"
echo " allocated terminates. When enabled, the memory pools"
echo " minimize calls to both BLIS_MALLOC_POOL() and"
echo " BLIS_FREE_POOL(), especially in a multithreaded"
echo " environment, but does so through a mechanism that may"
echo " incur additional overhead in some (but not all)"
echo " situations."
echo " "
echo " -q, --quiet Suppress informational output. By default, configure"
echo " is verbose. (NOTE: -q is not yet implemented)"
echo " "
echo " -i SIZE, --int-size=SIZE"
echo " "
echo " Set the size (in bits) of internal BLIS integers and"
echo " integer types used in native BLIS interfaces. The"
echo " default inteter type size is architecture dependent."
echo " (Hint: You can always find this value printed at the"
echo " beginning of the testsuite output.)"
echo " "
echo " -b SIZE, --blas-int-size=SIZE"
echo " "
echo " Set the size (in bits) of integer types in external"
echo " BLAS and CBLAS interfaces, if enabled. The default"
echo " integer type size used in BLAS/CBLAS is 32 bits."
echo " "
echo " --disable-blas, --enable-blas"
echo " "
echo " Disable (enabled by default) building the BLAS"
echo " compatibility layer."
echo " "
echo " --enable-cblas, --disable-cblas"
echo " "
echo " Enable (disabled by default) building the CBLAS"
echo " compatibility layer. This automatically enables the"
echo " BLAS compatibility layer as well."
echo " "
echo " --force-version=STRING"
echo " "
echo " Force configure to use an arbitrary version string"
echo " STRING. This option may be useful when repackaging"
echo " custom versions of BLIS by outside organizations."
echo " "
echo " -c, --show-config-lists"
echo " "
echo " Print the config and kernel lists, and kernel-to-config"
echo " map after they are read from file. This can be useful"
echo " when debugging certain configuration issues, and/or as"
echo " a sanity check to make sure these lists are constituted"
echo " as expected."
echo " "
echo " -h, --help Output this information and quit."
echo " "
echo " Environment Variables:"
echo " "
echo " CC Specifies the C compiler to use."
echo " "
echo " Environment variables may also be specified as command line"
echo " options, e.g.:"
echo " "
echo " ./configure [options] CC=gcc sandybridge"
echo " "
echo " Note that not all compilers are compatible with a given"
echo " configuration."
echo " "
# Exit with non-zero exit status
exit 1
}
query_array()
{
array_name=$1
key_name=$2
var_name="${array_name}_${key_name}"
echo "${!var_name}"
}
read_registry_file()
{
local cname clist
filename="$1"
while read -r line
do
curline="${line}"
#echo "curline: ${curline}"
# Remove leading whitespace from the current line.
# NOTE: read -r already prunes leading whitespace
#curline=$(echo "${curline}" | sed "s/^[ \t]*//")
# Remove everything after comment character '#'.
curline=${curline%%#*}
# We've stripped out leading whitespace and trailing comments. If
# the line is now empty, then we can skip it altogether.
if [ "x${curline}" = "x" ]; then
continue;
fi
# Read the config name and config list for the current line.
cname=${curline%%:*}
list=${curline##*:}
# If we encounter a slash, it means the name of the configuration
# and the kernel set needed by that configuration are different.
if [[ ${list} == *[/]* ]]; then
#echo "Slash found."
klist=""
clist=""
for item in "${list}"; do
# The sub-configuration name is always the first sub-word in
# the slash-separated compound word.
config=${item%%/*}
# Delete the sub-configuration name from the front of the
# string, leaving the slash-separated kernel names (or just
# the kernel name, if there is only one).
kernels=${list#*/}
# Replace the slashes with spaces to transform the string
# into a space-separated list of kernel names.
kernels=$(echo -e ${kernels} | sed -e "s/\// /g")
clist="${clist} ${config}"
klist="${klist} ${kernels}"
done
else
#echo "Slash not found."
clist=${list}
klist=${list}
fi
# Strip out whitespace from the config name and config/kernel list
# on each line.
cname=$(canonicalize_ws "${cname}")
clist=$(canonicalize_ws "${clist}")
klist=$(canonicalize_ws "${klist}")
# Store the config and kernel lists to the entry in the associative
# arrays that corresponds to the config name.
#config_registry[${cname}]=${clist}
#kernel_registry[${cname}]=${klist}
printf -v "config_registry_${cname}" %s "${clist}"
printf -v "kernel_registry_${cname}" %s "${klist}"
done < "${filename}"
# Now go back through the kernel registry and substitute any remaining
# configuration names occurring in the kernel list (right side of ':')
# with its registered kernel set.
#for config in "${!kernel_registry[@]}"; do
for kr_var in ${!kernel_registry_*}; do
config=${kr_var##kernel_registry_}
#for ker in ${kernel_registry[$config]}; do
for ker in ${!kr_var}; do
#kers_ker="${kernel_registry[${ker}]}"
kers_ker=$(query_array "kernel_registry" ${ker})
# If kers_ker is empty string, then ker was not found as a key
# in the kernel list associative array. In that case, we continue
# and will echo an error later in the script.
if [ "${kers_ker}" == "" ]; then
#echo " kernel for ${ker} is empty string! no entry in kernel list."
continue;
fi
# If the current config/kernel (ker) differs from its singleton kernel
# entry (kers_ker), then that singleton entry was specified to use
# a different configuration's kernel set. Thus, we need to replace the
# occurrence in the current config/kernel name with that of the kernel
# set it needs.
if [ "${ker}" != "${kers_ker}" ]; then
#klist="${kernel_registry[$config]}"
klist=$(query_array "kernel_registry" ${config})
# Replace the current config with its requisite kernels,
# canonicalize whitespace, and then remove duplicate kernel
# set names, if they exist. Finally, update the kernel registry
# with the new kernel list.
newklist=$(echo -e "${klist}" | sed -e "s/${ker}/${kers_ker}/g")
newklist=$(canonicalize_ws "${newklist}")
newklist=$(rm_duplicate_words "${newklist}")
#kernel_registry[${config}]=${newklist}
printf -v "kernel_registry_${config}" %s "${newklist}"
fi
done
done
}
build_kconfig_registry()
{
familyname="$1"
#clist="${config_registry[${familyname}]}"
clist=$(query_array "config_registry" ${familyname})
for config in ${clist}; do
#echo "${config}"
# Look up the kernel for the current sub-configuration.
#kernels="${kernel_registry[${config}]}"
kernels=$(query_array "kernel_registry" ${config})
for kernel in ${kernels}; do
#echo " ${kernel}"
# Add the sub-configuration to the list associated with the
# kernel.
# Query the current sub-configs for the current ${kernel}.
#cur_configs="${kconfig_registry[${kernel}]}"
cur_configs=$(query_array "kconfig_registry" ${kernel})
# Add the current sub-configuration to the list of sub-configs
# we just queried.
newvalue=$(canonicalize_ws "${cur_configs} ${config}")
# Update the array.
#kconfig_registry[${kernel}]="${newvalue}"
printf -v "kconfig_registry_${kernel}" %s "${newvalue}"
done
done
}
is_word_in_list()
{
word="$1"
list="$2"
rval="false"
for item in ${list}; do
if [ "${item}" == "${word}" ]; then
rval="true"
break
fi
done
echo "${rval}"
}
is_singleton()
{
list="$1"
rval="false"
count_str=""
for item in ${list}; do
count_str="${count_str}x"
done
if [ ${count_str} == "x" ]; then
rval="true"
fi
echo "${rval}"
}
canonicalize_ws()
{
local str="$1"
# Remove leading and trailing whitespace.
str=$(echo -e "${str}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
# Remove duplicate spaces between words.
str=$(echo -e "${str}" | tr -s " ")
# Update the input argument.
echo "${str}"
}
rm_duplicate_words()
{
str="$1"
str=$(echo "${str}" | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')
echo "${str}"
}
#
# -- main function -------------------------------------------------------------
#
main()
{
#declare -A config_registry
#declare -A kernel_registry
#declare -A kconfig_registry
# The name of the script, stripped of any preceeding path.
script_name=${0##*/}
# The path to the script. We need this to find the top-level directory
# of the source distribution in the event that the user has chosen to
# build elsewhere.
dist_path=${0%/${script_name}}
# The path to the directory in which we are building. We do this to
# make explicit that we distinguish between the top-level directory
# of the distribution and the directory in which we are building.
cur_dirpath="."
# The file in which the version string is kept.
version_file="version"
version_filepath="${dist_path}/${version_file}"
# The name of and path to the directory named "build" in the top-level
# directory of the source distribution.
build_dir='build'
build_dirpath="${dist_path}/${build_dir}"
# The name/path to the registry (master list) of supported configurations.
registry_file="config_registry"
registry_filepath=${dist_path}/${registry_file}
# The names/paths for the template config.mk.in and its instantiated
# counterpart.
config_mk_in='config.mk.in'
config_mk_out='config.mk'
config_mk_in_path="${build_dirpath}/${config_mk_in}"
config_mk_out_path="${cur_dirpath}/${config_mk_out}"
# The names/paths for the template bli_config.h.in and its instantiated
# counterpart.
bli_config_h_in='bli_config.h.in'
bli_config_h_out='bli_config.h'
bli_config_h_in_path="${build_dirpath}/${bli_config_h_in}"
bli_config_h_out_path="${cur_dirpath}/${bli_config_h_out}"
# Path to 'update-version-file.sh' script.
update_version_file_sh="${build_dirpath}/update-version-file.sh"
# Path to 'mirror-tree.sh' script.
mirror_tree_sh="${build_dirpath}/mirror-tree.sh"
# Path to 'gen-make-frags.sh' script and directory.
gen_make_frags_dirpath="${build_dirpath}/gen-make-frags"
gen_make_frags_sh="${gen_make_frags_dirpath}/gen-make-frag.sh"
# The name of the (top-level) configuration directory.
config_dir='config'
config_dirpath="${dist_path}/${config_dir}"
# The name of the (top-level) kernels directory.
kernels_dir='kernels'
kernels_dirpath="${dist_path}/${kernels_dir}"
# The name of the (top-level) reference kernels directory.
refkern_dir='ref_kernels'
refkern_dirpath="${dist_path}/${refkern_dir}"
# The root directory of the BLIS framework.
frame_dir='frame'
frame_dirpath="${dist_path}/${frame_dir}"
# The name of the directory in which object files will be kept.
obj_dir='obj'
obj_dirpath="${cur_dirpath}/${obj_dir}"
# The name of the directory in which libraries will be kept.
lib_dir='lib'
lib_dirpath="${cur_dirpath}/${lib_dir}"
# The name of the directory in which headers will be kept.
include_dir='include'
include_dirpath="${cur_dirpath}/${include_dir}"
# The name of the directory in which the test suite is kept.
testsuite_dir='testsuite'
# The install prefix flag.
install_prefix_def="${HOME}/blis"
install_prefix=''
prefix_flag=''
# The debug flag.
debug_type=''
debug_flag=''
# The threading flag.
threading_model='no'
# Option variables.
quiet_flag=''
show_config_list=''
# Additional flags.
enable_verbose='no'
enable_static='yes'
enable_shared='no'
enable_packbuf_pools='yes'
int_type_size=0
blas2blis_int_type_size=32
enable_blas2blis='yes'
enable_cblas='no'
force_version='no'
# The path to the auto-detection script.
auto_detect_sh="${build_dirpath}/auto-detect/auto-detect.sh"
# The name of the chosen configuration (the configuration "family").
config_name=''
# The list of sub-configurations associated with config_name.
config_list=''
# The list of kernel sets that will be needed by the sub-configurations
# in config_list..
kernel_list=''
# The list of kernel:sub-configuration pairs for all kernels contained
# in kernel_list.
kconfig_map=''
# Dummy file. Used to check whether the cwd is the same as the top-level
# source distribution directory.
dummy_file='_blis_dir_detect.tmp'
# -- Command line option/argument parsing ----------------------------------
# Process our command line options.
while getopts ":hp:d:t:qci:b:-:" opt; do
case $opt in
-)
case "$OPTARG" in
help)
print_usage
;;
quiet)
quiet_flag=1
;;
prefix=*)
prefix_flag=1
install_prefix=${OPTARG#*=}
;;
enable-debug)
debug_flag=1
debug_type=noopt
;;
enable-debug=*)
debug_flag=1
debug_type=${OPTARG#*=}
;;
disable-debug)
debug_flag=0
;;
enable-verbose-make)
enable_verbose='yes'
;;
disable-verbose-make)
enable_verbose='no'
;;
enable-static)
enable_static='yes'
;;
disable-static)
enable_static='no'
;;
enable-shared)
enable_shared='yes'
;;
disable-shared)
enable_shared='no'
;;
enable-threading=*)
threading_model=${OPTARG#*=}
;;
disable-threading)
threading_model='no'
;;
enable-packbuf-pools)
enable_packbuf_pools='yes'
;;
disable-packbuf-pools)
enable_packbuf_pools='no'
;;
int-size=*)
int_type_size=${OPTARG#*=}
;;
blas-int-size=*)
blas2blis_int_type_size=${OPTARG#*=}
;;
enable-blas)
enable_blas2blis='yes'
;;
disable-blas)
enable_blas2blis='no'
;;
enable-cblas)
enable_cblas='yes'
;;
disable-cblas)
enable_cblas='no'
;;
force-version=*)
force_version=${OPTARG#*=}
;;
show-config-list)
show_config_list=1
;;
*)
print_usage
;;
esac;;
h)
print_usage
;;
p)
prefix_flag=1
install_prefix=$OPTARG
;;
d)
debug_flag=1
debug_type=$OPTARG
;;
q)
quiet_flag=1
;;
t)
threading_model=$OPTARG
;;
i)
int_type_size=$OPTARG
;;
b)
blas2blis_int_type_size=$OPTARG
;;
c)
show_config_list=1
;;
\?)
print_usage
;;
esac
done
shift $(($OPTIND - 1))
# Parse environment variables
while [ $# -gt 0 ]; do
case $1 in
CC=*)
CC=${1#*=}
shift
;;
*=*)
print_usage
;;
*)
break
;;
esac
done
# -- Read the configuration registry ---------------------------------------
# Make sure the config registry file exists and can be opened.
if [ ! -f "${registry_filepath}" ]; then
echo "${script_name}: could not open '${registry_file}' file; cannot continue."
echo "${script_name}: BLIS distribution appears to be incomplete."
exit 1
fi
# Read the registered configuration names and lists into an associative
# array.
echo -n "${script_name}: reading configuration registry..."
read_registry_file ${registry_filepath}
echo "done."
# -- Acquire the BLIS version ----------------------------------------------
# Check whether we need to update the version file.
${update_version_file_sh} -o "${script_name}" "${version_filepath}"
# Query which version of BLIS this is.
version=$(cat ${version_filepath})
# Initial message.
echo "${script_name}: starting configuration of BLIS ${version}."
# Check if the user requested a custom version string.
if [ "x${force_version}" = "xno" ]; then
echo "${script_name}: configuring with official version string."
else
echo "${script_name}: configuring with custom version string '${force_version}'."
version="${force_version}"
fi
# -- Various pre-configuration checks --------------------------------------
# Set config_name based on the number of arguments leftover (after command
# line option processing).
if [ $# = "0" ]; then
#configs_avail="auto "$(ls ${config_dirpath})
echo "${script_name}: "
echo "${script_name}: *** No configuration given! ***"
echo "${script_name}: "
echo "${script_name}: Default configuration behavior is not implemented (for your"
echo "${script_name}: own safety). Please re-run '${script_name}' and specify one"
echo "${script_name}: of the existing configurations in the source distribution's"
echo "${script_name} '${registry_file}' file:"
echo "${script_name}: "
#for k in "${!config_registry[@]}"; do
for cr_var in ${!config_registry_*}; do
#v=${config_registry[$k]}
k=${cr_var##config_registry_}; v=${!cr_var}
echo "${script_name}: $k (${v})"
done
echo "${script_name}: "
exit 1
elif [ $# != "1" ]; then # more than one configuration argument given.
print_usage
fi
if [ $1 = "auto" ]; then
echo "${script_name}: automatic configuration requested."
# Run the auto-detect script and save the result in config_name.
config_name=`${build_dirpath}/auto-detect/auto-detect.sh`
echo "${script_name}: auto-detect script returned '${config_name}'."
else
# Use the command line argument as the configuration name.
config_name=$1
#echo "${script_name}: manual configuration requested."
echo "${script_name}: manual configuration requested; configuring with '${config_name}'."
fi
# Use the selected config name to look up the list of configurations
# and kernels associated with that name.
#config_list=${config_registry[${config_name}]}
#kernel_list=${kernel_registry[${config_name}]}
config_list=$(query_array "config_registry" ${config_name})
kernel_list=$(query_array "kernel_registry" ${config_name})
# Use the config_registry and kernel_registry to build a kconfig_registry
# for the selected config_name.
build_kconfig_registry "${config_name}"
# Print the configuration list and kernel list, if requested.
if [ "${show_config_list}" == "1" ]; then
echo "${script_name}: configuration list:"
#for k in "${!config_registry[@]}"; do
for cr_var in ${!config_registry_*}; do
#v=${config_registry[$k]}
k=${cr_var##config_registry_}; v=${!cr_var}
echo "${script_name}: $k: ${v}"
done
echo "${script_name}: kernel list:"
#for k in "${!kernel_registry[@]}"; do
for kr_var in ${!kernel_registry_*}; do
#v=${kernel_registry[$k]}
k=${kr_var##kernel_registry_}; v=${!kr_var}
echo "${script_name}: $k: ${v}"
done
echo "${script_name}: kernel-to-config map:"
#for k in "${!kconfig_registry[@]}"; do
for kc_var in ${!kconfig_registry_*}; do
#v=${kconfig_registry[$k]}
k=${kc_var##kconfig_registry_}; v=${!kc_var}
echo "${script_name}: $k: ${v}"
done
fi
# For each kernel in the kernel list, reduce the list of associated
# sub-configurations (in the kconfig_registry) to a singleton using
# the following rules:
# 1. If the list is a singleton, use that name.
# 2. If the list contains a sub-configuration name that matches the
# kernel name, use that name.
# 3. Otherwise, use the first name in the list.
# We use the chosen singleton to ceate a "kernel:subconfig" pair, which
# we accumulate into a list. This list is the kernel-to-config map, or
# kconfig_map.
# We use a sorted version of kernel_list so that it ends up matching the
# display order of the kconfig_registry above.
kernel_list_sort=$(echo ${kernel_list} | xargs -n1 | sort -u)
kconfig_map=""
for kernel in ${kernel_list_sort}; do
#configs="${kconfig_registry[$kernel]}"
configs=$(query_array "kconfig_registry" ${kernel})
has_one_kernel=$(is_singleton "${configs}")
contains_kernel=$(is_word_in_list "${kernel}" "${configs}")
# Check if the list is a singleton.
if [ "${has_one_kernel}" == "true" ]; then
reducedclist="${configs}"
# Check if the list contains a sub-config name that matches the kernel.
elif [ "${contains_kernel}" == "true" ]; then
reducedclist="${kernel}"
# Otherwise, use the first name.
else
first_config=${configs%% *}
reducedclist="${first_config}"
fi
# Create a new "kernel:subconfig" pair and add it to the kconfig_map
# list, removing whitespace.
new_pair="${kernel}:${reducedclist}"
kconfig_map=$(canonicalize_ws "${kconfig_map} ${new_pair}")
done
if [ "${show_config_list}" == "1" ]; then
echo "${script_name}: kernel-to-config map (chosen pairs):"
for k in ${kconfig_map}; do
echo "${script_name}: $k"
done
fi
echo "${script_name}: checking configuration against contents of '${registry_file}'."
# First, ensure that the config name is registered (ie: it is present
# in the config_registry file).
if [ -z "${config_list}" ]; then
# NOTE: This branch should never execute when using the
# auto-detect script, but we have it here just in case.
if [ $1 = "auto" ]; then
echo "${script_name}: 'auto-detected configuration '${conf}' is NOT registered!"
echo "${script_name}: "
echo "${script_name}: *** Cannot continue with unregistered configuration '${conf}'. ***"
echo "${script_name}: "
exit 1;
else
echo "${script_name}: 'user-specified configuration '${conf}' is NOT registered!"
echo "${script_name}: "
echo "${script_name}: *** Cannot continue with unregistered configuration '${conf}'. ***"
echo "${script_name}: "
exit 1;
fi
else
# This branch executes when the configuration is found to be present
# (i.e. registered) in the config_registry file.
echo "${script_name}: configuration '${config_name}' is registered."
echo "${script_name}: '${config_name}' is defined as having the following sub-configurations:"
echo "${script_name}: ${config_list}"
echo "${script_name}: which collectively require the following kernels:"
echo "${script_name}: ${kernel_list}"
fi
echo "${script_name}: checking sub-configurations:"
# Now, verify that the constituent configurations associated with the
# config name are all valid.
for conf in ${config_list}; do
# First confirm that the current configuration is registered.
#this_clist=${config_registry[${conf}]}
this_clist=$(query_array "config_registry" ${conf})
# If the config_list associated with conf is empty, then it was
# never entered into the config_registry to begin with. Thus,
# conf must be unregistered.
if [ -z "${this_clist}" ]; then
echo "${script_name}: '${conf}' is NOT registered!"
echo "${script_name}: "
echo "${script_name}: *** Cannot continue with unregistered configuration '${conf}'. ***"
echo "${script_name}: "
exit 1;
else
echo -n "${script_name}: '${conf}' is registered."
fi
# Then confirm that the current sub-configuration directory exists.
if [ ! -d "${config_dirpath}/${conf}" ]; then
echo "..but does NOT exist!"
echo "${script_name}: "
echo "${script_name}: *** Cannot continue with nonexistent configuration '${conf}'. ***"
echo "${script_name}: "
exit 1;
else
echo "..and exists."
fi
done
echo "${script_name}: checking sub-configurations' requisite kernels:"
# Also, let's verify that the requisite kernel sets associated with
# the config name all correspond to directories that exist.
for kernel in ${kernel_list}; do
echo -n "${script_name}: '${kernel}' kernels..."
# Confirm that the current kernel sub-directory exists.
if [ ! -d "${kernels_dirpath}/${kernel}" ]; then
echo "do NOT exist!"
echo "${script_name}: "
echo "${script_name}: *** Cannot continue with nonexistent kernel '${kernel}'. ***"
echo "${script_name}: "
exit 1;
else
echo "exist."
fi
done
# -- Prepare variables for subsitution into template files -----------------
# Set the install prefix if it was not already set when parsing the install
# prefix flag.
if [ -n "${prefix_flag}" ]; then
echo "${script_name}: using install prefix '${install_prefix}'."
else
install_prefix="${install_prefix_def}"
echo "${script_name}: no install prefix given; defaulting to '${install_prefix}'."
fi
# Check if the debug flag was specified.
if [ -n "${debug_flag}" ]; then
if [ "x${debug_type}" = "xopt" ]; then
echo "${script_name}: enabling debug symbols with optimizations."
elif [ "x${debug_type}" = "xsde" ]; then
debug_type='sde'
echo "${script_name}: enabling SDE processor emulation."
else
debug_type='noopt'
echo "${script_name}: enabling debug symbols; optimizations disabled."
fi
else
debug_type='off'
echo "${script_name}: debug symbols disabled."
fi
# Check if the verbose make flag was specified.
if [ "x${enable_verbose}" = "xyes" ]; then
echo "${script_name}: enabling verbose make output, disable with 'make V=0'."
else
echo "${script_name}: disabling verbose make output, enable with 'make V=1'."
fi
# Check if the static lib flag was specified.
if [ "x${enable_static}" = "xyes" ]; then
echo "${script_name}: building BLIS as a static library."
fi
# Check if the shared lib flag was specified.
if [ "x${enable_shared}" = "xyes" ]; then
echo "${script_name}: building BLIS as a shared library."
fi
# Check if neither flag was specified.
if [ "x${enable_static}" = "xno" -a "x${enable_shared}" = "xno" ]; then
echo "Neither a shared nor static library build has been requested."
exit 1
fi
# Check the threading model flag and standardize its value, if needed.
# NOTE: 'omp' is deprecated but still supported; 'openmp' is preferred.
enable_openmp='no'
enable_openmp_01=0
enable_pthreads='no'
enable_pthreads_01=0
if [ "x${threading_model}" = "xauto" ]; then
echo "${script_name}: determining the threading model automatically."
elif [ "x${threading_model}" = "xopenmp" ] ||
[ "x${threading_model}" = "xomp" ]; then
echo "${script_name}: using OpenMP for threading."
enable_openmp='yes'
enable_openmp_01=1
threading_model="openmp" # Standardize the value.
elif [ "x${threading_model}" = "xpthreads" ] ||
[ "x${threading_model}" = "xpthread" ] ||
[ "x${threading_model}" = "xposix" ]; then
echo "${script_name}: using Pthreads for threading."
enable_pthreads='yes'
enable_pthreads_01=1
threading_model="pthreads" # Standardize the value.
elif [ "x${threading_model}" = "xno" ] ||
[ "x${threading_model}" = "xnone" ]; then
echo "${script_name}: threading is disabled."
else
echo "Unsupported threading model: ${threading_model}."
exit 1
fi
# Convert 'yes' and 'no' flags to booleans.
if [ "x${enable_packbuf_pools}" = "xyes" ]; then
echo "${script_name}: internal memory pools for packing buffers are enabled."
enable_packbuf_pools_01=1
else
echo "${script_name}: internal memory pools for packing buffers are disabled."
enable_packbuf_pools_01=0
fi
if [ "x${enable_blas2blis}" = "xyes" ]; then
echo "${script_name}: the BLAS compatibility layer is enabled."
enable_blas2blis_01=1
else
echo "${script_name}: the BLAS compatibility layer is disabled."
enable_blas2blis_01=0
fi
if [ "x${enable_cblas}" = "xyes" ]; then
echo "${script_name}: the CBLAS compatibility layer is enabled."
enable_cblas_01=1
# Force BLAS layer when CBLAS is enabled
enable_blas2blis='yes'
else
echo "${script_name}: the CBLAS compatibility layer is disabled."
enable_cblas_01=0
fi
# Report integer sizes
if [ "x${int_type_size}" = "x32" ]; then
echo "${script_name}: the internal integer size is 32-bit."
elif [ "x${int_type_size}" = "x64" ]; then
echo "${script_name}: the internal integer size is 64-bit."
else
echo "${script_name}: the internal integer size is automatically determined."
fi
if [ "x${blas2blis_int_type_size}" = "x32" ]; then
echo "${script_name}: the BLAS/CBLAS interface integer size is 32-bit."
elif [ "x${blas2blis_int_type_size}" = "x64" ]; then
echo "${script_name}: the BLAS/CBLAS interface integer size is 64-bit."
else
echo "${script_name}: the BLAS/CBLAS interface integer size is automatically determined."
fi
# Variables that contain forward slashes, such as paths, need extra
# escaping when used in sed commands. We insert those extra escape
# characters here so that the sed commands below do the right thing.
install_prefix_esc=$(echo "${install_prefix}" | sed 's/\//\\\//g')
dist_path_esc=$(echo "${dist_path}" | sed 's/\//\\\//g')
cc_esc=$(echo "${CC}" | sed 's/\//\\\//g')
# Create a #define for the configuration family (config_name).
uconf=$(echo ${config_name} | tr '[:lower:]' '[:upper:]')
config_name_define="#define BLIS_FAMILY_${uconf}\n"
# Create a list of #defines, one for each configuration in config_list.
config_list_defines=""
for conf in ${config_list}; do
# Convert the current config name to uppercase.
uconf=$(echo ${conf} | tr '[:lower:]' '[:upper:]')
# Create a #define and add it to the running list.
config_define="BLIS_CONFIG_${uconf}"
config_list_defines="${config_list_defines}#define ${config_define}\n"
done
# Create a list of #defines, one for each kernel set in kernel_list.
kernel_list_defines=""
for kern in ${kernel_list}; do
# Convert the current config name to uppercase.
uconf=$(echo ${kern} | tr '[:lower:]' '[:upper:]')
# Create a #define and add it to the running list.
kernel_define="BLIS_KERNELS_${uconf}"
kernel_list_defines="${kernel_list_defines}#define ${kernel_define}\n"
done
# -- Instantiate config.mk, bli_config.h files from templates --------------
# Begin substituting information into the config_mk_in file, outputting
# to config_mk_out.
echo "${script_name}: creating ${config_mk_out_path} from ${config_mk_in_path}"
cat "${config_mk_in_path}" \
| sed -e "s/@version@/${version}/g" \
| sed -e "s/@config_name@/${config_name}/g" \
| sed -e "s/@config_list@/${config_list}/g" \
| sed -e "s/@kernel_list@/${kernel_list}/g" \
| sed -e "s/@kconfig_map@/${kconfig_map}/g" \
| sed -e "s/@dist_path@/${dist_path_esc}/g" \
| sed -e "s/@CC@/${cc_esc}/g" \
| sed -e "s/@debug_type@/${debug_type}/g" \
| sed -e "s/@install_prefix@/${install_prefix_esc}/g" \
| sed -e "s/@enable_verbose@/${enable_verbose}/g" \
| sed -e "s/@enable_static@/${enable_static}/g" \
| sed -e "s/@enable_dynamic@/${enable_shared}/g" \
| sed -e "s/@threading_model@/${threading_model}/g" \
| sed -e "s/@enable_blas2blis@/${enable_blas2blis}/g" \
| sed -e "s/@enable_cblas@/${enable_cblas}/g" \
> "${config_mk_out_path}"
# Begin substituting information into the bli_config_h_in file, outputting
# to bli_config_h_out. NOTE: We use perl instead of sed because the version
# of sed used on OS X is old and does not handle the '\n' character
# intuitively, which was used when constructing ${config_name_define},
# ${config_list_defines}, and ${kernel_list_defines}.
echo "${script_name}: creating ${bli_config_h_out_path} from ${bli_config_h_in_path}"
cat "${bli_config_h_in_path}" \
| perl -pe "s/\@config_name_define\@/${config_name_define}/g" \
| perl -pe "s/\@config_list_defines\@/${config_list_defines}/g" \
| perl -pe "s/\@kernel_list_defines\@/${kernel_list_defines}/g" \
| sed -e "s/@enable_openmp@/${enable_openmp_01}/g" \
| sed -e "s/@enable_pthreads@/${enable_pthreads_01}/g" \
| sed -e "s/@enable_packbuf_pools@/${enable_packbuf_pools_01}/g" \
| sed -e "s/@int_type_size@/${int_type_size}/g" \
| sed -e "s/@blas2blis_int_type_size@/${blas2blis_int_type_size}/g" \
| sed -e "s/@enable_blas2blis@/${enable_blas2blis_01}/g" \
| sed -e "s/@enable_cblas@/${enable_cblas_01}/g" \
> "${bli_config_h_out_path}"
# -- Create top-level object directories -----------------------------------
# Create obj sub-directories (if they do not already exist).
base_obj_dirpath="${obj_dirpath}/${config_name}"
echo "${script_name}: creating ${base_obj_dirpath}"
mkdir -p ${base_obj_dirpath}
obj_config_dirpath="${base_obj_dirpath}/${config_dir}"
echo "${script_name}: creating ${obj_config_dirpath}"
mkdir -p ${obj_config_dirpath}
for conf in ${config_list}; do
echo "${script_name}: creating ${obj_config_dirpath}/${conf}"
mkdir -p ${obj_config_dirpath}/${conf}
done
obj_kernels_dirpath="${base_obj_dirpath}/${kernels_dir}"
echo "${script_name}: creating ${obj_kernels_dirpath}"
mkdir -p ${obj_kernels_dirpath}
for kern in ${kernel_list}; do
echo "${script_name}: creating ${obj_kernels_dirpath}/${kern}"
mkdir -p ${obj_kernels_dirpath}/${kern}
done
obj_refkern_dirpath="${base_obj_dirpath}/${refkern_dir}"
echo "${script_name}: creating ${obj_refkern_dirpath}"
mkdir -p ${obj_refkern_dirpath}
for conf in ${config_list}; do
echo "${script_name}: creating ${obj_refkern_dirpath}/${conf}"
mkdir -p ${obj_refkern_dirpath}/${conf}
done
obj_frame_dirpath="${base_obj_dirpath}/${frame_dir}"
echo "${script_name}: creating ${obj_frame_dirpath}"
mkdir -p ${obj_frame_dirpath}
obj_testsuite_dirpath="${base_obj_dirpath}/${testsuite_dir}"
echo "${script_name}: creating ${obj_testsuite_dirpath}"
mkdir -p ${obj_testsuite_dirpath}
# Create lib directory (if it does not already exist).
base_lib_dirpath="${lib_dirpath}/${config_name}"
echo "${script_name}: creating ${base_lib_dirpath}"
mkdir -p ${base_lib_dirpath}
# Create include directory (if it does not already exist).
base_include_dirpath="${include_dirpath}/${config_name}"
echo "${script_name}: creating ${base_include_dirpath}"
mkdir -p ${base_include_dirpath}
# -- Mirror source directory hierarchies to object directories -------------
# Mirror each of the sub-configuration directories to the object directory.
for conf in ${config_list}; do
echo "${script_name}: mirroring ${config_dirpath}/${conf} to ${obj_config_dirpath}/${conf}"
${mirror_tree_sh} "${config_dirpath}/${conf}" "${obj_config_dirpath}/${conf}"
done
# Mirror optimized kernels source tree to its object sub-directory.
# We perform the mirroring on each configuration/kernel sub-directory
# within 'kernels'.
for kern in ${kernel_list}; do
# Only mirror the optimized kernels source directory if it exists.
# There are occasions where one of the sub-configurations in the
# config_list does not correspond to a kernels sub-directory, such
# as when architecture B is so close to architecture A that B can
# use A's kernel source code unmodified (though perhaps with
# different blocksizes).
#if [ -d "${kernels_dirpath}/${conf}" ]; then
echo "${script_name}: mirroring ${kernels_dirpath}/${kern} to ${obj_kernels_dirpath}/${kern}"
${mirror_tree_sh} "${kernels_dirpath}/${kern}" "${obj_kernels_dirpath}/${kern}"
#else
# echo "${script_name}: mirroring ${kernels_dirpath}/${conf} skipped... directory does not exist"
#fi
done
# Mirror reference kernels source tree to its object sub-directory.
for conf in ${config_list}; do
echo "${script_name}: mirroring ${refkern_dirpath} to ${obj_refkern_dirpath}/${conf}"
${mirror_tree_sh} "${refkern_dirpath}" "${obj_refkern_dirpath}/${conf}"
done
# Mirror framework source tree to its object sub-directory.
echo "${script_name}: mirroring ${frame_dirpath} to ${obj_frame_dirpath}"
${mirror_tree_sh} ${frame_dirpath} ${obj_frame_dirpath}
# -- Generate makefile fragements ------------------------------------------
clist_contains_cname=$(is_word_in_list "${config_name}" "${config_list}")
# If the config_list does not already contain the config_name, generate
# makefiles in that directory.
if [ "${clist_contains_cname}" == "false" ]; then
${gen_make_frags_sh} \
-h -r -v1 \
-o ${script_name} \
-p 'CONFIG' \
${config_dirpath}/${config_name} \
${gen_make_frags_dirpath}/fragment.mk \
${gen_make_frags_dirpath}/suffix_list \
${gen_make_frags_dirpath}/ignore_list
fi
# Generate makefile fragments for each of the sub-configurations present
# in the configuration list.
for conf in ${config_list}; do
${gen_make_frags_sh} \
-h -r -v1 \
-o ${script_name} \
-p 'CONFIG' \
${config_dirpath}/${conf} \
${gen_make_frags_dirpath}/fragment.mk \
${gen_make_frags_dirpath}/suffix_list \
${gen_make_frags_dirpath}/ignore_list
done
# Generate makefile fragments for each of the kernel sets required by
# the configuration list (in the kernel list).
for kern in ${kernel_list}; do
${gen_make_frags_sh} \
-h -r -v1 \
-o ${script_name} \
-p 'KERNELS' \
${kernels_dirpath}/${kern} \
${gen_make_frags_dirpath}/fragment.mk \
${gen_make_frags_dirpath}/suffix_list \
${gen_make_frags_dirpath}/ignore_list
done
# Generate makefile fragments in the reference kernels directory.
${gen_make_frags_sh} \
-h -r -v1 \
-o ${script_name} \
-p 'REFKERN' \
${refkern_dirpath} \
${gen_make_frags_dirpath}/fragment.mk \
${gen_make_frags_dirpath}/suffix_list \
${gen_make_frags_dirpath}/ignore_list
# Generate makefile fragments in the framework directory.
${gen_make_frags_sh} \
-h -r -v1 \
-o ${script_name} \
-p 'FRAME' \
${frame_dirpath} \
${gen_make_frags_dirpath}/fragment.mk \
${gen_make_frags_dirpath}/suffix_list \
${gen_make_frags_dirpath}/ignore_list
# -- Handle out-of-tree builds ---------------------------------------------
# Under some circumstances, we need to create a symbolic link to the
# Makefile. We only proceed with this if configure was run with a path
# other than "./".
if [ ${dist_path} != "./" ]; then
# At this point, we know the user did not run "./configure". But we
# have not yet ruled out "<fullpath>/configure" or some # equivalent
# that uses relative paths. To further rule out these possibilities,
# we create a dummy file in the current build directory.
touch "./${dummy_file}"
# If the dummy file we just created in the current directory does not
# appear in the source distribution path, then we are in a different
# directory and thus we must create a symbolic link.
if [ ! -f "${dist_path}/${dummy_file}" ]; then
# If 'Makefile' does not already exist in the current directory,
# create a symbolic link to it. If one does exist, we us -f to
# force creation of a new link.
if [ ! -e "./Makefile" ]; then
echo "${script_name}: creating symbolic link to Makefile."
ln -s "${dist_path}/Makefile"
else
echo "${script_name}: symbolic link to Makefile already exists; forcing creation of new link."
ln -sf "${dist_path}/Makefile"
fi
# If 'common.mk' does not already exist in the current directory,
# create a symbolic link to it. If one does exist, we us -f to
# force creation of a new link.
if [ ! -e "./common.mk" ]; then
echo "${script_name}: creating symbolic link to common.mk."
ln -s "${dist_path}/common.mk"
else
echo "${script_name}: symbolic link to common.mk already exists; forcing creation of new link."
ln -sf "${dist_path}/common.mk"
fi
echo "${script_name}: configured to build outside of source distribution."
else
# Echo what is happening.
echo "${script_name}: configured to build within top-level directory of source distribution."
fi
# Remove the dummy file.
rm -f "./${dummy_file}"
fi
# Exit peacefully.
return 0
}
# The script's main entry point, passing all parameters given.
main "$@"