├── .gitignore ├── Dockerfile ├── LICENSE ├── .github └── workflows │ ├── docker.yml │ └── release.yml ├── README.md └── i686-elf-tools.sh /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE=ubuntu:latest 2 | FROM $BASE_IMAGE 3 | 4 | RUN mkdir /i686-elf-tools 5 | COPY ./i686-elf-tools.sh /i686-elf-tools/i686-elf-tools.sh 6 | RUN apt-get update && apt-get install -y \ 7 | git \ 8 | wget \ 9 | sudo \ 10 | make \ 11 | lsb-release \ 12 | && chmod +x /i686-elf-tools/i686-elf-tools.sh \ 13 | && /i686-elf-tools/i686-elf-tools.sh env -parallel \ 14 | && rm -rf /var/lib/apt/lists/* \ 15 | && rm -rf /opt/mxe/.ccache \ 16 | && rm -rf /opt/mxe/pkg 17 | 18 | ENTRYPOINT ["/i686-elf-tools/i686-elf-tools.sh"] 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 lordmilko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: docker 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | paths: 7 | - Dockerfile 8 | - i686-elf-tools.sh 9 | pull_request: 10 | branches: [ "master" ] 11 | paths: 12 | - Dockerfile 13 | - i686-elf-tools.sh 14 | 15 | jobs: 16 | push_to_registry: 17 | name: Update Docker Image 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout the repo 21 | uses: actions/checkout@v4 22 | 23 | - name: Login to Docker Hub 24 | uses: docker/login-action@v3 25 | with: 26 | username: ${{ secrets.DOCKER_USERNAME }} 27 | password: ${{ secrets.DOCKER_PASSWORD }} 28 | 29 | - name: Extract metadata (tags, labels) for Docker 30 | id: meta 31 | uses: docker/metadata-action@v5 32 | with: 33 | images: lordmilko/i686-elf-tools 34 | tags: | 35 | type=raw,value=latest 36 | 37 | - name: Build and push Docker Image 38 | uses: docker/build-push-action@v5 39 | with: 40 | context: . 41 | file: ./Dockerfile 42 | push: true 43 | tags: ${{ steps.meta.outputs.tags }} 44 | labels: ${{ steps.meta.outputs.labels }} -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | gcc_version: 7 | required: true 8 | type: string 9 | 10 | binutils_version: 11 | required: true 12 | type: string 13 | 14 | gdb_version: 15 | required: true 16 | type: string 17 | 18 | jobs: 19 | i686: 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - name: build 26 | run: docker run -v "${{ github.workspace }}:/root" --rm lordmilko/i686-elf-tools -parallel -gv ${{ inputs.gcc_version }} -bv ${{ inputs.binutils_version }} -dv ${{ inputs.gdb_version }} 27 | 28 | - uses: actions/upload-artifact@v4 29 | with: 30 | name: i686-elf-tools 31 | path: ${{ github.workspace }}/build-i686-elf/*.zip 32 | 33 | x86_64: 34 | runs-on: ubuntu-latest 35 | 36 | steps: 37 | - uses: actions/checkout@v4 38 | 39 | - name: build 40 | run: docker run -v "${{ github.workspace }}:/root" --rm lordmilko/i686-elf-tools -parallel -gv ${{ inputs.gcc_version }} -bv ${{ inputs.binutils_version }} -dv ${{ inputs.gdb_version }} -64 41 | 42 | - uses: actions/upload-artifact@v4 43 | with: 44 | name: x86_64-elf-tools 45 | path: ${{ github.workspace }}/build-x86_64-elf/*.zip 46 | 47 | release: 48 | runs-on: ubuntu-latest 49 | needs: [i686, x86_64] 50 | 51 | steps: 52 | - uses: actions/download-artifact@v4.1.7 53 | 54 | - name: release 55 | uses: softprops/action-gh-release@v0.1.15 56 | with: 57 | name: GCC ${{ inputs.gcc_version }} 58 | tag_name: ${{ inputs.gcc_version }} 59 | draft: true 60 | files: '**/*.zip' 61 | body: | 62 | i686/x86_64-elf Win32/Linux binaries 63 | -GCC ${{ inputs.gcc_version }} 64 | -Binutils ${{ inputs.binutils_version }} 65 | -GDB ${{ inputs.gdb_version }} 66 | 67 | * 🤖This modern version of i686-elf-tools has automatically been built by GitHub Actions 68 | * ⚠️It is completely untested, and merely provided for your convenience in the event that you would prefer to use a modern version of the toolchain 69 | * 🚀Having said all this, the [original release](https://github.com/lordmilko/i686-elf-tools/releases/tag/7.1.0) of the toolchain has been thoroughly tested, and is generally recommended unless you specifically know that you need to use a newer version 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i686-elf-tools 2 | Cross compiling an i386- or i686-elf Win32 toolchain is an outstandingly complicated and painful process. Both Binutils and GCC fail to properly articulate the extent of software dependencies required to build them, resulting in a litany of spurious and confusing error messages being emitted during compilation. Even once you do have the required software dependencies in place, you will still run into roadblocks due to anomalies in how GCC performs cross compilation. 3 | 4 | This repo provides a set of precompiled binaries to those who want to use get what they came for and move on (an i686-elf toolchain that, **unlike others on the internet, includes cc1 and GDB**), as well as a set of instructions for those that would like to build these things themselves. Also featured are a set of instructions for those that wish to install these tools on Mac OS X or Linux. 5 | 6 | [Pre-compiled binaries can be found here!](https://github.com/lordmilko/i686-elf-tools/releases) 7 | 8 | [Information on using i686-elf-tools in Visual Studio can be found here!](https://github.com/lordmilko/VSKernelDev) 9 | 10 | ## Win32 11 | ### Tutorial 12 | 13 | By default, `i686-elf-tools.sh` will download 14 | 15 | * GCC 7.1.0 16 | * Binutils 2.28 17 | * GDB 8.0 18 | 19 | If you would like to change these versions, specify the `-gv`, `-bv` and `-dv` parameters when invoking the script (for overriding the Binutils, GCC and Debugger versions, respectively). Instead of using MinGW32 or MinGW64, [MXE](http://mxe.cc) is used, providing us with an awesome Win32 toolchain that always produces statically linked binaries that just work (and don't need random MinGW DLLs). 20 | 21 | Note: if you already have MXE installed, `i686-elf-tools.sh` won't attempt to make MXE's version of GCC. Please ensure that MXE's gcc has been built (run `make gcc` in your MXE install directory), else you will experience issues during compilation. 22 | 23 | ### Docker 24 | 25 | The following command will compile all Linux/Windows binaries, placing the results under the current user's profile. Substitute `/home/admin` in this command for whatever your home directory is. 26 | 27 | ```sh 28 | docker run -it -v "/home/admin:/root" --rm lordmilko/i686-elf-tools 29 | ``` 30 | 31 | Any arguments (see below) specified after the image name (`lordmilko/i686-elf-tools`) will be passed as arguments to `i686-elf-tools.sh` within the container. In the above example, build results will be stored in `/home/admin/build-i686-elf`. 32 | 33 | Note that absolute paths must be used when when specifying Docker volumes, as such specifying `~` for the local user's home directory will not work. 34 | To avoid making a mess on your system, the container will automatically self delete itself after it has run (`--rm`) leaving only the build results in your home directory. 35 | 36 | ```sh 37 | # Compile GCC 9.2.0, Binutils 2.34 and GDB 9.1 38 | docker run -it -v "/home/admin:/root" --rm lordmilko/i686-elf-tools -gv 9.2.0 -bv 2.34 -dv 9.1 39 | ``` 40 | 41 | ### Native 42 | 43 | 1. Install a Debian based operating system, ideally 32-bit (i386). This procedure has successfully been performed on Debian 9.5 i386 and Ubuntu 18.04 64-bit (amd64). If you wish to compile a x86_64-elf toolchain (via `-64`), you should probably use a 64-bit operating system. 44 | 45 | 2. Remove the CD-ROM source from `/etc/apt/sources.list` (if applicable) 46 | 47 | 3. If you are running Ubuntu, you may need to modify `/etc/apt/sources.list` to include `universe` and `multiverse` in addition to `main`. If you simply do the default Ubuntu install, these appear to be included by default. 48 | 49 | ```diff 50 | -deb http://archive.ubuntu.com/ubuntu bionic main 51 | +deb http://archive.ubuntu.com/ubuntu bionic main universe multiverse 52 | deb http://archive.ubuntu.com/ubuntu bionic-security main 53 | deb http://archive.ubuntu.com/ubuntu bionic-updates main 54 | ``` 55 | 56 | 4. Run the following commands. `sudo -s` is optional, however if you are not running as root you will get repeated password request prompts during the course of the execution. 57 | 58 | ```sh 59 | sudo -s 60 | wget https://raw.githubusercontent.com/lordmilko/i686-elf-tools/master/i686-elf-tools.sh 61 | chmod +x ./i686-elf-tools.sh 62 | ./i686-elf-tools.sh 63 | ``` 64 | 65 | A full run (including installing prerequisites and configuring MXE) takes approximately 1.5-2 hours on a 4xCPU virtual machine. 66 | 67 | 5. When the script completes you will have two zip files containing your i686-elf toolchain 68 | 69 | * `~/build-i686-elf/i686-elf-tools-windows.zip` 70 | * `~/build-i686-elf/i686-elf-tools-linux.zip` 71 | 72 | If you experience any issues, you can specify one or more command line arguments to only perform certain parts of the script. The following arguments are supported 73 | 74 | * `binutils` 75 | * `gcc` 76 | * `gdb` 77 | * `zip` - zip it all up! 78 | * `linux` - compile the linux toolchain only 79 | * `win` - compile the windows toolchain only 80 | * `env` - only install the prerequisite packages + MXE 81 | * `-gv`/`--gcc-version` - specify the GCC version to build 82 | * `-bv`/`--binutils-version` - specify the Binutils version to build 83 | * `-dv`/`--gdb-version` - specify the GDB version to build 84 | * `-64` - compile for x86_64-elf instead of i686-elf 85 | * `-parallel` - build `make` recipes in [parallel](https://www.gnu.org/software/make/manual/html_node/Parallel.html) (`-j4`). To modify the number of jobs executed in parallel, modify `i686-elf-tools.sh` 86 | 87 | ```sh 88 | # Compile binutils and gcc only 89 | ./i686-elf-tools.sh binutils gcc 90 | ``` 91 | 92 | The `win` argument should only be used if the Linux toolchain has already been compiled and you're experiencing issues with the Win32 part. 93 | 94 | Logs are stored for each stage of the process under *~/build-i686-elf/build-**xyz**/**xyz**_**stage**.log* 95 | 96 | e.g. **~/build-i686-elf/build-gcc-7.1.0/gcc_make.log** 97 | 98 | If you attempt to run `make` and `configure` commands manually that depend on components of the linux i686-elf toolchain, ensure `~/build-i686-elf/linux/output/bin` is on your path, else you may get errors about binaries being missing. 99 | 100 | By default, i686-elf-tools will build `make` recipes in parallel. If any arguments are specified to `i686-elf-tools.sh` however, parallel compilation must be opted into by explicitly specifying `-parallel`. 101 | 102 | ## Mac OS X 103 | 104 | Installing an i386-elf toolchain on Mac OS X is - theoretically - outstandingly simple process. Note that the following relies on a third party script and is not supported by me. It may be possible to run *i686-elf-tools.sh* on Mac OS X with a bit of tweaking (like not using `apt-get` to install packages) however this is not supported. 105 | 106 | 1. Install [Brew](http://brew.sh/) 107 | 2. Download the [i386-elf recipes](https://github.com/altkatz/homebrew-gcc_cross_compilers) 108 | 3. Copy `i386-elf-binutils.rb`, `i386-elf-gcc.rb` and `i386-elf-gdb.rb` to `/usr/local/Library/Formula`. As these formulae depend on one another, attempting to execute these directly with `brew install i386-elf-gcc.rb`, etc will fail. 109 | 4. Run `brew install i386-elf-binutils`, `brew install i386-elf-gcc` and `brew install i386-elf-gdb` 110 | 111 | ## Linux 112 | 113 | Extract the contents of `i686-elf-tools-linux.zip` somewhere. By default GCC installs them under `/usr/local/`. 114 | 115 | To compile a newer i686-elf toolchain, invoke `i686-elf-tools.sh` as follows 116 | 117 | ```sh 118 | ./i686-elf-tools.sh linux 119 | ``` 120 | 121 | ## FAQ 122 | 123 | ### Why would I want to use this? 124 | For building your own [Operating System](http://wiki.osdev.org/Bare_Bones), of course! 125 | 126 | ### How do I install this on Windows? 127 | After copying `i686-elf-tools-windows.zip` to your PC, all necessary programs can be found in the `bin` folder. You can then put this folder in your `PATH`, or simply browse to the programs in this folder manually. When running these programs, it is important to make sure all of the subfolders are kept together, as files outside of the bin folder are required for certain programs (such as GCC). 128 | 129 | ### Does this include libgcc? 130 | Seems so! For more information see the section *How on earth did you compile libgcc?* below. 131 | 132 | ### Can I use MSYS/MSYS2/MinGW/MinGW/MinGW-w32/MinGW-w64/Cygwin, etc to do this? 133 | No. But you can try. I got all sorts of crazy errors I was simply unable to resolve when I was looking at solutions to compile these tools. I have successfully compiled on Windows in the past, however there have been two issues with this: 134 | * Executables had dependencies on MinGW/Cygwin libraries (most likely as I just didn't know how to statically link) 135 | * GDB would randomly quit whenever I tried to type a command 136 | 137 | YMMV. 138 | 139 | ### Can I use `$DISTRO` instead of Debian? 140 | I originally tried to use CentOS 7 64-bit, however along the way I encountered various issues potentially attributable to bitness, resulting in my switching to a 32-bit OS to simplify troubleshooting. CentOS 7 32-bit _cannot_ be used, as all the packages required by MXE are not available on yum. 141 | 142 | If you are determined not to use Debian (or another Debian derivitive), please see the [prerequisites for MXE](http://mxe.cc/#requirements). Note: you may need additional packages to these to successfully compile gcc, e.g. _texinfo_, _readline-devel_, etc. Google any error messages you get to reveal the appropriate package you need to install. 143 | 144 | ### When running these steps manually and running `make` for binutils I get an error _GCC_NO_EXECUTABLES_ 145 | The path to the compiler specified as `--host` to `configure` cannot be found on your `PATH`. (i.e. if you're compiling for Windows, check that `/opt/mxe/usr/bin` is present). Update your `.bashrc` and login/logout. 146 | 147 | ### When running these steps manually I get _i686-elf-gcc: command not found_ 148 | This is caused by two bugs(?) in the GCC Makefile 149 | 150 | 1. The file `make` is looking for is called `xgcc`, not `i686-elf-gcc` 151 | 2. To create `i686-elf-gcc` you must compile a toolchain for linux first 152 | 153 | You can try and hack the GCC makefile to execute `wine ./xgcc.exe` instead, however you'll still run into issues when you try and compile libgcc. If you compile a linux i686-elf toolchain first, all your issues go away. Is this the correct way to do things? Who knows. 154 | 155 | ### How do I compile x86_64 myself? 156 | 157 | See the [OSDev Wiki](https://wiki.osdev.org/Libgcc_without_red_zone). Note that when compiling for Windows however, `make install-target-libgcc` does not appear to copy the no-red-zone libgcc version to the output directory. To get around this, simply `cd` into `x86_64-elf/no-red-zone/libgcc` in your output directory and run `make install` yourself. 158 | 159 | ### How on earth did you compile libgcc? 160 | 161 | One does not simply `make all-target-libgcc` for `host=MinGW32`. The reason for this is that when libgcc is configured, both its target *and* host are set to **i686-elf**. As a result, libgcc's makefile will look for a *host=linux, target=1686-elf* `i686-elf-gcc`, will only find your MinGW32 `i686-elf-gcc.exe` from your previous `make all-gcc` (which it obviously can't execute) and thus will fail. 162 | 163 | Attempting to trick the makefile by creating shell scripts on your path named after the missing binaries that internally invoke `wine ` does not work (you get strange errors on during compilation). 164 | 165 | The solution to this therefore is to first compile a linux i686-elf toolchain, followed by the MinGW32 toolchain we're actually interested in. This helps solve other bugs in the compilation process, such as GCC attempting to perform selftests on your MinGW32 cross compiler (which won't work) yet looking for i686-elf-gcc instead (which wouldn't exist). 166 | 167 | One would expect libgcc would have host=<the actual host> instead of i686-elf and thus generate a file `libgcc.dll` for mingw32, but from what I've found that doesn't appear to be the case. If you do have issues with GCC not interfacing with libgcc properly, let me know! 168 | -------------------------------------------------------------------------------- /i686-elf-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # i686-elf-tools.sh 4 | # v1.3.5 5 | 6 | # Define Global Variables 7 | 8 | BINUTILS_VERSION=2.28 9 | GCC_VERSION=7.1.0 10 | GDB_VERSION=8.0 11 | 12 | BUILD_TARGET="i686-elf" 13 | 14 | set -e 15 | 16 | ALL_PRODUCTS=true 17 | 18 | # Parse Commandline Options 19 | 20 | if [ $# -eq 0 ]; then 21 | BUILD_BINUTILS=true 22 | BUILD_GCC=true 23 | BUILD_GDB=true 24 | ZIP=true 25 | PARALLEL=true 26 | args="binutils gcc gdb zip" 27 | else 28 | args=$@ 29 | fi 30 | 31 | while [[ $# -gt 0 ]] 32 | do 33 | key="$1" 34 | 35 | case $key in 36 | binutils) BUILD_BINUTILS=true; ALL_PRODUCTS=false; shift ;; 37 | gcc) BUILD_GCC=true; ALL_PRODUCTS=false; shift ;; 38 | gdb) BUILD_GDB=true; ALL_PRODUCTS=false; shift ;; 39 | win) WINDOWS_ONLY=true; shift ;; 40 | linux) LINUX_ONLY=true; shift ;; 41 | zip) ZIP=true; ALL_PRODUCTS=false; shift ;; 42 | env) ENV_ONLY=true; shift ;; 43 | -64) x64=true; shift ;; 44 | -parallel) PARALLEL=true; shift ;; 45 | -bv|--binutils-version) BINUTILS_VERSION="$2"; shift; shift ;; 46 | -gv|--gcc-version) GCC_VERSION="$2"; shift; shift ;; 47 | -dv|--gdb-version) GDB_VERSION="$2"; shift; shift ;; 48 | *) shift ;; 49 | esac 50 | done 51 | 52 | if [[ $x64 == true ]]; then 53 | BUILD_TARGET="x86_64-elf" 54 | fi 55 | 56 | BUILD_DIR="$HOME/build-${BUILD_TARGET}" 57 | export PATH="/opt/mxe/usr/bin:$BUILD_DIR/linux/output/bin:$BUILD_DIR/windows/output/bin:$PATH" 58 | 59 | echo "BUILD_TARGET = ${BUILD_TARGET}" 60 | echo "BUILD_DIR = ${BUILD_DIR}" 61 | echo "BUILD_BINUTILS = ${BUILD_BINUTILS}" 62 | echo "BUILD_GCC = ${BUILD_GCC}" 63 | echo "BUILD_GDB = ${BUILD_GDB}" 64 | echo "ZIP = ${ZIP}" 65 | echo "WIN = ${WINDOWS_ONLY}" 66 | echo "LINUX = ${LINUX_ONLY}" 67 | echo "ENV = ${ENV_ONLY}" 68 | echo "x64 = ${x64}" 69 | echo "BINUTILS_VERSION = ${BINUTILS_VERSION}" 70 | echo "GCC_VERSION = ${GCC_VERSION}" 71 | echo "GDB_VERSION = ${GDB_VERSION}" 72 | echo "PATH = ${PATH}" 73 | echo "PARALLEL = ${PARALLEL}" 74 | 75 | function main { 76 | 77 | installPackages 78 | installMXE 79 | 80 | if [[ $ENV_ONLY == true ]]; then 81 | echoColor "Successfully installed build environment. Exiting as 'env' only was specified" 82 | return 83 | fi 84 | 85 | downloadSources 86 | 87 | if [[ $WINDOWS_ONLY == true ]]; then 88 | echoColor "Skipping compiling Linux as 'win' was specified in commandline args '$args'" 89 | else 90 | compileAll "linux" 91 | fi 92 | 93 | if [[ $LINUX_ONLY == true ]]; then 94 | echoColor "Skipping compiling Windows as 'linux' was specified in commandline args '$args'" 95 | else 96 | compileAll "windows" 97 | fi 98 | 99 | finalize 100 | } 101 | function installPackages { 102 | pkgList=( 103 | git 104 | autoconf 105 | automake 106 | autopoint 107 | bash 108 | bison 109 | bzip2 110 | flex 111 | gettext 112 | g++ 113 | gperf 114 | intltool 115 | libffi-dev 116 | libgdk-pixbuf2.0-dev 117 | libgmp-dev 118 | libmpfr-dev 119 | libtool 120 | libltdl-dev 121 | libssl-dev 122 | libxml-parser-perl 123 | make 124 | python3-mako 125 | openssl 126 | p7zip-full 127 | patch 128 | perl 129 | pkg-config 130 | ruby 131 | scons 132 | sed 133 | unzip 134 | wget 135 | xz-utils 136 | libtool-bin 137 | texinfo 138 | g++-multilib 139 | lzip) 140 | echoColor "Installing packages" 141 | 142 | # Fix correct python packages on modern Ubuntu and Ubuntu-based distros 143 | if [[ $(apt-cache search --names-only ^python3$ | wc -m) -gt 0 ]]; then 144 | pkgList+=(python3 python-is-python3) 145 | else 146 | pkgList+=(python) 147 | fi 148 | 149 | for pkg in ${pkgList[@]}; do 150 | sudo -E DEBIAN_FRONTEND=noninteractive apt-get -qq install $pkg -y 151 | done 152 | } 153 | 154 | # MXE 155 | function installMXE { 156 | 157 | echoColor "Installing MXE" 158 | 159 | if [ ! -d "/opt/mxe/usr/bin" ] 160 | then 161 | echoColor " Cloning MXE and compiling mingw32.static GCC" 162 | cd /opt 163 | sudo -E git clone https://github.com/mxe/mxe.git 164 | cd mxe 165 | if [[ $PARALLEL == true ]]; then 166 | sudo make -j4 gcc gmp mpfr 167 | else 168 | sudo make gcc gmp mpfr 169 | fi 170 | else 171 | echoColor " MXE is already installed. You'd better make sure that you've previously made MXE's gcc! (/opt/mxe/usr/bin/i686-w64-mingw32.static-gcc)" 172 | fi 173 | } 174 | 175 | # Downloads 176 | 177 | function downloadSources { 178 | mkdir -p $BUILD_DIR 179 | cd $BUILD_DIR 180 | 181 | echoColor "Downloading all sources" 182 | 183 | if [[ $BUILD_BINUTILS == true || $ALL_PRODUCTS == true ]]; then 184 | downloadAndExtract "binutils" $BINUTILS_VERSION 185 | else 186 | echoColor " Skipping binutils as 'binutils' was ommitted from commandline args '$args'" 187 | fi 188 | 189 | if [[ $BUILD_GCC == true || $ALL_PRODUCTS == true ]]; then 190 | downloadAndExtract "gcc" $GCC_VERSION "http://ftpmirror.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.gz" 191 | 192 | echoColor " Downloading GCC prerequisites" 193 | 194 | # Automatically download GMP, MPC and MPFR. These will be placed into the right directories. 195 | # You can also download these separately, and specify their locations as arguments to ./configure 196 | 197 | if [[ $WINDOWS_ONLY != true ]]; then 198 | echoColor " Linux" 199 | cd ./linux/gcc-$GCC_VERSION 200 | ./contrib/download_prerequisites 201 | fi 202 | 203 | cd $BUILD_DIR 204 | 205 | if [[ $LINUX_ONLY != true ]]; then 206 | echoColor " Windows" 207 | cd ./windows/gcc-$GCC_VERSION 208 | ./contrib/download_prerequisites 209 | fi 210 | 211 | cd $BUILD_DIR 212 | else 213 | echoColor " Skipping gcc as 'gcc' was ommitted from commandline args '$args'" 214 | fi 215 | 216 | if [[ $BUILD_GDB == true || $ALL_PRODUCTS == true ]]; then 217 | downloadAndExtract "gdb" $GDB_VERSION 218 | else 219 | echoColor " Skipping gdb as 'gdb' was ommitted from commandline args '$args'" 220 | fi 221 | } 222 | 223 | function downloadAndExtract { 224 | name=$1 225 | version=$2 226 | override=$3 227 | 228 | echoColor " Processing $name" 229 | 230 | if [ ! -f $name-$version.tar.gz ] 231 | then 232 | echoColor " Downloading $name-$version.tar.gz" 233 | 234 | if [ -z $3 ] 235 | then 236 | wget -q http://ftpmirror.gnu.org/gnu/$name/$name-$version.tar.gz 237 | else 238 | wget -q $override 239 | fi 240 | else 241 | echoColor " $name-$version.tar.gz already exists" 242 | fi 243 | 244 | if [[ $WINDOWS_ONLY == true ]]; then 245 | echoColor " Skipping extracting Linux as 'win' was specified in commandline args '$args'" 246 | else 247 | mkdir -p linux 248 | cd linux 249 | 250 | if [ ! -d $name-$version ] 251 | then 252 | echoColor " [linux] Extracting $name-$version.tar.gz" 253 | tar -xf ../$name-$version.tar.gz 254 | else 255 | echoColor " [linux] Folder $name-$version already exists" 256 | fi 257 | 258 | cd .. 259 | fi 260 | 261 | if [[ $LINUX_ONLY == true ]]; then 262 | echoColor " Skipping extracting Linux as 'win' was specified in commandline args '$args'" 263 | else 264 | mkdir -p windows 265 | cd windows 266 | 267 | if [ ! -d $name-$version ] 268 | then 269 | echoColor " [windows] Extracting $name-$version.tar.gz" 270 | tar -xf ../$name-$version.tar.gz 271 | else 272 | echoColor " [windows] Folder $name-$version already exists" 273 | fi 274 | 275 | cd .. 276 | fi 277 | } 278 | 279 | function compileAll { 280 | 281 | echoColor "Compiling all $1" 282 | 283 | cd $1 284 | 285 | mkdir -p output 286 | 287 | compileBinutils $1 288 | compileGCC $1 289 | compileGDB $1 290 | 291 | cd .. 292 | } 293 | 294 | function compileBinutils { 295 | if [[ $BUILD_BINUTILS == true || $ALL_PRODUCTS == true ]]; then 296 | echoColor " Compiling binutils [$1]" 297 | 298 | mkdir -p build-binutils-$BINUTILS_VERSION 299 | cd build-binutils-$BINUTILS_VERSION 300 | 301 | configureArgs="--target=${BUILD_TARGET} --with-sysroot --disable-nls --disable-werror --prefix=$BUILD_DIR/$1/output" 302 | 303 | if [ $1 == "windows" ] 304 | then 305 | configureArgs="--host=i686-w64-mingw32.static $configureArgs" 306 | fi 307 | 308 | # Configure 309 | echoColor " Configuring binutils (binutils_configure.log)" 310 | ../binutils-$BINUTILS_VERSION/configure $configureArgs >> binutils_configure.log 311 | 312 | # Make 313 | echoColor " Making (binutils_make.log)" 314 | if [[ $PARALLEL == true ]]; then 315 | make -j4 >> binutils_make.log 316 | else 317 | make >> binutils_make.log 318 | fi 319 | 320 | # Install 321 | echoColor " Installing (binutils_install.log)" 322 | sudo make install >> binutils_install.log 323 | cd .. 324 | else 325 | echoColor " Skipping binutils [$1] as 'binutils' was ommitted from commandline args '$args'" 326 | fi 327 | } 328 | 329 | function compileGCC { 330 | if [[ $BUILD_GCC == true || $ALL_PRODUCTS == true ]]; then 331 | 332 | echoColor " Compiling gcc [$1]" 333 | 334 | mkdir -p build-gcc-$GCC_VERSION 335 | cd build-gcc-$GCC_VERSION 336 | 337 | configureArgs="--target=${BUILD_TARGET} --disable-nls --enable-languages=c,c++ --without-headers --prefix=$BUILD_DIR/$1/output" 338 | 339 | if [ $1 == "windows" ] 340 | then 341 | configureArgs="--host=i686-w64-mingw32.static $configureArgs" 342 | fi 343 | 344 | if [[ $x64 == true ]]; then 345 | 346 | # https://wiki.osdev.org/Libgcc_without_red_zone#Preparations 347 | 348 | echoColor " Installing config/i386/t-x86_64-elf" 349 | echo -e "# Add libgcc multilib variant without red-zone requirement\n\nMULTILIB_OPTIONS += mno-red-zone\nMULTILIB_DIRNAMES += no-red-zone" > ../gcc-$GCC_VERSION/gcc/config/i386/t-x86_64-elf 350 | 351 | echoColor " Patching gcc/config.gcc" 352 | sed -i '/x86_64-\*-elf\*)/a \\ttmake_file="${tmake_file} i386/t-x86_64-elf" # include the new multilib configuration' ../gcc-$GCC_VERSION/gcc/config.gcc 353 | fi 354 | 355 | # Configure 356 | echoColor " Configuring gcc (gcc_configure.log)" 357 | ../gcc-$GCC_VERSION/configure $configureArgs >> gcc_configure.log 358 | 359 | # Make GCC 360 | echoColor " Making gcc (gcc_make.log)" 361 | if [[ $PARALLEL == true ]]; then 362 | make -j4 all-gcc >> gcc_make.log 363 | else 364 | make all-gcc >> gcc_make.log 365 | fi 366 | 367 | # Install GCC 368 | echoColor " Installing gcc (gcc_install.log)" 369 | sudo make install-gcc >> gcc_install.log 370 | 371 | # Make libgcc 372 | echoColor " Making libgcc (libgcc_make.log)" 373 | if [[ $PARALLEL == true ]]; then 374 | make -j4 all-target-libgcc >> libgcc_make.log 375 | else 376 | make all-target-libgcc >> libgcc_make.log 377 | fi 378 | 379 | # Install libgcc 380 | echoColor " Installing libgcc (libgcc_install.log)" 381 | sudo make install-target-libgcc >> libgcc_install.log 382 | 383 | if [[ $x64 == true ]]; then 384 | 385 | if [ $1 == "windows" ] 386 | then 387 | # no-red-zone doesn't appear to get installed by make install-target-libgcc for some reason. Manually install it ourselves 388 | 389 | cd "${BUILD_TARGET}/no-red-zone/libgcc" 390 | sudo make install >> ../../../libgcc_install_noredzone.log 391 | 392 | cd ../../.. 393 | fi 394 | 395 | if [[ ! -d "../output/lib/gcc/x86_64-elf/$GCC_VERSION/no-red-zone" ]]; then 396 | echoError "ERROR: no-red-zone was not created. x64 patching failed" 397 | exit 1 398 | else 399 | echoColor " Successfully compiled for no-red-zone" 400 | fi 401 | fi 402 | 403 | cd .. 404 | else 405 | echoColor " Skipping gcc [$1] as 'gcc' was ommitted from commandline args '$args'" 406 | fi 407 | } 408 | 409 | function compileGDB { 410 | if [[ $BUILD_GDB == true || $ALL_PRODUCTS == true ]]; then 411 | 412 | echoColor " Compiling gdb [$1]" 413 | 414 | configureArgs="--target=${BUILD_TARGET} --disable-nls --disable-werror --prefix=$BUILD_DIR/$1/output" 415 | 416 | if [ $1 == "windows" ] 417 | then 418 | configureArgs="--host=i686-w64-mingw32.static $configureArgs" 419 | fi 420 | 421 | mkdir -p build-gdb-$GDB_VERSION 422 | cd build-gdb-$GDB_VERSION 423 | 424 | # Configure 425 | echoColor " Configuring (gdb_configure.log)" 426 | ../gdb-$GDB_VERSION/configure $configureArgs >> gdb_configure.log 427 | 428 | # Make 429 | echoColor " Making (gdb_make.log)" 430 | if [[ $PARALLEL == true ]]; then 431 | make -j4 >> gdb_make.log 432 | else 433 | make >> gdb_make.log 434 | fi 435 | 436 | # Install 437 | echoColor " Installing (gdb_install.log)" 438 | sudo make install >> gdb_install.log 439 | cd .. 440 | else 441 | echoColor " Skipping gdb [$1] as 'gdb' was ommitted from commandline args '$args'" 442 | fi 443 | } 444 | 445 | function finalize { 446 | if [[ $ZIP == true || $ALL_PRODUCTS == true ]]; then 447 | echo "Zipping everything up!" 448 | 449 | if [[ -d "$BUILD_DIR/windows/output" ]]; then 450 | cd $BUILD_DIR/windows/output 451 | zip -r "${BUILD_DIR}/${BUILD_TARGET}-tools-windows.zip" * 452 | fi 453 | 454 | if [[ -d "$BUILD_DIR/linux/output" ]]; then 455 | cd $BUILD_DIR/linux/output 456 | zip -r "${BUILD_DIR}/${BUILD_TARGET}-tools-linux.zip" * 457 | fi 458 | 459 | echo -e "\e[92mZipped everything to $BUILD_DIR/${BUILD_TARGET}-tools-[windows | linux].zip\e[39m" 460 | else 461 | echoColor " Skipping zipping 'zip' was ommitted from commandline args '$args'" 462 | fi 463 | } 464 | 465 | function echoColor { 466 | echo -e "\e[96m$1\e[39m" 467 | } 468 | 469 | function echoError { 470 | echo -e "\e[31m$1\e[39m" 471 | } 472 | 473 | main 474 | --------------------------------------------------------------------------------