How to specify C++ compiler executable

I would like to set up a build for an embedded system which can either produce a Xilinx MicroBlaze binary or a Windows binary (compiled by Mingw for simulation). I have succeeded in compiling a simple test project under Windows, but I haven’t figured out how to specify the MicroBlaze compiler (mb-g++ instead of g++).

I could resort to tricks such as redirecting the PATH to a g++.bat file which calls mb-g++, but I would still need to declare a “microblaze” processor architecture so that the build would produce the correct variant – and I cannot seem to find how to do that, either.

You might consider having a look at https://nokee.dev/ which is greatly simplified the native support that Gradle should have built-in. :smiley:

Thanks for the link! I’ll definitely check that out.

I took a look at nokee, but aside from providing an additional plugin for compiling JNI modules, it seems very similar to the Gradle 8.1 C++ plugins. The site did mention the deprecated model-based native plugin, though. Since that one supports cross-compilation, I thought I’d give it a try, assuming it won’t be discontinued until the new version reaches feature parity.

Using the build script below, I successfully got Gradle to invoke the mb-gcc compiler, but it looks like the compiler does not accept @option files. Is there a way to get Gradle to specify compiler options directly on the command line?

build.gradle:

plugins {
    id 'c'
}

model {
    platforms {
        x86 {
            architecture 'x86'
        }
        microblaze {
            architecture 'microblaze'
        }
    }

    toolChains {
        gcc(Gcc) {
            target('x86')
            target('microblaze') {
                cCompiler.executable = 'mb-gcc.exe'
                linker.executable = 'mb-ld.exe'

                cCompiler.withArguments { args ->
                    args << '-mno-xl-soft-mul'
                    args << '-mxl-barrel-shift'
                    args << '-mno-xl-soft-div'
                    args << '-mhard-float'
                    args << '-mxl-float-convert'
                    args << '-mxl-float-sqrt'
                    args << '-mcpu=v7.10.a'
                }
            }
        }
    }

    components {
        main(NativeExecutableSpec) {
            targetPlatform 'x86'
            targetPlatform 'microblaze'
        }
    }
}

Result:

> Task :compileMainMicroblazeExecutableMainC FAILED
Found all include files for ':compileMainMicroblazeExecutableMainC'
Caching disabled for task ':compileMainMicroblazeExecutableMainC' because:
  Build cache is disabled
Task ':compileMainMicroblazeExecutableMainC' is not up-to-date because:
  Task has failed previously.
The input changes require a full rebuild for incremental task ':compileMainMicroblazeExecutableMainC'.
See file:///C:/globe/c-application/build/tmp/compileMainMicroblazeExecutableMainC/output.txt for all output for compileMainMicroblazeExecutableMainC.
Starting process 'command 'C:\Xilinx\13.4\ISE_DS\EDK\gnu\microblaze\nt64\bin\mb-gcc.exe''. Working directory: C:\globe\c-application\build\objs\main\microblaze\mainC Command: C:\Xilinx\13.4\ISE_DS\EDK\gnu\microblaze\nt64\bin\mb-gcc.exe @C:\globe\c-application\build\tmp\compileMainMicroblazeExecutableMainC\options.txt C:\globe\c-application\src\main\c\main.c -o C:\globe\c-application\build\objs\main\microblaze\mainC\7ywyobd9l7sopuxey9ya912jy\main.obj
Successfully started process 'command 'C:\Xilinx\13.4\ISE_DS\EDK\gnu\microblaze\nt64\bin\mb-gcc.exe''
mb-gcc.exe: @C:\globe\c-application\build\tmp\compileMainMicroblazeExecutableMainC\options.txt: Invalid argument

What you are experiencing is a limitation of the toolchain declaration in Gradle. Internally, it supports not using command files, and for this, you have to use canUseCommandFile = false under the microblaze configuration action. I hope that help.

Thanks for that, it almost worked. Gradle accepts the syntax, but it still attempts to specify the options in a command file.

    toolChains {
        gcc(Gcc) {
            target('x86')
            target('microblaze') {
                cCompiler.executable = 'mb-gcc.exe'
                linker.executable = 'mb-ld.exe'
                canUseCommandFile = false

                cCompiler.withArguments { args ->
                    args << '-mno-xl-soft-mul'
                    args << '-mxl-barrel-shift'
                    args << '-mno-xl-soft-div'
                    args << '-mhard-float'
                    args << '-mxl-float-convert'
                    args << '-mxl-float-sqrt'
                    args << '-mcpu=v7.10.a'
                }
            }
        }
    }

Let me trace the property a bit more. I may have overlooked something.

Hi. Do you have this working with gradle 8.5? (For me it seems to be not working on 8.5). What version did you use?

The code to configure the toolChains is part of the legacy native support, which is still used today. It should still work on Gradle 8.5. If you have an example of what is failing, I can give it a try and help you.

Hi Daniel
Thanks for your offer and quick response.
Below is my app/build.gradle.kts. As documented below I used gradle init to generate the project. And did (try) to update the apps build file as follows:

/*
 * This file was generated by the Gradle 8.5 'init' task.
 * init settings: application/C++/Kotlin/CppExample/old api's
 *
 * There is a directory "~/luckfox/arm-rockchip830-linux-uclibcgnueabihf/arm-rockchip830-linux-uclibcgnueabihf/bin" (called bindir below)
 * it contains:
 * arm-rockchip830-linux-uclibcgnueabihf-gcc
 * arm-rockchip830-linux-uclibcgnueabihf-ar
 * arm-rockchip830-linux-uclibcgnueabihf-as
 * arm-rockchip830-linux-uclibcgnueabihf-ld
 * ...
 *
 * purpose: cross compile c++ application for 32 bits luckfox arm-v7 processor on ubuntu
 */
import org.gradle.nativeplatform.toolchain.Gcc

plugins {
   `cpp-application`
   `cpp-unit-test`
}

// luckfox is 32 bits arm v7 processor
application {
    targetMachines.add(machines.linux.x86)
}

toolChains {
    gcc(Gcc) {
        target('x86')
        cCompiler.executable = "[bindir]/arm-rockchip830-linux-uclibcgnueabihf-cpp"
        linker.executable = "[bindir]/arm-rockchip830-linux-uclibcgnueabihf-ld"
        canUseCommandFile = false
    }
}

The attempt fails at the gcc configuration. It seems the old configuration is not working here as it fails with the error gcc is not allowed there (Unresolved reference: gcc).
Can you give me a pointer how to proceed (or what documentation I’ve missed :slight_smile: )?
Thanks on advance!
Peter

Was able to hack a bit (but I do not think this is the solution):

toolChains {
    toolChains.withType<GccToolChain>() {
        eachPlatform {
            cppCompiler.executable = "[bindir]/arm-rockchip830-linux-uclibcgnueabihf-cpp"
        }
    }
}

but this gives error

Execution failed for task ':app:compileDebugCpp'.
> Error while evaluating property 'compilerVersion' of task ':app:compileDebugCpp'.
   > Cannot invoke "org.gradle.nativeplatform.toolchain.internal.gcc.metadata.GccMetadata.getVendor()" because the return value of "org.gradle.platform.base.internal.toolchain.SearchResult.getComponent()" is null

Peter

I was never able to get canUseCommandFile = false to work (using Gradle 8.2, if I recall). Due to this, and the fact that the model-based native plugin was deprecated, we decided to stick with SCons for building our embedded code.