gradle / gradle-native

The home of Gradle's support for natively compiled languages
https://blog.gradle.org/introducing-the-new-cpp-plugins
Apache License 2.0
93 stars 8 forks source link

Custom gcc executable #1073

Open iharh opened 4 years ago

iharh commented 4 years ago

I'm using a new native plugins (cpp-library, cpp-application) without old software model.

My question is:

I don’t see any sample of customizing toolChain object - just selection other options based on the value of toolChain

UPDATE: managed to find this sample, but it does not work as exected

application {
    toolChains {
        withType<Gcc> {
            eachPlatform {
                // this: GccPlatformToolChain
                cppCompiler.setExecutable("compat-g++")
                println("cppCompiler.executable: ${cppCompiler.executable}")
            }
       }
    }
    ...
}
lacasseio commented 4 years ago

Unfortunately, this is an unfinished business. You will have to use the software model for that specific task (the new plugins use the software model tool chain repository under the hood. You can see how it's done over here: https://docs.gradle.org/current/userguide/native_software.html#native_binaries:tool_chain

Unfortunately, you can't use Kotlin build script with the software model.

Correct me if I'm wrong. The use case you are trying to solve is building with a specialized toolchain. I assume the compat part is for backward compatibility on older system.

iharh commented 4 years ago

You are right. BTW, are there any workarounds, hacks and so on to deal with my case?

bamboo commented 4 years ago

The Gradle Kotlin DSL doesn't provide a model DSL but it is still possible to write model rules in pure Kotlin, the following sample might be helpful: https://github.com/gradle/kotlin-dsl-samples/tree/master/samples/model-rules

Alternatively, a Groovy script could be applied from the main Kotlin build script specifically to configure the model.

iharh commented 4 years ago

Thank you. The groovy script works (and worked fine for me long time ago):

model {
    toolChains {
        gcc(Gcc) {
            eachPlatform {
                cCompiler.executable 'compat-g++'
                cppCompiler.executable 'compat-g++'
                linker.executable 'compat-g++'
            }
        }
    }

Let me just try to use them with a new 'cpp-application' plugin (vs old-one 'cpp')...

lacasseio commented 4 years ago

Unfortunately, dealing with toolchain has always been an issue, especially with native where there is a large number of them with slight differences between each one of them. With the Nokee plugins, I will soon start some work on addressing this pain. Feel free to follow the work being done there.

iharh commented 4 years ago

Thank you. Will wait.

andreiled commented 4 years ago

Hi all,

I am working on a build configuration using emscripten and was able to get rather far with the help of this discussion.

However, I am now following issue:


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':linkDebug'.
> java.lang.NullPointerException (no error message)

After debugging Gradle's code, I was able to determine that Gradle refuses to recognize emlink as a valid replacement for ld since it does not support special -dM -E -v arguments combination that Gradle relies on in order to determine linker version.

Could you suggest how I can completely sidestep whole compiler's metadata resolution process via build configuration or a custom build plugin?

andreiled commented 4 years ago

Could you suggest how I can completely sidestep whole compiler's metadata resolution process via build configuration or a custom build plugin?

Never mind: more snooping around the code revealed that for Clang/Gcc tool chains C++ compiler is expected to function as a linker as well. In other words, above problem is addressed by configuring Gradle to use em++.bat as linker instead of emlink.

lacasseio commented 4 years ago

In an ideal world, you should be able to compose the compilation for other language with the building block of native where it overlap. Unfortunately, Gradle native code model didn't achieve this level and is opinionated to building strictly native code (C/C++, Objective-C/C++ and Swift). On the Nokee project, we will soon start a process to allow users to use each part of the model individually. Feel free to tell us what you would need.

With regards to using Gradle core modeling for your use case, you could create a replacement task that you wire in place of the current link task. Then you just disable the old link task. It allow you to access the configuration of the old task while providing a new implementation.

andreiled commented 4 years ago

On the Nokee project, we will soon start a process to allow users to use each part of the model individually. Feel free to tell us what you would need.

Could you clarify a bit on that: does Nokee re-imagines/replaces Gradle's own native plugins, or does it built on top of them? I have a feeling that I will end up implementing my own emcc-compiler plugin using clang-compiler plugin as a sample.

lacasseio commented 4 years ago

Nokee is a continuous effort on bringing native support to Gradle. It borrows ideas from current implementations and move forward with the initial plan. It focus on C, C++, Objective-C, Objective-C++ and Swift. Other languages are out of scope but we are keeping in mind the possibility to compose components out of Nokee's infrastructure.

lacasseio commented 4 years ago

At the moments, it borrows some of the core Gradle infrastructure and will move to our own as required.

andreiled commented 4 years ago

Got that, I will proceed in a similar fashion for my case as well: start by implementing new {{Emcc extends Clang}} toolchain and override aspects of default behavior that do not suite me.

dickensas commented 3 years ago

I did this in Kotlin DSL

I have created a class

class PlatformAction : Action<GccPlatformToolChain> {
    override fun execute(toolChain: GccPlatformToolChain) {
        toolChain.getCppCompiler().setExecutable("gfortran")
    }
}

either application block or library block


library {
    targetMachines.add(machines.windows.x86_64)
    linkage.set(listOf(Linkage.SHARED))
    toolChains.configureEach {
        when (this) {
            is GccCompatibleToolChain -> {
                this.eachPlatform(PlatformAction() as Action<in GccPlatformToolChain>)
            }
            else -> {}
        }
    }
}