Compute "-Wl,-rpath ..." flag suitable for native shared library

software-model

(Ben Liblit) #1

I am building a native executable that depends on a prebuilt shared library installed in a non-standard location. Let’s call that prebuilt library “zebra”. On Linux it would be appropriate to use -Wl,-rpath to help my executable find the zebra library at run time. I would like to avoid repeating this long path twice, though. I will already have given the path when setting up the zebra component of my PrebuiltLibraries repository, so how can I recover that information instead of repeating it?

Consider the following model configuration. Notice that sharedLIbraryLinkFile already contains the full, absolute path to the zebra library, which might be long and nontrivial to compute:

apply plugin: 'cpp'

model {
	repositories {
		libs(PrebuiltLibraries) {
			zebra {
				headers.srcDir ...
				sharedLibraryLinkFile = file("/long/nontrivially/computed/path/to/libzebra.so")
			}
		}
	}
	components {
		hello(NativeExecutableSpec) {
			sources.cpp {
				source ...
				lib library: 'zebra'
			}
			binaries.all {
				// TODO: how to compute rpath from zebra's sharedLibraryLinkFile?
				linker.args '-Wl,-rpath', "????????"
			}
		}
	}
}

In the linker.args call, how can I set the -Wl,-rpath argument to the directory name of the zebra library’s sharedLibraryLinkFile? I have figured out that I can use $.repositories['libs'].zebra.binaries.withType(SharedLibraryBinary) to iterate over all of the possible zebra shared library binaries. But I really need just one of these binaries: the one that will be used by the corresponding hello binary. How can I get my hands on that specific SharedLibraryBinary, from which I’d hope to extract the corresponding sharedLibraryLinkFile?

Is there a more elegant way to deal with this? I love how the headers.srcDirs property of a library automatically propagates up and turns into include path flags (-I) on things that use the library. Is there a way to configure the zebra library so that it propages -Wl,-rpath flags up to anything that links with it?

I’ve simplified this all to make for a compact, self-contained question. My real project has multiple sub-projects, multiple native shared libraries, and multiple native executables. I need to set proper -Wl,-rpath flags for all of these, including paths to both system-installed prebuilt libraries as well as paths to native shared libraries built within the same or other sub-projects. I hope that I’ll be able to generalize any answer received to my real situation, but if there are any special cavéats, please let me know!