[CMake] Best way to handle application data path for local run vs. installation

Ruslan Baratov ruslan_baratov at yahoo.com
Wed Dec 2 00:27:42 EST 2015


On 02-Dec-15 05:13, Alexander Neundorf wrote:
>
> On Tuesday, December 01, 2015 07:17:35 Ruslan Baratov wrote:
>
> > On 01-Dec-15 03:51, Alexander Neundorf wrote:
>
> > > On Monday, November 30, 2015 16:13:03 Ruslan Baratov via CMake wrote:
>
> > > > On 30-Nov-15 09:10, Dmitry Marakasov wrote:
>
> > > > > Hi!
>
> > >
>
> > > ...
>
> > >
>
> > > > > The best solution would be for cmake to fix path in executable 
> file
>
> > > > >
>
> > > > > right after installation, something similar to what cmake does 
> with
>
> > > > >
>
> > > > > rpaths.
>
> > > >
>
> > > > I doubt there is a general way to patch data section with string in
>
> > > >
>
> > > > executable. At least with different size and in safe manner. For 
> example
>
> > > >
>
> > > > Clang is smart enough to figure out 'strlen' of literal string at
>
> > > >
>
> > > > compile time, so changing string affects logic and hence is 
> dangerous.
>
> > > >
>
> > > > And rpaths unlike data is designed to be modifiable
>
> > >
>
> > > Not really. CMake has extra code to make sure the build rpath is as
>
> > > long as the install rpath will be, so it can be patched in later.
>
> >
>
> > Well, that's exactly what I said - RPATH can be patched.
>
> 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

> 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?

(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
---------------------------

> Not sure there is a simple tool to do that, but writing one shouldn't 
> be hard.
>
sed? :)

> Maybe it would even be accepted as an option into cmake.
>
Note that even if you solve all the issues above and make peace with 
violation logic you still will not able to create relocatable package. 
And just to be clear by relocation I mean packing application to 
*.tar.gz archive so user can install it just by doing "tar xf" to any 
place, like CMake do: https://cmake.org/download/

Out of curiosity can somebody show me cross-platform application 
(Windows, Linux, OSX) that expect resources in hard-coded location?

Cheers, Ruslo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20151202/d9091047/attachment-0001.html>


More information about the CMake mailing list