C/C++ Unable to get the executable to link to the recently built shared library


(Joseph Fota) #1

./gradlew libhbase-jni produces the share library *.o files ./gradlew libhbase_test failes with the

[...]
libhbase_test.c:(.text+0x6e1): undefined reference to 'hb_format_log_message'
libhbase_test.c:(.text+0x6fd): undefined reference to 'hb_log_message'
libhbase_test.c:(.text+0x709): undefined reference to 'hb_client_disconnect'
collect2: ld returned 1 exit status
:linkLibhbase_testExecutable FAILED
  FAILURE: Build failed with an exception.
  * What went wrong:
Execution failed for task ':linkLibhbase_testExecutable'.
> Linker failed; see the error output for details.

When I add what I think is correct:

/*
 * libhbase_test executable
 */
executables {
    libhbase_test {
        binaries.all {
            lib 'libraries.libhbase-jni.shared'
            cCompiler.args "-std=gnu99"
        }
    }
}

The build fails with the error:

> Not a valid type for a library dependency: libraries.libhbase-jni.shared

What am I missing?

apply plugin: 'c'
apply plugin: 'cpp'
import org.apache.tools.ant.taskdefs.condition.Os
    ext {
     javaHome = System.getenv('JAVA_HOME')
    javaHomeInclude = javaHome + '/include'
      if (System.properties['os.name'].toLowerCase().contains('linux'))
    {
        javaHomeIncludeOs = javaHomeInclude + '/linux'
    }
    else
    {
        javaHomeIncludeOs = javaHomeInclude + '/win32'
    }
}
    dependencies {
    if (! javaHome) {
        logger.error('JAVA_HOME is not set.')
    }
          println 'JAVA_HOME: ' + javaHome
}
    /*
 * libhbase-jni shared library
 */
libraries {
    'libhbase-jni' {
        binaries.withType(SharedLibraryBinary)
     }
}
    sources {
    'libhbase-jni' {
        cpp {
            source {
                srcDirs "src/jni_impl"
                include "*.cc"
            }
            exportedHeaders {
                srcDirs "include", javaHomeInclude, javaHomeIncludeOs
                include "**/*.h"
            }
        }
        c {
            source {
                srcDirs "src/common"
                include "*.c"
            }
            exportedHeaders {
                srcDirs "include"
                include "*.h"
            }
        }
    }
}
    /*
 * libhbase_test executable
 */
executables {
    libhbase_test {
        binaries.all {
            lib 'libraries.libhbase-jni.shared'
            cCompiler.args "-std=gnu99"
        }
    }
}
    sources {
    libhbase_test {
        c {
            source {
                srcDir "example"
                include "*.c"
            }
              exportedHeaders {
                srcDir "include"
            }
         }
    }
}
    /*
 * Build tasks
 */
task wrapper(type: Wrapper) {
    description 'A wrapper which downloads and/or uses Gradle 1.10-rc-1'
    gradleVersion = '1.10-rc-1'
}
    task 'libhbase-jni' (dependsOn: 'libhbase-jniSharedLibrary') {
    description 'Build libhbase-jni shared library.'
}
    task 'libhbase_test' (dependsOn: 'libhbase_testExecutable') {
    description 'Build libhabase_test executable.'
}

#2

The string ‘libraries.libhbase-jni.shared’ is not a valid way to specify a dependency.

1) Your first option is to supply a library reference directly. The following are equivalent:

lib libraries.LIBRARY_NAME // shared is the default linkage lib libraries.LIBRARY_NAME.shared lib libraries.‘LIBRARY_NAME’.shared lib libraries[‘LIBRARY_NAME’].shared 
Note that the last 2 may be necessary since your library has a dash in it’s name, making the first 2 invalid groovy code.

2) The other (and possibly better) option is to use a dependency notation instead of an object reference.
lib library: ‘libhbase-jni’ // shared is the default linkage lib library: ‘libhbase-jni’, linkage: ‘shared’

(Joseph Fota) #3

In Gradle version 1.10-rc-1, both examples in option #2 failed with the same “Not a valid type for a library dependency …” error.

However, the last two examples in option #1 worked like a charm.

Thank you.


#4

Yep. I’d strongly suggest that you track a nightly build when using the C++ stuff. It’s such a rapidly moving target that it’s tough to provide support for older versions…

http://www.gradle.org/nightly describes how to configure your wrapper for a nightly build.


(Joseph Fota) #5

Sage advice. Thank you.


(Joseph Fota) #6

I’m posting this solution for others that may be looking for C/C++ examples.

apply plugin: 'c'
apply plugin: 'cpp'
import org.apache.tools.ant.taskdefs.condition.Os
model {
    buildTypes {
        release
    }
    repositories {
        libs(PrebuiltLibraries) {
            jvm {
                binaries.withType(SharedLibraryBinary) {
                    sharedLibraryFile = file("/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/libjvm.so")
                }
            }
        }
    }
}
ext {
     javaHome = System.getenv('JAVA_HOME')
    javaHomeInclude = javaHome + '/include'
    if (System.properties['os.name'].toLowerCase().contains('linux'))
    {
        javaHomeIncludeOs = javaHomeInclude + '/linux'
    }
    else
    {
        javaHomeIncludeOs = javaHomeInclude + '/win32'
    }
}
dependencies {
    if (! javaHome) {
        logger.error('JAVA_HOME is not set.')
    }
    println 'JAVA_HOME: ' + javaHome
}
/*
 * libhbase-jni shared library
 */
libraries {
    'libhbase-jni' {
        binaries.withType(SharedLibraryBinary)
     }
}
sources {
    'libhbase-jni' {
        cpp {
            source {
                srcDirs "src/jni_impl"
                include "*.cc"
            }
            exportedHeaders {
                srcDirs "include", javaHomeInclude, javaHomeIncludeOs
                include "**/*.h"
            }
        }
        c {
            source {
                srcDirs "src/common"
                include "*.c"
            }
            exportedHeaders {
                srcDirs "include"
                include "*.h"
            }
        }
    }
}
/*
 * libhbase_test executable
 */
executables {
    libhbase_test {
        binaries.all {
            lib libraries['libhbase-jni'].shared
             cCompiler.args "-ljvm", "-std=gnu99"
         }
    }
}
sources {
    libhbase_test {
        c {
            source {
                srcDir "example"
                include "*.c"
            }
            exportedHeaders {
                srcDir "include"
            }
             lib library: 'jvm'
        }
    }
}
/*
 * Build tasks
 */
task wrapper(type: Wrapper) {
    description 'A wrapper which downloads and/or uses Gradle 1.11-20140109230012+0000'
    gradleVersion = '1.11-20140109230012+0000'
}
task 'libhbase-jni' (dependsOn: 'libhbase-jniSharedLibrary') {
    description 'Build libhbase-jni shared library.'
}
task 'libhbase_test' (dependsOn: 'libhbase_testExecutable') {
    description 'Build libhabase_test executable.'
}