-
-
Notifications
You must be signed in to change notification settings - Fork 18.2k
setup-hooks: add auto-patch-pc-hook #394610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # autoPatchPkgConfigHook {#auto-patch-pkg-config-hook} | ||
|
|
||
| The `autoPatchPkgConfigHook` hook replaces all packages listed in `Requires` and | ||
| `Requires.private` fields with absolute paths to their pkg-config files. This | ||
| effectively means that dependency resolution by `pkg-config` is moved from the | ||
| build phase of the dependent package to the build phase of the dependency which | ||
| is important since the dependent package may not be aware of its transitive | ||
| dependencies. | ||
|
|
||
| You should use this hook if your package produces pkg-config files with | ||
| non-empty `Requires` or `Requires.private` fields. To use it simply add it to | ||
| the `nativeBuildInputs`. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,52 @@ | ||||||
| # Replaces dependencies in pc files with their absolute paths | ||||||
| # | ||||||
| # Usage: python patch-pc.py /path/to/pkgconf libfoo.pc | ||||||
| # The tool writes patched .pc file to the stdout | ||||||
|
|
||||||
| from subprocess import run | ||||||
| import sys | ||||||
| import re | ||||||
|
|
||||||
| LINE_SEP = re.compile(r"(?<!\\)\n") | ||||||
|
|
||||||
| pkgconf_bin = sys.argv[1] | ||||||
| pc_file = sys.argv[2] | ||||||
|
|
||||||
|
|
||||||
| def run_pkgconf(*args: str) -> str: | ||||||
| result = run([pkgconf_bin, *args], capture_output=True, check=True) | ||||||
| return result.stdout.decode().rstrip() | ||||||
|
|
||||||
|
|
||||||
| def get_path(name: str) -> str: | ||||||
| return run_pkgconf("--path", name) | ||||||
|
|
||||||
|
|
||||||
| def list_requires(file: str, private: bool) -> list[str]: | ||||||
| return run_pkgconf( | ||||||
| f"--print-requires{"-private" if private else ""}", file | ||||||
| ).splitlines() | ||||||
|
|
||||||
|
|
||||||
| def transform_dep_spec(dep_spec: str) -> str: | ||||||
| def escape(s: str) -> str: | ||||||
| return s.replace("#", "\\#") | ||||||
|
|
||||||
| [name, *version_spec] = dep_spec.split(" ") | ||||||
| return " ".join(escape(s) for s in [get_path(name), *version_spec]) | ||||||
|
|
||||||
|
|
||||||
| def print_requires(file: str, private: bool): | ||||||
| requires = (transform_dep_spec(dep) for dep in list_requires(file, private)) | ||||||
|
||||||
| requires = (transform_dep_spec(dep) for dep in list_requires(file, private)) | |
| requires = map(transform_dep_spec, list_requires(file, private)) |
We do functional programming in nix, a map might be more appropriate than list comprehension, but i am happy with either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't write a lot of Python but my understanding is that list comprehensions are considered more pythonic than the functional equivalents, e.g., see here.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1004,6 +1004,36 @@ with pkgs; | |
| ]; | ||
| } ../build-support/setup-hooks/validate-pkg-config.sh; | ||
|
|
||
| autoPatchPkgConfigHook = | ||
| makeSetupHook | ||
| { | ||
| name = "auto-patch-pkg-config-hook"; | ||
| propagatedBuildInputs = [ pkg-config ]; | ||
| } | ||
| ( | ||
| writeScript "patch-pc.sh" '' | ||
| fixupOutputHooks+=(autoPatchPcHook) | ||
|
|
||
| autoPatchPcHook() ( | ||
| # Some packages list their own libraries as deps, they should be searched first in case of cyclic deps | ||
| export PKG_CONFIG_PATH_${pkgconf.suffixSalt}="$prefix/lib/pkgconfig:$prefix/share/pkgconfig:$PKG_CONFIG_PATH_${pkgconf.suffixSalt}" | ||
|
|
||
| shopt -s nullglob | ||
| for pc in $prefix/{lib,lib64,share}/pkgconfig/*.pc; do | ||
| echo Fixing require paths in $pc file | ||
|
|
||
| if ! ${lib.getExe python3Minimal} \ | ||
| ${../build-support/setup-hooks/patch-pc.py} \ | ||
| ${lib.getExe pkgconf} "$pc" > "$pc.patched"; then | ||
|
||
| exit 1 | ||
| fi | ||
| mv "$pc.patched" "$pc" | ||
| done | ||
| ) | ||
|
|
||
| '' | ||
| ); | ||
|
|
||
| #package writers | ||
| writers = callPackage ../build-support/writers { }; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.