Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpath doesn't work correctly with relative CMAKE_INSTALL_LIBDIR #437

Open
jirislaby opened this issue Jul 26, 2022 · 12 comments · May be fixed by #438
Open

rpath doesn't work correctly with relative CMAKE_INSTALL_LIBDIR #437

jirislaby opened this issue Jul 26, 2022 · 12 comments · May be fixed by #438

Comments

@jirislaby
Copy link
Contributor

openSUSE build system defines:

 -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix}
 -DCMAKE_INSTALL_LIBDIR:PATH=%{_lib}

where:

$ rpm -E '%{_prefix} XX %{_lib}'
/usr XX lib64

I.e. CMAKE_INSTALL_LIBDIR is relative. Which is perfectly fine -- in fact https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html says:

It should typically be a path relative to the installation prefix so that it can be converted to an absolute path in a relocatable way (see CMAKE_INSTALL_FULL_<dir>). However, an absolute path is also allowed.

So this test doesn't work properly:

stp/CMakeLists.txt

Lines 191 to 194 in e8d153f

LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_LIBDIR}" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_LIBDIR}")
ENDIF("${isSystemDir}" STREQUAL "-1")

and rpath is set to "lib64". If you used GNUInstallDirs, you could use CMAKE_INSTALL_FULL_LIBDIR in the test above. I don't know how to solve it without GNUInstallDirs.

BTW. minisat has exactly the same problem:
https://github.com/stp/minisat/blob/37158a35c62d448b3feccfa83006266e12e5acb7/CMakeLists.txt#L86

@aytey
Copy link
Member

aytey commented Jul 26, 2022

Hmm, so, just so I understand: on some platforms, the above check fails and then we rpath the STP libs to be lib64 (like it is relative path), when actually it shouldn't be done because the install directory is /lib64 so the rpathing shouldn't be done at all?

The part I don't understand is: why does that check fail? Surely on OpenSUSE lib64 is a CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES?

Just so we know, the snippet you highlighted came from the Kitware (the makers of CMake) wiki:

Given it is also used in other places:

I'm slightly inclined that there's a bit more going on here than just "OpenSUSE uses lib64".

@jirislaby
Copy link
Contributor Author

jirislaby commented Jul 26, 2022

Hmm, so, just so I understand: on some platforms, the above check fails and then we rpath the STP libs to be lib64 (like it is relative path),

Right.

when actually it shouldn't be done because the install directory is /lib64 so the rpathing shouldn't be done at all?

Mostly, the path is /usr/lib64.

And according to the script, the rpath setting happens always. It's just that it should be set to /usr/lib64. Not sure what's the reason behind that...

The part I don't understand is: why does that check fail? Surely on OpenSUSE lib64 is a CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES?

No, it's all absolute:

$ cat CMakeLists.txt 
message("${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}")
$ cmake .
...
/lib;/lib32;/lib64;/usr/lib;/usr/lib32;/usr/lib64
...

I'm slightly inclined that there's a bit more going on here than just "OpenSUSE uses lib64".

I noticed only now, because openSUSE started complaining about buggy rpaths in libs only recently.

As I wrote:

If you used GNUInstallDirs, you could use CMAKE_INSTALL_FULL_LIBDIR in the test above.

@aytey
Copy link
Member

aytey commented Jul 26, 2022

Just so you know: your issue here is totally legitimate; I'm just trying to understand it so we know how to fix it correctly.

No, it's all absolute:

$ cat CMakeLists.txt 
message("${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}")
$ cmake .
...
/lib;/lib32;/lib64;/usr/lib;/usr/lib32;/usr/lib64
...

Okay, but as you wrote above:

Mostly, the path is /usr/lib64.

So why does the check fail here? Surely /usr/lib64 is in CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES?

@jirislaby
Copy link
Contributor Author

jirislaby commented Jul 26, 2022

So why does the check fail here? Surely /usr/lib64 is in CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES?

But CMAKE_INSTALL_LIBDIR is lib64.

CMAKE_INSTALL_PREFIX is /usr.

And CMAKE_INSTALL_FULL_LIBDIR would be /usr/lib64, with GNUInstallDirs.

With this CMakeLists.txt:

if (USE_GID)
        include(GNUInstallDirs)
endif()
message("CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES=${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}")
message("CMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}")
message("CMAKE_INSTALL_FULL_LIBDIR=${CMAKE_INSTALL_FULL_LIBDIR}")
$ cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib64 . |& grep CMAKE
CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES=/lib;/lib32;/lib64;/usr/lib;/usr/lib32;/usr/lib64
CMAKE_INSTALL_LIBDIR=lib64
CMAKE_INSTALL_FULL_LIBDIR=
$ cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib64 -DUSE_GID=1 . |& grep CMAKE
CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES=/lib;/lib32;/lib64;/usr/lib;/usr/lib32;/usr/lib64
CMAKE_INSTALL_LIBDIR=lib64
CMAKE_INSTALL_FULL_LIBDIR=/usr/lib64

@aytey
Copy link
Member

aytey commented Jul 26, 2022

You seem to be hesitant for STP to adopt GNUInstallDirs; what's the disadvantage (if you know)?

@aytey
Copy link
Member

aytey commented Jul 26, 2022

Another question: could we just "emulate" GNUInstallDirs by joining CMAKE_INSTALL_PREFIX with CMAKE_INSTALL_LIBDIR?

@jirislaby
Copy link
Contributor Author

jirislaby commented Jul 26, 2022

You seem to be hesitant for STP to adopt GNUInstallDirs; what's the disadvantage (if you know)?

I use it for all my projects. But they are all linux. I don't know how it behaves on win for example.

For example here:
https://github.com/jirislaby/ifoxtrot-qt/blob/master/CMakeLists.txt

That works for mingw too:
https://build.opensuse.org/package/live_build_log/home:jirislaby/mingw64-ifoxtrot-qt/win64/x86_64
but I have never tried native win compilation.

@jirislaby
Copy link
Contributor Author

Another question: could we just "emulate" GNUInstallDirs by joining CMAKE_INSTALL_PREFIX with CMAKE_INSTALL_LIBDIR?

CMAKE_INSTALL_LIBDIR could be absolute, so the join would fail in that case.

@aytey
Copy link
Member

aytey commented Jul 26, 2022

Would you be happy to make a PR that uses GNUInstallDirs only on Linux?

@jirislaby
Copy link
Contributor Author

Would you be happy to make a PR that uses GNUInstallDirs only on Linux?

Heh:

include(GNUInstallDirs)

So it should be matter of correct use of CMAKE_INSTALL_FULL_LIBDIR now.

@jirislaby
Copy link
Contributor Author

jirislaby commented Jul 26, 2022

Just so we know, the snippet you highlighted came from the Kitware (the makers of CMake) wiki:

* https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling#always-full-rpath

Given it is also used in other places:

* https://github.com/dls-controls/hdf5filters/blob/master/CMakeLists.txt#L52-L55

Just noticed that these two links behave differently than stp+minisat. They have ${CMAKE_INSTALL_PREFIX}/lib. That would actually work. (But only on 32 bit -- lib vs lib64.) This was changed in a26083b. It should have been changed to CMAKE_INSTALL_FULL_PREFIX and it would work fine IMO (I'll check tomorrow).

What I don't understand is this (from the either) link:

set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
...
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
    set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif("${isSystemDir}" STREQUAL "-1")

What's the purpose of the whole if given CMAKE_INSTALL_RPATH is set to ${CMAKE_INSTALL_PREFIX}/lib above unconditionally?

jirislaby pushed a commit to jirislaby/stp that referenced this issue Jul 27, 2022
Commit a26083b (Fixing libdirs for CMakeLists) switched from
"${CMAKE_INSTALL_PREFIX}/lib" to "${CMAKE_INSTALL_LIBDIR}". It fixed the
issue with lib vs lib64. But while the former is absolute, the latter
needs not. That causes troubles as rpath can be set to simething like
"lib64" only. That is bogus

So fix this by using absolute ${CMAKE_INSTALL_FULL_LIBDIR}" from
GNUInstallDirs which is already included and handles the paths correctly.

Fixes stp#437.
@jirislaby
Copy link
Contributor Author

jirislaby commented Jul 27, 2022

Just noticed that these two links behave differently than stp+minisat. They have ${CMAKE_INSTALL_PREFIX}/lib. That would actually work. (But only on 32 bit -- lib vs lib64.) This was changed in a26083b. It should have been changed to CMAKE_INSTALL_FULL_PREFIX and it would work fine IMO (I'll check tomorrow).

Yes, that works for me. Let's do a PR.

What's the purpose of the whole if given CMAKE_INSTALL_RPATH is set to ${CMAKE_INSTALL_PREFIX}/lib above unconditionally?

This, I still have no clue -- reported:
https://discourse.cmake.org/t/rpath-handling-in-the-wiki-bug/6155

jirislaby pushed a commit to jirislaby/stp that referenced this issue Jul 27, 2022
Commit a26083b (Fixing libdirs for CMakeLists) switched from
"${CMAKE_INSTALL_PREFIX}/lib" to "${CMAKE_INSTALL_LIBDIR}". It fixed the
issue with lib vs lib64. But while the former is absolute, the latter
needs not. That causes troubles as rpath can be set to something like
"lib64" only. That is bogus.

So fix this by using absolute "${CMAKE_INSTALL_FULL_LIBDIR}" from
GNUInstallDirs which is already included and handles the paths
correctly.

Fixes stp#437.
@jirislaby jirislaby linked a pull request Jul 27, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants