Issue #294: "apple silicon build problem(s?)": If the "--flavor/-f" flag is not specified on the command line, then complain loudly, print help and exit. The script used to default to "Unix Makefiles". Updates: - Add missing "-DHAVE_LIBPNG" compiler command line define when the PNG library is detected/present for screen capture support. - Add "clang64" to the list of MinGW64 platforms for which the .travis/deps.sh script can install build dependencies. - Add PThread4W_FOUND to the condition that sets async I/O for Win32 when using vcpkg for build dependencies. - Add vs2022-x64, vs2019-x64 and vs2017-x64 build environments to build 64-bit Windows executables. - Use simulator AIO only where needed by the simulator (i.e., the simulator calls/uses AIO_CHECK_EVENT in sim_instr()) - Add "USES_AIO" flag to add_simulator() to mark a simulator that acutally uses asynchronous I/O. - Build "_aio" SIMH core library variants that have AIO turned on, link with the "_aio" variant when a simulator sets USES_AIO. - Emit a warning message when WITH_ASYNC is False (CMake configuration option) to notify the user/developer that some functionality will be crippled. Affected simulator builds: 3b2 family, PDP-6, PDP-11, VAX family, IMLAC and TT2500. The makefile and cmake/generate.py also updated to remain in sync with CMake. N.B.: Simulators still link with the underlying platform's threading library. SEL32 requires pthreads or equivalent threading library, independent of AIO. - cmake/cmake-builder.sh - New "--no-aio" flag: Build simulators without async I/O. - New "--no-aio-intrinsics" flag: Don't build async I/O using compiler compare-exchange, atomic load intrinsics. - cmake/cmake-builder.ps1 - New "-noaio" flag: Build simulators without async I/O. - New "-noaiointrinsics" flag: Don't build async I/O using compiler compare-exchange, atomic load intrinsics. CMake 3.28.1 INTERFACE_LINK_LIBRARIES behavior change: The file name must now be an absolute path. Relative paths no longer accepted. Internally, SIMH enforces this if CMAKE_VERSION >= 3.19, when REAL_PATH was first implemented.
426 lines
13 KiB
Bash
Executable file
426 lines
13 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
##-- Bash functions --
|
|
showHelp()
|
|
{
|
|
[ x"$1" != x ] && { echo "${scriptName}: $1"; echo ""; }
|
|
cat <<EOF
|
|
Configure and build simh simulators on Linux and *nix-like platforms.
|
|
|
|
-Compile/Build options:
|
|
-----------------------
|
|
--clean (-x) Remove the build subdirectory
|
|
--generate (-g) Generate the build environment, don't compile/build
|
|
--cache '--generate' and show CMake's variable cache
|
|
--parallel (-p) Enable build parallelism (parallel builds)
|
|
--notest Do not execute 'ctest' test cases
|
|
--noinstall Do not install SIMH simulators.
|
|
--testonly Do not build, execute the 'ctest' test cases
|
|
--installonly Do not build, install the SIMH simulators
|
|
|
|
--flavor (-f) [Required] Specifies the build flavor. Valid flavors are:
|
|
unix
|
|
ninja
|
|
xcode
|
|
xcode-universal
|
|
msys
|
|
msys2
|
|
mingw
|
|
ucrt
|
|
--config (-c) Specifies the build configuration: 'Release' or 'Debug'
|
|
|
|
--target Build a specific simulator or simulators. Separate multiple
|
|
targets with a comma, e.g. "--target pdp8,pdp11,vax750,altairz80,3b2"
|
|
--lto Enable Link Time Optimization (LTO) in Release builds
|
|
--debugWall Enable maximal warnings in Debug builds
|
|
--cppcheck Enable cppcheck static code analysis rules
|
|
|
|
--cpack_suffix Specify CPack's packaging suffix, e.g., "ubuntu-22.04"
|
|
to produce the "simh-4.1.0-ubuntu-22.04.deb" Debian
|
|
package.
|
|
|
|
--verbose Turn on verbose build output
|
|
|
|
SIMH feature control options:
|
|
-----------------------------
|
|
--nonetwork Build simulators without network support
|
|
--novideo Build simulators without video support
|
|
--no-aio Build simulators without AIO (asynchronous I/O). NOTE: This will
|
|
impact certain devices' functionality, notably networking.
|
|
--no-aio-intrinsics
|
|
Do not use compiler/platform intrinsics to implement AIO
|
|
functions (aka "lock-free" AIO), reverts to lock-based AIO
|
|
if threading libraries are detected.
|
|
|
|
Other options:
|
|
--------------
|
|
--help (-h) Print this help.
|
|
EOF
|
|
|
|
exit 1
|
|
}
|
|
|
|
scriptName=$0
|
|
generateArgs=
|
|
buildArgs=
|
|
buildPostArgs=""
|
|
buildClean=
|
|
buildFlavor=
|
|
buildSubdir=
|
|
buildConfig=Release
|
|
testArgs=
|
|
notest=no
|
|
buildParallel=no
|
|
generateOnly=
|
|
testOnly=
|
|
noinstall=
|
|
installOnly=
|
|
verboseMode=
|
|
simTarget=
|
|
cpack_suffix=
|
|
|
|
## CMake supports "-S" flag (implies -B works as well.) Otherwise, it's
|
|
## the older invocation command line.
|
|
cmakeSFlag=
|
|
|
|
## This script really needs GNU getopt. Really. And try reallly hard to
|
|
## find the version that supports "--long-opt"
|
|
##
|
|
## MacOS workaround: MacOS has an older getopt installed in /usr/bin, brew
|
|
## has an updated version that installs in a custom place.
|
|
[[ -d /usr/local/opt/gnu-getopt/bin ]] && PATH="/usr/local/opt/gnu-getopt/bin:$PATH"
|
|
[[ -d /opt/homebrew/opt/gnu-getopt/bin ]] && PATH="/opt/homebrew/opt/gnu-getopt/bin:$PATH"
|
|
[[ -d /usr/local/opt/coreutils/libexec/gnubin ]] && PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
|
|
|
|
getopt_prog=
|
|
IFS_SAVE="${IFS}"; IFS=":"; for p in ${PATH}; do
|
|
"${p}/getopt" -T > /dev/null 2>&1
|
|
if [[ $? -eq 4 ]]; then
|
|
getopt_prog="${p}/getopt"
|
|
break
|
|
fi
|
|
done
|
|
IFS="${IFS_SAVE}"
|
|
|
|
if [[ "x${getopt_prog}" = "x" ]]; then
|
|
echo "${scriptName}: GNU getopt needed for this script to function properly."
|
|
echo "${scriptName}: Specifically, a 'getopt' that supports the '-T' flag (enhanced getopt)"
|
|
exit 1
|
|
fi
|
|
|
|
## This script also needs GNU coreutils
|
|
realpath=$(which realpath) || {
|
|
echo "${scriptName}: Could not find 'realpath'. Please install and re-execute this script."
|
|
echo "${scriptName}: 'realpath' is a component of the GNU coreutils collection."
|
|
}
|
|
dirname=$(which dirname) || {
|
|
echo "${scriptName}: Could not find 'dirname'. Please install and re-execute this script."
|
|
echo "${scriptName}: 'dirname' is a component of the GNU coreutils collection."
|
|
}
|
|
|
|
## Check if CMake supports parallel
|
|
cmake=$(which cmake) || {
|
|
echo "${scriptName}: Could not find 'cmake'. Please install and re-execute this script."
|
|
exit 1
|
|
}
|
|
|
|
ctest=$(which ctest) || {
|
|
echo "${scriptName}: Could not find 'ctest'. Please check your 'cmake' installation."
|
|
exit 1
|
|
}
|
|
|
|
echo "** $(${cmake} --version)"
|
|
|
|
$(${cmake} -h 2>&1 | grep -- "-S" > /dev/null) && {
|
|
cmakeSFlag=yes
|
|
}
|
|
|
|
canParallel=no
|
|
(${cmake} --build /tmp --help 2>&1 | grep parallel > /dev/null) && {
|
|
canParallel=yes
|
|
}
|
|
|
|
canTestParallel=no
|
|
# (${ctest} --help 2>&1 | grep parallel > /dev/null) && {
|
|
# canTestParallel=yes
|
|
# }
|
|
|
|
if [[ "x${MSYSTEM}" != x ]]; then
|
|
case "${MSYSTEM}" in
|
|
MSYS|MINGW64)
|
|
buildFlavor="MinGW Makefiles"
|
|
buildSubdir=build-mingw
|
|
;;
|
|
UCRT64)
|
|
buildFlavor="Ninja"
|
|
buildSubdir=build-ninja
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
longopts=clean,help,flavor:,config:,nonetwork,novideo,notest,parallel,generate,testonly
|
|
longopts=${longopts},noinstall,installonly,verbose,target:,lto,debugWall,cppcheck,cpack_suffix:
|
|
longopts=${longopts},cache,no-aio,no-aio-intrinsics
|
|
|
|
ARGS=$(${getopt_prog} --longoptions $longopts --options xhf:c:pg -- "$@")
|
|
if [ $? -ne 0 ] ; then
|
|
showHelp "${scriptName}: Usage error (use -h for help.)"
|
|
fi
|
|
|
|
eval set -- ${ARGS}
|
|
while true; do
|
|
case $1 in
|
|
-x | --clean)
|
|
buildClean=yes; shift
|
|
;;
|
|
-h | --help)
|
|
showHelp
|
|
;;
|
|
-f | --flavor)
|
|
case "$2" in
|
|
unix)
|
|
buildFlavor="Unix Makefiles"
|
|
buildSubdir=build-unix
|
|
shift 2
|
|
;;
|
|
ninja|ucrt64)
|
|
buildFlavor=Ninja
|
|
buildSubdir=build-ninja
|
|
shift 2
|
|
;;
|
|
xcode)
|
|
buildFlavor=Xcode
|
|
buildSubdir=build-xcode
|
|
shift 2
|
|
;;
|
|
xcode-universal)
|
|
buildFlavor=Xcode
|
|
buildSubdir=build-xcode-universal
|
|
generateArgs="${generateArgs} -DMAC_UNIVERSAL:Bool=On"
|
|
shift 2
|
|
;;
|
|
mingw|mingw64|msys|msys2)
|
|
buildFlavor="MinGW Makefiles"
|
|
buildSubdir=build-mingw
|
|
shift 2
|
|
;;
|
|
*)
|
|
showHelp "Invalid build flavor: $2"
|
|
;;
|
|
esac
|
|
;;
|
|
-c | --config)
|
|
case "$2" in
|
|
Release|Debug)
|
|
buildConfig=$2
|
|
shift 2
|
|
;;
|
|
*)
|
|
showHelp "Invalid build configuration: $2"
|
|
;;
|
|
esac
|
|
;;
|
|
--nonetwork)
|
|
generateArgs="${generateArgs} -DWITH_NETWORK:Bool=Off"
|
|
shift
|
|
;;
|
|
--novideo)
|
|
generateArgs="${generateArgs} -DWITH_VIDEO:Bool=Off"
|
|
shift
|
|
;;
|
|
--no-aio)
|
|
generateArgs="${generateArgs} -DWITH_ASYNC:Bool=Off"
|
|
shift
|
|
;;
|
|
--no-aio-intrinsics)
|
|
generateArgs="${generateArgs} -DDONT_USE_AIO_INTRINSICS:Bool=On"
|
|
shift
|
|
;;
|
|
--notest)
|
|
notest=yes
|
|
shift
|
|
;;
|
|
--noinstall)
|
|
noinstall=yes
|
|
shift
|
|
;;
|
|
--lto)
|
|
generateArgs="${generateArgs} -DRELEASE_LTO:Bool=On"
|
|
shift
|
|
;;
|
|
--debugWall)
|
|
generateArgs="${generateArgs} -DDEBUG_WALL:Bool=On"
|
|
shift
|
|
;;
|
|
--cppcheck)
|
|
generateArgs="${generateArgs} -DENABLE_CPPCHECK:Bool=On"
|
|
shift
|
|
;;
|
|
--cpack_suffix)
|
|
generateArgs="${generateArgs} -DSIMH_PACKAGE_SUFFIX=$2"
|
|
shift 2
|
|
;;
|
|
-p | --parallel)
|
|
buildParallel=yes
|
|
shift
|
|
;;
|
|
-g | --generate)
|
|
generateOnly=yes
|
|
shift
|
|
;;
|
|
--cache)
|
|
generateOnly=yes
|
|
generateArgs="${generateArgs} -LA"
|
|
shift
|
|
;;
|
|
--testonly)
|
|
testOnly=yes
|
|
shift
|
|
;;
|
|
--installonly)
|
|
installOnly=yes
|
|
shift
|
|
;;
|
|
--verbose)
|
|
verboseMode="--verbose"
|
|
shift
|
|
;;
|
|
--target)
|
|
noinstall=yes
|
|
simTarget="${simTarget} $2"
|
|
shift 2
|
|
;;
|
|
--)
|
|
## End of options. we'll ignore.
|
|
shift
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Sanity check: buildSubdir should be set, unless the '-f' flag wasn't present.
|
|
if [ "x${buildSubdir}" = x ]; then
|
|
echo ""
|
|
echo "${scriptName}: Build flavor is NOT SET -- see the \"--flavor\"/\"-f\" flag in the help."
|
|
echo ""
|
|
showHelp
|
|
fi
|
|
|
|
## Determine the SIMH top-level source directory:
|
|
simhTopDir=$(${dirname} $(${realpath} $0))
|
|
while [ "x${simhTopDir}" != x -a ! -f "${simhTopDir}/CMakeLists.txt" ]; do
|
|
simhTopDir=$(${dirname} "${simhTopDir}")
|
|
done
|
|
|
|
if [[ "x${simhTopDir}" = x ]]; then
|
|
echo "${scriptName}: Can't determine SIMH top-level source directory."
|
|
echo "Did this really happen?"
|
|
exit 1
|
|
else
|
|
buildSubdir=$(${realpath} "${simhTopDir}/cmake/")"/${buildSubdir}"
|
|
echo "${scriptName}: SIMH top-evel directory: ${simhTopDir}"
|
|
echo "${scriptName}: Build directory: ${buildSubdir}"
|
|
fi
|
|
|
|
if [[ x"$buildClean" != x ]]; then
|
|
echo "${scriptName}: Cleaning ${buildSubdir}"
|
|
rm -rf ${buildSubdir}
|
|
fi
|
|
|
|
if [[ ! -d ${buildSubdir} ]]; then
|
|
mkdir ${buildSubdir}
|
|
fi
|
|
|
|
## Setup test arguments (and add parallel later)
|
|
testArgs="-C ${buildConfig} --timeout 180 --output-on-failure"
|
|
|
|
## Parallel only applies to the unix flavor. GNU make will overwhelm your
|
|
## machine if the number of jobs isn't capped.
|
|
if [[ x"$canParallel" = xyes ]] ; then
|
|
if [ x"$buildParallel" = xyes -a "$buildFlavor" != Ninja ] ; then
|
|
(${cmake} --build . --help 2>&1 | grep parallel 2>&1 > /dev/null) && {
|
|
buildArgs="${buildArgs} --parallel"
|
|
buildPostArgs="${buildPostArgs} -j 8"
|
|
}
|
|
|
|
# Don't execute ctest in parallel...
|
|
# [ x${canTestParallel} = xyes ] && {
|
|
# testArgs="${testArgs} --parallel 4"
|
|
# }
|
|
fi
|
|
else
|
|
buildParallel=
|
|
fi
|
|
|
|
if [[ x"${simTarget}" != x ]]; then
|
|
simTests=""
|
|
for tgt in $(echo ${simTarget} | sed 's/,/ /g'); do
|
|
buildArgs="${buildArgs} --target ${tgt}"
|
|
[[ x"${simTests}" != x ]] && simTests="${simTests}|"
|
|
simTests="${simTests}${tgt}"
|
|
done
|
|
testArgs="${testArgs} -R simh-(${simTests})\$"
|
|
fi
|
|
|
|
buildArgs="${buildArgs} --config ${buildConfig}"
|
|
|
|
if [[ x$generateOnly = xyes ]]; then
|
|
phases=generate
|
|
elif [[ x$testOnly = xyes ]]; then
|
|
phases=test
|
|
elif [[ x$installOnly = xyes ]]; then
|
|
phases=install
|
|
else
|
|
phases="generate build"
|
|
if [[ x${notest} != xyes ]]; then
|
|
phases="${phases} test"
|
|
fi
|
|
fi
|
|
|
|
for ph in ${phases}; do
|
|
case $ph in
|
|
generate)
|
|
## Uncondintionally remove the CMake cache.
|
|
echo "${scriptName}: Removing CMakeCache.txt and CMakeFiles"
|
|
rm -rf ${buildSubdir}/CMakeCache.txt ${buildSubdir}/CMakefiles
|
|
|
|
if [[ "x${cmakeSFlag}" != x ]]; then
|
|
echo "${cmake} -G "\"${buildFlavor}\"" -DCMAKE_BUILD_TYPE="${buildConfig}" -S "${simhTopDir}" -B ${buildSubdir} ${generateArgs}"
|
|
${cmake} -G "${buildFlavor}" -DCMAKE_BUILD_TYPE="${buildConfig}" -S "${simhTopDir}" -B "${buildSubdir}" ${generateArgs} || { \
|
|
echo "*** ${scriptName}: Errors detected during environment generation. Exiting."
|
|
exit 1
|
|
}
|
|
else
|
|
echo "${cmake} -G "\"${buildFlavor}\"" -DCMAKE_BUILD_TYPE="${buildConfig}" "${simhTopDir}" ${generateArgs}"
|
|
( cd "${buildSubdir}"; \
|
|
${cmake} -G "${buildFlavor}" -DCMAKE_BUILD_TYPE="${buildConfig}" "${simhTopDir}" ${generateArgs}) || { \
|
|
echo "*** ${scriptName}: Errors detected during environment generation. Exiting.";
|
|
exit 1
|
|
}
|
|
fi
|
|
;;
|
|
build)
|
|
${cmake} --build "${buildSubdir}" ${buildArgs} ${verboseMode} -- ${buildPostArgs} || {
|
|
echo "*** ${scriptName}: Build errors detected. Exiting."
|
|
exit 1
|
|
}
|
|
;;
|
|
test)
|
|
(cd "${buildSubdir}" \
|
|
&& echo ${ctest} ${testArgs} ${verboseMode} \
|
|
&& ${ctest} ${testArgs} ${verboseMode}) || {
|
|
echo "*** ${scriptName}: Errors detected during testing. Exiting."
|
|
exit 1
|
|
}
|
|
;;
|
|
install)
|
|
${cmake} --build "${buildSubdir}" --target install --config "${buildConfig}"
|
|
;;
|
|
package)
|
|
(cd "${buildSubdir}" \
|
|
&& ${cpack} -G ZIP -C ${buildConfig} ${verboseMode} \
|
|
&& mv *.zip ${simhTopDir}/PACKAGES \
|
|
)
|
|
;;
|
|
esac
|
|
done
|