[CMake] Best way to handle application data path for local run vs. installation
Alexander Neundorf
a.neundorf-work at gmx.net
Wed Dec 2 16:34:25 EST 2015
On Wednesday, December 02, 2015 12:27:42 Ruslan Baratov wrote:
> On 02-Dec-15 05:13, Alexander Neundorf wrote:
...
> > well, the RPATH entry was not designed to be patched,
>
> RPATH designed to be patched. And since it's a third time I'm making
> this statement please provide any arguments if you don't agree.
>
> Here is mine (comes from wikipedia,
https://en.wikipedia.org/wiki/Rpath):
>
> The rpath of an executable or shared library is an optional entry
> in the
> .dynamic section of the ELF executable or shared libraries, with
> the type
> DT_RPATH, called the DT_RPATH attribute. It can be stored there at
> link time by
> the linker. Tools such as chrpath and patchelf can create or MODIFY
> the entry
> later.
>
> Man chrpath (http://linux.die.net/man/1/chrpath):
>
> -r <path> | --replace <path>
> Replace current rpath or runpath setting with the path given
It doesn't matter and it is nitpicking: the RPATH entry has some size, and
its content cannot simply be changed. I.e. it could be replaced with a
string of the same length or a shorter one, but not a longer one.
CMake works around this by extending the build RPATH artificially with
":" at the end I think, patchelf works around this by making the whole
executable one page bigger if the new entry is longer.
If RPATH was _designed_ to be patchable, tools could just do it, instead
of having to implement workarounds for longer strings. E.g. the linker
would support a command line argument how much space it should
reserve for the RPATH entry, or something like that.
> > any other string in an executable could be patched too:
> RPATH and C++ string literals have not the same nature. E.g. on my
Linux
> machine RPATH string goes to ".dynstr" section and C++ literal to
> ".rodata" section.
> The difference is quite huge. By parsing ELF headers you can figure
out
> RPATH offset and be 100% sure that patching is totally correct and
> doesn't affect other binary or general executable logic. RPATH is just a
> hint for linker.
> Changing bytes in .rodata is much trickier. E.g. how do you distinguish
> two strings:
>
> void print_some_info() {
> const char* path = "/usr/local"; // must not be changed
> std::cout << "General note: user specific packages usually installed
> to " << path << std::endl;
> }
>
> void parse_resources() {
> const char* resources_path = "/usr/local"; // want to change it in
future
> std::string myresource = resources_path + "/foo/some.file";
> }
>
> What if compiler merge them?
By using a very special string which is very unlikely to be used by
something else, like e.g. "$$$_CMAKE_I_AM_NOT_INSTALLED_$$$".
Maybe it could even be put into a custom ELF section, and then tools
could just look at that section (... but then it's ELF-only).
I would actually (despite it being hacky) trust the uniqueness of a string
like the one above.
Probably the string could be made even more unique by embedding the
target name or something using cmake functionality.
> (Just a general note, not related to how you want to implement
resources
> trick)
>
> > const char* my_builddir_flag = "$$$$_I_M_NOT_INSTALLED_$$$$";
> >
> > ...
> >
> > if (*my_builddir_flag)
> >
> > {
> >
> > ... code when not installed
> >
> > }
> >
> > else
> >
> > {
> >
> > ... code for the installed version
> >
> > }
> >
> > Just search for that string in the executable and replace the first
> > byte with a '\0'.
>
> Still can violates logic. What if I want to print string to resources in
> next format:
> 1. "-" x size of path to resources (compiler can figure out it at
> compile time!)
> 2. path to resources
> 3. "-" x size of path to resources
>
> If you pass "/usr/local" output will be (nice):
>
> --------------
> /usr/local
> --------------
>
> If you pass "/home/username", output will be (nice):
>
> ------------------------
> /home/username
> ------------------------
>
> If you pass "$$$$_I_M_NOT_INSTALLED_$$$$" then change string to
> "/usr/local" after install (ugly, not what I expect!):
>
> ---------------------------
> /usr/local
> ---------------------------
Sorry, I don't understand.
The idea above was only for solving the question "am I installed ?"
yes/no, not "where am I installed ?".
> > Not sure there is a simple tool to do that, but writing one shouldn't
> > be hard.
>
> sed? :)
I have never used sed on binary files. Does that work ?
Alex
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20151202/51f02432/attachment-0001.html>
More information about the CMake
mailing list