The C++ support seems to be compiling .c files as C++ instead of C

1.7-rc-2 In the documentation section 54.1 states “By default, a named CppSourceSet contains .cpp and .c source files…”

In my project a have a couple C files that need to build with C conventions (no name mangling, etc)

In one file that uses a lot of JNI it seems that it is getting the C++ version of the JNIEnv data structure instead of the C version.

/Users/scott/dev/MyProject/JNIUtils.c: In function ‘JavaVM* GetJavaVMForJNIEnv(JNIEnv*)’: /Users/scott/dev/MyProject/JNIUtils.c:312: error: base operand of ‘->’ has non-pointer type ‘JNIEnv_’ /Users/scott/dev/MyProject/JNIUtils.c: In function ‘JNIEnv* GetJNIEnvForCurrentThreadIfCurrentlyAttached(JavaVM*)’: /Users/scott/dev/MyProject/JNIUtils.c:342: error: base operand of ‘->’ has non-pointer type ‘JavaVM_’ /Users/scott/dev/MyProject/JNIUtils.c: In function ‘JNIEnv* GetJNIEnvForCurrentThread(JavaVM*)’: /Users/scott/dev/MyProject/JNIUtils.c:370: error: base operand of ‘->’ has non-pointer type ‘JavaVM_’ /Users/scott/dev/MyProject/JNIUtils.c:382: error: no match for ‘operator==’ in ‘* env == 0l’

Could it be the case that .c files aren’t being compiled as ‘C’ ?

The user guide isn’t completely up-to-date in 1.7. Gradle now supports separate source-sets for C and C++. The best place to see how this works is probably to check out the “c” and “c-with-assembler” samples.

By convention, the ‘c’ and ‘cpp’ sourcesets are in ‘src/{component}/c’ and ‘src/{component}/cpp’. You can customise the locations:

sources {
    main {
        cpp {
            source {
                srcDirs "src"
                include "**/*.cpp"
            }
            exportedHeaders {
                srcDirs "src/hello", "include"
            }
        }
        c {
            source {
                srcDirs "src", "include"
                include "**/*.c"
            }
            exportedHeaders {
                srcDirs "src/hello", "include"
            }
        }
    }
}

We’ll get this stuff into the User Guide soon.

I tried the above but gradle complained:

  • What went wrong: A problem occurred evaluating script. > Cannot create a LanguageSourceSet named ‘cpp’ because this container does not support creating elements by name alone. Please specify which subtype of LanguageSourceSet to create. Known subtypes are: (None)

I’m trying to build a library and the source code is located in the same folder as build.gradle (I’m converting a NetBeans C++ project on OS X, but the project must also build with Visual Studio on Windows)

I apply the ‘cpp’ plugin (not ‘cpp-lib’ as I seem to need more control) and I tried this:

sources {

lib {

cpp {

source {

srcDir ‘.’

include ‘*.cpp’

}

exportedHeaders {

srcDir ‘.’

}

}

c {

source {

srcDir ‘.’

include ‘*.c’

}

}

}

}

libraries {

MyLibrary {

source cpp.sourceSets.lib

source c.sourceSets.lib

}

}

binaries.all {

// Define a preprocessor macro for every binary

//define “NDEBUG”

define ‘__STDC_LIMIT_MACROS’

// Define toolchain-specific compiler and linker options

if (toolChain == toolChains.gcc) {

compilerArgs ‘-O2’, ‘-DOS_X’, “-I${JAVA_HOME}/include”, “-I${JAVA_HOME}/include/darwin”, ‘-I’ , file(’.’).getAbsolutePath(), ‘-I’, file(’…/ProjectDir/src-generated/cpp’).getAbsolutePath(), ‘-fPIC’, ‘-MMD’, ‘-MP’, ‘-MF’

linkerArgs ‘-march=i686’

}

}

Where do I find the ‘c’ and ‘c-with-assembler’ samples… I looked in the samples folder of the 1.7 zip and didn’t see them.

Checked the source on github and still don’t see the samples you are referring to.

Sorry, I should have been more explicit: the samples are nested under the “cpp” samples directory: https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples/cpp.

You should find them at the same location in the 1.7 distro.

The following should work:

apply plugin: 'cpp'
 sources {
      lib {
          cpp {
              source {
                  srcDir '.'
                  include '*.cpp'
              }
              exportedHeaders {
                  srcDir '.'
              }
          }
          c {
              source {
                  srcDir '.'
                  include '*.c'
              }
          }
      }
  }
  libraries {
      MyLibrary {
          source sources.lib
      }
  }

Weird:

gradle-1.7-all.zip\gradle-1.7\samples\cpp\ contains only: cpp cpp-exe cpp-lib dependencies multi-project varients

When I try that with gradle 1.7 I get the following error from line 4:

Cannot create a LanguageSourceSet named ‘cpp’ because this container does not support creating elements by name alone. Please specify which subtype of LanguageSourceSet to create. Known subtypes are: (None)

Well I’m a drongo. The branch for the Gradle 1.7 release happened so far before the final release that I assumed that the ‘C’ language support made it into 1.7. This is not the case.

Your best bet is to update to the latest Gradle nightly build: then you’ll get the samples I mentioned, and above code should function fine.

If you need to stick with Gradle 1.7 then I’m afraid that you’ll need to do without the new C language support, which means that *.c will get compiled as C++.

Okay, I can play around with the nightly builds for now, as I am just researching the feasibility of using Gradle more directly for our C/C++ builds. (We already rolled our own gradle tasks to invoke make or visual studio way back with Gradle 1.0-milestone-3)

Is there any way to force it? Like have one source set compiled with different options than another. So I could somehow tell the compiler (let’s assume GCC for now, but Visual Studio is a requirement for the project) to treat all files in a particular source set as ‘C’ ?

Tried againg using 1.8-20130809022440+0000 via the gradle wrapper…

Scott-Palmers-MacBook-Pro:MyProject scott$ ./gradlew -u zipNative :assembleMyProjectSharedLibraryLibAsm UP-TO-DATE :libCExtractHeaders :libCppExtractHeaders :compileMyProjectSharedLibraryLibC Undefined symbols for architecture x86_64:

“_main”, referenced from:

start in crt1.10.6.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status :compileMyProjectSharedLibraryLibC FAILED

FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ‘:compileMyProjectSharedLibraryLibC’. > C compile failed; see the error output for details.

Why does it think my library needs a ‘main’ method? I don’t get this error when I build the project with ‘make’