Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle C Plugin by Example

On my local file system I have the following C project directory structure:

derpus/
    src/
        derpus/
            c/
                derpus.c
            headers/
    build.gradle

Where derpus.c is:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    puts("Derp!");
    return EXIT_SUCCESS;
}

I would like to use the Gradle Native (C) Plugin to manage the full spectrum of the derpus build. Specifically I would like Gradle to:

  1. Generate a Gradle wrapper so that I can use gradlew for all my build invocations; and
  2. Compile & build derpus into derpus.exe via gradlew; and
  3. Generate Eclipse project info when I run gradlew eclipse so I can then import the project into Eclipse (I have already pre-installed the Eclipse CDT plugin)

Here is my build.gradle:

apply plugin: 'c'
apply plugin: 'eclipse'

sources {
    c {
        source {
            srcDir "src/derpus/c"
            include "**/*.c"
        }
        exportedHeaders {
            srcDir "src/derpus/headers"
        }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

Obviously I should be able to run gradle wrapper to take care of the first item. But as for compiling and building, no where in the C plugin docs do I actually see a command or build invocation that actually runs a compile and build!

As for the third item, using the Eclipse plugin and invoking it via gradlew eclipse, I'm wondering if there's anything else I need to do so that the resultant project/settings configs are compatible with what the Eclipse CDT plugin expects in order to work with C programs. Although I intend to let Gradle handle all my builds, I still want to do all my development in Eclipse, and so all the things that CDT comes with (syntax highlighting, compiling, etc.) is important to me.

like image 469
smeeb Avatar asked May 07 '15 10:05

smeeb


People also ask

Does Gradle support C?

Gradle is a build automation system that provides plugins to build C/C++ libraries and applications. In CLion, you can work with Gradle projects that are based on cpp-application and cpp-library plugins (for more details on C/C++ Gradle plugins, see this blog post: Introducing the new C++ plugins).

Can you use Gradle with C++?

Gradle has general support for the three major tool chains on major operating system: Clang, GCC and Visual C++ (Windows-only).

How do I add plugins to Gradle?

Put the source of the plugin directly into the build. gradle file. One big advantage of this approach is that the class is automatically compiled and added to the classpath of the build script without you configuring anything. The disadvantage is that the plugin cannot be used in another module.

Is Bazel better than Gradle?

In summary, the data and analysis indicates clearly that Gradle is a better choice than Bazel for most JVM projects. We will provide an equivalent comparison for Android projects in a follow up article.


2 Answers

OK I figured all 3 out, and thought I would post this answer for any future readers.

Please note: This solution is really on viable for modern C programmers who:

  • Want to do all development in Eclipse, taking advantage of modern IDE facilities like syntax highlighting, error, goto declaration, open call hierarchy, Eclipse's debugger, etc.; but...
  • Want a modern, kick-a** build system like Gradle to do all the command-line/shell building

Furthermore, because I'm on Windows, I chose to use MinGW for my GCC provisioning, and so if you're either on *nix or Mac, or if you prefer Cygwin, you'll have to customize this solution even further.

Even furthermore, I have only verified this works with Eclipse Luna, using the latest Eclipse CDT plugin (8.6) and using Gradle 2.3.

Solution

First I had to correct my usage of the C plugin, changing my build.gradle to look like this:

apply plugin: 'c'
apply plugin: 'eclipse'

model {
    components {
        derpus(NativeExecutableSpec) {
            sources {
                c(CSourceSet) {
                    source {
                        srcDir "src/derpus/c"
                        include "**/*.c"
                    }
                    exportedHeaders {
                        srcDir "src/derpus/headers"
                    }
                }
            }
        }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

This allowed me to run gradle wrapper without any errors.

Next, I began to find it very peculiar that the Gradle Native Binaries documentation never mentions the build invocation for compiling/building native executables. I took a wild guess that it might be leveraging Gradle's "convention over configuration" approach, and I ran gradlew build - voila! Great success. Now under derpus/build/binaries/derpusExecutable I have derpus.exe! So far, so good.

The real headache sets in when you want to now import this Gradle-managed project into Eclipse, but still have Eclipse CDT provide all the normal features of a modern C IDE.

I started off by running gradlew eclipse, which added the following files under the derpus/ project root:

  • .project
  • .settings/language.settings

I opened Eclipse and imported it as a project, however I got all sorts of errors, and when I hovered over #include <stdio.h> in my derpus.c file, and clicked F3, Eclipse did nothing. Clearly something was still not configured right. And so I got to hacking.

Turns out you just need to:

  • Of course, first make sure the CDT plugin is installed and working correctly (doh!)
  • Create a "dummy" C project in Eclipse, which will allow you to copy n' paste Eclipse CDT-generated settings/configs to your actual project
  • Modify your actual .project file to include the same <buildSpec /> and <natures /> elements that were generated in the dummy project's .project file
  • Copy the dummy project's .cproject file over to your actual project's root, and then open it in a text editor. You want to rename ALL instances of the dummy project's name with the name of your actual project; in my case there were 3 instances. In my case, my dummy project was literally named dummy, and my actual project is named derpus. So I had to change 3 instances of dummy to derpus in this file.
  • Restart Eclipse

Your actual project will now behave exactly the same way as a C project created with the CDT plugin. Don't forget to delete you "dummy" project ;-)

like image 168
smeeb Avatar answered Sep 18 '22 12:09

smeeb


You can add the c++ nature to the project with help of:

  1. create a gradle project
  2. select the project
  3. use Eclipse->new->other
  4. select c++ -> convert to a c++ project
  5. clean up the project
like image 36
klaus Avatar answered Sep 20 '22 12:09

klaus