Compile and build c++ project through gradle using cpp plugin

Hey

I am working on gradle script and getting some issue it is getting failed everytime at the same point

/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/ds64.lib:1: error: expected unqualified-id before ‘!’ token
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/ds64.lib:9: error: expected declaration before ‘}’ token
:compileMainSharedLibraryMainCpp FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ‘:compileMainSharedLibraryMainCpp’.

C++ compiler failed; see the error output for details.

apply plugin: 'cpp'
apply plugin: 'java'
//-- set the group for publishing
group = 'com.tran.ana'

/**
 * Initializing GAVC settings
 */
def buildProperties = new Properties()
file("version.properties").withInputStream {
        stream -> buildProperties.load(stream)
}
//add the jenkins build version to the version
def env = System.getenv()
if (env["BUILD_NUMBER"]) buildProperties.analyticsengineBuildVersion += "_${env["BUILD_NUMBER"]}"
version = buildProperties.ana
println "${version}"

//name is set in the settings.gradle file
group = "com.tran.ana"
version = buildProperties.analyticsengineBuildVersion
println "Building ${project.group}:${project.name}:${project.version}"

  repositories {

        maven {
      url "http://xyz.ts.tho.com:80/artifactory/repo1-cache"
    }
  }

dependencies {
    compile ([
    "com.truvenhealth.analyticsengine:analytics-engine-common:4.+",
    "junit:junit:4.+"
      ])
}



model {
  components {
           main(NativeLibrarySpec) {
      platforms {
      x64 {
       architecture "x86_64"
       }
       sources {
        cpp {
          source {
            srcDir "src/main/c++/native"
            srcDir "src/main/c++/headers"
          }
        }
      }
    }
  }
}
}
binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-fPIC"
        linker.args "-Xlinker", "-S", "-LNativeJNI/src/main/resources/DSresources/DSLib -lds64", "-Wl", "-rpath", "NativeJNI/src/main/resources/DSresources/DSLib"
    }

I am running it on my linux machine which is having the gcc compiler and it running fine with maven script.Below is my project structure

└───src
└───main
├───c++
│ ├───headers (headres is having **.h files)
│ └───native (native contains **.cpp files & ds64.dll ds64.lib)
└───resources
└───DSresources
└───DSLib

You need to have an include filter on your source set (inside cpp { source { /* here */ } }. Right now, we don’t apply any sort of default filtering, so the compiler is trying to parse the .lib files as C++ source files.

Is this the correct way to define the linker option

binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-fPIC"
        linker.args "-Xlinker", "-S", "-LNativeJNI/src/main/resources/DSresources/DSLib -lds64", "-Wl", "-rpath", "NativeJNI/src/main/resources/DSresources/DSLib"
    }

You shouldn’t need -fPIC (Gradle adds that for shared objects). I’d model the ds64 lib as a prebuilt library: https://github.com/gradle/gradle/blob/master/subprojects/docs/src/samples/native-binaries/prebuilt/build.gradle

Then you can add a dependency to your component with lib library: 'whatever-you-call-it'

Hi

I did the same but still not able to get the desired result

apply plugin: 'cpp'

model {
  components {
      main(NativeLibrarySpec) {
      platforms {
      x64 {
      architecture "x86_64"
       }
       sources {
         cpp {
         source {
            cpp.lib library: 'main', linkage: 'static'
            srcDir "src/main/c++/native"
            include "**/JniSupport.cpp"
            include "**/DiseaseStagingJni.cpp"
          }
        }
      }
    }
  }
}
}

binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-g"
        linker.args "-Xlinker", "-shared -LNativeJNI/src/main/resources/DSresources/DSLib -lds64 -Wl", "-rpath", "NativeJNI/src/main/resources/DSresources/DSLib"
    }
}

Error:After running the gradle script

:compileMainSharedLibraryMainCpp
In file included from /applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:6:
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:15:17: error: jni.h: No such file or directory
In file included from /applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:6:
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:19: error: ‘jfieldID’ does not name a type
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:24: error: ‘JNIEnv’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:24: error: ‘env’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:24: error: ‘jobject’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:24: error: ‘jfieldID’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:24: error: expected primary-expression before ‘const’
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:28: error: variable or field ‘convertException’ declared void
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:28: error: ‘JNIEnv’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:28: error: ‘env’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:28: error: expected primary-expression before ‘const’
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:11: error: ‘jfieldID’ does not name a type
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:26: error: redefinition of ‘std::string getStrField’
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.hpp:24: error: ‘std::string getStrField’ previously declared here
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:26: error: ‘JNIEnv’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:26: error: ‘env’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:26: error: ‘jobject’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:26: error: ‘jfieldID’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:26: error: expected primary-expression before ‘const’
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:43: error: variable or field ‘convertException’ declared void
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:43: error: ‘JNIEnv’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:43: error: ‘env’ was not declared in this scope
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/JniSupport.cpp:43: error: expected primary-expression before ‘const’
:compileMainSharedLibraryMainCpp FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ‘:compileMainSharedLibraryMainCpp’.

C++ compiler failed; see the error output for details.

Basically I am changing the POM file to gradle.Below is the POM file

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.txxx.ana</groupId>
        <artifactId>Analytics</artifactId>
        <version>4.0.0-SNAPSHOT</version>
    </parent>
    <groupId>com.trxx.ana</groupId>
    <artifactId>NativeJNI</artifactId>
    <version>4.0.0-SNAPSHOT</version>
    <name>NativeJNI</name>
    <url>http://maven.apache.org</url>
    <packaging>${packaging.type}</packaging>
    <profiles>
        
        <profile>
            <id>Windows</id>
            <activation>
                <os>
                    <family>Windows</family>
                </os>
            </activation>
            <properties>
                <packaging.type>dll</packaging.type>
            </properties>
            <build>
                <plugins> 

                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>native-maven-plugin</artifactId>
                        <version>1.0-alpha-8</version>
                        <extensions>true</extensions>
                        <configuration>

                            <javahOS>win32</javahOS>

                            <compilerProvider>generic-classic</compilerProvider>
                            <compilerExecutable>g++</compilerExecutable>
                            <linkerExecutable>g++</linkerExecutable>
                            <sources>
                                <source>
                                    <directory>NativeJNI/../src/main/c++/native</directory>
                                    <fileNames>
                                        <fileName>JniSupport.cpp</fileName>
                                        <fileName>i</fileName>
                                    </fileNames>
                                </source>
                            </sources>

                            <linkerStartOptions>
                                <linkerStartOption>-shared -LNativeJNI/../src/main/resources/DSresources/DSLib -lds64 -Wl,-rpath,NativeJNI/../src/main/resources/DSresources/DSLib</linkerStartOption>
                            </linkerStartOptions>

                        </configuration>
                        <executions>
                            <execution>
                                <id>javah</id>
                                <phase>generate-sources</phase>
                                <configuration>
                                    <javahOS>win32</javahOS>
                                    <javahProvider>default</javahProvider>
                                    <javahOutputDirectory>${project.build.directory}/custom-javah</javahOutputDirectory>
                                    <workingDirectory>${basedir}</workingDirectory>
                                    <javahOutputFileName>DiseaseStagingJniWrapper.h</javahOutputFileName>
                                    <javahClassNames>
                                        <javahClassName>com.truxxx.ana.common.diseasestaging.DiseaseStagingJniWrapper</javahClassName>
                                    </javahClassNames>
                                </configuration>
                                <goals>
                                    <goal>javah</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>Linux</id>
            <activation>
                <os>
                    <family>Linux</family>
                </os>
            </activation>
            <properties>
                <packaging.type>so</packaging.type>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>native-maven-plugin</artifactId>
                        <version>1.0-alpha-8</version>
                        <extensions>true</extensions>
                        <configuration>

                            <javahOS>linux</javahOS>

                            <compilerProvider>generic-classic</compilerProvider>
                            <compilerExecutable>g++</compilerExecutable>
                            <linkerExecutable>g++</linkerExecutable>
                            <sources>
                                <source>
                                    <directory>NativeJNI/../src/main/c++/native</directory>
                                    <fileNames>
                                        <fileName>JniSupport.cpp</fileName>
                                        <fileName>DiseaseStagingJni.cpp</fileName>
                                    </fileNames>
                                </source>
                            </sources>
                            <compilerStartOptions>
                                <compilerStartOption>-fPIC</compilerStartOption>
                            </compilerStartOptions>
                            <linkerFinalName>NativeJNI</linkerFinalName>
                            <linkerStartOptions>
                                <linkerStartOption>-shared -L${basedir}/src/main/resources/DSresources/DSLib -lds64 -Wl,-rpath,${basedir}/src/main/resources/DSresources/DSLib</linkerStartOption>
                            </linkerStartOptions>

                        </configuration>
                        <executions>
                            <execution>
                                <id>javah</id>
                                <phase>generate-sources</phase>
                                <configuration>
                                    <finalName>LinuxNativeJNI</finalName>
                                    <javahOS>linux</javahOS>
                                    <javahProvider>default</javahProvider>
                                    <javahOutputDirectory>${project.build.directory}/custom-javah</javahOutputDirectory>
                                    <workingDirectory>${basedir}</workingDirectory>
                                    <javahOutputFileName>DiseaseStagingJniWrapper.h</javahOutputFileName>
                                    <javahClassNames>
                                        <javahClassName>com.trxx.anae.common.diseasestaging.DiseaseStagingJniWrapper</javahClassName>
                                    </javahClassNames>
                                </configuration>
                                <goals>
                                    <goal>javah</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
   
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
      
        <dependency>
            <groupId>com.trxx.ana</groupId>
            <artifactId>Common</artifactId>
            <version>${project.version}</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
      
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

OK. You’re missing a dependency for the JDK.

Try adding this to the model block:

    repositories {
        libs(PrebuiltLibraries) {
            jdk {
                headers.srcDirs "${System.properties['java.home']}/../include", 
                    "${System.properties['java.home']}/../include/win32",
                    "${System.properties['java.home']}/../include/darwin",
                    "${System.properties['java.home']}/../include/linux"
            }
        }
    }

And then add a dependency to your cpp source set:

lib library: 'jdk', linkage: 'api'

I added it in my script but it is throwing an error

model {
  components {
//    main(NativeExecutableSpec) {
      main(NativeLibrarySpec) {
      platforms {
      x64 { architecture "x86_64" }
      x86 { architecture "x86" }
      repositories {
    libs(PrebuiltLibraries) {
        jdk {
        def javaHome = System.getenv("JAVA_HOME")
        headers.srcDir "${javaHome}/include"
        binaries.all {
          if (targetPlatform.operatingSystem.windows) {
            headers.srcDir "${javaHome}/include/win32"
          } else if (targetPlatform.operatingSystem.linux) {
            headers.srcDir "${javaHome}/include/linux"
          } else {
            headers.srcDir "${javaHome}/include/darwin"
        sources {
           cpp {
         source {
            lib library: 'main', linkage: 'static'
            lib library: 'jdk', linkage: 'api'
            srcDir "src/main/c++/native"
            include "**/JniSupport.cpp"
            include "**/DiseaseStagingJni.cpp"
          }
        }
      }
    }
  }
}
}
}
}
}
}
}


binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-g"
        linker.args '-Xlinker', '-shared -LNativeJNI/src/main/resources/DSresources/DSLib -lds64 -Wl', '-rpath', 'NativeJNI/src/main/resources/DSresources/DSLib'
    }
}

FAILURE: Build failed with an exception.

  • Where:
    Build file ‘/applications/jenkins/workspace/NativeJNI/NativeJNI/build.gradle’ line: 47

  • What went wrong:
    A problem occurred configuring root project ‘NativeJNI’.

Exception thrown while executing model rule: model.components
Cannot create a PrebuiltLibraries because this type is not known to this container. Known types are: NativePlatform, Platform

You’re getting a lot of things mixed together there…

You want components, repositories and platforms to be top-level blocks inside model {} It looks like you’re putting everything inside components right now.

Yep I did the same which you told me and it is working but it didn’t give me any output

model {
repositories {
    libs(PrebuiltLibraries) {
        jdk {
        def javaHome = System.getenv("JAVA_HOME")
        headers.srcDir "${javaHome}/include"
        binaries.all {
          if (targetPlatform.operatingSystem.windows) {
            headers.srcDir "${javaHome}/include/win32"
          } else if (targetPlatform.operatingSystem.linux) {
            headers.srcDir "${javaHome}/include/linux"
          } else {
            headers.srcDir "${javaHome}/include/darwin"
  components {
//    main(NativeExecutableSpec) {
      main(NativeLibrarySpec) {
      platforms {
      x64 { architecture "x86_64" }
      x86 { architecture "x86" }
       sources {
           cpp {
         source {
            lib library: 'main', linkage: 'static'
            lib library: 'jdk', linkage: 'api'
            srcDir "src/main/c++/native"
            include "**/JniSupport.cpp"
            include "**/DiseaseStagingJni.cpp"
          }
        }
      }
    }
  }
}
}
}
}
}
}
}


binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-g"
        linker.args '-Xlinker', '-shared -LNativeJNI/src/main/resources/DSresources/DSLib -lds64 -Wl', '-rpath', 'NativeJNI/src/main/resources/DSresources/DSLib'
    }
}

Output
:clean
:assemble UP-TO-DATE
:check UP-TO-DATE
:build UP-TO-DATE

Please check your indentation and braces. You’re stuffing everything inside the binaries.all block inside jdk.

I am completey stuck now and not able to move.Please help me here

repositories {
    libs(PrebuiltLibraries) {
        jdk {
        headers.srcDirs "${System.properties['java.home']}/../include",
                    "${System.properties['java.home']}/../include/win32",
                    "${System.properties['java.home']}/../include/darwin",
                    "${System.properties['java.home']}/../include/linux"
      components {
      main(NativeLibrarySpec) {
      platforms {
      x64 { architecture "x86_64" }
      x86 { architecture "x86" }
       sources {
           cpp {
         source {
            lib library: 'main', linkage: 'static'
            lib library: 'jdk', linkage: 'api'
            srcDir "src/main/c++/native"
              include "**/JniSupport.cpp"
              include "**/DiseaseStagingJni.cpp"
          }
        }
      }
    }
  }
}
}
}
}
binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-g"
        linker.args '-Xlinker', '-shared -LNativeJNI/src/main/resources/DSresources/DSLib -lds64 -Wl', '-rpath', 'NativeJNI/src/main/resources/DSresources/DSLib'
}
}

Your braces are very wrong. They need to enclose the block like a Java method would. It might make it a little easier to see if you put all of the top-level pieces in their own separate model {} block.

Something like

model {
  repositories {
    libs(PrebuiltLibraries) {
      jdk {
        headers.srcDirs "${System.properties['java.home']}/../include",
        "${System.properties['java.home']}/../include/win32",
        "${System.properties['java.home']}/../include/darwin",
        "${System.properties['java.home']}/../include/linux"
      }
    }
  }
}

model { 
  platforms {
    x64 { architecture "x86_64" }
    x86 { architecture "x86" }  
  }
}

model {
  components {
    main(NativeLibrarySpec) {
      sources {
        cpp {
          source {
            lib library: 'main', linkage: 'static'
            lib library: 'jdk', linkage: 'api'
            srcDir "src/main/c++/native"
            include "**/JniSupport.cpp"
            include "**/DiseaseStagingJni.cpp"
          }
        }
      }
    }
  }
}

Hi,

I used the same code which you gave me and it is giving me some results

model {
  repositories {
    libs(PrebuiltLibraries) {
      jdk {
        headers.srcDirs "${System.properties['java.home']}/../include",
        "${System.properties['java.home']}/../include/win32",
        "${System.properties['java.home']}/../include/darwin",
        "${System.properties['java.home']}/../include/linux"
      }
    }
  }
}

model {
  platforms {
    x64 { architecture "x86_64" }
    x86 { architecture "x86" }
  }
}

model {
  components {
    main(NativeLibrarySpec) {
      sources {
        cpp {
          source {
            lib library: 'main', linkage: 'static'
            lib library: 'jdk', linkage: 'api'
            srcDir "src/main/c++/native"
            include "**/JniSupport.cpp"
            include "**/DiseaseStagingJni.cpp"
          }
        }
      }
    }
  }
}


binaries.all {
    // Define toolchain-specific compiler and linker options
    if (toolChain in Gcc) {
        cppCompiler.args "-g"
        linker.args '-Xlinker', '-shared -LNativeJNI/src/main/resources/DSresources/DSLib -lds64 -Wl', '-rpath NativeJNI/src/main/resources/DSresources/DSLib'
}
}

But while I run this code it throws an error
:compileMainSharedLibraryMainCpp
/applications/jenkins/workspace/NativeJNI/NativeJNI/src/main/c++/native/DiseaseStagingJni.cpp:42:38: error: DiseaseStagingJniWrapper.h: No such file or directory
:compileMainSharedLibraryMainCpp FAILED

beacuse DiseaseStagingJni.cpp file mentioned the name of DiseaseStagingJniWrapper.h file as
#include DiseaseStagingJniWrapper.h
and this file is not avilable in the source code it looks me the last part of the POM file is doing it all

</configuration>
                        <executions>
                            <execution>
                                <id>javah</id>
                                <phase>generate-sources</phase>
                                <configuration>
                                    <finalName>LinuxNativeJNI</finalName>
                                    <javahOS>linux</javahOS>
                                    <javahProvider>default</javahProvider>
                                    <javahOutputDirectory>${project.build.directory}/custom-javah</javahOutputDirectory>
                                    <workingDirectory>${basedir}</workingDirectory>
                                    <javahOutputFileName>DiseaseStagingJniWrapper.h</javahOutputFileName>
                                    <javahClassNames>
                                        <javahClassName>com.trxx.anae.common.diseasestaging.DiseaseStagingJniWrapper</javahClassName>
                                    </javahClassNames>
                                </configuration>
                                <goals>
                                    <goal>javah</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
   
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
      
        <dependency>
            <groupId>com.trxx.ana</groupId>
            <artifactId>Common</artifactId>
            <version>${project.version}</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

which is having the dependency on common module and then use the class.if I commented this file in the source code where it is mentioned then the build completed succesfully with one error

:clean
:compileMainSharedLibraryMainCpp
:compileMainStaticLibraryMainCpp
:createMainStaticLibrary
:mainStaticLibrary
:linkMainSharedLibrary
g++: unrecognized option ‘-rpath NativeJNI/src/main/resources/DSresources/DSLib’
:mainSharedLibrary
:assemble
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 6.209 secs

I am using the linker option as welll where it is throwing an error I took the same option which is in POM file

Could you please help me how could I fix this I mean use the Common module as dependency and the use it’s class for generated resources as they are doing it in POM file

Do I need to use java plugin to fetch the Common module from my binary repository(Artifactory)and then use it.

Please suggest me