Skip to content

Instantly share code, notes, and snippets.

@nh2
Created February 13, 2020 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nh2/fc01e3652b55e36a6a03f4295c3e8388 to your computer and use it in GitHub Desktop.
Save nh2/fc01e3652b55e36a6a03f4295c3e8388 to your computer and use it in GitHub Desktop.
Hack to work around nix duplicate -L flags causing `argument list too long` for GCC, see https://github.com/NixOS/nixpkgs/issues/41340
#!/usr/bin/env python3
# Script to deduplicate linker flags in nix variables.
# Workaround for:
# https://github.com/NixOS/nixpkgs/issues/41340
#
# This is obviously a hack and it should be fixed in nixpkgs.
#
# Usage (from bash to update env vars in the current shell context):
# eval <(nix-env-flags-deduper.py)
#
# Note that currently no effort is taken to deduplicate flags *across*
# different env vars, e.g.
# NIX_LDFLAGS
# NIX_TARGET_LDFLAGS
# may both be passed to the same compiler/linker and contain overlapping
# entries, but we don't deduplicate across those here.
#
# This script maintains flag ordering but assumes that space-separated
# LDFLAGS are independent of each other.
# Any usage like `--option A --option B` will result in `--option A B`
# and thus probably break things.
import os
import re
import sys
# Check minimum Python version.
# See https://stackoverflow.com/questions/7961363/removing-duplicates-in-lists/7961425#7961425
MIN_PYTHON = (3, 6)
if sys.version_info < MIN_PYTHON:
sys.exit("Python %s.%s or later is required for dict.fromkeys() order-preserving list deduplication.\n" % MIN_PYTHON)
# For each relevant nix variable, write an `export VAR=...deduped contents...`
# to stdout.
# We only dedupe `-L` flags because the multiple `-l` flags can actually be
# important for some use cases on some linkers (like GNU ld and gold with their
# "symbol hole filling" approach).
for var_name, val in os.environ.items():
if re.match(r'NIX_(.*_)?LDFLAGS', var_name): # e.g. NIX_LFAGS, NIX_TARGET_LDFLAGS
flags = val.split(' ')
deduped_flags = []
seen_flags_set = set()
for f in flags:
if f.startswith('-L') and f not in seen_flags_set:
deduped_flags.append(f)
seen_flags_set.add(f)
print("export {}='{}'".format(var_name, ' '.join(deduped_flags)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment