From 9761c719c8a8c442285bea98bd60d406dd2df109 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Thu, 12 Sep 2024 19:15:29 +0200 Subject: [PATCH] postgresql: improve fake pg_config in default output This fixes some build systems which look up the location of pg_config via the location of the postgres binary itself, e.g. timescaledb, instead of calling pg_config which is on PATH. Since the -dev output is correctly placed before the default output of postgresql in PATH, we can rely on that and call "pg_config" from the default output's fake script. Only do that, when the one on PATH is actually a different file, though, to prevent infinite loops. Resolves #341408 --- pkgs/servers/sql/postgresql/generic.nix | 19 ++++++++------- pkgs/servers/sql/postgresql/pg_config.sh | 30 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 pkgs/servers/sql/postgresql/pg_config.sh diff --git a/pkgs/servers/sql/postgresql/generic.nix b/pkgs/servers/sql/postgresql/generic.nix index de9dc49a09e1c09..ce922e807667d41 100644 --- a/pkgs/servers/sql/postgresql/generic.nix +++ b/pkgs/servers/sql/postgresql/generic.nix @@ -6,7 +6,8 @@ let , glibc, zlib, readline, openssl, icu, lz4, zstd, systemdLibs, libossp_uuid , pkg-config, libxml2, tzdata, libkrb5, substituteAll, darwin , linux-pam - , removeReferencesTo + + , removeReferencesTo, writeShellApplication # This is important to obtain a version of `libpq` that does not depend on systemd. , systemdSupport ? lib.meta.availableOn stdenv.hostPlatform systemdLibs && !stdenv.hostPlatform.isStatic @@ -54,6 +55,11 @@ let }) else stdenv; + + pg_config = writeShellApplication { + name = "pg_config"; + text = builtins.readFile ./pg_config.sh; + }; in stdenv'.mkDerivation (finalAttrs: { inherit version; pname = pname + lib.optionalString jitSupport "-jit"; @@ -201,15 +207,10 @@ let moveToOutput "lib/pgxs" "$dev" # Pretend pg_config is located in $out/bin to return correct paths, but - # actually have it in -dev to avoid pulling in all other outputs. + # actually have it in -dev to avoid pulling in all other outputs. See the + # pg_config.sh script's comments for details. moveToOutput "bin/pg_config" "$dev" - # To prevent a "pg_config: could not find own program executable" error, we fake - # pg_config in the default output. - cat << EOF > "$out/bin/pg_config" && chmod +x "$out/bin/pg_config" - #!${stdenv'.shell} - echo The real pg_config can be found in the -dev output. - exit 1 - EOF + install -c -m 755 "${pg_config}"/bin/pg_config "$out/bin/pg_config" wrapProgram "$dev/bin/pg_config" --argv0 "$out/bin/pg_config" # postgres exposes external symbols get_pkginclude_path and similar. Those diff --git a/pkgs/servers/sql/postgresql/pg_config.sh b/pkgs/servers/sql/postgresql/pg_config.sh new file mode 100644 index 000000000000000..60da284f5ec601c --- /dev/null +++ b/pkgs/servers/sql/postgresql/pg_config.sh @@ -0,0 +1,30 @@ +# The real pg_config needs to be in the same path as the "postgres" binary +# to return proper paths. However, we want it in the -dev output to prevent +# cyclic references and to prevent blowing up the runtime closure. Thus, we +# have wrapped -dev/bin/pg_config to fake its argv0 to be in the default +# output. Unfortunately, pg_config tries to be smart and tries to find itself - +# which will then fail with: +# pg_config: could not find own program executable +# To counter this, we're creating *this* fake pg_config script and put it into +# the default output. The real pg_config is happy. +# Some extensions, e.g. timescaledb, use the reverse logic and look for pg_config +# in the same path as the "postgres" binary to support multi-version-installs. +# Thus, they will end up calling this script during build, even though the real +# pg_config would be available on PATH, provided by nativeBuildInputs. To help +# this case, we're checking whether *this* script is the same as the one available +# in PATH, and if not we're redirecting the call there. +# If this script is called directly, we can't do anything except to error out. + +# compares "path of *this* script" with "path of pg_config on PATH" +if [[ "$(readlink -f -- "$0")" != "$(readlink -f -- "$(type -P pg_config)")" ]]; then + # There is a different pg_config in PATH, let's call this instead. + # This happens when the -dev output has been put in native build + # inputs and allows us to call the real pg_config without referencing + # the -dev output itself. + pg_config "$@" +else + # This will happen if either *this* script is the first on PATH or if there was + # no pg_config on PATH at all. + echo The real pg_config can be found in the -dev output. + exit 1 +fi