Correct handling of absolute/relative installation paths

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Correct handling of absolute/relative installation paths

David Demelier
Hello,

I'm still trying to find a correct solution to handle user specified
installation paths.

Let's consider two kind of paths:

   - WITH_BINDIR (default: bin/) where to install executables,
   - WITH_DATADIR (default: share/project_name/) where to install extra
data.

I want to let the user configuring those paths because not all
distributions use the same paths (e.g. bin vs usr/bin).

Then, I also like to build the whole CMake project by creating the
hierarchy as it would be installed like:

<binarydir>/WITH_BINDIR/myapp
<binarydir>/WITH_DATADIR/somestuff.txt

Using relative paths makes the application relocatable, if I keep
WITH_BINDIR set as "bin" I can get the executable path at runtime, going
through its parent (bin/../) and then I can go share/project_name.
Obviously this is only valid for relative paths.

However, a very high number of package managers build programs by
specifying absolute paths, it is not an issue: instead of getting the
directories at runtime, I use directly the absolute ones.

On unix it can still work because it will just be translated as:

<binarydir>/usr/local/bin/myapp
<binarydir>/usr/local/share/project_name/somestuff.txt

This is much bigger an issue on Windows if the user set WITH_BINDIR to
something like D:/alt/bin

The path would be translated to

<binarydir>D:/alt/bin

which is invalid on Windows.

I like very much having this kind of `fakeroot' directory where you can
have a preview on how the project looks like but I don't know what to do
if paths are absolute, especially on Windows.

What are your thoughts on that, recommandations?

Regards,

--
David Demelier
--

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
|  
Report Content as Inappropriate

Re: Correct handling of absolute/relative installation paths

Eric Noulard


2017-07-27 12:28 GMT+02:00 David Demelier <[hidden email]>:
Hello,

I'm still trying to find a correct solution to handle user specified installation paths.

Let's consider two kind of paths:

  - WITH_BINDIR (default: bin/) where to install executables,
  - WITH_DATADIR (default: share/project_name/) where to install extra data.

I want to let the user configuring those paths because not all distributions use the same paths (e.g. bin vs usr/bin).

Then, I also like to build the whole CMake project by creating the hierarchy as it would be installed like:

<binarydir>/WITH_BINDIR/myapp
<binarydir>/WITH_DATADIR/somestuff.txt

Do you mean here that you setup CMAKE_<XXXX>_OUTPUT_DIRECTORY (variable or target property) to your favorite value
or
You build and then install with the <binarydir>/ prefix?
 

Using relative paths makes the application relocatable, if I keep WITH_BINDIR set as "bin" I can get the executable path at runtime, going through its parent (bin/../) and then I can go share/project_name. Obviously this is only valid for relative paths.

However, a very high number of package managers build programs by specifying absolute paths, it is not an issue: instead of getting the directories at runtime, I use directly the absolute ones.

On unix it can still work because it will just be translated as:

<binarydir>/usr/local/bin/myapp
<binarydir>/usr/local/share/project_name/somestuff.txt

This is much bigger an issue on Windows if the user set WITH_BINDIR to something like D:/alt/bin

The path would be translated to

<binarydir>D:/alt/bin

which is invalid on Windows.

I like very much having this kind of `fakeroot' directory where you can have a preview on how the project looks like but I don't know what to do if paths are absolute, especially on Windows.

My opinion is that you should never use absolute path (besides some very specific case on unix where you want to put something in /etc/...)
You should ask your user for

   DATADIR
   BINDIR
   etc...

all those var should be relative path.

and an eventual
   INSTALL_PREFIX
which could be absolute.

In any case if you really want to tolerate absolute path given by the user, but still want to mimic install location during the build
then you'll have to escape it.

For each path you expect from the user:

check the path with if(IS_ABSOLUTE path) and compute some relative path
  a) if you are on Windows remove the drive letter, i.e. D:/alt/bin becomes alt/bin
          (or network drive share name //shairedisk/alt/bin  becomes alt/bin)
  b) if you are on Unix 
 

What are your thoughts on that, recommandations?

I wouldn't try to mimic install tree during the build (if it is what you are doing),
If I have a need to "verify" install tree structure then **after the build** I would do a fake install with a particular
local prefix (as CPack does before packaging).

Note that for similar reason CPack has to track files installed with absolute destination and
possibly error out when it cannot handle it, particularly on Windows oriented generator:
see e.g.:

AFAIK, IFW and NSIS do not work with, absolute installed files.


--
Eric

--

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
|  
Report Content as Inappropriate

Re: Correct handling of absolute/relative installation paths

J Decker
It's also handy to get installation paths from GNUInstallDirs

https://cmake.org/cmake/help/v3.4/module/GNUInstallDirs.html  especially if you expect to install libs on linux which either go to lib or lib64.

many things that install to windows just supply a standard base path (/program files/<your app>) and then still use bin, lib, share, etc in that path...

It is an annoyance to have to override dll installation to bin instead of lib on windows....

include( GNUInstallDirs )

if( WIN32 )
    set( BINARY_OUTPUT_DIR ${CMAKE_INSTALL_BINDIR} )
    set( SHARED_LIBRARY_OUTPUT_DIR ${CMAKE_INSTALL_BINDIR} )
    set( SHARED_LIBRARY_LINK_DIR ${CMAKE_INSTALL_LIBDIR} )
else( WIN32 )
      set( BINARY_OUTPUT_DIR ${CMAKE_INSTALL_BINDIR} )
      set( SHARED_LIBRARY_OUTPUT_DIR ${CMAKE_INSTALL_LIBDIR} )
      set( SHARED_LIBRARY_LINK_DIR ${CMAKE_INSTALL_LIBDIR} )
endif( WIN32 )

and then use the aliased path instead

macro( install_my_thing )
install( TARGETS ${ARGV}
RUNTIME DESTINATION ${BINARY_OUTPUT_DIR} 
LIBRARY DESTINATION ${SHARED_LIBRARY_OUTPUT_DIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} )
endmacro( install_my_thing )

People will inevitably also respond and say 'but dlls install as runtime' which is probably true these days.  All I can do is copy the cmake stuff I have that definitely works; which has been around since 2.6 or something...

So it's probably simpler than what I've shared above.


On Thu, Jul 27, 2017 at 4:08 AM, Eric Noulard <[hidden email]> wrote:


2017-07-27 12:28 GMT+02:00 David Demelier <[hidden email]>:
Hello,

I'm still trying to find a correct solution to handle user specified installation paths.

Let's consider two kind of paths:

  - WITH_BINDIR (default: bin/) where to install executables,
  - WITH_DATADIR (default: share/project_name/) where to install extra data.

I want to let the user configuring those paths because not all distributions use the same paths (e.g. bin vs usr/bin).

Then, I also like to build the whole CMake project by creating the hierarchy as it would be installed like:

<binarydir>/WITH_BINDIR/myapp
<binarydir>/WITH_DATADIR/somestuff.txt

Do you mean here that you setup CMAKE_<XXXX>_OUTPUT_DIRECTORY (variable or target property) to your favorite value
or
You build and then install with the <binarydir>/ prefix?
 

Using relative paths makes the application relocatable, if I keep WITH_BINDIR set as "bin" I can get the executable path at runtime, going through its parent (bin/../) and then I can go share/project_name. Obviously this is only valid for relative paths.

However, a very high number of package managers build programs by specifying absolute paths, it is not an issue: instead of getting the directories at runtime, I use directly the absolute ones.

On unix it can still work because it will just be translated as:

<binarydir>/usr/local/bin/myapp
<binarydir>/usr/local/share/project_name/somestuff.txt

This is much bigger an issue on Windows if the user set WITH_BINDIR to something like D:/alt/bin

The path would be translated to

<binarydir>D:/alt/bin

which is invalid on Windows.

I like very much having this kind of `fakeroot' directory where you can have a preview on how the project looks like but I don't know what to do if paths are absolute, especially on Windows.

My opinion is that you should never use absolute path (besides some very specific case on unix where you want to put something in /etc/...)
You should ask your user for

   DATADIR
   BINDIR
   etc...

all those var should be relative path.

and an eventual
   INSTALL_PREFIX
which could be absolute.

In any case if you really want to tolerate absolute path given by the user, but still want to mimic install location during the build
then you'll have to escape it.

For each path you expect from the user:

check the path with if(IS_ABSOLUTE path) and compute some relative path
  a) if you are on Windows remove the drive letter, i.e. D:/alt/bin becomes alt/bin
          (or network drive share name //shairedisk/alt/bin  becomes alt/bin)
  b) if you are on Unix 
 

What are your thoughts on that, recommandations?

I wouldn't try to mimic install tree during the build (if it is what you are doing),
If I have a need to "verify" install tree structure then **after the build** I would do a fake install with a particular
local prefix (as CPack does before packaging).

Note that for similar reason CPack has to track files installed with absolute destination and
possibly error out when it cannot handle it, particularly on Windows oriented generator:
see e.g.:

AFAIK, IFW and NSIS do not work with, absolute installed files.


--
Eric

--

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
|  
Report Content as Inappropriate

Re: Correct handling of absolute/relative installation paths

David Demelier
In reply to this post by Eric Noulard
Le 27/07/2017 à 13:08, Eric Noulard a écrit :

>
>
> 2017-07-27 12:28 GMT+02:00 David Demelier <[hidden email]
> <mailto:[hidden email]>>:
>
>     Hello,
>
>     I'm still trying to find a correct solution to handle user specified
>     installation paths.
>
>     Let's consider two kind of paths:
>
>        - WITH_BINDIR (default: bin/) where to install executables,
>        - WITH_DATADIR (default: share/project_name/) where to install
>     extra data.
>
>     I want to let the user configuring those paths because not all
>     distributions use the same paths (e.g. bin vs usr/bin).
>
>     Then, I also like to build the whole CMake project by creating the
>     hierarchy as it would be installed like:
>
>     <binarydir>/WITH_BINDIR/myapp
>     <binarydir>/WITH_DATADIR/somestuff.txt
>
>
> Do you mean here that you setup CMAKE_<XXXX>_OUTPUT_DIRECTORY (variable
> or target property) to your favorite value
> or
>
Both, I set the output directory for executable to WITH_BINDIR value and
also install it as destination.

> My opinion is that you should never use absolute path (besides some very
> specific case on unix where you want to put something in /etc/...)
> You should ask your user for
>
>     DATADIR
>     BINDIR
>     etc...
>

This is what I have done in my CMakeLists.txt, the cmake invocation
fails if BINDIR and/or DATADIR are absolute. But again, then with some
package managers you get in troubles because they specify absolute path.

See the RPM default macro:

   /usr/bin/cmake \
         -DCMAKE_C_FLAGS_RELEASE:STRING="-DNDEBUG" \
         -DCMAKE_CXX_FLAGS_RELEASE:STRING="-DNDEBUG" \
         -DCMAKE_Fortran_FLAGS_RELEASE:STRING="-DNDEBUG" \
         -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
         -DCMAKE_INSTALL_PREFIX:PATH=/usr \
         -DINCLUDE_INSTALL_DIR:PATH=/usr/include \
         -DLIB_INSTALL_DIR:PATH=/usr/lib64 \
         -DSYSCONF_INSTALL_DIR:PATH=/etc \
         -DSHARE_INSTALL_PREFIX:PATH=/usr/share \

And if you add any new variable, you should prefix by %{prefix} which is
also absolute...

> I wouldn't try to mimic install tree during the build (if it is what you
> are doing),

The nice thing is that you can easily run/debug the application
especially if that application needs to find some plugins/data while
running by evaluating paths to them.

I'll probably go for something like a pre-install target like you said
instead of mimic'ing the build tree. And disable that target if any of
the paths are absolute.

Thanks for the answers!
--

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