The Arm Toolchain for Linux (ATfL)

July 7, 2026 ยท View on GitHub

Welcome to the Arm Toolchain for Linux!

This toolchain is based on the LLVM compiler suite. It has been prepared specifically for the AArch64 GNU/Linux systems.

Installation

After unpacking the ATfL tarball, the atfl directory becomes available, which contains a complete toolchain directory tree.

Usage

The ATfL toolchain consists of the full LLVM toolkit: the compiler and the auxiliary tools. There are three compilers available:

  • armclang - The C compiler
  • armclang++ - The C++ compiler
  • armflang - The Fortran compiler

Before using the compiler, it is worth sourcing the env.bash script, which sets the PATH variable, so the compiler commands are easily available:

$ . atfl/env.bash

$ which armclang
~/atfl/bin/armclang

The command line syntax is the same as LLVM's. For a more detailed description of LLVM and the Clang compiler, you can visit this page: https://clang.llvm.org/docs/UsersManual.html

The Fortran compiler has been described here: https://flang.llvm.org/docs and its command line reference has been provided here: https://flang.llvm.org/docs/FlangCommandLineReference.html

Fortran support

The armflang compiler is the mainline LLVM Flang compiler (previously known as flang-new). It supports the Fortran language standards up to and including 2003, except for length PDTs. It also largely (but not completely) supports the 2008 standard and some features of the 2018 standard (like assumed-rank). The Coarrays are not supported.

OpenMP support in Fortran

Experimental OpenMP 2.5 support has been made available, except atomic write and capture with a COMPLEX type.

Vectorizing loops with optimized math function calls

To extend auto-vectorization capabilities with the ability to make it vectorize the loops containing any calls to the math library functions, The -fveclib=ArmPL flag has been set by default. The consequence of this is that the final executable binary is linked against the vectorized functions library.

Using Arm Performance Libraries (ArmPL) with ATfL

The Arm Performance Libraries suite (ArmPL) provides optimized standard core math libraries for numerical applications on 64-bit Arm(R) processors (AArch64).

In order to use ArmPL with ATfL, a special version of ArmPL needs to be downloaded from this page: https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Libraries#Downloads

The Fortran part of this library has been compiled with Flang (known as flang-new at the time the ArmPL tarballs have been created), which should be library-compatible with the ATfL's Fortran compiler.

A tarball matching with the installed Linux distribution should be downloaded (for example, arm-performance-libraries_24.10_deb_flang-new.tar). In this guide, Ubuntu is being used as an example.

By default, ArmPL is installed to the globally accessible /opt/arm directory. However, this requires root privileges during installation. For simplicity, this guide follows the single-user installation flow, which installs ArmPL into your home directory.

Installation in the user's home directory

To proceed with the installation, unpack the tarball and run the installation script:

$ tar -xf arm-performance-libraries_24.10_deb_flang-new.tar

$ arm-performance-libraries_24.10_deb/arm-performance-libraries_24.10_deb.sh -a -i $HOME/armpl

Note that the installation script will extract the ArmPL files into your $HOME/armpl directory from unpacked the .deb files, it will execute the dpkg command for this purpose.

Using provided environment module files

Although this is optional, it is worth loading the provided armpl environment module. This should set the ARMPL_-prefixed environment variables and two other critical environment variables: LD_LIBRARY_PATH and PKG_CONFIG_PATH:

$ MODULEPATH=$HOME/armpl/modulefiles module avail
---- $HOME/armpl/modulefiles ----
armpl/24.10.0_flang-new

Key:
modulepath

$ MODULEPATH=$HOME/armpl/modulefiles module load armpl

$ set | grep ARMPL
ARMPL_BUILD=16
ARMPL_DIR=/home/pawosm01/armpl/armpl_24.10_flang-new
ARMPL_INCLUDES=/home/pawosm01/armpl/armpl_24.10_flang-new/include
ARMPL_LIBRARIES=/home/pawosm01/armpl/armpl_24.10_flang-new/lib

$ echo $LD_LIBRARY_PATH
$HOME/armpl/armpl_24.10_flang-new/lib

$ echo $PKG_CONFIG_PATH
$HOME/armpl/armpl_24.10_flang-new/lib/pkgconfig

$ pkg-config armpl --modversion
24.10.0

$ pkg-config armpl --variable=libdir
$HOME/armpl/armpl_24.10_flang-new/lib/pkgconfig/../../lib

$ ls -1 `pkg-config armpl --variable=libdir`
libamath.a
libamath.so
libarmpl.a
libarmpl.so
libarmpl_ilp64.a
libarmpl_ilp64.so
libarmpl_ilp64.so.3
libarmpl_ilp64.so.3.12.0
libarmpl_ilp64_mp.a
libarmpl_ilp64_mp.so
libarmpl_ilp64_mp.so.3
libarmpl_ilp64_mp.so.3.12.0
libarmpl_int64.a
libarmpl_int64.so
libarmpl_int64_mp.a
libarmpl_int64_mp.so
libarmpl_lp64.a
libarmpl_lp64.so
libarmpl_lp64.so.3
libarmpl_lp64.so.3.12.0
libarmpl_lp64_mp.a
libarmpl_lp64_mp.so
libarmpl_lp64_mp.so.3
libarmpl_lp64_mp.so.3.12.0
libarmpl_mp.a
libarmpl_mp.so
libastring.a
libastring.so
pkgconfig

Note that the ArmPL library exports several pkg-config modules, you should be picking the one that you really need, particularly when you plan to use OpenMP:

$ pkg-config --list-all | grep armpl
armpl                           ArmPL - Arm Performance Libraries
armpl-Fortran-dynamic-ilp64-omp ArmPL - Arm Performance Libraries
armpl-Fortran-dynamic-ilp64-seq ArmPL - Arm Performance Libraries
armpl-Fortran-dynamic-lp64-omp  ArmPL - Arm Performance Libraries
armpl-Fortran-dynamic-lp64-seq  ArmPL - Arm Performance Libraries
armpl-Fortran-static-ilp64-omp  ArmPL - Arm Performance Libraries
armpl-Fortran-static-ilp64-seq  ArmPL - Arm Performance Libraries
armpl-Fortran-static-lp64-omp   ArmPL - Arm Performance Libraries
armpl-Fortran-static-lp64-seq   ArmPL - Arm Performance Libraries
armpl-dynamic-ilp64-omp         ArmPL - Arm Performance Libraries
armpl-dynamic-ilp64-seq         ArmPL - Arm Performance Libraries
armpl-dynamic-lp64-omp          ArmPL - Arm Performance Libraries
armpl-dynamic-lp64-seq          ArmPL - Arm Performance Libraries
armpl-static-ilp64-omp          ArmPL - Arm Performance Libraries
armpl-static-ilp64-seq          ArmPL - Arm Performance Libraries
armpl-static-lp64-omp           ArmPL - Arm Performance Libraries
armpl-static-lp64-seq           ArmPL - Arm Performance Libraries

$ pkg-config armpl-dynamic-ilp64-omp --cflags
-DINTEGER64 -fopenmp -I$HOME/armpl/armpl_24.10_flang-new/lib/pkgconfig/../../include

The default armpl module is an equivalent of armpl-static-lp64-seq.pc:

$ pkg-config armpl --cflags
-static -I$HOME/armpl/armpl_24.10_flang-new/lib/pkgconfig/../../include

Examples of use

Compiling and linking an example C/C++ program

Note that the --libs flag is not yet supported by the ArmPL's pkg-config modules, hence the examples below make use only of the --libs-only-L flag instead and the libraries to link are being listed explicitly.

Plain C file

Compiling:

$ armclang -c example.c `pkg-config armpl --cflags`

Linking:

$ armclang -o example example.o `pkg-config armpl --libs-only-L` -larmpl -lm -static
Plain C++ file

Compiling:

$ armclang++ -c example.cc `pkg-config armpl --cflags`

Linking:

$ armclang++ -o example example.o `pkg-config armpl --libs-only-L` -larmpl -lm -static
An OpenMP C example

Compiling:

$ armclang -fopenmp -c example.c `pkg-config armpl-dynamic-lp64-omp --cflags`

Linking:

$ armclang -fopenmp -o example example.o `pkg-config armpl-dynamic-lp64-omp --libs-only-L` -larmpl -lm

$ ldd ./example
    linux-vdso.so.1 (0x0000f76d2927d000)
    libarmpl.so => $HOME/armpl/armpl_24.10_flang-new/lib/libarmpl.so (0x0000f76d25200000)
    libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000f76d25160000)
    libomp.so => $HOME/atfl/bin/../lib/aarch64-unknown-linux-gnu/libomp.so (0x0000f76d25050000)
    libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000f76d24ea0000)
    librt.so.1 => /lib/aarch64-linux-gnu/librt.so.1 (0x0000f76d29210000)
    libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000f76d24e70000)
    /lib/ld-linux-aarch64.so.1 (0x0000f76d29244000)

Compiling and linking example Fortran program

Compiling (yes, it is still --cflags being passed to pkg-config):

$ armflang -c example.f90 `pkg-config armpl --cflags`

Linking:

$ armflang -o example example.o `pkg-config armpl --libs-only-L` -larmpl -lm -static

An OpenMP Fortran example:

$ armflang -fopenmp -c example.f90 `pkg-config armpl-Fortran-dynamic-lp64-omp --cflags`
flang-20: warning: OpenMP support in flang is still experimental [-Wexperimental-option]

$ armflang -fopenmp -o example example.o `pkg-config armpl-Fortran-dynamic-lp64-omp --libs-only-L` -larmpl -lm

$ ldd ./example
    linux-vdso.so.1 (0x0000f0bd2175a000)
    libarmpl.so => $HOME/armpl/armpl_24.10_flang-new/lib/libarmpl.so (0x0000f0bd1d600000)
    libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000f0bd21660000)
    libFortranRuntime.so.20.0 => $HOME/atfl/bin/../lib/aarch64-unknown-linux-gnu/libFortranRuntime.so.20.0 (0x0000f0bd1cc00000)
    libFortranDecimal.so.20.0 => $HOME/atfl/bin/../lib/aarch64-unknown-linux-gnu/libFortranDecimal.so.20.0 (0x0000f0bd21610000)
    libatomic.so.1 => /lib/aarch64-linux-gnu/libatomic.so.1 (0x0000f0bd215f0000)
    libomp.so => $HOME/atfl/bin/../lib/aarch64-unknown-linux-gnu/libomp.so (0x0000f0bd1caf0000)
    libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000f0bd1c940000)
    librt.so.1 => /lib/aarch64-linux-gnu/librt.so.1 (0x0000f0bd1d5e0000)
    libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000f0bd1c910000)
    /lib/ld-linux-aarch64.so.1 (0x0000f0bd21721000)

Using ArmPL without loading the environment module

In the examples above it was assumed that the environment module for ArmPL has been loaded, therefore the LD_LIBRARY_PATH variable has been set. This helps the dynamic linker to find the ArmPL shared object file when an executable program is being loaded. Yet if loading a module is not desirable, the RPATH needs to be set for the non-static builds at the link time.

An OpenMP C example:

$ armclang -fopenmp -o example example.o `pkg-config armpl-dynamic-lp64-omp --libs-only-L` -larmpl -lm -Wl,-rpath=`pkg-config armpl-dynamic-lp64-omp --variable=libdir`

$ chrpath -l ./example
./example: RUNPATH=$HOME/armpl/armpl_24.10_flang-new/lib/pkgconfig/../../lib:$HOME/atfl/lib/clang/20/lib/aarch64-unknown-linux-gnu:$HOME/atfl/bin/../lib/aarch64-unknown-linux-gnu

Nightly build binary distribution

ATfL Nightly Build and Test hosts nightly builds, and provides binary artifacts in form of tarball.

Verify sha256 checksum of tarball, before further usage.

ATfL binaries must be used on trusted inputs (such as the customer's own source code). If it is run on untrusted code, then the customer must sandbox the compiler.

It is recommended to use latest binaries from nightly builds.

Providing feedback and reporting issues

Please see the Contribution Guide for guidance on how to report an issue or raise a feature request.

Contributions and Pull Requests

Please see the Contribution Guide for details.