Link native library against existing external headers


(Alexander Nozik) #1

Hello all. I’ve recently posted a question to StackOverflow, but since there is no reply there and I really need it fast, I decided to also post it here. Here it goes.

I am building an API to create bridge between C, Puthon an JVM using swig and gradle as a build system. The problem is if I want to link swig generated source code against python headers, I need to include those headers into the build and I could not find a clear way to do so. Sadly, gradle currently lacks documentation for native builds.

From different sources I’ve composed following model definition:

model {
    repositories {
        libs(PrebuiltLibraries) {
            pythonHeaders {
                headers.srcDirs "$pythonPath/include"
            }

            jdkHeaders{...}
        }
    }

    components {
        transport(NativeLibrarySpec) {
            sources {
                lib library: 'pythonHeaders'
                c {
                    source {...}
                    exportedHeaders {...}
                }
            }
        }

    }

    toolChains {...}
}

This definition works for static library, but won’t work for shared library because python36.lib is not on linker path.

PreabuiltLibrary interface has a field called binaries, but I see no way to add to it using DSL. Is there any standard way of fixing it or workaround?


(Alexander Volanis) #2

The answer is in the samples.

Look for the samples/native-binaries/prebuilt example. What you created is an API only library definitions. Headers but no shared library.

The complete definition is like so:

model {
    repositories {
        libs(PrebuiltLibraries) {
            pythonHeaders {
                headers.srcDirs "$pythonPath/include"
                binaries.withType(StaticLibraryBinary) {
                  if (targetPlatform.operatingSystem.windows) {
                     staticLibraryFile = file("$pythonPath/lib/python36.lib")
                  } else {
                     staticLibraryFile = file("$pythonPath/lib/python36.a")
                  }
                }
                binaries.withType(SharedLibraryBinary) {
                  if (targetPlatform.operatingSystem.windows) {
                     sharedLibraryFile = file("$pythonPath/lib/python36.dll")
                     sharedLibraryLinkFile = file("$pythonPath/lib/python36.lib")
                  } else {
                     sharedLibraryFile = file("$pythonPath/lib/python36.so")
                  }
                }
            }
       }
    }
}

Not sure if the paths are correct since I did not try to get a python install and do not use Windows much…

Of course the extra logic for additional platforms can be omitted if you only target Windows or Linux.


(Alexander Nozik) #3

Thanks a lot, after fixing paths, all libraries are recognized. I still have some problems with binary compatibility, but it probably has nothing to do with gradle.