Skip to content

Commit ada4230

Browse files
committed
[POST] Added instructions for cross-compiling binutils for Windows
1 parent d8d77f5 commit ada4230

File tree

1 file changed

+262
-0
lines changed

1 file changed

+262
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
---
2+
layout: posts
3+
title: Building GCC / GNU Toolchain for Windows
4+
author: James Walmsley
5+
author_email: [email protected]
6+
category: misc
7+
---
8+
9+
I've been trying to sucessfully compile GCC for Windows to allow me to maintain a Windows version of the BTDK
10+
(BitThunder development kit). Well the documentation on the internet describing how to do this is thin and far between.
11+
The good news is that I've finally managed to create one.
12+
13+
# Strategies
14+
Most guides talk about setting up MSYS and MinGW or cygwin or some other native Windows build environment. I explicitly do NOT
15+
recommend this approach. Its extremely slow and tedious, you will simply waste months of your life!
16+
17+
The approach I eventually settled for is to cross-compile for Windows on Linux (Ubuntu 14.10). To do this I use the excellent MXE
18+
cross compile environment.
19+
20+
The build involves the following steps:
21+
22+
1. Clone and build MXE.
23+
2. Configure build environment.
24+
3. Clone and build binutils-gdb
25+
4. Download and build libgmp (4.3.2)
26+
5. Download and build libmpfr (2.4.2)
27+
6. Download and build libmpc (0.8.1)
28+
7. Clone and build gcc (stage 1).
29+
8. Clone and build newlib.
30+
9. Clone build gcc (final stage).
31+
32+
## 1. Get and Install MXE
33+
34+
{% highlight bash %}
35+
git clone git://github.com/mxe/mxe.git
36+
cd mxe
37+
git checkout stable
38+
make
39+
{% endhighlight %}
40+
41+
Now wait for a really long time... You don't actually need the whole environment to be built, but it will come in useful.
42+
43+
## 2. Build Variables & Environment
44+
45+
PATH : Path must include the mxe binary path:
46+
{% highlight bash %}
47+
export PATH=/path/to/mxe/usr/bin:$PATH
48+
{% endhighlight %}
49+
50+
TARGET : This is the target type, e.g. arm-unknown-eabi or arm-eabi-bt
51+
PREFIX : Where the toolchain will reside on the system. E.g. /opt/btdk
52+
HOST : The type of system that will host the compiler (Windows in our case).
53+
BUILD : The type of system that is being used to build the toolchain.
54+
PKGVERSION : A toolchain package name/version.
55+
56+
BTDK uses the following defaults:
57+
58+
{% highlight bash %}
59+
export TARGET=arm-unknown-eabi
60+
export PREFIX=/opt/mytoolchain
61+
export HOST=i686-pc-mingw32
62+
export BUILD="$(config.guess)"
63+
export PKGVERSION="mytoolchain v1.0.0"
64+
{% endhighlight %}
65+
66+
## 3. Building Binutils (ld gas nm gdb etc)
67+
68+
{% highlight bash %}
69+
git clone git://sourceware.org/git/binutils-gdb.git
70+
mkdir build-binutils
71+
cd build-binutils
72+
../binutils-gdb/configure --host=${HOST} --build=${BUILD} --target=${TARGET} \
73+
--prefix=${PREFIX} --enable-interwork --enable-multilib \
74+
--enable-target-optspace --with-float=soft --disable-werror \
75+
--with-pkgversion=${PKGVERSION}
76+
make
77+
sudo make install
78+
{% endhighlight %}
79+
80+
### Patch / Fix for Binutils
81+
Currently the build tree contains a fix for compiling for windows, but MXE is good enough not to need it.
82+
If the build complains something like:
83+
84+
{% highlight bash %}
85+
mxe/usr/lib/gcc/i686-pc-mingw32/4.8.1/../../../../i686-pc-mingw32/lib/libncurses.a(lib_tputs.o):lib_tputs.c:(.text+0x780): multiple definition of `tputs'
86+
windows-termcap.o:mytoolchain/binutils-gdb/gdb/windows-termcap.c:62: first defined here
87+
{% endhighlight %}
88+
89+
The simply open the file gdb/windows-termcap.c
90+
91+
Comment out the tputs() function, or apply the following patch:
92+
93+
{% highlight bash %}
94+
diff --git a/gdb/windows-termcap.c b/gdb/windows-termcap.c
95+
index 7c258cf..e7d5fa3 100644
96+
--- a/gdb/windows-termcap.c
97+
+++ b/gdb/windows-termcap.c
98+
@@ -57,14 +57,14 @@ tgetstr (char *name, char **area)
99+
return NULL;
100+
}
101+
102+
-int
103+
+/*int
104+
tputs (char *string, int nlines, int (*outfun) ())
105+
{
106+
while (*string)
107+
outfun (*string++);
108+
109+
return 0;
110+
-}
111+
+}*/
112+
113+
char *
114+
tgoto (const char *cap, int col, int row)
115+
{% endhighlight %}
116+
117+
You can apply it by saving it into a .patch file and ...
118+
119+
{% highlight bash %}
120+
cd ../binutils-gdb
121+
git apply binutils.patch
122+
cd ../build-binutils
123+
make
124+
sudo make install
125+
{% endhighlight %}
126+
127+
There's also a problem with the install target, of binutils it cannot find the ranlib tool for some reason. You can fix this with the following patch:
128+
129+
{% highlight bash %}
130+
# Obviously adjust the path to your actual mxe ranlib binary :D
131+
sed -i 's:i686-pc-mingw32-ranlib:/home/wl/develop/tools/mxe/usr/bin/i686-pc-mingw32-ranlib:g' Makefile sim/Makefile sim/arm/Makefile
132+
sudo make install
133+
{% endhighlight %}
134+
135+
You should now have a full gdb and binutils for windows:
136+
137+
{% highlight bash %}
138+
tree ${PREFIX}/bin/
139+
/opt/mytoolchain/bin/
140+
├── arm-unknown-eabi-addr2line.exe
141+
├── arm-unknown-eabi-ar.exe
142+
├── arm-unknown-eabi-as.exe
143+
├── arm-unknown-eabi-c++filt.exe
144+
├── arm-unknown-eabi-elfedit.exe
145+
├── arm-unknown-eabi-gdb.exe
146+
├── arm-unknown-eabi-gprof.exe
147+
├── arm-unknown-eabi-ld.bfd.exe
148+
├── arm-unknown-eabi-ld.exe
149+
├── arm-unknown-eabi-nm.exe
150+
├── arm-unknown-eabi-objcopy.exe
151+
├── arm-unknown-eabi-objdump.exe
152+
├── arm-unknown-eabi-ranlib.exe
153+
├── arm-unknown-eabi-readelf.exe
154+
├── arm-unknown-eabi-run.exe
155+
├── arm-unknown-eabi-size.exe
156+
├── arm-unknown-eabi-strings.exe
157+
└── arm-unknown-eabi-strip.exe
158+
159+
0 directories, 18 files
160+
{% endhighlight %}
161+
162+
## 4. Build libgmp
163+
Yup building these libraries is boring, but its probably the safest option in the long run
164+
(trust me I wasted hours of my life trying to make this all link with pre-compiled versions in mingw32, mxe is probably better
165+
but lets just use my working method :D )
166+
167+
{% highlight bash %}
168+
wget https://gmplib.org/download/gmp/gmp-4.3.2.tar.bz2
169+
tar xvf gmp-4.3.2.tar.bz2
170+
mkdir build-gmp
171+
cd build-gmp
172+
../gmp-4.3.2/configure --host=${HOST} --build=${BUILD} --prefix=$(pwd)/../libgmp \
173+
--disable-shared --enable-static --without-readline --enable-cxx
174+
make
175+
# We install into ../libgmp/ so we don't need sudo.
176+
make install
177+
{% endhighlight %}
178+
179+
## 5. Build libmpfr
180+
181+
{% highlight bash %}
182+
wget https://ftp.gnu.org/gnu/mpfr/mpfr-2.4.2.tar.bz2
183+
tar xvf mpfr-2.4.2.tar.bz2
184+
mkdir build-mpfr
185+
cd build-mpfr
186+
../mpfr-2.4.2/configure --host=${HOST} --build=${BUILD} --prefix=$(pwd)/../libmpfr \
187+
--with-gmp=$(pwd)/../libgmp --disable-shared --enable-static
188+
make
189+
make check
190+
make install
191+
{% endhighlight %}
192+
193+
## 6. Build libmpc
194+
{% highlight bash %}
195+
wget http://www.multiprecision.org/mpc/download/mpc-0.8.1.tar.gz
196+
tar xvf mpc-0.8.1.tar.gz
197+
mkdir build-mpc
198+
cd build-mpc
199+
../mpc-0.8.1/configure --host=${HOST} --build=${BUILD} --prefix=$(pwd)/../libmpc \
200+
--with-gmp=$(pwd)/../libgmp --with-mpfr=$(pwd)/../libmpfr \
201+
--disable-shared --enable-static
202+
make
203+
make install
204+
{% endhighlight %}
205+
206+
## 7. Build GCC - Stage 1
207+
208+
Building GCC for Windows is the most complex part of this cross-compile.
209+
210+
{% highlight bash %}
211+
git clone git://gcc.gnu.org/git/gcc.git
212+
cd gcc
213+
git checkout gcc-4_9_0-release
214+
mkdir build-gcc
215+
cd build-gcc
216+
../gcc/configure --host=${HOST} --build=${BUILD} --target=${TARGET} --prefix=${PREFIX} \
217+
--enable-interwork --enable-multilib --enable-languages="c" \
218+
--with-newlib --without-headers --disable-shared --disable-libssp \
219+
--with-gnu-as --with-gnu-ld --disable-nls \
220+
--with-pkgversion=${PKGVERSION} --with-gmp=$(pwd)/../libgmp \
221+
--with-mpfr=$(pwd)/../libmpfr --with-mpc=$(pwd)/../libmpc
222+
make all-gcc
223+
sudo make install-gcc
224+
#make all-target-libgcc # Cannot build using the Windows compiler in Wine on linux.
225+
#sudo make install-target-libgcc # Solution is to copy the libraries produced when building the toolchain for linux.
226+
{% endhighlight %}
227+
228+
You'll find that at this point building libgcc and libstdc++ etc will actually fail. I finally realised that actually it doesn't matter
229+
from this point on. You don't actually need to compile anything further with the Windows toolchain at this point.
230+
231+
Simply use the libraries as compiled by your native linux cross compiler, and copy them into your windows cross-compiler appropriately.
232+
233+
### Fixes or Patches for GCC 4.9.0
234+
235+
Currently you'll probably get a cannot find arm-unknown-eabi-gcc error when the build system attempts to dump the compiler
236+
specs. To work around this, you can apply the following patch:
237+
238+
{% highlight bash %}
239+
sed -i 's:$(GCC_FOR_TARGET) -dumpspecs > tmp-specs:./xgcc$(exeext) -dumpspecs > tmp-specs:g' gcc/Makefile
240+
make all-gcc
241+
sudo make install-gcc
242+
make all-target-libgcc
243+
sudo make install-target-libgcc
244+
{% endhighlight %}
245+
246+
At this stage you should have a working cross-compiler. As long as you don't use any standard libraries at all, then you can
247+
build a working kernel. In fact you should be able to use such a compiler to build BitThunder.
248+
249+
You can even use this compiler to build your own libc and then manually link with it.
250+
251+
For most purposes a basic libc is useful, and its really convenient to use e.g. the BTDK which uses a ported version of
252+
newlib to provide a complete libc implementation on top of bitthunder.
253+
254+
## 8. Build Newlib
255+
256+
Again the secret is to simply copy the libraries produced by linux to the Windows toolchain folders.
257+
258+
## 9. Finalise GCC.
259+
260+
Not 100% sure what this stage does. I think it creates a arm-eabi-bt/bin/gcc.exe etc. In anycase I don't think they are needed,
261+
and you can always copy the bin/arm-eabi-bt-gcc.exe files to the appropriate place manually.
262+

0 commit comments

Comments
 (0)