Skip to content
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

cc-wrapper: Cleanup of Nix #28556

Merged
merged 4 commits into from
Aug 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 141 additions & 107 deletions pkgs/build-support/cc-wrapper/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,10 @@ let
else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1"
else null;

expand-response-params = if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null"
then buildPackages.stdenv.mkDerivation {
name = "expand-response-params";
src = ./expand-response-params.c;
buildCommand = ''
# Work around "stdenv-darwin-boot-2 is not allowed to refer to path /nix/store/...-expand-response-params.c"
cp "$src" expand-response-params.c
"$CC" -std=c99 -O3 -o "$out" expand-response-params.c
strip -S $out
${optionalString hostPlatform.isLinux "patchelf --shrink-rpath $out"}
'';
} else "";
expand-response-params =
if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null"
then import ../expand-response-params { inherit (buildPackages) stdenv; }
else "";

in

Expand Down Expand Up @@ -120,8 +112,17 @@ stdenv.mkDerivation {
'';
};

buildCommand =
dontBuild = true;
dontConfigure = true;

unpackPhase = ''
src=$PWD
'';

installPhase =
''
set -u

mkdir -p $out/bin $out/nix-support $man/nix-support

wrap() {
Expand All @@ -133,103 +134,16 @@ stdenv.mkDerivation {
}
''

+ optionalString (libc != null) (''
if [[ -z ''${dynamicLinker+x} ]]; then
echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2
dynamicLinker="${libc_lib}/lib/ld*.so.?"
fi

# Expand globs to fill array of options
dynamicLinker=($dynamicLinker)

case ''${#dynamicLinker[@]} in
0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;;
1) echo "Using dynamic linker: '$dynamicLinker'" >&2;;
*) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;;
esac

if [ -n "$dynamicLinker" ]; then
echo $dynamicLinker > $out/nix-support/dynamic-linker

'' + (if targetPlatform.isDarwin then ''
printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook
'' else ''
if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then
echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
fi

ldflagsBefore=(-dynamic-linker "$dynamicLinker")
'') + ''
fi

# 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).
printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before
'')

+ optionalString (libc != null) ''
# The "-B${libc_lib}/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.)
#
# Unfortunately, setting -B appears to override the default search
# path. Thus, the gcc-specific "../includes-fixed" directory is
# now longer searched and glibc's <limits.h> header fails to
# compile, because it uses "#include_next <limits.h>" to find the
# limits.h file in ../includes-fixed. To remedy the problem,
# another -idirafter is necessary to add that directory again.
echo "-B${libc_lib}/lib/ -idirafter ${libc_dev}/include -idirafter ${cc}/lib/gcc/*/*/include-fixed" > $out/nix-support/libc-cflags

echo "-L${libc_lib}/lib" > $out/nix-support/libc-ldflags

echo "${libc_lib}" > $out/nix-support/orig-libc
echo "${libc_dev}" > $out/nix-support/orig-libc-dev
''

+ (if nativeTools then ''
echo ${if targetPlatform.isDarwin then cc else nativePrefix} > $out/nix-support/orig-cc

ccPath="${if targetPlatform.isDarwin then cc else nativePrefix}/bin"
ldPath="${nativePrefix}/bin"
'' else ''
echo $cc > $out/nix-support/orig-cc

# GCC shows ${cc_solib}/lib in `gcc -print-search-dirs', but not
# ${cc_solib}/lib64 (even though it does actually search there...)..
# This confuses libtool. So add it to the compiler tool search
# path explicitly.
if [ -e "${cc_solib}/lib64" -a ! -L "${cc_solib}/lib64" ]; then
ccLDFlags+=" -L${cc_solib}/lib64"
ccCFlags+=" -B${cc_solib}/lib64"
fi
ccLDFlags+=" -L${cc_solib}/lib"
ccCFlags+=" -B${cc_solib}/lib"

${optionalString cc.langVhdl or false ''
ccLDFlags+=" -L${zlib.out}/lib"
''}

# Find the gcc libraries path (may work only without multilib).
${optionalString cc.langAda or false ''
basePath=`echo ${cc_solib}/lib/*/*/*`
ccCFlags+=" -B$basePath -I$basePath/adainclude"
gnatCFlags="-aI$basePath/adainclude -aO$basePath/adalib"
echo "$gnatCFlags" > $out/nix-support/gnat-cflags
''}

echo "$ccLDFlags" > $out/nix-support/cc-ldflags
echo "$ccCFlags" > $out/nix-support/cc-cflags

ccPath="${cc}/bin"
ldPath="${binutils_bin}/bin"

# Propagate the wrapped cc so that if you install the wrapper,
# you get tools like gcov, the manpages, etc. as well (including
# for binutils and Glibc).
printWords ${cc} ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages
printWords ${cc.man or ""} > $man/nix-support/propagated-user-env-packages

printWords ${toString extraPackages} > $out/nix-support/propagated-native-build-inputs
''

+ optionalString (targetPlatform.isSunOS && nativePrefix != "") ''
Expand Down Expand Up @@ -320,15 +234,129 @@ stdenv.mkDerivation {

+ optionalString cc.langVhdl or false ''
ln -s $ccPath/${prefix}ghdl $out/bin/${prefix}ghdl
'';

propagatedBuildInputs = extraPackages;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was tantamount propagatedNativeBuildInputs before, but it doesn't (currently) make a difference with native, and this is more correct with cross.


setupHook = ./setup-hook.sh;

postFixup =
''
set -u
''

+ optionalString (libc != null) (''
##
## General libc support
##

# The "-B${libc_lib}/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.)
#
# Unfortunately, setting -B appears to override the default search
# path. Thus, the gcc-specific "../includes-fixed" directory is
# now longer searched and glibc's <limits.h> header fails to
# compile, because it uses "#include_next <limits.h>" to find the
# limits.h file in ../includes-fixed. To remedy the problem,
# another -idirafter is necessary to add that directory again.
echo "-B${libc_lib}/lib/ -idirafter ${libc_dev}/include -idirafter ${cc}/lib/gcc/*/*/include-fixed" > $out/nix-support/libc-cflags

echo "-L${libc_lib}/lib" > $out/nix-support/libc-ldflags

echo "${libc_lib}" > $out/nix-support/orig-libc
echo "${libc_dev}" > $out/nix-support/orig-libc-dev

##
## Dynamic linker support
##

if [[ -z ''${dynamicLinker+x} ]]; then
echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2
local dynamicLinker="${libc_lib}/lib/ld*.so.?"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added local to avoid it lasting to the next phase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensured in both builds this made it the right file.

fi

# Expand globs to fill array of options
dynamicLinker=($dynamicLinker)

case ''${#dynamicLinker[@]} in
0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;;
1) echo "Using dynamic linker: '$dynamicLinker'" >&2;;
*) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;;
esac

if [ -n "$dynamicLinker" ]; then
echo $dynamicLinker > $out/nix-support/dynamic-linker

'' + (if targetPlatform.isDarwin then ''
printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook
'' else ''
if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then
echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
fi

local ldflagsBefore=(-dynamic-linker "$dynamicLinker")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added local to avoid it lasting to the next phase, and because it weirdly caused substituteAll problems if I didn't.

Copy link
Member Author

@Ericson2314 Ericson2314 Aug 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensured in finished Linux build that these were still written to the right file.

'') + ''
fi

# 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).
printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before
'')

+ optionalString (!nativeTools) ''

##
## Initial CFLAGS
##

# GCC shows ${cc_solib}/lib in `gcc -print-search-dirs', but not
# ${cc_solib}/lib64 (even though it does actually search there...)..
# This confuses libtool. So add it to the compiler tool search
# path explicitly.
if [ -e "${cc_solib}/lib64" -a ! -L "${cc_solib}/lib64" ]; then
ccLDFlags+=" -L${cc_solib}/lib64"
ccCFlags+=" -B${cc_solib}/lib64"
fi
ccLDFlags+=" -L${cc_solib}/lib"
ccCFlags+=" -B${cc_solib}/lib"

${optionalString cc.langVhdl or false ''
ccLDFlags+=" -L${zlib.out}/lib"
''}

# Find the gcc libraries path (may work only without multilib).
${optionalString cc.langAda or false ''
basePath=`echo ${cc_solib}/lib/*/*/*`
ccCFlags+=" -B$basePath -I$basePath/adainclude"
gnatCFlags="-aI$basePath/adainclude -aO$basePath/adalib"
echo "$gnatCFlags" > $out/nix-support/gnat-cflags
''}

echo "$ccLDFlags" > $out/nix-support/cc-ldflags
echo "$ccCFlags" > $out/nix-support/cc-cflags

##
## User env support
##

# Propagate the wrapped cc so that if you install the wrapper,
# you get tools like gcov, the manpages, etc. as well (including
# for binutils and Glibc).
printWords ${cc} ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages
printWords ${cc.man or ""} > $man/nix-support/propagated-user-env-packages
''

+ ''
substituteAll ${./setup-hook.sh} $out/nix-support/setup-hook.tmp
cat $out/nix-support/setup-hook.tmp >> $out/nix-support/setup-hook
rm $out/nix-support/setup-hook.tmp

##
## Hardening support
##

# some linkers on some platforms don't support specific -z flags
hardening_unsupported_flags=""
export hardening_unsupported_flags=""
if [[ "$($ldPath/${prefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
hardening_unsupported_flags+=" bindnow"
fi
Expand All @@ -345,12 +373,18 @@ stdenv.mkDerivation {
substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh
substituteAll ${./utils.sh} $out/nix-support/utils.sh

##
## Extra custom steps
##

''
+ extraBuildCommands;

inherit dynamicLinker expand-response-params;

expandResponseParams = expand-response-params; # for substitution in utils.sh
# for substitution in utils.sh
expandResponseParams = "${expand-response-params}/bin/expand-response-params";

crossAttrs = {
shell = shell.crossDrv + shell.crossDrv.shellPath;
Expand Down
2 changes: 1 addition & 1 deletion pkgs/build-support/cc-wrapper/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ expandResponseParams() {
if [[ "$arg" == @* ]]; then
# phase separation makes this look useless
# shellcheck disable=SC2157
if [ -n "@expandResponseParams@" ]; then
if [ -x "@expandResponseParams@" ]; then
# params is used by caller
#shellcheck disable=SC2034
readarray -d '' params < <("@expandResponseParams@" "$@")
Expand Down
19 changes: 19 additions & 0 deletions pkgs/build-support/expand-response-params/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{ stdenv }:

stdenv.mkDerivation {
name = "expand-response-params";
src = ./expand-response-params.c;
# Work around "stdenv-darwin-boot-2 is not allowed to refer to path
# /nix/store/...-expand-response-params.c"
unpackPhase = ''
cp "$src" expand-response-params.c
src=$PWD
'';
buildPhase = ''
"$CC" -std=c99 -O3 -o "expand-response-params" expand-response-params.c
'';
installPhase = ''
mkdir -p $prefix/bin
mv expand-response-params $prefix/bin/
'';
}
2 changes: 1 addition & 1 deletion pkgs/stdenv/linux/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ in
# More complicated cases
++ [
glibc.out glibc.dev glibc.bin/*propagated from .dev*/ linuxHeaders
gcc gcc.cc gcc.cc.lib gcc.expandResponseParams
gcc gcc.cc gcc.cc.lib gcc.expand-response-params
]
++ lib.optionals (system == "aarch64-linux")
[ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ];
Expand Down