diff options
author | Andrew Brooks <andrew.brooks@flightaware.com> | 2021-04-30 17:25:06 -0500 |
---|---|---|
committer | Andrew Brooks <andrew.brooks@flightaware.com> | 2021-05-21 15:18:03 -0500 |
commit | c6ca1ba9c7975dfab7dec0e7ee5c6f31c458333f (patch) | |
tree | fdbc3e96dd810db3e70c01b22009fcf34717f25a /pkgs/development/interpreters/tcl | |
parent | d0fd8a029de0b3a1f4b81d020893b337f35a4348 (diff) |
tcl: Add tclPackageHook and mkTclDerivation
Implement tclPackageHook, a setup hook that adjusts TCLLIBPATH to include the paths of any installed Tcl packages, propagates that TCLLIBPATH to anti-dependencies, and wraps any installed binaries to set their TCLLIBPATH. Additionally, implement a makePythonPackage-style mkDerivation wrapper to use reasonable defaults for Tcl packages and use tclPackageHook.
Diffstat (limited to 'pkgs/development/interpreters/tcl')
-rw-r--r-- | pkgs/development/interpreters/tcl/generic.nix | 112 | ||||
-rw-r--r-- | pkgs/development/interpreters/tcl/mk-tcl-derivation.nix | 69 | ||||
-rw-r--r-- | pkgs/development/interpreters/tcl/tcl-package-hook.sh | 74 |
3 files changed, 206 insertions, 49 deletions
diff --git a/pkgs/development/interpreters/tcl/generic.nix b/pkgs/development/interpreters/tcl/generic.nix index e665e8cfb1ead..4c144699fc8fc 100644 --- a/pkgs/development/interpreters/tcl/generic.nix +++ b/pkgs/development/interpreters/tcl/generic.nix @@ -1,55 +1,69 @@ -{ lib, stdenv +{ lib, stdenv, callPackage, makeSetupHook, makeWrapper # Version specific stuff , release, version, src , ... }: -stdenv.mkDerivation { - pname = "tcl"; - inherit version; - - inherit src; - - outputs = [ "out" "man" ]; - - setOutputFlags = false; - - preConfigure = '' - cd unix - ''; - - configureFlags = [ - "--enable-threads" - # Note: using $out instead of $man to prevent a runtime dependency on $man. - "--mandir=${placeholder "out"}/share/man" - "--enable-man-symlinks" - # Don't install tzdata because NixOS already has a more up-to-date copy. - "--with-tzdata=no" - "tcl_cv_strtod_unbroken=ok" - ] ++ lib.optional stdenv.is64bit "--enable-64bit"; - - enableParallelBuilding = true; - - postInstall = let - dllExtension = stdenv.hostPlatform.extensions.sharedLibrary; - in '' - make install-private-headers - ln -s $out/bin/tclsh${release} $out/bin/tclsh - ln -s $out/lib/libtcl${release}${dllExtension} $out/lib/libtcl${dllExtension} - ''; - - meta = with lib; { - description = "The Tcl scripting language"; - homepage = "https://www.tcl.tk/"; - license = licenses.tcltk; - platforms = platforms.all; - maintainers = with maintainers; [ vrthra ]; - }; - - passthru = rec { - inherit release version; - libPrefix = "tcl${release}"; - libdir = "lib/${libPrefix}"; - }; -} +let + baseInterp = + stdenv.mkDerivation { + pname = "tcl"; + inherit version; + + inherit src; + + outputs = [ "out" "man" ]; + + setOutputFlags = false; + + preConfigure = '' + cd unix + ''; + + configureFlags = [ + "--enable-threads" + # Note: using $out instead of $man to prevent a runtime dependency on $man. + "--mandir=${placeholder "out"}/share/man" + "--enable-man-symlinks" + # Don't install tzdata because NixOS already has a more up-to-date copy. + "--with-tzdata=no" + "tcl_cv_strtod_unbroken=ok" + ] ++ lib.optional stdenv.is64bit "--enable-64bit"; + + enableParallelBuilding = true; + + postInstall = let + dllExtension = stdenv.hostPlatform.extensions.sharedLibrary; + in '' + make install-private-headers + ln -s $out/bin/tclsh${release} $out/bin/tclsh + ln -s $out/lib/libtcl${release}${dllExtension} $out/lib/libtcl${dllExtension} + ''; + + meta = with lib; { + description = "The Tcl scripting language"; + homepage = "https://www.tcl.tk/"; + license = licenses.tcltk; + platforms = platforms.all; + maintainers = with maintainers; [ vrthra ]; + }; + + passthru = rec { + inherit release version; + libPrefix = "tcl${release}"; + libdir = "lib/${libPrefix}"; + tclPackageHook = callPackage ({}: makeSetupHook { + name = "tcl-package-hook"; + deps = [ makeWrapper ]; + } ./tcl-package-hook.sh) {}; + }; + }; + + mkTclDerivation = callPackage ./mk-tcl-derivation.nix { tcl = baseInterp; }; + +in baseInterp.overrideAttrs (self: { + passthru = self.passthru // { + inherit mkTclDerivation; + }; +}) diff --git a/pkgs/development/interpreters/tcl/mk-tcl-derivation.nix b/pkgs/development/interpreters/tcl/mk-tcl-derivation.nix new file mode 100644 index 0000000000000..4f3ffe6f995f4 --- /dev/null +++ b/pkgs/development/interpreters/tcl/mk-tcl-derivation.nix @@ -0,0 +1,69 @@ +# Generic builder for tcl packages/applications, generally based on mk-python-derivation.nix +{ tcl +, lib +, makeWrapper +, runCommand +, writeScript +}: + +{ buildInputs ? [] +, nativeBuildInputs ? [] +, propagatedBuildInputs ? [] +, checkInputs ? [] + +# true if we should skip the configuration phase altogether +, dontConfigure ? false + +# Extra flags passed to configure step +, configureFlags ? [] + +# Whether or not we should add common Tcl-related configure flags +, addTclConfigureFlags ? true + +, meta ? {} +, passthru ? {} +, doCheck ? true +, ... } @ attrs: + +let + inherit (tcl) stdenv; + inherit (lib) getBin optionalAttrs optionals; + + defaultTclPkgConfigureFlags = [ + "--with-tcl=${tcl}/lib" + "--with-tclinclude=${tcl}/include" + "--exec-prefix=\${out}" + ]; + + self = (stdenv.mkDerivation ((builtins.removeAttrs attrs [ + "addTclConfigureFlags" "checkPhase" "checkInputs" "doCheck" + ]) // { + + buildInputs = buildInputs ++ [ makeWrapper tcl.tclPackageHook ]; + nativeBuildInputs = nativeBuildInputs ++ [ tcl ]; + propagatedBuildInputs = propagatedBuildInputs ++ [ tcl ]; + + TCLSH = "${getBin tcl}/bin/tclsh"; + + # Run tests after install, at which point we've done all TCLLIBPATH setup + doCheck = false; + doInstallCheck = attrs.doCheck or ((attrs ? doInstallCheck) && attrs.doInstallCheck); + installCheckInputs = checkInputs ++ (optionals (attrs ? installCheckInputs) attrs.installCheckInputs); + + # Add typical values expected by TEA for configureFlags + configureFlags = + if (!dontConfigure && addTclConfigureFlags) + then (configureFlags ++ defaultTclPkgConfigureFlags) + else configureFlags; + + meta = { + platforms = tcl.meta.platforms; + } // meta; + + + } // optionalAttrs (attrs?checkPhase) { + installCheckPhase = attrs.checkPhase; + } + )); + +in lib.extendDerivation true passthru self diff --git a/pkgs/development/interpreters/tcl/tcl-package-hook.sh b/pkgs/development/interpreters/tcl/tcl-package-hook.sh new file mode 100644 index 0000000000000..5f105e2fc7ea7 --- /dev/null +++ b/pkgs/development/interpreters/tcl/tcl-package-hook.sh @@ -0,0 +1,74 @@ +# This hook ensures that we do the following in post-fixup: +# * wrap any installed executables with a wrapper that configures TCLLIBPATH +# * write a setup hook that extends the TCLLIBPATH of any anti-dependencies + +# Add a directory to TCLLIBPATH, provided that it exists +_addToTclLibPath() { + local -r tclPkg="$1" + if [ -z "$tclPkg" ]; then + return + fi + + if [ ! -d "$tclPkg" ]; then + >&2 echo "can't add $tclPkg to TCLLIBPATH; that directory doesn't exist" + exit 1 + fi + + if [[ "$tclPkg" == *" "* ]]; then + tclPkg="{$tclPkg}" + fi + + if [ -z "${TCLLIBPATH-}" ]; then + export TCLLIBPATH="$tclPkg" + else + if [[ "$TCLLIBPATH" != *"$tclPkg"* ]]; then + export TCLLIBPATH="${TCLLIBPATH} $tclPkg" + fi + fi +} + +# Locate any directory containing an installed pkgIndex file +findInstalledTclPkgs() { + local -r newLibDir="${!outputLib}/lib" + if [ ! -d "$newLibDir" ]; then + >&2 echo "Assuming no loadable tcl packages installed ($newLibDir does not exist)" + return + fi + echo "$(find "$newLibDir" -name pkgIndex.tcl -exec dirname {} \;)" +} + +# Wrap any freshly-installed binaries and set up their TCLLIBPATH +wrapTclBins() { + if [ -z "${TCLLIBPATH-}" ]; then + echo "skipping automatic Tcl binary wrapping (nothing to do)" + return + fi + + local -r tclBinsDir="${!outputBin}/bin" + if [ ! -d "$tclBinsDir" ]; then + echo "No outputBin found, not using any TCLLIBPATH wrapper" + return + fi + + find "$tclBinsDir" -type f -executable -print | + while read -r someBin; do + echo "Adding TCLLIBPATH wrapper for $someBin" + wrapProgram "$someBin" --set TCLLIBPATH "$TCLLIBPATH" + done +} + +# Generate hook to adjust TCLLIBPATH in anti-dependencies +writeTclLibPathHook() { + local -r hookPath="${!outputLib}/nix-support/setup-hook" + mkdir -p "$(dirname "$hookPath")" + + typeset -f _addToTclLibPath >> "$hookPath" + local -r tclPkgs=$(findInstalledTclPkgs) + while IFS= read -r tclPkg; do + echo "_addToTclLibPath \"$tclPkg\"" >> "$hookPath" + _addToTclLibPath "$tclPkg" true + done <<< "$tclPkgs" +} + +postFixupHooks+=(writeTclLibPathHook) +postFixupHooks+=(wrapTclBins) |