libstdc++ headers in the header search path, otherwise libstdc++'s use of #include_next to include Glibc headers breaks. svn path=/nixpkgs/trunk/; revision=12195wip/yesman
parent
34f583224d
commit
1cdb7e4831
@ -0,0 +1,24 @@ |
||||
# `-B@out@/bin' forces gcc to use ld-wrapper.sh when calling ld. |
||||
export NIX_CFLAGS_COMPILE="-B@out@/bin/ $NIX_CFLAGS_COMPILE" |
||||
|
||||
if test -e @out@/nix-support/libc-cflags; then |
||||
export NIX_CFLAGS_COMPILE="$(cat @out@/nix-support/libc-cflags) $NIX_CFLAGS_COMPILE" |
||||
fi |
||||
|
||||
if test -e @out@/nix-support/libc-ldflags; then |
||||
export NIX_LDFLAGS="$(cat @out@/nix-support/libc-ldflags) $NIX_LDFLAGS" |
||||
fi |
||||
|
||||
if test -e @out@/nix-support/gcc-cflags; then |
||||
export NIX_CFLAGS_COMPILE="$(cat @out@/nix-support/gcc-cflags) $NIX_CFLAGS_COMPILE" |
||||
fi |
||||
|
||||
if test -e @out@/nix-support/gcc-ldflags; then |
||||
export NIX_LDFLAGS="$(cat @out@/nix-support/gcc-ldflags) $NIX_LDFLAGS" |
||||
fi |
||||
|
||||
if test -e @out@/nix-support/libc-ldflags-before; then |
||||
export NIX_LDFLAGS_BEFORE="$(cat @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE" |
||||
fi |
||||
|
||||
export NIX_GCC_WRAPPER_FLAGS_SET=1 |
@ -0,0 +1,130 @@ |
||||
source $stdenv/setup |
||||
|
||||
|
||||
ensureDir $out/bin |
||||
ensureDir $out/nix-support |
||||
|
||||
|
||||
if test -z "$nativeLibc"; then |
||||
dynamicLinker="$libc/lib/$dynamicLinker" |
||||
echo $dynamicLinker > $out/nix-support/dynamic-linker |
||||
|
||||
# The "-B$libc/lib/" flag is a quick hack to force gcc to link |
||||
# against the crt1.o from our own glibc, rather than the one in |
||||
# /usr/lib. (This is only an issue when using an `impure' |
||||
# compiler/linker, i.e., one that searches /usr/lib and so on.) |
||||
echo "-B$libc/lib/ -isystem $libc/include" > $out/nix-support/libc-cflags |
||||
|
||||
echo "-L$libc/lib" > $out/nix-support/libc-ldflags |
||||
|
||||
# The dynamic linker is passed in `ldflagsBefore' to allow |
||||
# explicit overrides of the dynamic linker by callers to gcc/ld |
||||
# (the *last* value counts, so ours should come first). |
||||
echo "-dynamic-linker $dynamicLinker" > $out/nix-support/libc-ldflags-before |
||||
fi |
||||
|
||||
if test -n "$nativeTools"; then |
||||
gccPath="$nativePrefix/bin" |
||||
ldPath="$nativePrefix/bin" |
||||
else |
||||
if test -e "$gcc/lib64"; then |
||||
gccLDFlags="$gccLDFlags -L$gcc/lib64" |
||||
fi |
||||
gccLDFlags="$gccLDFlags -L$gcc/lib" |
||||
echo "$gccLDFlags" > $out/nix-support/gcc-ldflags |
||||
|
||||
# Explicitly add the libstdc++ header files to the search path. |
||||
# G++ already finds them automatically, but it adds them to the |
||||
# very end of the header search path. This means that |
||||
# #include_next constructs in the libstdc++ headers won't find the |
||||
# Glibc headers, since they appear *before* the libstdc++ headers. |
||||
# So we add them here using -isystem. Note that `add-flags' adds |
||||
# the libc flags before the gcc flags. |
||||
gccCFlags="$gccCFlags -isystem $(echo $gcc/include/c++/*.*)" |
||||
|
||||
# GCC shows $gcc/lib in `gcc -print-search-dirs', but not |
||||
# $gcc/lib64 (even though it does actually search there...).. |
||||
# This confuses libtool. So add it to the compiler tool search |
||||
# path explicitly. |
||||
if test -e "$gcc/lib64"; then |
||||
gccCFlags="$gccCFlags -B$gcc/lib64" |
||||
fi |
||||
echo "$gccCFlags" > $out/nix-support/gcc-cflags |
||||
|
||||
gccPath="$gcc/bin" |
||||
ldPath="$binutils/bin" |
||||
fi |
||||
|
||||
|
||||
doSubstitute() { |
||||
local src=$1 |
||||
local dst=$2 |
||||
# Can't use substitute() here, because replace may not have been |
||||
# built yet (in the bootstrap). |
||||
sed \ |
||||
-e "s^@out@^$out^g" \ |
||||
-e "s^@shell@^$shell^g" \ |
||||
-e "s^@gcc@^$gcc^g" \ |
||||
-e "s^@gccProg@^$gccProg^g" \ |
||||
-e "s^@binutils@^$binutils^g" \ |
||||
-e "s^@libc@^$libc^g" \ |
||||
-e "s^@ld@^$ldPath/ld^g" \ |
||||
< "$src" > "$dst" |
||||
} |
||||
|
||||
|
||||
# Make wrapper scripts around gcc, g++, and g77. Also make symlinks |
||||
# cc, c++, and f77. |
||||
mkGccWrapper() { |
||||
local dst=$1 |
||||
local src=$2 |
||||
|
||||
if ! test -f "$src"; then |
||||
echo "$src does not exist (skipping)" |
||||
return |
||||
fi |
||||
|
||||
gccProg="$src" |
||||
doSubstitute "$gccWrapper" "$dst" |
||||
chmod +x "$dst" |
||||
} |
||||
|
||||
mkGccWrapper $out/bin/gcc $gccPath/gcc |
||||
ln -s gcc $out/bin/cc |
||||
|
||||
mkGccWrapper $out/bin/g++ $gccPath/g++ |
||||
ln -s g++ $out/bin/c++ |
||||
|
||||
mkGccWrapper $out/bin/g77 $gccPath/g77 |
||||
ln -s g77 $out/bin/f77 |
||||
|
||||
|
||||
# Create a symlink to as (the assembler). This is useful when a |
||||
# gcc-wrapper is installed in a user environment, as it ensures that |
||||
# the right assembler is called. |
||||
ln -s $ldPath/as $out/bin/as |
||||
|
||||
|
||||
# Make a wrapper around the linker. |
||||
doSubstitute "$ldWrapper" "$out/bin/ld" |
||||
chmod +x "$out/bin/ld" |
||||
|
||||
|
||||
# Emit a setup hook. Also store the path to the original GCC and |
||||
# Glibc. |
||||
test -n "$gcc" && echo $gcc > $out/nix-support/orig-gcc |
||||
test -n "$libc" && echo $libc > $out/nix-support/orig-libc |
||||
|
||||
doSubstitute "$addFlags" "$out/nix-support/add-flags.sh" |
||||
|
||||
doSubstitute "$setupHook" "$out/nix-support/setup-hook" |
||||
|
||||
cp -p $utils $out/nix-support/utils.sh |
||||
|
||||
|
||||
# Propagate the wrapped gcc so that if you install the wrapper, you get |
||||
# tools like gcov, the manpages, etc. as well (including for binutils |
||||
# and Glibc). |
||||
if test -z "$nativeTools"; then |
||||
echo $gcc $binutils $libc > $out/nix-support/propagated-user-env-packages |
||||
fi |
@ -0,0 +1,46 @@ |
||||
# The Nix `gcc' stdenv.mkDerivation is not directly usable, since it doesn't |
||||
# know where the C library and standard header files are. Therefore |
||||
# the compiler produced by that package cannot be installed directly |
||||
# in a user environment and used from the command line. This |
||||
# stdenv.mkDerivation provides a wrapper that sets up the right environment |
||||
# variables so that the compiler and the linker just "work". |
||||
|
||||
{ name ? "", stdenv, nativeTools, nativeLibc, nativePrefix ? "" |
||||
, gcc ? null, libc ? null, binutils ? null, shell ? "" |
||||
}: |
||||
|
||||
assert nativeTools -> nativePrefix != ""; |
||||
assert !nativeTools -> gcc != null && binutils != null; |
||||
assert !nativeLibc -> libc != null; |
||||
|
||||
stdenv.mkDerivation { |
||||
builder = ./builder.sh; |
||||
setupHook = ./setup-hook.sh; |
||||
gccWrapper = ./gcc-wrapper.sh; |
||||
ldWrapper = ./ld-wrapper.sh; |
||||
utils = ./utils.sh; |
||||
addFlags = ./add-flags; |
||||
|
||||
inherit nativeTools nativeLibc nativePrefix gcc; |
||||
libc = if nativeLibc then null else libc; |
||||
binutils = if nativeTools then null else binutils; |
||||
|
||||
name = if name == "" then gcc.name else name; |
||||
langC = if nativeTools then true else gcc.langC; |
||||
langCC = if nativeTools then true else gcc.langCC; |
||||
langF77 = if nativeTools then false else gcc.langF77; |
||||
shell = if shell == "" then stdenv.shell else shell; |
||||
|
||||
meta = if gcc != null && (gcc ? meta) then removeAttrs gcc.meta ["priority"] else |
||||
{ description = "System C compiler wrapper"; |
||||
}; |
||||
|
||||
# The dynamic linker has different names on different Linux platforms. |
||||
dynamicLinker = |
||||
if !nativeLibc then |
||||
(if stdenv.system == "i686-linux" then "ld-linux.so.2" else |
||||
if stdenv.system == "x86_64-linux" then "ld-linux-x86-64.so.2" else |
||||
if stdenv.system == "powerpc-linux" then "ld.so.1" else |
||||
abort "don't know the name of the dynamic linker for this platform") |
||||
else ""; |
||||
} |
@ -0,0 +1,144 @@ |
||||
#! @shell@ -e |
||||
|
||||
if test -n "$NIX_GCC_WRAPPER_START_HOOK"; then |
||||
source "$NIX_GCC_WRAPPER_START_HOOK" |
||||
fi |
||||
|
||||
if test -z "$NIX_GCC_WRAPPER_FLAGS_SET"; then |
||||
source @out@/nix-support/add-flags.sh |
||||
fi |
||||
|
||||
source @out@/nix-support/utils.sh |
||||
|
||||
|
||||
# Figure out if linker flags should be passed. GCC prints annoying |
||||
# warnings when they are not needed. |
||||
dontLink=0 |
||||
getVersion=0 |
||||
nonFlagArgs=0 |
||||
|
||||
for i in "$@"; do |
||||
if test "$i" = "-c"; then |
||||
dontLink=1 |
||||
elif test "$i" = "-S"; then |
||||
dontLink=1 |
||||
elif test "$i" = "-E"; then |
||||
dontLink=1 |
||||
elif test "$i" = "-E"; then |
||||
dontLink=1 |
||||
elif test "$i" = "-M"; then |
||||
dontLink=1 |
||||
elif test "$i" = "-MM"; then |
||||
dontLink=1 |
||||
elif test "${i:0:1}" != "-"; then |
||||
nonFlagArgs=1 |
||||
fi |
||||
done |
||||
|
||||
# If we pass a flag like -Wl, then gcc will call the linker unless it |
||||
# can figure out that it has to do something else (e.g., because of a |
||||
# "-c" flag). So if no non-flag arguments are given, don't pass any |
||||
# linker flags. This catches cases like "gcc" (should just print |
||||
# "gcc: no input files") and "gcc -v" (should print the version). |
||||
if test "$nonFlagArgs" = "0"; then |
||||
dontLink=1 |
||||
fi |
||||
|
||||
|
||||
# Optionally filter out paths not refering to the store. |
||||
params=("$@") |
||||
if test "$NIX_ENFORCE_PURITY" = "1" -a -n "$NIX_STORE"; then |
||||
rest=() |
||||
n=0 |
||||
while test $n -lt ${#params[*]}; do |
||||
p=${params[n]} |
||||
p2=${params[$((n+1))]} |
||||
if test "${p:0:3}" = "-L/" && badPath "${p:2}"; then |
||||
skip $p |
||||
elif test "$p" = "-L" && badPath "$p2"; then |
||||
n=$((n + 1)); skip $p2 |
||||
elif test "${p:0:3}" = "-I/" && badPath "${p:2}"; then |
||||
skip $p |
||||
elif test "$p" = "-I" && badPath "$p2"; then |
||||
n=$((n + 1)); skip $p2 |
||||
elif test "$p" = "-isystem" && badPath "$p2"; then |
||||
n=$((n + 1)); skip $p2 |
||||
else |
||||
rest=("${rest[@]}" "$p") |
||||
fi |
||||
n=$((n + 1)) |
||||
done |
||||
params=("${rest[@]}") |
||||
fi |
||||
|
||||
|
||||
# Add the flags for the C compiler proper. |
||||
extraAfter=($NIX_CFLAGS_COMPILE) |
||||
extraBefore=() |
||||
|
||||
if test "$dontLink" != "1"; then |
||||
|
||||
# Add the flags that should only be passed to the compiler when |
||||
# linking. |
||||
extraAfter=(${extraAfter[@]} $NIX_CFLAGS_LINK) |
||||
|
||||
# Add the flags that should be passed to the linker (and prevent |
||||
# `ld-wrapper' from adding NIX_LDFLAGS again). |
||||
for i in $NIX_LDFLAGS_BEFORE; do |
||||
extraBefore=(${extraBefore[@]} "-Wl,$i") |
||||
done |
||||
for i in $NIX_LDFLAGS; do |
||||
if test "${i:0:3}" = "-L/"; then |
||||
extraAfter=(${extraAfter[@]} "$i") |
||||
else |
||||
extraAfter=(${extraAfter[@]} "-Wl,$i") |
||||
fi |
||||
done |
||||
export NIX_LDFLAGS_SET=1 |
||||
|
||||
if test "$NIX_STRIP_DEBUG" = "1"; then |
||||
# Add executable-stripping flags. |
||||
extraAfter=(${extraAfter[@]} $NIX_CFLAGS_STRIP) |
||||
fi |
||||
fi |
||||
|
||||
# As a very special hack, if the arguments are just `-v', then don't |
||||
# add anything. This is to prevent `gcc -v' (which normally prints |
||||
# out the version number and returns exit code 0) from printing out |
||||
# `No input files specified' and returning exit code 1. |
||||
if test "$*" = "-v"; then |
||||
extraAfter=() |
||||
extraBefore=() |
||||
fi |
||||
|
||||
# Optionally print debug info. |
||||
if test "$NIX_DEBUG" = "1"; then |
||||
echo "original flags to @gccProg@:" >&2 |
||||
for i in "${params[@]}"; do |
||||
echo " $i" >&2 |
||||
done |
||||
echo "extraBefore flags to @gccProg@:" >&2 |
||||
for i in ${extraBefore[@]}; do |
||||
echo " $i" >&2 |
||||
done |
||||
echo "extraAfter flags to @gccProg@:" >&2 |
||||
for i in ${extraAfter[@]}; do |
||||
echo " $i" >&2 |
||||
done |
||||
fi |
||||
|
||||
if test -n "$NIX_GCC_WRAPPER_EXEC_HOOK"; then |
||||
source "$NIX_GCC_WRAPPER_EXEC_HOOK" |
||||
fi |
||||
|
||||
|
||||
# Call the real `gcc'. Filter out warnings from stderr about unused |
||||
# `-B' flags, since they confuse some programs. Deep bash magic to |
||||
# apply grep to stderr (by swapping stdin/stderr twice). |
||||
if test -z "$NIX_GCC_NEEDS_GREP"; then |
||||
@gccProg@ ${extraBefore[@]} "${params[@]}" ${extraAfter[@]} |
||||
else |
||||
(@gccProg@ ${extraBefore[@]} "${params[@]}" ${extraAfter[@]} 3>&2 2>&1 1>&3- \ |
||||
| (grep -v 'file path prefix' || true); exit ${PIPESTATUS[0]}) 3>&2 2>&1 1>&3- |
||||
exit $? |
||||
fi |
@ -0,0 +1,145 @@ |
||||
#! @shell@ -e |
||||
|
||||
if test -n "$NIX_LD_WRAPPER_START_HOOK"; then |
||||
source "$NIX_LD_WRAPPER_START_HOOK" |
||||
fi |
||||
|
||||
if test -z "$NIX_GCC_WRAPPER_FLAGS_SET"; then |
||||
source @out@/nix-support/add-flags.sh |
||||
fi |
||||
|
||||
source @out@/nix-support/utils.sh |
||||
|
||||
|
||||
# Optionally filter out paths not refering to the store. |
||||
params=("$@") |
||||
if test "$NIX_ENFORCE_PURITY" = "1" -a -n "$NIX_STORE" \ |
||||
-a \( -z "$NIX_IGNORE_LD_THROUGH_GCC" -o -z "$NIX_LDFLAGS_SET" \); then |
||||
rest=() |
||||
n=0 |
||||
while test $n -lt ${#params[*]}; do |
||||
p=${params[n]} |
||||
p2=${params[$((n+1))]} |
||||
if test "${p:0:3}" = "-L/" && badPath "${p:2}"; then |
||||
skip $p |
||||
elif test "$p" = "-L" && badPath "$p2"; then |
||||
n=$((n + 1)); skip $p2 |
||||
elif test "$p" = "-rpath" && badPath "$p2"; then |
||||
n=$((n + 1)); skip $p2 |
||||
elif test "$p" = "-dynamic-linker" && badPath "$p2"; then |
||||
n=$((n + 1)); skip $p2 |
||||
elif test "${p:0:1}" = "/" && badPath "$p"; then |
||||
# We cannot skip this; barf. |
||||
echo "impure path \`$p' used in link" >&2 |
||||
exit 1 |
||||
else |
||||
rest=("${rest[@]}" "$p") |
||||
fi |
||||
n=$((n + 1)) |
||||
done |
||||
params=("${rest[@]}") |
||||
fi |
||||
|
||||
|
||||
extra=() |
||||
extraBefore=() |
||||
|
||||
if test -z "$NIX_LDFLAGS_SET"; then |
||||
extra=(${extra[@]} $NIX_LDFLAGS) |
||||
extraBefore=(${extraBefore[@]} $NIX_LDFLAGS_BEFORE) |
||||
fi |
||||
|
||||
|
||||
# Add all used dynamic libraries to the rpath. |
||||
if test "$NIX_DONT_SET_RPATH" != "1"; then |
||||
|
||||
# First, find all -L... switches. |
||||
allParams=("${params[@]}" ${extra[@]}) |
||||
libPath="" |
||||
addToLibPath() { |
||||
local path="$1" |
||||
if test "${path:0:1}" != "/"; then return 0; fi |
||||
case "$path" in |
||||
*..*|*./*|*/.*|*//*) |
||||
local path2 |
||||
if path2=$(readlink -f "$path"); then |
||||
path="$path2" |
||||
fi |
||||
;; |
||||
esac |
||||
case $libPath in |
||||
*\ $path\ *) return 0 ;; |
||||
esac |
||||
libPath="$libPath $path " |
||||
} |
||||
n=0 |
||||
while test $n -lt ${#allParams[*]}; do |
||||
p=${allParams[n]} |
||||
p2=${allParams[$((n+1))]} |
||||
if test "${p:0:3}" = "-L/"; then |
||||
addToLibPath ${p:2} |
||||
elif test "$p" = "-L"; then |
||||
addToLibPath ${p2} |
||||
n=$((n + 1)) |
||||
fi |
||||
n=$((n + 1)) |
||||
done |
||||
|
||||
# Second, for each -l... switch, find the directory containing the |
||||
# library and add it to the rpath. |
||||
rpath="" |
||||
addToRPath() { |
||||
# If the path is not in the store, don't add it to the rpath. |
||||
# This typically happens for libraries in /tmp that are later |
||||
# copied to $out/lib. If not, we're screwed. |
||||
if test "${1:0:${#NIX_STORE}}" != "$NIX_STORE"; then return 0; fi |
||||
case $rpath in |
||||
*\ $1\ *) return 0 ;; |
||||
esac |
||||
rpath="$rpath $1 " |
||||
} |
||||
findLib() { |
||||
for i in $libPath; do |
||||
if test -f $i/lib$1.so; then |
||||
addToRPath $i |
||||
fi |
||||
done |
||||
} |
||||
n=0 |
||||
while test $n -lt ${#allParams[*]}; do |
||||
p=${allParams[n]} |
||||
p2=${allParams[$((n+1))]} |
||||
if test "${p:0:2}" = "-l"; then |
||||
findLib ${p:2} |
||||
elif test "$p" = "-l"; then |
||||
# I haven't seen `-l foo', but you never know... |
||||
findLib ${p2} |
||||
n=$((n + 1)) |
||||
fi |
||||
n=$((n + 1)) |
||||
done |
||||
|
||||
# Finally, add `-rpath' switches. |
||||
for i in $rpath; do |
||||
extra=(${extra[@]} -rpath $i) |
||||
done |
||||
fi |
||||
|
||||
|
||||
# Optionally print debug info. |
||||
if test "$NIX_DEBUG" = "1"; then |
||||
echo "original flags to @ld@:" >&2 |
||||
for i in "${params[@]}"; do |
||||
echo " $i" >&2 |
||||
done |
||||
echo "extra flags to @ld@:" >&2 |
||||
for i in ${extra[@]}; do |
||||
echo " $i" >&2 |
||||
done |
||||
fi |
||||
|
||||
if test -n "$NIX_LD_WRAPPER_EXEC_HOOK"; then |
||||
source "$NIX_LD_WRAPPER_EXEC_HOOK" |
||||
fi |
||||
|
||||
exec @ld@ ${extraBefore[@]} "${params[@]}" ${extra[@]} |
@ -0,0 +1,29 @@ |
||||
addCVars () { |
||||
if test -d $1/include; then |
||||
export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -I$1/include" |
||||
fi |
||||
|
||||
if test -d $1/lib64; then |
||||
export NIX_LDFLAGS="$NIX_LDFLAGS -L$1/lib64" |
||||
fi |
||||
|
||||
if test -d $1/lib; then |
||||
export NIX_LDFLAGS="$NIX_LDFLAGS -L$1/lib" |
||||
fi |
||||
} |
||||
|
||||
envHooks=(${envHooks[@]} addCVars) |
||||
|
||||
# Note: these come *after* $out in the PATH (see setup.sh). |
||||
|
||||
if test -n "@gcc@"; then |
||||
PATH=$PATH:@gcc@/bin |
||||
fi |
||||
|
||||
if test -n "@binutils@"; then |
||||
PATH=$PATH:@binutils@/bin |
||||
fi |
||||
|
||||
if test -n "@libc@"; then |
||||
PATH=$PATH:@libc@/bin |
||||
fi |
@ -0,0 +1,23 @@ |
||||
skip () { |
||||
if test "$NIX_DEBUG" = "1"; then |
||||
echo "skipping impure path $1" >&2 |
||||
fi |
||||
} |
||||
|
||||
|
||||
# Checks whether a path is impure. E.g., `/lib/foo.so' is impure, but |
||||
# `/nix/store/.../lib/foo.so' isn't. |
||||
badPath() { |
||||
local p=$1 |
||||
|
||||
# Relative paths are okay (since they're presumably relative to |
||||
# the temporary build directory). |
||||
if test "${p:0:1}" != "/"; then return 1; fi |
||||
|
||||
# Otherwise, the path should refer to the store or some temporary |
||||
# directory (including the build directory). |
||||
test \ |
||||
"${p:0:${#NIX_STORE}}" != "$NIX_STORE" -a \ |
||||
"${p:0:4}" != "/tmp" -a \ |
||||
"${p:0:${#NIX_BUILD_TOP}}" != "$NIX_BUILD_TOP" |
||||
} |
Loading…
Reference in new issue