Adds JNI symbol check to ensure we don't miss any definitions (#160)

This commit is contained in:
Thad House
2016-11-25 18:07:58 -07:00
committed by Peter Johnson
parent b8e9439d32
commit bc06c843c7
6 changed files with 104 additions and 0 deletions

View File

@@ -93,6 +93,27 @@ task jniHeadersNetworkTables {
}
}
ext.getNativeJNISymbols = {
def symbolsList = []
jniHeadersNetworkTables.outputs.files.each {
FileTree tree = fileTree(dir: it)
tree.each { File file ->
file.eachLine { line ->
if (line.trim()) {
if (line.startsWith("JNIEXPORT ") && line.contains('JNICALL')) {
def (p1, p2) = line.split('JNICALL').collect { it.trim() }
// p2 is our JNI call
symbolsList << p2
}
}
}
}
}
return symbolsList
}
clean {
delete generatedJNIHeaderLoc
}

View File

@@ -12,6 +12,7 @@ def ntcoreSetupModel = { project ->
if (includeJava) {
project.setupJniIncludes(binaries)
project.checkNativeSymbols(project.getNativeJNISymbols)
binaries.all {
project.setupDef(linker, "${rootDir}/ntcore-jni.def")
}

View File

@@ -92,3 +92,29 @@ ext.debugStripSetup = {
}
}
}
ext.checkNativeSymbols = { getSymbolFunc ->
project.tasks.whenObjectAdded { task ->
if (task.name.contains('link') && task.name.contains('SharedLibrary')) {
def library = task.outputFile.absolutePath
task.doLast {
def nmOutput = new ByteArrayOutputStream()
exec {
commandLine "${compilerPrefix}nm", library
standardOutput nmOutput
}
// Remove '\r' so we can check for full string contents
String nmSymbols = nmOutput.toString().replace('\r', '')
def symbolList = getSymbolFunc()
symbolList.each {
//Add \n so we can check for the exact symbol
def found = nmSymbols.contains(it + '\n')
if (!found) {
throw new GradleException("Found a definition that does not have a matching symbol ${it}")
}
}
}
}
}
}

View File

@@ -59,3 +59,29 @@ ext.debugStripSetup = {
}
}
}
ext.checkNativeSymbols = { getSymbolFunc ->
project.tasks.whenObjectAdded { task ->
if (task.name.contains('link') && task.name.contains('SharedLibrary')) {
def library = task.outputFile.absolutePath
task.doLast {
def nmOutput = new ByteArrayOutputStream()
exec {
commandLine "nm", library
standardOutput nmOutput
}
// Remove '\r' so we can check for full string contents
String nmSymbols = nmOutput.toString().replace('\r', '')
def symbolList = getSymbolFunc()
symbolList.each {
//Add \n so we can check for the exact symbol
def found = nmSymbols.contains(it + '\n')
if (!found) {
throw new GradleException("Found a definition that does not have a matching symbol ${it}")
}
}
}
}
}
}

View File

@@ -46,3 +46,29 @@ ext.debugStripSetup = {
}
}
}
ext.checkNativeSymbols = { getSymbolFunc ->
project.tasks.whenObjectAdded { task ->
if (task.name.contains('link') && task.name.contains('SharedLibrary')) {
def library = task.outputFile.absolutePath
task.doLast {
def nmOutput = new ByteArrayOutputStream()
exec {
commandLine "nm", library
standardOutput nmOutput
}
// Remove '\r' so we can check for full string contents
String nmSymbols = nmOutput.toString().replace('\r', '')
def symbolList = getSymbolFunc()
symbolList.each {
//Add \n so we can check for the exact symbol
def found = nmSymbols.contains(it + '\n')
if (!found) {
throw new GradleException("Found a definition that does not have a matching symbol ${it}")
}
}
}
}
}
}

View File

@@ -50,3 +50,7 @@ ext.setupDef = { linker, deffile ->
// This is a noop on Windows. On gcc platforms, we strip the release binary and create a separate
// debug library, but Windows already separates debug symbols into a .pdb file.
ext.debugStripSetup = { }
// This is a noop on Windows. The def file already implicilty checks for the symbols
ext.checkNativeSymbols = { getSymbolFunc ->
}