HTEC Public

Hi,

> This likely needs to be updated for the trunk.

> Before:


>                  === gcc Summary ===

> # of expected passes            95
> # of unexpected failures        25


> After:
>                  === gcc Summary ===

> # of expected passes            70
> # of unexpected failures        50

> Clearly not going in the right direction.  Configured as
> mips64el-linux-gnuabi64.  Running just the near-far-?.c tests.

> Jeff

I would like to inform you that the version 2 of this patch with the
appropriate ChangeLog entry is available at the following link:

https://gcc.gnu.org/pipermail/gcc-patches/2025-March/677827.html

Please find attached scripts that I used for building the GCC
cross-compiler and for running the GCC testsuite for the
mips64-r6-linux-gnu target.
The script run_mips_gcc_testsuite is meant to be run inside the
$BUILD_DIR/gcc-build directory with the following arguments:

--sys-root=$SYSROOT --test-driver=mips.exp --test-regex="near-far-?.c"

I ran the near-far-?.c tests and all of them passed:

Before:
                === gcc Summary ===

# of expected passes            168

After:
                === gcc Summary ===

# of expected passes            168

Kind regards,
Aleksandar
# How to Build a *GNU* Toolchain from Source

## Introduction

A *GNU Toolchain* consists of:  
- *GCC*, which can be obtained with the following command:
  ```
  $ git clone git://gcc.gnu.org/git/gcc.git
  ```
- *binutils*, which can be obtained with the following command:
  ```
  $ git clone git://sourceware.org/git/binutils-gdb.git
  ```
- *glibc*, which can be obtained with the following command:
  ```
  $ git clone https://sourceware.org/git/glibc.git
  ```
- *Linux Kernel Headers*, which can be downloaded from [here](https://mirrors.edge.kernel.org/pub/linux/kernel). Version 5.10.116 was used for this tutorial.  
  
The source directory will consist of one main directory (from this point on, referred to as the `$SOURCE_DIR`) and multiple subdirectories - one for each of the previously mentioned parts of the *GNU Toolchain*.  

Besides the source directory, there will be a build directory, which will consist of one main directory (from this point on, referred to as the `$BUILD_DIR`) and multiple subdirectories - one for a build of each of the previously mentioned parts of the *GNU Toolchain* (excluding the *Linux Kernel Headers*).  

Finally, there will be an install directory (from this point on, referred to as the `$PREFIX` directory). Within it, there will be a *system root* subdirectory (from this point on, referred to as the `$SYSROOT` directory). The `$SYSROOT` directory is the root directory in which the target system headers, libraries and run-time objects will be searched for.  

Make sure to add the `bin/` subdirectory of the `$PREFIX` directory to your `PATH` environment variable before proceeding:  
  
```
$ export PATH=$PREFIX/bin:$PATH
```
  
For this tutorial, we'll use the `mips64-r6-linux-gnu` target:  

```
$ export TARGET=mips64-r6-linux-gnu
```
  

## Step 1: Build and Install *binutils*

First, position yourself inside the `$BUILD_DIR`, create `binutils-gdb-build/` subdirectory, and position yourself inside it:  
  
```
$ cd $BUILD_DIR
$ mkdir binutils-gdb-build
$ cd binutils-gdb-build
```
  
Next, configure the build:  
  
```
$ $SOURCE_DIR/binutils-gdb/configure \
    --prefix=$PREFIX \
    --target=$TARGET \
    --with-sysroot=$SYSROOT \
    --disable-nls \
    --disable-werror \
    --with-arch=mips64r6 \
    --with-abi=64 \
    --disable-multilib
```
  
`--with-sysroot=$SYSROOT` tells *binutils* to consider the `$SYSROOT` directory as the *system root*.  

`--disable-nls` tells *binutils* not to include native language support. This is basically optional, but reduces dependencies and compile time.  

`--disable-werror` tells *binutils* to disable promoting warnings into errors (such as overflow warnings, for example).  

`--with-arch=mips64r6` and `--with-abi=64` options manually specify the target architecture and the target *ABI*, respectively. This is needed to override the default 32-bit *ABI MIPS* has (even if you specify a 64-bit target). For other targets, this should be adjusted or removed.  

Optionally, you can enable the *multilib* support with the `--enable-multilib` option. *multilib* is a mechanism to support building and running code for different *ABI*s for the same *CPU* family on a given system. Most commonly it is used to support 32-bit code on 64-bit systems and 64-bit code on 32-bit systems with a 64-bit kernel. This requires even more setup and will not be covered in this tutorial.  

Finally, build and install *binutils*:  
  
```
$ make
$ make install
```
  

## Step 2: Install *Linux Kernel Headers*

In order to install *Linux Kernel Headers*, position yourself inside the `$SOURCE_DIR/linux-5.10.116/` directory and run the following commands:  
  
```
$ make mrproper
$ make ARCH=mips INSTALL_HDR_PATH=$SYSROOT/usr headers_install
$ make headers_check
```
  
*Note*: The *Linux Kernel Headers* is a different open-source project, so it has its own way of identifying the target *CPU* architecture. The `$SOURCE_DIR/linux-5.10.116/arch/` directory holds a subdirectory for each available target *CPU* architecture.  

The `make mrproper` command cleans up any leftover files in the source directory from previous builds.  

The `make headers_check` command runs sanity checks on installed headers.  

The headers are now installed in the `$SYSROOT/usr/include/` directory (`/usr/include/` is the default directory in which the compiler searches for native system headers).

## Step 3: Build and Install *C*/*C++* Compilers

Starting from this point on, we're only building *GCC* and *glibc*. The tricky part is that there are parts of *GCC* which depend on parts of *glibc* already being built, and vice-versa.  

Step 3 will only build and install *GCC*'s *C* and *C++* cross-compilers. It won't invoke those compilers to build any libraries just yet.  

First, position yourself inside the `$BUILD_DIR`, create `gcc-build/` subdirectory, and position yourself inside it:  
  
```
$ cd $BUILD_DIR
$ mkdir gcc-build
$ cd gcc-build
```
  
Next, configure the build: 
  
```
$ $SOURCE_DIR/gcc/configure \
    --prefix=$PREFIX \
    --host=$MACHTYPE \
    --build=$MACHTYPE \
    --target=$TARGET \
    --enable-languages=c,c++ \
    --disable-libmudflap \
    --disable-decimal-float \
    --with-mips-plt \
    --enable-__cxa_atexit \
    --with-arch=mips64r6 \
    --with-abi=64 \
    --disable-multilib \
    --with-sysroot=$SYSROOT
```
  
The `MACHTYPE` environment variable fully describes the system type on which *Bash* is running, in the standard *GNU* <*CPU*>-<*COMPANY*>-<*SYSTEM*> format (`x86_64-pc-linux-gnu`, for example).  

`--disable-libmudflap` and `--disable-decimal-float` options disable libraries that will not be needed. You can specify which libraries you don't want to be built with your cross-compilers accordingly.  

The `--with-mips-plt` option is a *MIPS*-specific option (more information can be found [here](https://gcc.gnu.org/onlinedocs/gcc/MIPS-Options.html)).  

The `--enable-__cxa_atexit` option defines that we want to use `__cxa_atexit` instead of `atexit` (more information can be found [here](https://gcc.gnu.org/install/configure.html)). We enable it for the *MIPS* target, but it is optional otherwise.  

`--with-sysroot=$SYSROOT` tells *GCC* to consider the `$SYSROOT` directory as the *system root*.  

Finally, build and install *GCC*'s *C* and *C++* cross-compilers:  
  
```
$ make all-gcc
$ make install-gcc
```
  

## Step 4: Build and Install Standard *C* Library Headers and Startup Files

In this step, we'll build and install *glibc*'s standard *C* library headers to the `$SYSROOT/usr/include/` directory.  

We also use the *C* compiler built in the previous step to compile the library's startup files and install them to the `$SYSROOT/usr/lib/` directory (`/usr/lib/` is the default directory in which the compiler searches for native system libraries).  

Finally, we create a couple of dummy files, `libc.so` and `stubs.h`, which are expected in step 5, but which will be replaced in step 6.  

First, position yourself inside the `$BUILD_DIR`, create `glibc-build/` subdirectory, and position yourself inside it:  
  
```
$ cd $BUILD_DIR
$ mkdir glibc-build
$ cd glibc-build
```
  
Next, configure the build: 
  
```
$ $SOURCE_DIR/glibc/configure \
    --prefix=/usr \
    --build=$MACHTYPE \
    --host=$TARGET \
    --target=$TARGET \
    --with-headers=$SYSROOT/usr/include \
    --with-arch=mips64r6 \
    --with-abi=64 \
    --disable-multilib \
    libc_cv_mips_force_execstack=no
```
  
The `/usr` prefix might seem confusing, but *glibc*'s build system checks if the prefix is equal to `/usr`, and does special handling if that is the case. Unless you use this prefix, you will end up with a *system root* that does not use the standard *Linux* layouts. The `install_root` variable in the following `make` commands indicates where the files should actually be installed; its value is treated as the parent directory of the directory we specified as the `--prefix` option in the `configure` command.  

Note that in *glibc*'s `configure`, both the `--host` and the `--target` options are meant to describe the system on which *glibc*'s libraries will ultimately run.  

The `--with-headers` option tells *glibc* where the *Linux Kernel Headers* have been installed.  

The `libc_cv_mips_force_execstack` variable is set to `no` in order to prevent warnings about forcing an executable stack for *MIPS* targets (more information can be found [here](https://sourceware.org/pipermail/glibc-cvs/2019q4/067958.html)).  

Finally, build and install standard *C* library headers and startup files:  
  
```
$ make install-headers install_root=$SYSROOT
$ make csu/subdir_lib
$ mkdir $SYSROOT/usr/lib64
$ install csu/crt1.o csu/crti.o csu/crtn.o $SYSROOT/usr/lib64
$ $TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $SYSROOT/usr/lib64/libc.so
$ touch $SYSROOT/usr/include/gnu/stubs.h
```
  
Note that we are using a `lib64/` directory, since we are building exclusively for a 64-bit architecture with a 64-bit *ABI*. For other architectures/*ABI*s, this should be adjusted accordingly.  

The `install-headers` *Makefile* target installs the headers.  

We also install *C* library's startup files, `crt1.o`, `crti.o`, and `crtn.o`, manually. There doesn't seem to be a `make` rule that does this without other side effects.  

`libgcc_s.so` requires a `libc.so` to link against. However, since we will never actually execute its code, it doesn't matter what it contains. So, treating `/dev/null` as a *C* source file, we produce a dummy `libc.so`.  

The `$SYSROOT/usr/include/gnu/stubs.h` header is needed by *glibc*'s *Makefile*. *glibc*'s *Makefile* targets create `stubs*.h` headers in each subdirectory, which contain `#define __stub_FUNCTION` for each function defined in that subdirectory which is a *stub*. Contents of all of these headers are pasted into the `$SYSROOT/usr/include/gnu/stubs.h` header, hence why we create an empty one.

## Step 5: Build and Install Compiler Support Library

This step uses *GCC*'s *C* and *C++* cross-compilers built in step 3 to build the compiler support library. The compiler support library contains some *C++* exception handling boilerplate code, among other things. This library depends on the startup files installed in step 4. The library itself is needed in step 6.  

To build and install the compiler support library, run the following commands:  
  
```
$ cd $BUILD_DIR/gcc-build
$ make all-target-libgcc
$ make install-target-libgcc
```
  
Two static libraries, `libgcc.a` and `libgcc_eh.a` are installed to the `$PREFIX/lib/gcc/$TARGET/<version>/` directory, and a shared library, `libgcc_s.so`, is installed to the `$PREFIX/$TARGET/lib64/` directory.

## Step 6: Build and Install the Standard *C* Library

This step finishes off the *glibc* package, which builds the standard *C* library and installs its files to the `$SYSROOT/usr/lib64/` directory. The static library is named `libc.a`, while the shared library is named `libc.so`.  

To build and install the standard *C* library, run the following commands:  
  
```
$ cd $BUILD_DIR/glibc-build
$ make
$ make install install_root=$SYSROOT
```
  
## Step 7: Build and Install the Standard *C++* Library

This step finishes off the *GCC* package, which builds the standard *C++* library and installs it to the `$PREFIX/$TARGET/lib64/` directory. It depends on the standard *C* library build in step 6. The static library is named `libstdc++.a`, while the shared library is named `libstdc++.so`.  

To build and install the standard *C++* library, run the following commands:  
  
```
$ cd $BUILD_DIR/gcc-build
$ make
$ make install
```
  
The build may throw an error because the `PATH_MAX` variable is not recognized within the `$SOURCE_DIR/gcc/libsanitizer/asan/asan_linux.cpp` file.  
  
The `PATH_MAX` variable is defined within the `$PREFIX/$TARGET/include/linux/limits.h` header (more information can be found [here](https://stackoverflow.com/questions/9449241/where-is-path-max-defined-in-linux)). By inspecting this header, we can see that the `PATH_MAX` variable has the value of 4096.  

In order to prevent the build error from happening, you can modify the `$SOURCE_DIR/gcc/libsanitizer/asan/asan_linux.cpp` file, by swapping:  
  
```
char filename[PATH_MAX];
```
  
with:  
  
```
char filename[4096];
```
  
# Cross-Compiling *DejaGNU*

*DejaGNU* tool is a framework for testing other programs, providing a single front-end for all tests. *GCC*'s *testsuite* is run via *DejaGNU*.

First, obtain the *DejaGNU* source code:

```
$ git clone git://git.sv.gnu.org/dejagnu.git
```

Next, configure the build:

```
$ cd $SOURCE_DIR/dejagnu
$ ./configure \
    --prefix=$PREFIX \
    --build=$MACHTYPE \
    --host=$TARGET \
    --target=$TARGET \
    CC=$PREFIX/bin/$TARGET-gcc \
    CXX=$PREFIX/bin/$TARGET-g++
```

Finally, build and install *DejaGNU*:

```
$ make
$ make install
```

# Testing the Cross-Compiler

In order to run the cross-compiler's testsuite, more setup might be required.

A fitting target board needs to be identified. Available target boards can be found in the `$PREFIX/share/dejagnu/baseboards/` directory. They might rely on linker to be using linker scripts from `libgloss`. Built cross-linker, however, uses an internal linker script, hence why setting `ldscript` needs to be skipped. For the `mips-sim-mti64_64` baseboard, commenting out the following line:

```
# Use the mti64_64.ld linker script from libgloss for the n64 ABI and the
# mips64 architecture on the gnu/gdb simulator.
set_board_info ldscript "-Tmti64_64.ld"
```

will do just that.

Additionally, if any execution tests are to be run, the default simulator can be overriden with the `SIM` variable. Its value is prepended to each test invocation.

For example, all of the cross-compiler's testsuite can be run (using a custom simulator) with the following command, invoked from the `$BUILD_DIR/gcc-build/` directory:

```
make check-gcc RUNTESTFLAGS="--target_board=<target-board-name>" SIM="<path-to-simulator> <option-1> <option-2> ..."
```

# Useful Links

- [https://wiki.osdev.org/GCC_Cross-Compiler](https://wiki.osdev.org/GCC_Cross-Compiler)
- [https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler](https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler)
- [http://www.eglibc.org/archives/patches/msg00078.html](http://www.eglibc.org/archives/patches/msg00078.html)
- [https://www.gnu.org/software/dejagnu](https://www.gnu.org/software/dejagnu)
# Running GCC Testsuite for MIPS architecture

A script named `run_mips_gcc_testsuite` is to be used for testing GCC cross-compiler
for the MIPS64R6 architecture.

## Requirements

- make (Comes pre-installed on most operating systems)
- DejaGNU
- QEMU

First, a fresh DejaGNU build from source is needed. DejaGNU is a testing framework
that is used for running the GCC testsuite. Clone the repository like so:

```
git clone git://git.sv.gnu.org/dejagnu.git
```

Next, position yourself inside the cloned directory and run `configure`:

```
./configure \
    --prefix=$PREFIX \
    --build=$MACHTYPE \
    --host=$TARGET \
    --target=$TARGET \
    CC=$PREFIX/bin/$TARGET-gcc \
    CXX=$PREFIX/bin/$TARGET-g++
```

Notice that there are three enviroment variables that are being used:
`$TARGET` is the target we are building for (`mipsisa64r6-linux-gnuabi64` in this case),
`$PREFIX` is the installation directory, and `$MACHTYPE` is the triple of your system
(it should be set to `x86_64-pc-linux-gnu` by your shell). 
These variables can be initialized or changed with `export` commands.

After configuring DejaGNU, run `make` and install it in the `$PREFIX` directory, as
configured in the previous step.

```
make
make install
```

Because we need to run tests on an architecture which is different from the architecture
those tests were compiled for, we need an emulator. Here, we'll be using QEMU.
In this case, we need to run programs compiled for MIPS architecture on x86_64 platform
in order to be able to run the testsuite.

On *Ubuntu* operating system, install QEMU by running the following command:

```
sudo apt install qemu-user
```

This will provide the user with different emulators for different architectures. One that
we'll be using is `qemu-mips64`.

## Running the script

Now, we are ready to run the script:

```
run_mips_gcc_testsuite [OPTION]
```
### Options usage:

- `--sys-root=path/to/sysroot` 

  This is the only mandatory field, where the sysroot directory must be specified.
- `--num-threads=number_of_threads_used` 

  Specifies the number of thread used for running the testsuite. By default, all
  threads are enabled.
- `--test-driver=driver_name` 

  Specifies the test driver name (e.g. `mips.exp`).
- `--test-regex="regex"` 

  Specifies the regular expression which filters the tests being run.
  This option requires `--test-driver` option being set.
- `--emulator-path=path/to/emulator/executable` 

  Set this option if you want to override the emulator used. 
  By default, script uses `qemu-mips64` executable located in PATH.

Attachment: run_mips_gcc_testsuite
Description: run_mips_gcc_testsuite

Reply via email to