gradle-native
gradle-native copied to clipboard
Add an equivalent to CMake's find_package() for finding native libraries
In CMake, you can use find_package()
, which inputs the name of a native library, and searches for the library on your system in a number of locations. It is platform agnostic, and thus works for macOS, Linux, and Windows. For example, my macOS computer has SDL2 installed via the Homebrew package manager, and when I run find_package(SDL2)
in my CMake script, it returns /usr/local/Cellar/sdl2/2.0.10/lib/libSDL2.dylib
.
I would like to request a Gradle equivalent to this functionality.
Expected Behavior
A very CMake-style solution might look like this:
components.main.binaries.whenElementFinalized { binary ->
project.dependencies {
add(findPackage('SDL2'))
}
}
A syntax more closely related to the closest current behavior (see below) might look like this:
def sdl2Lib = file(OperatingSystem.current().findPackage('SDL2'))
components.main.binaries.whenElementFinalized { binary ->
project.dependencies {
add(sdl2Lib)
}
}
Current Behavior
The closest behavior I can find is that found in this native sample.
file(OperatingSystem.current().getSharedLibraryName('../simple-library/build/lib/main/debug/list'))
Which will return a file like ~/Projects/simple-library/build/lib/main/debug/liblist.dylib
However, this requires the file location of the library to be known. If I pass in just the name of the library as I would with CMake's find_package
, like this:
file(OperatingSystem.current().getSharedLibraryName('SDL2'))
I get the following error:
Could not find ~/Projects/MyProject/libSDL2.dylib
In other words, it correctly transformed the name of the library for macOS, but it assumed the library was in the root of the project, rather than in the locations that CMake's find_package
would search.
A custom method that searches all of those locations could be created, but given the length of such a method and its lack of portability, it would make more sense for it to be a core functionality.
Context
I am wanting to convert a few CMake project to Gradle, and a lack of equivalent for find_package
for finding third-party native libraries, such as SDL2, is the main obstacle. Here is one relatively simple project that uses find_package
to load three libraries in a platform-agnostic way.
We made a spike recently around Homebrew (and Linuxbrew) resolution. I think expending the work we did previously to include more search location could be really beneficial in supporting the feature. We still have some discussion internally around how this work but I'm pretty confident this is the direction we would like to go. The discussion around the next step is more about searching the current system for libraries vs supporting a package manager like Conan or NuGet. Could you help us understand your workflow? Would a package manager support be beneficial to you or you are strictly using locally installed libraries?
@lacasseio Glad to hear that this sort of thing is being explored!
The current workflow is that developers on macOS, Windows, and Linux are all attempting to build open source projects such as the one I linked to. The lowest common denominator for cross-platform CMake projects seems to be for developers to locally install the libraries, then use find_package()
to detect where they are. For me personally, I don't need to pass in the locations of these libraries as CMake parameters because find_package()
is able to detect the default installation location for Homebrew packages, but I'm not sure that's true for all developers; they might be passing in locations as parameters.
If I'm understanding the Spike correctly, it would allow Gradle to go out and download the dependency from Homebrew, and keep it scoped to this Gradle project only. Thus it would be comparable to a Gradle Java project downloading a dependency off of MavenCentral, and perhaps another project downloading a different version. If that's the correct interpretation, then I think that would certainly be a welcome step that I didn't know was possible! As someone who primarily uses Gradle with Java, I miss being able to have my C++ projects download all dependencies and compile with a simple gradlew build
, so a solution that uses Homebrew/Linuxbrew to download the correct versions of all dependencies would be welcome for me indeed!
I know that some open-source projects are macOS/Linux only, so a Homebrew/Linuxbrew solution would work, but for the open source projects that I'm working on in particular, we wouldn't want to sacrifice being able to build on Windows. So we'd want a solution that either works with both, or it's easy enough to do an if/then statement to do one solution on macOS/Linux an a similarly simple solution for Windows.
Does that answer your questions?
The ultimate goal is to eliminate any need to specify how the dependencies are located. Only what library you need with the constraint to respect (which features are enabled or disable, debuggability, optimization, version, etc). Gradle should be able to find the library either locally or through a provider. At the moment, the spike just locate the dependency from the file system. It doesn't install any dependencies using Homebrew. Then the correct step forward would be to aim for a system agnostic package manager. Your build configuration should be, as much as possible, the same for any system. Thanks for your answer, it aligns with what we had in mind.