| 1 | #!/bin/bash |
|---|
| 2 | # This is my script for building a complete MinGW cross-compiler toolchain |
|---|
| 3 | # that runs under Linux to produce executables that run under Windows. It |
|---|
| 4 | # probably works (or can easily be adapted to work) under any unix system. |
|---|
| 5 | # |
|---|
| 6 | # It is based in large part on Sam Lantinga's script, which in turn was |
|---|
| 7 | # based partly on Ray Kelm's script, which in turn was built on |
|---|
| 8 | # Mo Dejong's script for doing the same, but with some added fixes. |
|---|
| 9 | # |
|---|
| 10 | # My changes: |
|---|
| 11 | # 1. Adapted the script to the new packaging of MinGW GCC, which is |
|---|
| 12 | # currently split into core and auxiliary components. |
|---|
| 13 | # 2. The script now determines the GCC and BINUTILS directory name |
|---|
| 14 | # directly from the tar file contents. This gets around common |
|---|
| 15 | # problems due to the directory names not always following the |
|---|
| 16 | # expected patterns. |
|---|
| 17 | # 3. Grouped together and simplified the macros that users need to |
|---|
| 18 | # define. |
|---|
| 19 | # 4. Made optional components truly optional -- leave the |
|---|
| 20 | # corresponding archive names blank and they will be ignored. |
|---|
| 21 | # 5. Included an option to purge the installation directory before |
|---|
| 22 | # installing the current cross-compiler. |
|---|
| 23 | # |
|---|
| 24 | # NOTE: If you choose a destination directory for the installation (set |
|---|
| 25 | # in the macro PREFIX) for which you do not have write access, you will |
|---|
| 26 | # need to run this script with root (or equivalent) privileges. |
|---|
| 27 | # |
|---|
| 28 | # |
|---|
| 29 | # Updated by Igor Mikolic-Torreira <igormt@alumni.caltech.edu> |
|---|
| 30 | |
|---|
| 31 | #----------------------------------------------------- |
|---|
| 32 | # |
|---|
| 33 | # BEGIN USER SETTINGS |
|---|
| 34 | # |
|---|
| 35 | # You need to review and adjust the macros that follow |
|---|
| 36 | # |
|---|
| 37 | #----------------------------------------------------- |
|---|
| 38 | |
|---|
| 39 | # What flavor of GCC cross-compiler are we building? |
|---|
| 40 | |
|---|
| 41 | TARGET=mingw32 |
|---|
| 42 | |
|---|
| 43 | # What directory will the cross-compiler be built in? |
|---|
| 44 | # This is the directory into which source archives will |
|---|
| 45 | # be downloaded, expanded, compiled, etc. You need to |
|---|
| 46 | # have write-access to this directory. If you leave it |
|---|
| 47 | # blank, it defaults to the current directory. |
|---|
| 48 | |
|---|
| 49 | BUILDDIR=$(pwd)/build |
|---|
| 50 | |
|---|
| 51 | # Where does the cross-compiler go? |
|---|
| 52 | # This should be the directory into which your cross-compiler |
|---|
| 53 | # will be installed. Remember that if you set this to a directory |
|---|
| 54 | # that only root has write access to, you will need to run this |
|---|
| 55 | # script as root. |
|---|
| 56 | |
|---|
| 57 | PREFIX=$(pwd)/xcomp |
|---|
| 58 | |
|---|
| 59 | # Purge anything and everything already in the $PREFIX |
|---|
| 60 | #(also known as the destination or installation) directory? |
|---|
| 61 | # Set to "Y" to purge, any other value omits the purge step. |
|---|
| 62 | |
|---|
| 63 | PURGE_DIR="Y" |
|---|
| 64 | |
|---|
| 65 | |
|---|
| 66 | # Set the following to the files from the current MinGW release |
|---|
| 67 | # (or whichever MinGW release you wish to build and install) |
|---|
| 68 | # You need to set both the URL they will be downloaded from |
|---|
| 69 | # and the exact name of the individual component files. |
|---|
| 70 | |
|---|
| 71 | MINGW_URL="http://heanet.dl.sourceforge.net/sourceforge/mingw" |
|---|
| 72 | |
|---|
| 73 | # GCC_CORE is required; the other components are optional. |
|---|
| 74 | # Set any you don't want to "". You need binutils, |
|---|
| 75 | # mingw runtime and w32api; do not ever set those to "". |
|---|
| 76 | |
|---|
| 77 | GCC_CORE_ARCHIVE="gcc-core-3.4.2-20040916-1-src.tar.gz" |
|---|
| 78 | GCC_GPP_ARCHIVE="gcc-g++-3.4.2-20040916-1-src.tar.gz" |
|---|
| 79 | GCC_G77_ARCHIVE="gcc-g77-3.4.2-20040916-1-src.tar.gz" |
|---|
| 80 | GCC_OBJC_ARCHIVE="gcc-objc-3.4.2-20040916-1-src.tar.gz" |
|---|
| 81 | GCC_JAVA_ARCHIVE="gcc-java-3.4.2-20040916-1-src.tar.gz" |
|---|
| 82 | GCC_ADA_ARCHIVE="" |
|---|
| 83 | GCC_PATCH="" |
|---|
| 84 | |
|---|
| 85 | BINUTILS_ARCHIVE="binutils-2.15.91-20040904-1-src.tar.gz" |
|---|
| 86 | |
|---|
| 87 | MINGW_ARCHIVE="mingw-runtime-3.7.tar.gz" |
|---|
| 88 | |
|---|
| 89 | W32API_ARCHIVE="w32api-3.2.tar.gz" |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | # These are the files from the SDL website |
|---|
| 93 | # These are optional, set them to "" if you don't want them) |
|---|
| 94 | |
|---|
| 95 | SDL_URL="http://www.libsdl.org/extras/win32/common" |
|---|
| 96 | |
|---|
| 97 | OPENGL_ARCHIVE="opengl-devel.tar.gz" |
|---|
| 98 | DIRECTX_ARCHIVE="directx-devel.tar.gz" |
|---|
| 99 | |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | #----------------------------------------------------- |
|---|
| 103 | # |
|---|
| 104 | # END USER SETTINGS |
|---|
| 105 | # |
|---|
| 106 | # The remainder of the script should not neet any edits |
|---|
| 107 | # |
|---|
| 108 | #----------------------------------------------------- |
|---|
| 109 | |
|---|
| 110 | |
|---|
| 111 | |
|---|
| 112 | # Make sure these are initialized as we want them |
|---|
| 113 | |
|---|
| 114 | GCC_CORE="" |
|---|
| 115 | BINUTILS="" |
|---|
| 116 | GCC_LANGS="c" |
|---|
| 117 | MAKE="make" |
|---|
| 118 | |
|---|
| 119 | |
|---|
| 120 | # Set our build directory and where our sources will go |
|---|
| 121 | |
|---|
| 122 | if [ "x$BUILDDIR" = "x" ]; then |
|---|
| 123 | # Default to the current directory |
|---|
| 124 | BUILDDIR=$(pwd) |
|---|
| 125 | fi |
|---|
| 126 | SRCDIR="$BUILDDIR/source" |
|---|
| 127 | |
|---|
| 128 | |
|---|
| 129 | # Need install directory first on the path so gcc can find binutils |
|---|
| 130 | |
|---|
| 131 | PATH="$PREFIX/bin:$PATH" |
|---|
| 132 | |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | #----------------------------------------------------- |
|---|
| 136 | # |
|---|
| 137 | # Functions that do most of the work |
|---|
| 138 | # |
|---|
| 139 | #----------------------------------------------------- |
|---|
| 140 | |
|---|
| 141 | |
|---|
| 142 | function download_files |
|---|
| 143 | { |
|---|
| 144 | # Download a file from a given url, only if it is not present |
|---|
| 145 | mkdir -p "$SRCDIR" |
|---|
| 146 | |
|---|
| 147 | # Make sure wget is installed |
|---|
| 148 | if test "x`which wget`" = "x" ; then |
|---|
| 149 | echo "You need to install wget." |
|---|
| 150 | exit 1 |
|---|
| 151 | fi |
|---|
| 152 | download_file "$GCC_CORE_ARCHIVE" "$MINGW_URL" |
|---|
| 153 | if [ "x$GCC_GPP_ARCHIVE" != "x" ]; then |
|---|
| 154 | download_file "$GCC_GPP_ARCHIVE" "$MINGW_URL" |
|---|
| 155 | fi |
|---|
| 156 | if [ "x$GCC_G77_ARCHIVE" != "x" ]; then |
|---|
| 157 | download_file "$GCC_G77_ARCHIVE" "$MINGW_URL" |
|---|
| 158 | fi |
|---|
| 159 | if [ "x$GCC_OBJC_ARCHIVE" != "x" ]; then |
|---|
| 160 | download_file "$GCC_OBJC_ARCHIVE" "$MINGW_URL" |
|---|
| 161 | fi |
|---|
| 162 | if [ "x$GCC_JAVA_ARCHIVE" != "x" ]; then |
|---|
| 163 | download_file "$GCC_JAVA_ARCHIVE" "$MINGW_URL" |
|---|
| 164 | fi |
|---|
| 165 | if [ "x$GCC_ADA_ARCHIVE" != "x" ]; then |
|---|
| 166 | download_file "$GCC_ADA_ARCHIVE" "$MINGW_URL" |
|---|
| 167 | fi |
|---|
| 168 | |
|---|
| 169 | download_file "$BINUTILS_ARCHIVE" "$MINGW_URL" |
|---|
| 170 | download_file "$MINGW_ARCHIVE" "$MINGW_URL" |
|---|
| 171 | download_file "$W32API_ARCHIVE" "$MINGW_URL" |
|---|
| 172 | |
|---|
| 173 | if [ "x$OPENGL_ARCHIVE" != "x" ]; then |
|---|
| 174 | download_file "$OPENGL_ARCHIVE" "$SDL_URL" |
|---|
| 175 | fi |
|---|
| 176 | if [ "x$DIRECTX_ARCHIVE" != "x" ]; then |
|---|
| 177 | download_file "$DIRECTX_ARCHIVE" "$SDL_URL" |
|---|
| 178 | fi |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | |
|---|
| 182 | function download_file |
|---|
| 183 | { |
|---|
| 184 | cd "$SRCDIR" |
|---|
| 185 | if test ! -f $1 ; then |
|---|
| 186 | echo "Downloading $1" |
|---|
| 187 | wget "$2/$1" |
|---|
| 188 | if test ! -f $1 ; then |
|---|
| 189 | echo "Could not download $1" |
|---|
| 190 | exit 1 |
|---|
| 191 | fi |
|---|
| 192 | else |
|---|
| 193 | echo "Found $1 in the srcdir $SRCDIR" |
|---|
| 194 | fi |
|---|
| 195 | cd "$BUILDDIR" |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | function purge_existing_install |
|---|
| 200 | { |
|---|
| 201 | echo "Purging the existing files in $PREFIX" |
|---|
| 202 | if cd "$PREFIX"; then |
|---|
| 203 | rm -rf * |
|---|
| 204 | fi |
|---|
| 205 | cd "$BUILDDIR" |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | |
|---|
| 209 | function install_libs |
|---|
| 210 | { |
|---|
| 211 | echo "Installing cross libs and includes" |
|---|
| 212 | mkdir -p "$PREFIX/$TARGET" |
|---|
| 213 | cd "$PREFIX/$TARGET" |
|---|
| 214 | |
|---|
| 215 | tar -xzf "$SRCDIR/$MINGW_ARCHIVE" |
|---|
| 216 | tar -xzf "$SRCDIR/$W32API_ARCHIVE" |
|---|
| 217 | |
|---|
| 218 | if [ "x$OPENGL_ARCHIVE" != "x" ]; then |
|---|
| 219 | tar -xzf "$SRCDIR/$OPENGL_ARCHIVE" |
|---|
| 220 | fi |
|---|
| 221 | |
|---|
| 222 | if [ "x$DIRECTX_ARCHIVE" != "x" ]; then |
|---|
| 223 | tar -xzf "$SRCDIR/$DIRECTX_ARCHIVE" |
|---|
| 224 | fi |
|---|
| 225 | |
|---|
| 226 | cd "$BUILDDIR" |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | |
|---|
| 230 | function extract_binutils |
|---|
| 231 | { |
|---|
| 232 | cd "$SRCDIR" |
|---|
| 233 | BINUTILS=`tar -tzf "$SRCDIR/$BINUTILS_ARCHIVE" | head -n 1` |
|---|
| 234 | rm -rf "$BINUTILS" |
|---|
| 235 | echo "Extracting binutils" |
|---|
| 236 | tar -xzf "$SRCDIR/$BINUTILS_ARCHIVE" |
|---|
| 237 | cd "$BUILDDIR" |
|---|
| 238 | } |
|---|
| 239 | |
|---|
| 240 | |
|---|
| 241 | function configure_binutils |
|---|
| 242 | { |
|---|
| 243 | cd "$BUILDDIR" |
|---|
| 244 | rm -rf "binutils-$TARGET" |
|---|
| 245 | mkdir "binutils-$TARGET" |
|---|
| 246 | cd "binutils-$TARGET" |
|---|
| 247 | echo "Configuring binutils" |
|---|
| 248 | "$SRCDIR/$BINUTILS/configure" --prefix="$PREFIX" --target=$TARGET --disable-nls \ |
|---|
| 249 | --with-gcc --with-gnu-as --with-gnu-ld --disable-shared &> configure.log |
|---|
| 250 | cd "$BUILDDIR" |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | |
|---|
| 254 | function build_binutils |
|---|
| 255 | { |
|---|
| 256 | cd "$BUILDDIR/binutils-$TARGET" |
|---|
| 257 | echo "Building binutils" |
|---|
| 258 | $MAKE CFLAGS="-O2 -fno-exceptions" LDFLAGS="-s" &> make.log |
|---|
| 259 | if test $? -ne 0; then |
|---|
| 260 | echo "make of binutils failed - log available: binutils-$TARGET/make.log" |
|---|
| 261 | exit 1 |
|---|
| 262 | fi |
|---|
| 263 | cd "$BUILDDIR" |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | |
|---|
| 267 | function install_binutils |
|---|
| 268 | { |
|---|
| 269 | cd "$BUILDDIR/binutils-$TARGET" |
|---|
| 270 | echo "Installing binutils" |
|---|
| 271 | $MAKE install &> make-install.log |
|---|
| 272 | if test $? -ne 0; then |
|---|
| 273 | echo "install of binutils failed - log available: binutils-$TARGET/make-install.log" |
|---|
| 274 | exit 1 |
|---|
| 275 | fi |
|---|
| 276 | cd "$BUILDDIR" |
|---|
| 277 | } |
|---|
| 278 | |
|---|
| 279 | |
|---|
| 280 | function extract_gcc |
|---|
| 281 | { |
|---|
| 282 | cd "$SRCDIR" |
|---|
| 283 | GCC=`tar -tzf "$SRCDIR/$GCC_CORE_ARCHIVE" | head -n 1` |
|---|
| 284 | rm -rf "$GCC" |
|---|
| 285 | echo "Extracting gcc" |
|---|
| 286 | tar -xzf "$SRCDIR/$GCC_CORE_ARCHIVE" |
|---|
| 287 | if [ "x$GCC_GPP_ARCHIVE" != "x" ]; then |
|---|
| 288 | GCC_LANGS=${GCC_LANGS}",c++" |
|---|
| 289 | tar -xzf "$SRCDIR/$GCC_GPP_ARCHIVE" |
|---|
| 290 | fi |
|---|
| 291 | if [ "x$GCC_G77_ARCHIVE" != "x" ]; then |
|---|
| 292 | GCC_LANGS=${GCC_LANGS}",f77" |
|---|
| 293 | tar -xzf "$SRCDIR/$GCC_G77_ARCHIVE" |
|---|
| 294 | fi |
|---|
| 295 | if [ "x$GCC_OBJC_ARCHIVE" != "x" ]; then |
|---|
| 296 | GCC_LANGS=${GCC_LANGS}",objc" |
|---|
| 297 | tar -xzf "$SRCDIR/$GCC_OBJC_ARCHIVE" |
|---|
| 298 | fi |
|---|
| 299 | if [ "x$GCC_JAVA_ARCHIVE" != "x" ]; then |
|---|
| 300 | GCC_LANGS=${GCC_LANGS}",java" |
|---|
| 301 | tar -xzf "$SRCDIR/$GCC_JAVA_ARCHIVE" |
|---|
| 302 | fi |
|---|
| 303 | if [ "x$GCC_ADA_ARCHIVE" != "x" ]; then |
|---|
| 304 | GCC_LANGS=${GCC_LANGS}",ada" |
|---|
| 305 | tar -xzf "$SRCDIR/$GCC_ADA_ARCHIVE" |
|---|
| 306 | fi |
|---|
| 307 | cd "$BUILDDIR" |
|---|
| 308 | } |
|---|
| 309 | |
|---|
| 310 | |
|---|
| 311 | function patch_gcc |
|---|
| 312 | { |
|---|
| 313 | if [ "$GCC_PATCH" != "" ]; then |
|---|
| 314 | echo "Patching gcc" |
|---|
| 315 | cd "$SRCDIR/$GCC" |
|---|
| 316 | patch -p1 < "$SRCDIR/$GCC_PATCH" |
|---|
| 317 | cd "$BUILDDIR" |
|---|
| 318 | fi |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | |
|---|
| 322 | function configure_gcc |
|---|
| 323 | { |
|---|
| 324 | cd "$BUILDDIR" |
|---|
| 325 | rm -rf "gcc-$TARGET" |
|---|
| 326 | mkdir "gcc-$TARGET" |
|---|
| 327 | cd "gcc-$TARGET" |
|---|
| 328 | echo "Configuring gcc" |
|---|
| 329 | "$SRCDIR/$GCC/configure" -v \ |
|---|
| 330 | --prefix="$PREFIX" --target=$TARGET \ |
|---|
| 331 | --with-headers="$PREFIX/$TARGET/include" \ |
|---|
| 332 | --with-gcc --with-gnu-ld --with-gnu-as \ |
|---|
| 333 | --enable-threads --disable-nls --enable-languages=$GCC_LANGS \ |
|---|
| 334 | --disable-win32-registry --disable-shared --enable-sjlj-exceptions --enable-libgcj \ |
|---|
| 335 | --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug \ |
|---|
| 336 | --enable-interpreter --enable-hash-synchronization --enable-libstdcxx-debug \ |
|---|
| 337 | &> configure.log |
|---|
| 338 | cd "$BUILDDIR" |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| 341 | |
|---|
| 342 | function build_gcc |
|---|
| 343 | { |
|---|
| 344 | cd "$BUILDDIR/gcc-$TARGET" |
|---|
| 345 | echo "Building gcc" |
|---|
| 346 | $MAKE CFLAGS="-O2" CXXFLAGS="-O2" GCJFLAGS="-O2" LDFLAGS="-s" DEBUG_FLAGS="-g0" &> make.log |
|---|
| 347 | if test $? -ne 0; then |
|---|
| 348 | echo "make of gcc failed - log available: gcc-$TARGET/make.log" |
|---|
| 349 | exit 1 |
|---|
| 350 | fi |
|---|
| 351 | if [ "x$GCC_ADA" != "x" ]; then |
|---|
| 352 | cd gcc |
|---|
| 353 | $MAKE "CFLAGS=-O2" "LDFLAGS=-s" gnatlib_and_tools &> make-gnatlib.log |
|---|
| 354 | if test $? -ne 0; then |
|---|
| 355 | echo "make of gnatlib and tools failed - log available: gcc-$TARGET/make-gnatlib.log" |
|---|
| 356 | exit 1 |
|---|
| 357 | fi |
|---|
| 358 | fi |
|---|
| 359 | cd "$BUILDDIR" |
|---|
| 360 | } |
|---|
| 361 | |
|---|
| 362 | |
|---|
| 363 | function install_gcc |
|---|
| 364 | { |
|---|
| 365 | cd "$BUILDDIR/gcc-$TARGET" |
|---|
| 366 | echo "Installing gcc" |
|---|
| 367 | $MAKE install &> make-install.log |
|---|
| 368 | if test $? -ne 0; then |
|---|
| 369 | echo "install of gcc failed - log available: gcc-$TARGET/make-install.log" |
|---|
| 370 | exit 1 |
|---|
| 371 | fi |
|---|
| 372 | cd "$BUILDDIR" |
|---|
| 373 | } |
|---|
| 374 | |
|---|
| 375 | |
|---|
| 376 | function final_tweaks |
|---|
| 377 | { |
|---|
| 378 | echo "Finalizing installation" |
|---|
| 379 | |
|---|
| 380 | # remove gcc build headers |
|---|
| 381 | rm -rf "$PREFIX/$TARGET/sys-include" |
|---|
| 382 | |
|---|
| 383 | # Add extra binary links |
|---|
| 384 | if [ ! -f "$PREFIX/$TARGET/bin/objdump" ]; then |
|---|
| 385 | ln "$PREFIX/bin/$TARGET-objdump" "$PREFIX/$TARGET/bin/objdump" |
|---|
| 386 | fi |
|---|
| 387 | |
|---|
| 388 | # make cc and c++ symlinks to gcc and g++ |
|---|
| 389 | if [ ! -f "$PREFIX/$TARGET/bin/g++" ]; then |
|---|
| 390 | ln "$PREFIX/bin/$TARGET-g++" "$PREFIX/$TARGET/bin/g++" |
|---|
| 391 | fi |
|---|
| 392 | if [ ! -f "$PREFIX/$TARGET/bin/cc" ]; then |
|---|
| 393 | ln -s "gcc" "$PREFIX/$TARGET/bin/cc" |
|---|
| 394 | fi |
|---|
| 395 | if [ ! -f "$PREFIX/$TARGET/bin/c++" ]; then |
|---|
| 396 | ln -s "g++" "$PREFIX/$TARGET/bin/c++" |
|---|
| 397 | fi |
|---|
| 398 | |
|---|
| 399 | # strip all the binaries |
|---|
| 400 | ls "$PREFIX"/bin/* "$PREFIX/$TARGET"/bin/* | egrep -v '.dll$' | egrep -v 'gccbug$' | |
|---|
| 401 | while read file; do |
|---|
| 402 | strip "$file" |
|---|
| 403 | done |
|---|
| 404 | |
|---|
| 405 | echo "Installation complete!" |
|---|
| 406 | } |
|---|
| 407 | |
|---|
| 408 | |
|---|
| 409 | |
|---|
| 410 | # |
|---|
| 411 | # Main part of the script |
|---|
| 412 | # |
|---|
| 413 | |
|---|
| 414 | download_files |
|---|
| 415 | |
|---|
| 416 | if [ "x$PURGE_DIR" = "xY" ]; then |
|---|
| 417 | purge_existing_install |
|---|
| 418 | fi |
|---|
| 419 | |
|---|
| 420 | install_libs |
|---|
| 421 | |
|---|
| 422 | extract_binutils |
|---|
| 423 | configure_binutils |
|---|
| 424 | build_binutils |
|---|
| 425 | install_binutils |
|---|
| 426 | |
|---|
| 427 | extract_gcc |
|---|
| 428 | patch_gcc |
|---|
| 429 | configure_gcc |
|---|
| 430 | build_gcc |
|---|
| 431 | install_gcc |
|---|
| 432 | |
|---|
| 433 | final_tweaks |
|---|
| 434 | |
|---|
| 435 | |
|---|
| 436 | # |
|---|
| 437 | # End |
|---|
| 438 | # |
|---|