Cross-Compilation Support

CFiddle support cross-compilation so you can compare assembly across architectures and compilers.

Compiling with Other Compilers

CFiddle knows about clang and clang++, so you can pass them as a build_parameter to cfiddle.build() as CC or CXX, and they should work.

Clang cross-compilation is not yet supported.

Compiling for Other Architectures

To compile for multiple architecture you have two choices

  1. Add ARCH to your build_parameters argument to cfiddle.build().

  2. Specify the relevent compiler as CC or CXX in build_parameters.

For example, using ARCH:

>>> from cfiddle import  *
>>> sample = code(r"""extern "C" int answer() {return 42;}""")
>>> b = build(sample, arg_map(ARCH=["native", "aarch64"]))
>>> print(b[0].get_toolchain().describe())
g++ compiling for X86_64
>>> print(b[1].get_toolchain().describe())
arm-linux-gnueabi-g++ compiling for AARCH64
>>> print(b[0].asm("answer")) 
answer:
.LFB0:
     .file 1 ".cfiddle/builds/anonymous_code/4a85359e935ea45cb52e2bd57d6c66cc.cpp"
     .loc 1 1 25
     .cfi_startproc
     endbr64
     pushq   %rbp
     .cfi_def_cfa_offset 16
     .cfi_offset 6, -16
     movq    %rsp, %rbp
     .cfi_def_cfa_register 6
     .loc 1 1 33
     movl    $42, %eax
     .loc 1 1 36
     popq    %rbp
     .cfi_def_cfa 7, 8
     ret
     .cfi_endproc
>>> print(b[1].asm("answer")) 
answer:
     .fnstart
.LFB0:
     .file 1 ".cfiddle/builds/anonymous_code/4a85359e935ea45cb52e2bd57d6c66cc.cpp"
     .loc 1 1 25
     .cfi_startproc
     @ args = 0, pretend = 0, frame = 0
     @ frame_needed = 1, uses_anonymous_args = 0
     @ link register save eliminated.
     str     fp, [sp, #-4]!
     .cfi_def_cfa_offset 4
     .cfi_offset 11, -4
     add     fp, sp, #0
     .cfi_def_cfa_register 11
     .loc 1 1 33
     mov     r3, #42
     .loc 1 1 36
     mov     r0, r3
     add     sp, fp, #0
     .cfi_def_cfa_register 13
     @ sp needed
     ldr     fp, [sp], #4
     .cfi_restore 11
     .cfi_def_cfa_offset 0
     bx      lr
     .cfi_endproc
.LFE0:
     .cantunwind
     .fnend

You can also set CXX: or CC: to any GCC compiler and CFiddle will figure out the tool chain:

>>> from cfiddle import  *
>>> sample = code(r"""extern "C" int answer() {return 42;}""")
>>> b = build(sample, arg_map(CXX=["g++", "arm-linux-gnueabi-g++"]))
>>> print(b[0].get_toolchain().describe())
g++ compiling for X86_64
>>> print(b[1].get_toolchain().describe())
arm-linux-gnueabi-g++ compiling for AARCH64

You can also set ARCH and CXX or CC to specify, for example, compiler versions:

>>> from cfiddle import  *
>>> from cfiddle.util import invoke_process
>>> sample = code(r"""extern "C" int answer() {return 42;}""")
>>> arm_versions = [x for x in ["g++-8", "g++-9", "g++-11"] if invoke_process([f"arm-linux-gnueabi-{x}", "-v"])[0]]
>>> b = build(sample, arg_map(ARCH="aarch64", CXX=arm_versions))
>>> print(b[0].get_toolchain().describe()) 
arm-linux-gnueabi-g++-9 compiling for AARCH64
>>> print(b[1].get_toolchain().describe()) 
arm-linux-gnueabi-g++-8 compiling for AARCH64

Available Architectures

ARCH just provides a shorthand for setting a prefix on your compiler (for gcc-based cross-compilers). The valid values are:

>>> print("\n".join(map(str,list_architectures())))
('AARCH64', 'arm-linux-gnueabi')
('ARM', 'arm-linux-gnueabi')
('X86_64', 'x86_64-linux-gnu')
('X86', 'x86_64-linux-gnu')
('PPC64', 'powerpc-linux-gnu')
('PPC', 'powerpc-linux-gnu')
('POWERPC', 'powerpc-linux-gnu')
('NATIVE', '')

The names are not case sensitive.

Installing Cross Compilers

The CFiddle distribution includes scripts to install ARM, PowerPC, and x86 cross compilers under Ubuntu with these scripts:

  • bin/install_arm_cross.sh

  • bin/install_ppc_cross.sh

  • bin/install_x86_cross.sh

Once installed these should just work if you installed using PyPi. If you installed from source, you’ll need to build libcfiddle.so for each architecture with :

cd src/cfiddle/resources/libcfiddle
make clean
make

To support for a new architecture, you’ll need to:

  1. Build and install libpfm4 for your architecture (follow the model in the scripts above).

  2. Build libcfiddle.so – follow the model in src/cfiddle/resources/libcfiddle/Makefile.

For new GCC-based toolchains, that should be it.

For others, you’ll need to add a subclass of cfiddle.Toolchain.Toolchain. Follow the examples under src/cfiddle/toolchains/.

Key Functions

cfiddle.list_architectures()

List available compilation-targets.

Returns:

Each tuple contains an architecture name and the corresponding toolchain prefix.

Return type:

list of tuples