mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-26 07:34:11 +00:00
69cf5181c3
The primary motivating example is openssl: Before the change full package build took 1m54s minutes. After the change full package build takes 59s. About a 2x speedup. The difference is visible because openssl builds hundreds of manpages spawning a perl process per manual in `install` phase. Such a workload is very easy to parallelize. Another example would be `autotools`+`libtool` based build system where install step requires relinking. The more binaries there are to relink the more gain it will be to do it in parallel. The change enables parallel installs by default only for buiilds that already have parallel builds enabled. There is a high chance those build systems already handle parallelism well but some packages will fail. Consistently propagated the enableParallelBuilding to: - cmake (enabled by default, similar to builds) - ninja (set parallelism explicitly, don't rely on default) - bmake (enable when requested) - scons (enable when requested) - meson (set parallelism explicitly, don't rely on default) - waf (set parallelism explicitly, don't rely on default) - qmake-4/5/6 (enable by default, similar to builds) - xorg (always enable, similar to builds)
185 lines
6.9 KiB
Bash
Executable File
185 lines
6.9 KiB
Bash
Executable File
addCMakeParams() {
|
||
addToSearchPath CMAKE_PREFIX_PATH $1
|
||
}
|
||
|
||
fixCmakeFiles() {
|
||
# Replace occurences of /usr and /opt by /var/empty.
|
||
echo "fixing cmake files..."
|
||
find "$1" \( -type f -name "*.cmake" -o -name "*.cmake.in" -o -name CMakeLists.txt \) -print |
|
||
while read fn; do
|
||
sed -e 's^/usr\([ /]\|$\)^/var/empty\1^g' -e 's^/opt\([ /]\|$\)^/var/empty\1^g' < "$fn" > "$fn.tmp"
|
||
mv "$fn.tmp" "$fn"
|
||
done
|
||
}
|
||
|
||
cmakeConfigurePhase() {
|
||
runHook preConfigure
|
||
|
||
# default to CMake defaults if unset
|
||
: ${cmakeBuildDir:=build}
|
||
|
||
export CTEST_OUTPUT_ON_FAILURE=1
|
||
if [ -n "${enableParallelChecking-1}" ]; then
|
||
export CTEST_PARALLEL_LEVEL=$NIX_BUILD_CORES
|
||
fi
|
||
|
||
if [ -z "${dontFixCmake-}" ]; then
|
||
fixCmakeFiles .
|
||
fi
|
||
|
||
if [ -z "${dontUseCmakeBuildDir-}" ]; then
|
||
mkdir -p "$cmakeBuildDir"
|
||
cd "$cmakeBuildDir"
|
||
: ${cmakeDir:=..}
|
||
else
|
||
: ${cmakeDir:=.}
|
||
fi
|
||
|
||
if [ -z "${dontAddPrefix-}" ]; then
|
||
cmakeFlags="-DCMAKE_INSTALL_PREFIX=$prefix $cmakeFlags"
|
||
fi
|
||
|
||
# We should set the proper `CMAKE_SYSTEM_NAME`.
|
||
# http://www.cmake.org/Wiki/CMake_Cross_Compiling
|
||
#
|
||
# Unfortunately cmake seems to expect absolute paths for ar, ranlib, and
|
||
# strip. Otherwise they are taken to be relative to the source root of the
|
||
# package being built.
|
||
cmakeFlags="-DCMAKE_CXX_COMPILER=$CXX $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_C_COMPILER=$CC $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_AR=$(command -v $AR) $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_RANLIB=$(command -v $RANLIB) $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_STRIP=$(command -v $STRIP) $cmakeFlags"
|
||
|
||
# on macOS we want to prefer Unix-style headers to Frameworks
|
||
# because we usually do not package the framework
|
||
cmakeFlags="-DCMAKE_FIND_FRAMEWORK=LAST $cmakeFlags"
|
||
|
||
# we never want to use the global macOS SDK
|
||
cmakeFlags="-DCMAKE_OSX_SYSROOT= $cmakeFlags"
|
||
|
||
# correctly detect our clang compiler
|
||
cmakeFlags="-DCMAKE_POLICY_DEFAULT_CMP0025=NEW $cmakeFlags"
|
||
|
||
# This installs shared libraries with a fully-specified install
|
||
# name. By default, cmake installs shared libraries with just the
|
||
# basename as the install name, which means that, on Darwin, they
|
||
# can only be found by an executable at runtime if the shared
|
||
# libraries are in a system path or in the same directory as the
|
||
# executable. This flag makes the shared library accessible from its
|
||
# nix/store directory.
|
||
cmakeFlags="-DCMAKE_INSTALL_NAME_DIR=${!outputLib}/lib $cmakeFlags"
|
||
|
||
# The docdir flag needs to include PROJECT_NAME as per GNU guidelines,
|
||
# try to extract it from CMakeLists.txt.
|
||
if [[ -z "$shareDocName" ]]; then
|
||
local cmakeLists="${cmakeDir}/CMakeLists.txt"
|
||
if [[ -f "$cmakeLists" ]]; then
|
||
local shareDocName="$(grep --only-matching --perl-regexp --ignore-case '\bproject\s*\(\s*"?\K([^[:space:]")]+)' < "$cmakeLists" | head -n1)"
|
||
fi
|
||
# The argument sometimes contains garbage or variable interpolation.
|
||
# When that is the case, let’s fall back to the derivation name.
|
||
if [[ -z "$shareDocName" ]] || echo "$shareDocName" | grep -q '[^a-zA-Z0-9_+-]'; then
|
||
if [[ -n "${pname-}" ]]; then
|
||
shareDocName="$pname"
|
||
else
|
||
shareDocName="$(echo "$name" | sed 's/-[^a-zA-Z].*//')"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# This ensures correct paths with multiple output derivations
|
||
# It requires the project to use variables from GNUInstallDirs module
|
||
# https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
|
||
cmakeFlags="-DCMAKE_INSTALL_BINDIR=${!outputBin}/bin $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_SBINDIR=${!outputBin}/sbin $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_INCLUDEDIR=${!outputInclude}/include $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_OLDINCLUDEDIR=${!outputInclude}/include $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_MANDIR=${!outputMan}/share/man $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_INFODIR=${!outputInfo}/share/info $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_DOCDIR=${!outputDoc}/share/doc/${shareDocName} $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_LIBDIR=${!outputLib}/lib $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_LIBEXECDIR=${!outputLib}/libexec $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_INSTALL_LOCALEDIR=${!outputLib}/share/locale $cmakeFlags"
|
||
|
||
# Don’t build tests when doCheck = false
|
||
if [ -z "${doCheck-}" ]; then
|
||
cmakeFlags="-DBUILD_TESTING=OFF $cmakeFlags"
|
||
fi
|
||
|
||
# Always build Release, to ensure optimisation flags
|
||
cmakeFlags="-DCMAKE_BUILD_TYPE=${cmakeBuildType:-Release} $cmakeFlags"
|
||
|
||
# Disable user package registry to avoid potential side effects
|
||
# and unecessary attempts to access non-existent home folder
|
||
# https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#disabling-the-package-registry
|
||
cmakeFlags="-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_FIND_USE_PACKAGE_REGISTRY=OFF $cmakeFlags"
|
||
cmakeFlags="-DCMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=OFF $cmakeFlags"
|
||
|
||
if [ "${buildPhase-}" = ninjaBuildPhase ]; then
|
||
cmakeFlags="-GNinja $cmakeFlags"
|
||
fi
|
||
|
||
echo "cmake flags: $cmakeFlags ${cmakeFlagsArray[@]}"
|
||
|
||
cmake "$cmakeDir" $cmakeFlags "${cmakeFlagsArray[@]}"
|
||
|
||
if ! [[ -v enableParallelBuilding ]]; then
|
||
enableParallelBuilding=1
|
||
echo "cmake: enabled parallel building"
|
||
fi
|
||
|
||
if ! [[ -v enableParallelInstalling ]]; then
|
||
enableParallelInstalling=1
|
||
echo "cmake: enabled parallel installing"
|
||
fi
|
||
|
||
runHook postConfigure
|
||
}
|
||
|
||
if [ -z "${dontUseCmakeConfigure-}" -a -z "${configurePhase-}" ]; then
|
||
setOutputFlags=
|
||
configurePhase=cmakeConfigurePhase
|
||
fi
|
||
|
||
addEnvHooks "$targetOffset" addCMakeParams
|
||
|
||
makeCmakeFindLibs(){
|
||
isystem_seen=
|
||
iframework_seen=
|
||
for flag in ${NIX_CFLAGS_COMPILE-} ${NIX_LDFLAGS-}; do
|
||
if test -n "$isystem_seen" && test -d "$flag"; then
|
||
isystem_seen=
|
||
export CMAKE_INCLUDE_PATH="${CMAKE_INCLUDE_PATH-}${CMAKE_INCLUDE_PATH:+:}${flag}"
|
||
elif test -n "$iframework_seen" && test -d "$flag"; then
|
||
iframework_seen=
|
||
export CMAKE_FRAMEWORK_PATH="${CMAKE_FRAMEWORK_PATH-}${CMAKE_FRAMEWORK_PATH:+:}${flag}"
|
||
else
|
||
isystem_seen=
|
||
iframework_seen=
|
||
case $flag in
|
||
-I*)
|
||
export CMAKE_INCLUDE_PATH="${CMAKE_INCLUDE_PATH-}${CMAKE_INCLUDE_PATH:+:}${flag:2}"
|
||
;;
|
||
-L*)
|
||
export CMAKE_LIBRARY_PATH="${CMAKE_LIBRARY_PATH-}${CMAKE_LIBRARY_PATH:+:}${flag:2}"
|
||
;;
|
||
-F*)
|
||
export CMAKE_FRAMEWORK_PATH="${CMAKE_FRAMEWORK_PATH-}${CMAKE_FRAMEWORK_PATH:+:}${flag:2}"
|
||
;;
|
||
-isystem)
|
||
isystem_seen=1
|
||
;;
|
||
-iframework)
|
||
iframework_seen=1
|
||
;;
|
||
esac
|
||
fi
|
||
done
|
||
}
|
||
|
||
# not using setupHook, because it could be a setupHook adding additional
|
||
# include flags to NIX_CFLAGS_COMPILE
|
||
postHooks+=(makeCmakeFindLibs)
|