I'm curious as to why FreeBSD doesn't work with multilib toolchains. As I recall, 32bit applications need to be run in a 32bit chroot.
I'm wondering why this hasn't been fixed. On ArchBSD, we can use -m32 and even use it with C++11 support using gcc 4.8.0. Should ports have this enabled by default on amd64 systems?
I know that most of the issues caused by multilib on FreeBSD was due to the includes/machine directory.
We worked around this by having machine/64 and machine/32 and using a wrapper to gcc, that would including from each directory depending on if -m32 was passed or not.
I'm posting this because I was reading the Wine page, and it still states that Wine needs to be run in a 32 bit chroot, but this problem is pretty easily overcome, and it would be highly beneficial to be able to use -m32 on FreeBSD amd64.
So I'm just curious on your thoughts about this, or why multilib support isn't enabled by default in base or ports.
Anyways, here are the documented steps took to get -m32 working in FreeBSD.
EDUCATIONAL PURPOSE ONLY!
Create the wrappers.
You'll want to build lib32 also:
That's the initial setup. You'll need to compile a multlilib gcc now.
You'll need to pull in gcc 4.8 source code, extract and
Set up the 32 bit headers for the gcc build:
Next you need to dump and patch the specs file.
Here is the specs.diff
We'll export some stuff to make sure our compiler uses the specs file:
and
Hopefully all builds well and you can install to /usr/local
After all is done, you should now be able to compile applications with -m32.
Test results:
Credits go to Blub for getting the initial steps working. Now compiling with -32 compiles and links correctly as seen above. This post was for educational purpose only, and not recommended unless you know what you're doing.
I'm wondering why this hasn't been fixed. On ArchBSD, we can use -m32 and even use it with C++11 support using gcc 4.8.0. Should ports have this enabled by default on amd64 systems?
I know that most of the issues caused by multilib on FreeBSD was due to the includes/machine directory.
We worked around this by having machine/64 and machine/32 and using a wrapper to gcc, that would including from each directory depending on if -m32 was passed or not.
I'm posting this because I was reading the Wine page, and it still states that Wine needs to be run in a 32 bit chroot, but this problem is pretty easily overcome, and it would be highly beneficial to be able to use -m32 on FreeBSD amd64.
So I'm just curious on your thoughts about this, or why multilib support isn't enabled by default in base or ports.
Anyways, here are the documented steps took to get -m32 working in FreeBSD.
EDUCATIONAL PURPOSE ONLY!
Code:
# Move machine headers to a 64/ directory and create wrappers
mv "$srcdir"/machine64 "$pkgdir"/usr/include/machine/64
# Install 32 bit machine headers to /usr/include/machine/32
cp -R "/usr/src/freebsd/sys/i386/include /usr/include/machine/32
Create the wrappers.
Code:
cd /usr/include/machine/
for i in 64/pc/*; do
b=${i#64/pc/}
cat > "pc/$b" <<EOF
#if __x86_64
# include <machine/64/pc/$b>
#else
# include <machine/32/pc/$b>
#endif
EOF
done
for i in 64/*; do
b=${i#64/}
if [ "$b" = "pc" ]; then continue; fi
if [ -e "32/$b" ]; then
cat > "$b" <<EOF
#if __x86_64
# include <machine/64/$b>
#else
# include <machine/32/$b>
#endif
EOF
else
cat > "$b" <<EOF
#if __x86_64
# include <machine/64/$b>
#else
# error "No such 32-bit include: <machine/32/$b>"
#endif
EOF
fi
done
for i in 32/*; do
if [ "$b" = "pc" ]; then continue; fi
b=${i#32/}
if [ ! -e "$b" ]; then
cat > "$b" <<EOF
#if __x86_64
# error "No such 64-bit include: <machine/64/$b>"
#else
# include <machine/32/$b>
#endif
EOF
fi
done
You'll want to build lib32 also:
Code:
cd /usr/src
make build32 install32 DESTDIR=/usr/lib32
That's the initial setup. You'll need to compile a multlilib gcc now.
You'll need to pull in gcc 4.8 source code, extract and
cd
into the directory.Set up the 32 bit headers for the gcc build:
Code:
mkdir include32
mkdir include32/machine
for i in /usr/src/sys/i386/include/*; do
ln -svf "$i" "include32/machine/$(basename "$i")"
done
Next you need to dump and patch the specs file.
Code:
gcc -dumpspecs > specs
patch -p1 -i specs.diff
Here is the specs.diff
Code:
--- a/specs 2013-07-11 17:40:39.532971335 +0200
+++ b/specs 2013-07-11 17:40:22.891970908 +0200
@@ -77,22 +77,22 @@ cc1 -E %{traditional|traditional-cpp:-tr
4.8.0
*multilib:
-. ;
+. !m64 !m32;64:../lib m64 !m32;32:../lib32 !m64 m32;
*multilib_defaults:
-
+m64
*multilib_extra:
*multilib_matches:
-
+m64 m64;m32 m32;
*multilib_exclusions:
*multilib_options:
-
+m64/m32
*multilib_reuse:
We'll export some stuff to make sure our compiler uses the specs file:
Code:
export CC="gcc -specs=$srcdir/specs"
export CXX="g++ -specs=$srcdir/specs"
export CPP=cpp
export _CHOST_=amd64-unknown-freebsd9.2
export _gccver=4.8.0
and
configure
and make
the new gcc.
Code:
../gcc-4.8.0/libstdc++-v3/configure \
--cache-file=./config.cache \
--prefix=/usr/local \
--build=${_CHOST_} --host=${_CHOST_} --target=${_CHOST_} \
--with-bugurl='https://bugs.archbsd.net/' \
--disable-nls \
--with-as=/usr/local/bin/as \
--with-gmp=/usr/local \
--with-ld=/usr/bin/ld \
--with-libiconv-prefix=/usr/local \
--with-pkgversion='ArchBSD Package Collection' \
--with-system-zlib \
--enable-cloog-backend=isl \
--disable-cloog-version-check \
--enable-multilib \
--enable-languages=c,c++,fortran,lto,objc \
--program-transform-name=s,y,y, \
--with-target-subdir=${_CHOST_} \
--srcdir=../gcc-4.8.0/libstdc++-v3 \
--with-build-libsubdir=.
Hopefully all builds well and you can install to /usr/local
Code:
gmake DESTDIR="temp-install-dir" install
mv "temp-install-dir/usr/lib32" "${pkgdir}/usr"
install -dm755 "/usr/local/include/c++/${_gccver}/${_CHOST_}"
mv "temp-install-dir/usr/local/include/c++/${_gccver}/${_CHOST_}/32" \
"/usr/local/include/c++/${_gccver}/${_CHOST_}/32"
rm -r "temp-install-dir"
cd "$srcdir"
# specs file
install -dm755 "/usr/local/lib/gcc/x86_64-unknown-freebsd9.2/${_gccver}"
install -m644 specs "/usr/local/lib/gcc/x86_64-unknown-freebsd9.2/${_gccver}/specs"
After all is done, you should now be able to compile applications with -m32.
Test results:
Code:
[amzo@Bahamut ~]$ gcc test.c -o test.64
[amzo@Bahamut ~]$ ./test.64
Long int size is 8 bytes long!
[amzo@Bahamut ~]$ gcc -m32 test.c -o test.32
[amzo@Bahamut ~]$ ./test.32
Long int size is 4 bytes long!
Code:
#include <stdio.h>
int main(){
long z; printf("Long int size is %i bytes long!\n", sizeof(z)); return 0;
}
Code:
[amzo@Bahamut ~]$ ldd test.32
test.32:
libc.so.7 => /usr/lib32/libc.so.7 (0x28069000)
[amzo@Bahamut ~]$ ldd test.64
test.64:
libc.so.7 => /lib/libc.so.7 (0x80081c000)
Credits go to Blub for getting the initial steps working. Now compiling with -32 compiles and links correctly as seen above. This post was for educational purpose only, and not recommended unless you know what you're doing.