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

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Dmitry Marakasov
Hi!

This question bugs me for a long time so I though maybe someone has
a solution. I have a project which includes an application and some
data for it. An application needs to know path to its data files, so
I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")

The problem is that this path is different based on whether I want to
run the application from build directory:

ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")

or want to install it systemwide:

ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")

I want my project to both run from build directory and to be
installable systemwide, without the need to rebuild or specify extra
options.

- I don't want to make an applications search for its data relative
  to executable path
  - There's no cross-platform way to get an executable path
  - This will break when executable is moved or hardlinked
- I don't want to try both paths, as this is error prone, as installed
  executable may pick data files from repository or vice versa
- I don't want to make user specify additional cmake flags like
  -DSYSTEMWIDE_INSTALLATION or -DRUN_LOCALLY.
- I don't want to use any wrapper scripts
- I don't want to build two executables

The best solution would be for cmake to fix path in executable file
right after installation, something similar to what cmake does with
rpaths. Or there could be a cross-platform way for executable to know
whether it was installed which I've missed.

Any ideas?

--
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
[hidden email]  ..:  jabber: [hidden email]      http://amdmi3.ru
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Zac Bergquist

So you want to hard code a location into the executable, but support multiple locations without making multiple executables?  These sound like conflicting requirements.

Supporting multiple locations seems reasonable, so this suggests that you'll have to change how your application looks for these data files.

My suggestion would be to use the hard-coded location (the one you specify with add_definition) as the default location, and add an alternate way to look in other directories for when you want to run local (not installed) dev builds.

I would either do this by:

1) searching the current working directory first, and falling back to the default only if you didn't find data files in the current directory.

2) checking an environment variable for a location and falling back to the default if the variable is not set.  When you want to run out of your build directory you would just set the environment variable first.  You could even have CMake copy a script into the build directory (but not the install directory) that sets up the environment for you to save a few keystrokes.

Zac

On Nov 29, 2015 9:17 PM, "Dmitry Marakasov" <[hidden email]> wrote:
Hi!

This question bugs me for a long time so I though maybe someone has
a solution. I have a project which includes an application and some
data for it. An application needs to know path to its data files, so
I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")

The problem is that this path is different based on whether I want to
run the application from build directory:

ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")

or want to install it systemwide:

ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")

I want my project to both run from build directory and to be
installable systemwide, without the need to rebuild or specify extra
options.

- I don't want to make an applications search for its data relative
  to executable path
  - There's no cross-platform way to get an executable path
  - This will break when executable is moved or hardlinked
- I don't want to try both paths, as this is error prone, as installed
  executable may pick data files from repository or vice versa
- I don't want to make user specify additional cmake flags like
  -DSYSTEMWIDE_INSTALLATION or -DRUN_LOCALLY.
- I don't want to use any wrapper scripts
- I don't want to build two executables

The best solution would be for cmake to fix path in executable file
right after installation, something similar to what cmake does with
rpaths. Or there could be a cross-platform way for executable to know
whether it was installed which I've missed.

Any ideas?

--
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
[hidden email]  ..:  jabber: [hidden email]      http://amdmi3.ru
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
In reply to this post by Dmitry Marakasov
On 30-Nov-15 09:10, Dmitry Marakasov wrote:

> Hi!
>
> This question bugs me for a long time so I though maybe someone has
> a solution. I have a project which includes an application and some
> data for it. An application needs to know path to its data files, so
> I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")
>
> The problem is that this path is different based on whether I want to
> run the application from build directory:
>
> ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")
>
> or want to install it systemwide:
>
> ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")
>
> I want my project to both run from build directory and to be
> installable systemwide, without the need to rebuild or specify extra
> options.
>
> - I don't want to make an applications search for its data relative
>    to executable path
>    - There's no cross-platform way to get an executable path
It's tricky but not impossible. Might be helpful:
* http://stackoverflow.com/a/1024937/2288008
*
https://github.com/Kitware/CMake/blob/31b013b14ad3bf4838f4ba327b5392018f4853b6/Source/cmSystemTools.cxx#L2227 
(see exe_dir)

>    - This will break when executable is moved or hardlinked
> - I don't want to try both paths, as this is error prone, as installed
>    executable may pick data files from repository or vice versa
> - I don't want to make user specify additional cmake flags like
>    -DSYSTEMWIDE_INSTALLATION or -DRUN_LOCALLY.
> - I don't want to use any wrapper scripts
> - I don't want to build two executables
...

> 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 (e.g. see
install_name_tool for OS X) so it's okay to hack it back and forth.

Second thought is that when you hardcode path in executable you make it
non-relocatable. E.g. it's not possible to pack it to .dmg installer so
user can unpack it wherever he wants.

>   Or there could be a cross-platform way for executable to know
> whether it was installed which I've missed.
>
> Any ideas?
>
...

Ruslo
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Dmitry Marakasov
* Ruslan Baratov ([hidden email]) wrote:

> > - I don't want to make an applications search for its data relative
> >    to executable path
> >    - There's no cross-platform way to get an executable path
> It's tricky but not impossible. Might be helpful:
> * http://stackoverflow.com/a/1024937/2288008
> *
> https://github.com/Kitware/CMake/blob/31b013b14ad3bf4838f4ba327b5392018f4853b6/Source/cmSystemTools.cxx#L2227 
> (see exe_dir)

I know how it is done - I've patched numberless applications which
only used /proc to work on FreeBSD, and that's why I absolutely
don't want to go this way.

Also this doesn't solve the problem of moving binary around without
moving data.

> >    - This will break when executable is moved or hardlinked
> > - I don't want to try both paths, as this is error prone, as installed
> >    executable may pick data files from repository or vice versa
> > - I don't want to make user specify additional cmake flags like
> >    -DSYSTEMWIDE_INSTALLATION or -DRUN_LOCALLY.
> > - I don't want to use any wrapper scripts
> > - I don't want to build two executables
> ...
>
> > 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.

I know that changing data is tricky, but I though more of something
like having both paths compiled in and switching by changing a
constant length data.

> And rpaths unlike data is designed to be modifiable (e.g. see
> install_name_tool for OS X) so it's okay to hack it back and forth.
>
> Second thought is that when you hardcode path in executable you make it
> non-relocatable. E.g. it's not possible to pack it to .dmg installer so
> user can unpack it wherever he wants.

Hmm, I didn't think of that, probably some other systems may need
this as well.

Though I just understood that this problem is different than the one
of making cmake produce executable suitable for both inplace run
and installation: even if I produce a relocatable binary, I /still/
needs different (relative) paths to data for inplace/systemwide
cases.

Anyway for now, I did some research and solved the problem of inplace
vs. systemwide compilation in a way that I find acceptable.

I check for CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT to basically
know whether a user has explicitly specified CMAKE_INSTALL_PREFIX.
If user specified install prefix, I prepare for systemwide install,
otherwise I prepare for inplace run.

https://github.com/AMDmi3/hoverboard-sdl/blob/0.4.0/CMakeLists.txt

This doesn't support inplace and systemwide /at the same time/, but
still supports either of them cleanly, doesn't require extra actions
from user and behaves sensibly by default.

--
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
[hidden email]  ..:  jabber: [hidden email]      http://amdmi3.ru
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Bill Somerville
In reply to this post by Dmitry Marakasov
On 30/11/2015 02:10, Dmitry Marakasov wrote:

> Hi!
>
> This question bugs me for a long time so I though maybe someone has
> a solution. I have a project which includes an application and some
> data for it. An application needs to know path to its data files, so
> I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")
>
> The problem is that this path is different based on whether I want to
> run the application from build directory:
>
> ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")
>
> or want to install it systemwide:
>
> ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")
>
> I want my project to both run from build directory and to be
> installable systemwide, without the need to rebuild or specify extra
> options.
>
> - I don't want to make an applications search for its data relative
>    to executable path
>    - There's no cross-platform way to get an executable path
>    - This will break when executable is moved or hardlinked
> - I don't want to try both paths, as this is error prone, as installed
>    executable may pick data files from repository or vice versa
> - I don't want to make user specify additional cmake flags like
>    -DSYSTEMWIDE_INSTALLATION or -DRUN_LOCALLY.
> - I don't want to use any wrapper scripts
> - I don't want to build two executables
>
> The best solution would be for cmake to fix path in executable file
> right after installation, something similar to what cmake does with
> rpaths. Or there could be a cross-platform way for executable to know
> whether it was installed which I've missed.
>
> Any ideas?
>
How about reading the path from a configuration file. The default when
there is no configuration file can be a relative path in the build tree.
Use an 'install(CODE ...)' command to write a configuration file to be
shipped with the executable that contains the path to use when
installed. Application reads configuration file if it is there and uses
contents to determine the path to the data.

Regards
Bill.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Alexander Neundorf-3
In reply to this post by CMake mailing list

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.

 

> (e.g. see

> install_name_tool for OS X) so it's okay to hack it back and forth.

>

> Second thought is that when you hardcode path in executable you make it

> non-relocatable.

 

E.g. on Linux $ORIGIN could be used in the RPATH.

 

Alex

 


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
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.

 

> (e.g. see

> install_name_tool for OS X) so it's okay to hack it back and forth.

>

> Second thought is that when you hardcode path in executable you make it

> non-relocatable.

 

E.g. on Linux $ORIGIN could be used in the RPATH.

 

Alex

 

It's not about RPATH, it's about string literal with path in C++ code. E.g. if you have:
const char* resources = "/usr/share/foo"

and installing your package to "/home/username/tools" then executable will not find resources since there is no files in "/usr/share/foo"

Ruslo

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Daniel Schepler
In reply to this post by Dmitry Marakasov
For what it's worth, what we do here is have the executable search for a file named paths.cfg in the same directory it's located in, and read settings from that file to get the paths to load resources from.  Then our CMake system is set up to create one paths.cfg when building, and another when installing.  Of course, we use Qt which makes it easy both to get the executable location directory (which you mentioned you don't want to do), and to read a configuration file.  Also, our installation is designed to be in a self-contained directory, e.g. /opt/Scalable/product; but in an installation to system directories, you wouldn't want to clutter /usr/bin with a paths.cfg file, so you would probably want to have a hard-coded system directory fallback compiled in to use if paths.cfg doesn't exist.

A possible hack that just occurred to me: maybe you could make use of the different RPATH by compiling a simple path configuration "plugin" - the executable would try to dlopen("mypaths.so") and if that's found call functions in the plugin to get the paths.  The plugin would only be compiled in the build directory, and not installed.  Of course, that would be totally non-portable to Windows.
--
Daniel Schepler
________________________________________
From: CMake [[hidden email]] on behalf of Dmitry Marakasov [[hidden email]]
Sent: Sunday, November 29, 2015 6:10 PM
To: [hidden email]
Subject: [CMake] Best way to handle application data path for local run vs. installation

Hi!

This question bugs me for a long time so I though maybe someone has
a solution. I have a project which includes an application and some
data for it. An application needs to know path to its data files, so
I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")

The problem is that this path is different based on whether I want to
run the application from build directory:

ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")

or want to install it systemwide:

ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")

I want my project to both run from build directory and to be
installable systemwide, without the need to rebuild or specify extra
options.

- I don't want to make an applications search for its data relative
  to executable path
  - There's no cross-platform way to get an executable path
  - This will break when executable is moved or hardlinked
- I don't want to try both paths, as this is error prone, as installed
  executable may pick data files from repository or vice versa
- I don't want to make user specify additional cmake flags like
  -DSYSTEMWIDE_INSTALLATION or -DRUN_LOCALLY.
- I don't want to use any wrapper scripts
- I don't want to build two executables

The best solution would be for cmake to fix path in executable file
right after installation, something similar to what cmake does with
rpaths. Or there could be a cross-platform way for executable to know
whether it was installed which I've missed.

Any ideas?

--
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
[hidden email]  ..:  jabber: [hidden email]      http://amdmi3.ru
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Alexander Neundorf-3
In reply to this post by CMake mailing list

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, any other string in an executable could be patched too:

 

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'. Not sure there is a simple tool to do that, but writing one shouldn't be hard.

Maybe it would even be accepted as an option into cmake.

 

Alex

 


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
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

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
On 02-Dec-15 12:27, Ruslan Baratov via CMake wrote:

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, for bad formatting. Use this link to see what I mean:
* https://gist.githubusercontent.com/ruslo/f6b143ff53cd3e8a2f91/raw/724dba7cf90cd425a5129e3dca0340e9066d6922/gistfile1.txt

Ruslo

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Alexander Neundorf-3
In reply to this post by CMake mailing list

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

 


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Roger Leigh
In reply to this post by Dmitry Marakasov
On 30/11/2015 02:10, Dmitry Marakasov wrote:

> Hi!
>
> This question bugs me for a long time so I though maybe someone has
> a solution. I have a project which includes an application and some
> data for it. An application needs to know path to its data files, so
> I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")
>
> The problem is that this path is different based on whether I want to
> run the application from build directory:
>
> ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")
>
> or want to install it systemwide:
>
> ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")
>
> I want my project to both run from build directory and to be
> installable systemwide, without the need to rebuild or specify extra
> options.
>
> Any ideas?

I don't claim this is a universal solution, but it works for me.  It's
also likely to be further improved--this is the first functional
implementation.

 
https://github.com/openmicroscopy/bioformats/blob/dev_5_1/cpp/lib/ome/common/module.cpp

While you can configure and use hardcoded install paths, it will also
optionally introspect itself at runtime and compute the install paths
dynamically.  This means you can have a relocatable installation and it
will discover this on the fly.  Lastly, you can overrride each path
component with an environment variable.  This is used to run inside the
install tree where the path layout doesn't match the installed layout.
It's also useful for testing or overriding things after installation, if
needed, or overriding the autodetection on platforms where autodetection
doesn't work.

This approach requires this source file to be in a shared library
(Linux/FreeBSD/MacOS X - using dlopen(3)/dladdr(3)) or in a DLL (Windows
- uses GetModuleHandleExW()/GetModuleFileNameW()).  It would also work
in an executable compiled with -rdynamic with suitable adjustment for
the install path computation.  Other platforms could be added, but this
covers all my needs at the present.  Basically we get the path to the
.so/.dylib/.dll, then remove the library runtime path to get the
installation root, then add on any relative path we need, e.g. the
datadir or anything else.  This works for system installations or
relocatable installs anywhere.

This uses the CMake GNUInstallDirs module variables via a generated
header to store all the paths.


Regards,
Roger
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
In reply to this post by Alexander Neundorf-3
On 03-Dec-15 04:34, Alexander Neundorf wrote:

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.

Still see no arguments, it's just your personal opinion.

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.

Just an implementation notes, doesn't change the fact that it can be done and it's designed to be modifiable.

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.

I think it's not possible. As far as I know there is no limitation for path size on Linux for example. Hence it's not possible to predict what size for path to library user want to use by setting RPATH.

 

> > 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_$$$".

Just like I said it was a general note to show that C++ literal strings is not the same as RPATH entry and can't be changed correctly/easily after code already compiled.

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

Then I don't understand how it's planned to be used. I thought that in build directory you changing "$$$$_I_M_NOT_INSTALLED_$$$$" to "/path/to/build/directory" so resources can be found there, and on install you change it to "/path/to/install/directory". So my guess is not correct?

 

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

Yes, why not.

> cat bar.cpp
#include <iostream>

int main() {
  std::cout << "Bar say: " << "11111abc22222" << std::endl;
}
> g++ -O3 bar.cpp -o bar
> ./bar
Bar say: 11111abc22222
> sed -i 's,11111abc22222,11111XYZ22222,' ./bar
> ./bar
Bar say: 11111XYZ22222

Ruslo


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Johannes Zarl-Zierl

> > 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.
>
> Just an implementation notes, doesn't change the fact that it can be
> done and it's designed to be modifiable.

This is only nitpicking about a side-topic, but: Just because it can be done
does not mean that it was designed for that purpose.
You argument is like saying that a wrench was designed to be used as a hammer
(after all, you can hit a nail with it).

If one were to follow that argument, it would be very hard *not* to design
something for a given purpose.

> > 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.
>
> I think it's not possible. As far as I know there is no limitation for
> path size on Linux for example. Hence it's not possible to predict what
> size for path to library user want to use by setting RPATH.

If RPATH were *designed* to be modifiable, it would need provisions to account
for arbitrary path lengths.
One possible solution (not necessarily the best, or even a good one) would be
to make RPATH a fixed-length field, part of which is a pointer to the next
entry, if any.

Regards,
  Johannes
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
On 03-Dec-15 16:59, Johannes Zarl-Zierl wrote:

>>> 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.
>> Just an implementation notes, doesn't change the fact that it can be
>> done and it's designed to be modifiable.
> This is only nitpicking about a side-topic, but: Just because it can be done
> does not mean that it was designed for that purpose.
If it succeed it doesn't break the things. And for every C++ string
changing trick can be created counter-example (yes, synthetic, but
anyway) that violates logic or even crash an application. At least in
the form how I see it will be implemented.

> You argument is like saying that a wrench was designed to be used as a hammer
> (after all, you can hit a nail with it).
I've never seen manual to the wrench but if one exists I doubt there is
a section "how to hit a nail with wrench". But I see chrpath tool on
Linux and install_name_tool on OSX.

Will you be okay if I change "designed" to "can be done correctly"?

Ruslo
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Alexander Neundorf-3
In reply to this post by CMake mailing list

On Thursday, December 03, 2015 09:27:29 Ruslan Baratov via CMake wrote:

 

> On 03-Dec-15 04:34, Alexander Neundorf wrote:

> > On Wednesday, December 02, 2015 12:27:42 Ruslan Baratov wrote:

 

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

>

> I think it's not possible. As far as I know there is no limitation for

> path size on Linux for example. Hence it's not possible to predict what

> size for path to library user want to use by setting RPATH.

 

More nitpicking about the meaning of "designed" ;-) :

 

CMake knows the length of the build RPATH and the length of the install RPATH. Let's say the build RPATH has a length of 100, and the install RPATH has a length of 150, it could, during linking, give the build RPATH to the linker, and also something like --rpath-size=150, and the linker would make the field for the RPATH 150 bytes big, so it could be patched easly later on.

This is what I would consider the minimum support if it was "designed" to be patched.

Instead cmake has to add 50 ":" at the end of the build RPATH. :-/

 

...

> > The idea above was only for solving the question "am I installed ?"

> > yes/no, not "where am I installed ?".

>

> Then I don't understand how it's planned to be used. I thought that in

> build directory you changing "$$$$_I_M_NOT_INSTALLED_$$$$" to

> "/path/to/build/directory" so resources can be found there, and on

> install you change it to "/path/to/install/directory". So my guess is

> not correct?

 

 

Nothing is planned, just some ideas.

The idea was, during install, to set the first byte of that special string to '\0', and in the code you test whether the string is empty ( -> it has been patched, so it is installed) or not (still the original "$$$$_I_M_NOT_INSTALLED_$$$$").

 

With that information, the developer can then do whatever he wants. e.g. when not installed, search just in $CMAKE_BINARY_DIR (which could be configured into some other string), and if installed, search in some other way.

 

Alex

 


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

CMake mailing list
On 04-Dec-15 03:47, Alexander Neundorf wrote:

On Thursday, December 03, 2015 09:27:29 Ruslan Baratov via CMake wrote:

 

> On 03-Dec-15 04:34, Alexander Neundorf wrote:

> > On Wednesday, December 02, 2015 12:27:42 Ruslan Baratov wrote:

 

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

>

> I think it's not possible. As far as I know there is no limitation for

> path size on Linux for example. Hence it's not possible to predict what

> size for path to library user want to use by setting RPATH.

 

More nitpicking about the meaning of "designed" ;-) :

 

CMake knows the length of the build RPATH and the length of the install RPATH. Let's say the build RPATH has a length of 100, and the install RPATH has a length of 150, it could, during linking, give the build RPATH to the linker, and also something like --rpath-size=150, and the linker would make the field for the RPATH 150 bytes big, so it could be patched easly later on.

This is what I would consider the minimum support if it was "designed" to be patched.

Instead cmake has to add 50 ":" at the end of the build RPATH. :-/

 

...

> > The idea above was only for solving the question "am I installed ?"

> > yes/no, not "where am I installed ?".

>

> Then I don't understand how it's planned to be used. I thought that in

> build directory you changing "$$$$_I_M_NOT_INSTALLED_$$$$" to

> "/path/to/build/directory" so resources can be found there, and on

> install you change it to "/path/to/install/directory". So my guess is

> not correct?

 

 

Nothing is planned, just some ideas.

The idea was, during install, to set the first byte of that special string to '\0', and in the code you test whether the string is empty ( -> it has been patched, so it is installed) or not (still the original "$$$$_I_M_NOT_INSTALLED_$$$$").

 

With that information, the developer can then do whatever he wants. e.g. when not installed, search just in $CMAKE_BINARY_DIR (which could be configured into some other string), and if installed, search in some other way.

Will not work, just like I said compiler is smart enough to figure out if the first char in string literal is '\0' or not. Just make some testing: https://gist.github.com/ruslo/04d8993800ee78513d1c

The only one possibility to implement what you want I see in creating new dynamic library (probably by CMake) with one literal:

// 3rd party library API
const char* path_to_install();

void parse_resources() {
  const char* x = path_to_install();
  assert(x != 0);
  if (x[0] == '\0') {
    // OK, can't be optimized since it's an external library
  }
  else {
    // load resources
  }
}

So CMake should create such library in build directory and then re-create and install it with new string in install directory. Of course if you move such library it will not work :) So still doesn't make sense to me...

Ruslo


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Best way to handle application data path for local run vs. installation

Dmitry Marakasov
In reply to this post by Dmitry Marakasov
* Dmitry Marakasov ([hidden email]) wrote:

> Anyway for now, I did some research and solved the problem of inplace
> vs. systemwide compilation in a way that I find acceptable.
>
> I check for CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT to basically
> know whether a user has explicitly specified CMAKE_INSTALL_PREFIX.
> If user specified install prefix, I prepare for systemwide install,
> otherwise I prepare for inplace run.
>
> https://github.com/AMDmi3/hoverboard-sdl/blob/0.4.0/CMakeLists.txt
>
> This doesn't support inplace and systemwide /at the same time/, but
> still supports either of them cleanly, doesn't require extra actions
> from user and behaves sensibly by default.

Wanted to add that this doesn't really work well. When cmake is run
second time, it always switches to systemwide installation because of
cache. I think I'll go with adding explicit SYSTEMWIDE and STANDALONE
options, former builds for systemwide installation with global paths,
and latter for installation into self-contained directory with local
paths (e.g. for windows/macos), and if neither is specified the
project runs from the build directory.

I don't see any better solution right now.

--
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
[hidden email]  ..:  jabber: [hidden email]      http://amdmi3.ru
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake