4

I've been building RPMs using CMake & CPack 3.13.4 on OEL7 for several months without issue. My CMake configuration contained these lines:

SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)

This has allowed me to ensure that the locally built versions of the library are used before any installed versions. Without making any changes to these lines I am suddenly unable to build RPMs any more. I now get this error message:

+ /usr/lib/rpm/check-rpaths
*******************************************************************************
*
* WARNING: 'check-rpaths' detected a broken RPATH and will cause 'rpmbuild'
*          to fail. To ignore these errors, you can set the '$QA_RPATHS'
*          environment variable which is a bitmask allowing the values
*          below. The current value of QA_RPATHS is 0x0000.
*
*    0x0001 ... standard RPATHs (e.g. /usr/lib); such RPATHs are a minor
*               issue but are introducing redundant searchpaths without
*               providing a benefit. They can also cause errors in multilib
*               environments.
*    0x0002 ... invalid RPATHs; these are RPATHs which are neither absolute
*               nor relative filenames and can therefore be a SECURITY risk
*    0x0004 ... insecure RPATHs; these are relative RPATHs which are a
*               SECURITY risk
*    0x0008 ... the special '$ORIGIN' RPATHs are appearing after other
*               RPATHs; this is just a minor issue but usually unwanted
*    0x0010 ... the RPATH is empty; there is no reason for such RPATHs
*               and they cause unneeded work while loading libraries
*    0x0020 ... an RPATH references '..' of an absolute path; this will break
*               the functionality when the path before '..' is a symlink
*          
*
* Examples:
* - to ignore standard and empty RPATHs, execute 'rpmbuild' like
*   $ QA_RPATHS=$[ 0x0001|0x0010 ] rpmbuild my-package.src.rpm
* - to check existing files, set $RPM_BUILD_ROOT and execute check-rpaths like
*   $ RPM_BUILD_ROOT=<top-dir> /usr/lib/rpm/check-rpaths
*  
*******************************************************************************
ERROR   0002: file '/opt/project/lib/libConfigLoader.so.4.0.0' contains an invalid rpath '/opt/project/lib' in [/opt/project/lib]
ERROR   0002: file '/opt/project/lib/libConfigLoaderDb.so.4.0.0' contains an invalid rpath '/opt/project/lib' in [/opt/project/lib]

This seems wrong because it's stating that /opt/project/lib is not an absolute path, which it is.

The permissions of /opt/project/lib are:

[user@c7 ]$ ll -d /opt/
drwxrwxr-x. 10 root root 139 Oct 11 14:31 /opt/
[user@c7 ]$ ll -d /opt/project/
drwxrwx--- 11 root project 114 Oct 11 14:32 /opt/project/
[user@c7 ]$ ll -d /opt/project/lib
drwxrwx--- 2 root project 4096 Oct 11 14:53 /opt/project/lib

I am able to suppress the error by prepending QA_RPATHS=0x0002 to my make command, but I'm concerned that doing this might obscure other errors in future.

I looked into the check-rpaths script (and the check-rpaths-worker script that it uses), and the issue seems to come from this part, where j has been set to the rpath, in this case /opt/project/lib:

            case "$j" in
                (/lib/*|/usr/lib/*|/usr/X11R6/lib/*|/usr/local/lib/*)
                    badness=0;;
                (/lib64/*|/usr/lib64/*|/usr/X11R6/lib64/*|/usr/local/lib64/*)
                    badness=0;;

                (\$ORIGIN|\${ORIGINX}|\$ORIGIN/*|\${ORIGINX}/*)
                    test $allow_ORIGIN -eq 0 && badness=8 || {
                        badness=0
                        new_allow_ORIGIN=1
                    }
                    ;;
                (/*\$PLATFORM*|/*\${PLATFORM}*|/*\$LIB*|/*\${LIB}*)
                    badness=0;;

                (/lib|/usr/lib|/usr/X11R6/lib)
                    badness=1;;
                (/lib64|/usr/lib64|/usr/X11R6/lib64)
                    badness=1;;

                (.*)
                    badness=4;;
                (*) badness=2;;
            esac

(Source)

I don't understand how this ever let /opt/project/lib pass, as from that 'case' statement it would always drop to the (*) case and set badness=2

What else can I try?

Obiphil
  • 361
  • 1
  • 6
  • 17
  • 1
    Hello. Did you find a solution/workaround? I had the same problem and [removing the `~/.rpmmacros` file](https://unix.stackexchange.com/a/220544) helped me. (I run `make package` with cmake/cpack-generated Makefile on the shared machine, and probably somebody or something changed the contents of this file on that machine (so that the line `%__arch_install_post /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot` appeared or was uncommented) — that seems to be the reason of the problem in my case.) – Sasha Jul 22 '20 at 00:25
  • Thanks for your comment, I ran into this problem again after starting a new project. I did as you said and the problem went away! If you want to make your comment a full answer I'll accept it – Obiphil Jul 16 '21 at 09:26

4 Answers4

3

I had the same problem.

In my case, removing the ~/.rpmmacros file has solved the problem.

(I was running make package with cmake/cpack-generated Makefile on the shared machine. Probably, somebody or something had changed the contents of that file in a way that the following line appeared or got uncommented:

%__arch_install_post   /usr/lib/rpm/check-rpaths   /usr/lib/rpm/check-buildroot

That seemed to be the reason of the problem in my case.)

Sasha
  • 3,599
  • 1
  • 31
  • 52
2

It seems that in some versions/platforms cmake / cpack assumes that the path used for the "make" step will affect the binaries for rpm-distribution. For example in my procect multiple CMakeList.txt files each link together binaries and related shared objects. There are defined include and library directories which are relevant for building each binary but have nothing to do with the resulting rpms for the distribution. So there are two type of directories, one for building the binaries and shared objects and other for the distribution of the binaries and related shared objects in rpms (often defined in the system path and LD_LIBRARY_PATH on the target platform). So in my case I got no rpath error/warning in the "make" step which would have been understandable but instead I got them in the "cpack"-step which makes no sense at all. I bypassed it with setting the environment variable export QA_SKIP_RPATHS=1 AFTER the "make" and BEFORE the "cpack" step.

1

you may optout with %global __brp_check_rpaths %{nil}

for more details read https://fedoraproject.org/wiki/Changes/Broken_RPATH_will_fail_rpmbuild

Sérgio
  • 6,966
  • 1
  • 48
  • 53
1

%global __brp_check_rpaths %{nil} simply lets you waive the check.

Ways to remove the rpath are described here: https://docs.fedoraproject.org/en-US/packaging-guidelines/#_beware_of_rpath.