gcc, libgcc: fix cross-compilation for SH4

- Pass --with-multilib-list=m4,m4-nofpu for SH4 so the kernel can use
  -m4-nofpu. Move libraries out of !m4/ multilib subdirectory in
  postInstall before moveToOutput.
- Generate sysroot-suffix.h for SH4 in the standalone libgcc builder.
- Add linux-kernel.target = "vmlinux" and installTarget for SH4.

All changes scoped to isSh4 to avoid rebuilds on other platforms.
This commit is contained in:
Ben Siraphob 2026-04-19 08:10:43 -07:00
commit 0f420e96c4
4 changed files with 124 additions and 101 deletions

View file

@ -632,6 +632,15 @@ rec {
else if platform.isPower64 then
if platform.isLittleEndian then powernv else ppc64
else if platform.isSh4 then
{
linux-kernel = {
target = "vmlinux";
# SH arch doesn't have a 'make install' target.
installTarget = "vmlinux";
};
}
else
{ };
}

View file

@ -278,106 +278,117 @@ originalAttrs:
makeCompatibilitySymlink lib $targetConfig/lib64
'';
postInstall = ''
# Clean up our compatibility symlinks (see above)
for link in "''${compatibilitySymlinks[@]}"; do
echo "Removing compatibility symlink: $link"
rm -f "$link"
done
# Move target runtime libraries to lib output.
# For non-cross, they're in $out/lib; for cross, they're in $out/$targetConfig/lib.
targetLibDir="''${targetConfig+$targetConfig/}lib"
moveToOutput "$targetLibDir/lib*.so*" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dylib" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dll.a" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dll" "''${!outputLib}"
moveToOutput "share/gcc-*/python" "''${!outputLib}"
if [ -z "$enableShared" ]; then
moveToOutput "$targetLibDir/lib*.a" "''${!outputLib}"
fi
for i in "''${!outputLib}"/$targetLibDir/*.py; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
# Multilib and cross can't exist at the same time, so just use lib64 here
if [ -n "$enableMultilib" ]; then
moveToOutput "lib64/lib*.so*" "''${!outputLib}"
moveToOutput "lib64/lib*.dylib" "''${!outputLib}"
moveToOutput "lib64/lib*.dll.a" "''${!outputLib}"
moveToOutput "lib64/lib*.dll" "''${!outputLib}"
for i in "''${!outputLib}"/lib64/*.py; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
fi
# Remove `fixincl' to prevent a retained dependency on the
# previous gcc.
rm -rf $out/libexec/gcc/*/*/install-tools
rm -rf $out/lib/gcc/*/*/install-tools
# More dependencies with the previous gcc or some libs (gccbug stores the build command line)
rm -rf $out/bin/gccbug
# Remove .la files, they're not adjusted for the makeCompatibilitySymlink magic,
# which confuses libtool and leads to weird linking errors.
# Removing the files just makes libtool link .so files directly, which is usually
# what we want anyway.
find $out -name '*.la' -delete
if type "install_name_tool"; then
for i in "''${!outputLib}"/lib/*.*.dylib "''${!outputLib}"/lib/*.so.[0-9]; do
install_name_tool -id "$i" "$i" || true
for old_path in $(otool -L "$i" | grep "$out" | awk '{print $1}'); do
new_path=`echo "$old_path" | sed "s,$out,''${!outputLib},"`
install_name_tool -change "$old_path" "$new_path" "$i" || true
done
done
fi
# Get rid of some "fixed" header files
rm -rfv $out/lib/gcc/*/*/include-fixed/{root,linux,sys/mount.h,bits/statx.h,pthread.h}
# Replace hard links for i686-pc-linux-gnu-gcc etc. with symlinks.
for i in $out/bin/*-gcc*; do
if cmp -s $out/bin/gcc $i; then
ln -sfn gcc $i
postInstall =
# SH installs libraries into a multilib subdirectory (e.g. lib/!m4/)
# even with --disable-multilib; move them to the expected location.
lib.optionalString stdenv.targetPlatform.isSh4 ''
for _mdir in $out/''${targetConfig+$targetConfig/}lib/!*/; do
if [ -d "$_mdir" ]; then
mv "$_mdir"/* $out/''${targetConfig+$targetConfig/}lib/
rmdir "$_mdir"
fi
done
done
''
+ ''
# Clean up our compatibility symlinks (see above)
for link in "''${compatibilitySymlinks[@]}"; do
echo "Removing compatibility symlink: $link"
rm -f "$link"
done
for i in $out/bin/c++ $out/bin/*-c++* $out/bin/*-g++*; do
if cmp -s $out/bin/g++ $i; then
ln -sfn g++ $i
fi
done
# Move target runtime libraries to lib output.
# For non-cross, they're in $out/lib; for cross, they're in $out/$targetConfig/lib.
targetLibDir="''${targetConfig+$targetConfig/}lib"
# Two identical man pages are shipped (moving and compressing is done later)
for i in "$out"/share/man/man1/*g++.1; do
if test -e "$i"; then
man_prefix=`echo "$i" | sed "s,.*/\(.*\)g++.1,\1,"`
ln -sf "$man_prefix"gcc.1 "$i"
fi
done
''
+ lib.optionalString stdenv.targetPlatform.isCygwin ''
targetBinDir="''${targetConfig+$targetConfig/}bin"
for i in "''${!outputBin}/$targetLibDir"/cyg*.dll; do
mkdir -p "''${!outputLib}/$targetBinDir"
mv "$i" "''${!outputLib}/$targetBinDir"/
done
''
# if cross-compiling, link from $lib/lib to $lib/${targetConfig}.
# since native-compiles have $lib/lib as a directory (not a
# symlink), this ensures that in every case we can assume that
# $lib/lib contains the .so files
+ lib.optionalString isCross ''
if [ -e "$lib/$targetConfig/lib" ]; then
ln -s "$lib/$targetConfig/lib" "$lib/lib"
fi
'';
moveToOutput "$targetLibDir/lib*.so*" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dylib" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dll.a" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dll" "''${!outputLib}"
moveToOutput "share/gcc-*/python" "''${!outputLib}"
if [ -z "$enableShared" ]; then
moveToOutput "$targetLibDir/lib*.a" "''${!outputLib}"
fi
for i in "''${!outputLib}"/$targetLibDir/*.py; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
# Multilib and cross can't exist at the same time, so just use lib64 here
if [ -n "$enableMultilib" ]; then
moveToOutput "lib64/lib*.so*" "''${!outputLib}"
moveToOutput "lib64/lib*.dylib" "''${!outputLib}"
moveToOutput "lib64/lib*.dll.a" "''${!outputLib}"
moveToOutput "lib64/lib*.dll" "''${!outputLib}"
for i in "''${!outputLib}"/lib64/*.py; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
fi
# Remove `fixincl' to prevent a retained dependency on the
# previous gcc.
rm -rf $out/libexec/gcc/*/*/install-tools
rm -rf $out/lib/gcc/*/*/install-tools
# More dependencies with the previous gcc or some libs (gccbug stores the build command line)
rm -rf $out/bin/gccbug
# Remove .la files, they're not adjusted for the makeCompatibilitySymlink magic,
# which confuses libtool and leads to weird linking errors.
# Removing the files just makes libtool link .so files directly, which is usually
# what we want anyway.
find $out -name '*.la' -delete
if type "install_name_tool"; then
for i in "''${!outputLib}"/lib/*.*.dylib "''${!outputLib}"/lib/*.so.[0-9]; do
install_name_tool -id "$i" "$i" || true
for old_path in $(otool -L "$i" | grep "$out" | awk '{print $1}'); do
new_path=`echo "$old_path" | sed "s,$out,''${!outputLib},"`
install_name_tool -change "$old_path" "$new_path" "$i" || true
done
done
fi
# Get rid of some "fixed" header files
rm -rfv $out/lib/gcc/*/*/include-fixed/{root,linux,sys/mount.h,bits/statx.h,pthread.h}
# Replace hard links for i686-pc-linux-gnu-gcc etc. with symlinks.
for i in $out/bin/*-gcc*; do
if cmp -s $out/bin/gcc $i; then
ln -sfn gcc $i
fi
done
for i in $out/bin/c++ $out/bin/*-c++* $out/bin/*-g++*; do
if cmp -s $out/bin/g++ $i; then
ln -sfn g++ $i
fi
done
# Two identical man pages are shipped (moving and compressing is done later)
for i in "$out"/share/man/man1/*g++.1; do
if test -e "$i"; then
man_prefix=`echo "$i" | sed "s,.*/\(.*\)g++.1,\1,"`
ln -sf "$man_prefix"gcc.1 "$i"
fi
done
''
+ lib.optionalString stdenv.targetPlatform.isCygwin ''
targetBinDir="''${targetConfig+$targetConfig/}bin"
for i in "''${!outputBin}/$targetLibDir"/cyg*.dll; do
mkdir -p "''${!outputLib}/$targetBinDir"
mv "$i" "''${!outputLib}/$targetBinDir"/
done
''
# if cross-compiling, link from $lib/lib to $lib/${targetConfig}.
# since native-compiles have $lib/lib as a directory (not a
# symlink), this ensures that in every case we can assume that
# $lib/lib contains the .so files
+ lib.optionalString isCross ''
if [ -e "$lib/$targetConfig/lib" ]; then
ln -s "$lib/$targetConfig/lib" "$lib/lib"
fi
'';
}
))

View file

@ -227,6 +227,9 @@ let
]
else
[ "--disable-multilib" ]
# SH targets need m4 and m4-nofpu variants (the kernel uses -m4-nofpu).
# An empty list disables -m4-nofpu entirely.
++ lib.optional targetPlatform.isSh4 "--with-multilib-list=m4,m4-nofpu"
)
++ lib.optional (!enableShared) "--disable-shared"
++ lib.singleton (lib.enableFeature enablePlugin "plugin")

View file

@ -94,7 +94,7 @@ stdenv.mkDerivation (finalAttrs: {
options.h \
insn-constants.h \
''
+ lib.optionalString stdenv.targetPlatform.isM68k ''
+ lib.optionalString (stdenv.targetPlatform.isM68k || stdenv.targetPlatform.isSh4) ''
sysroot-suffix.h \
''
+ lib.optionalString stdenv.targetPlatform.isAarch32 ''