[cmake-developers] [CMake 0012431]: CPackDeb.cmake creates debian directory only, DEBIAN sometimes needed - dpkg-shlibdeps bails out upon a $ORIGIN RPATH

Mantis Bug Tracker mantis at public.kitware.com
Tue Aug 30 10:34:50 EDT 2011


The following issue has been SUBMITTED. 
====================================================================== 
http://www.itk.org/Bug/view.php?id=12431 
====================================================================== 
Reported By:                Andreas Mohr
Assigned To:                
====================================================================== 
Project:                    CMake
Issue ID:                   12431
Category:                   CPack
Reproducibility:            always
Severity:                   minor
Priority:                   normal
Status:                     new
====================================================================== 
Date Submitted:             2011-08-30 10:34 EDT
Last Modified:              2011-08-30 10:34 EDT
====================================================================== 
Summary:                    CPackDeb.cmake creates debian directory only, DEBIAN
sometimes needed - dpkg-shlibdeps bails out upon a $ORIGIN RPATH
Description: 
Hi,

to try to finally make .deb package automatic dependency resolving work,
I added a local override of CPackDeb.cmake (add 2.8.5 CPackDeb.cmake to a
separate dir, then set(CMAKE_MODULE_PATH ...)) for old CMake versions (< 2.8.3).

This module then called dpkg-shlibdeps (after activating
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)).

dpkg-shlibdeps then bailed out due to an error complaining about not being able
to locate dependencies (said it needs either proper RPATH setup or
LD_LIBRARY_PATH).

Thus I decided to finally set up a proper RPATH instead of using LD_LIBRARY_PATH
in launcher scripts.

I used:

set(CMAKE_BUILD_WITH_INSTALL_RPATH true)
file(RELATIVE_PATH path_executable_to_lib_dir
   "${CMAKE_BINARY_DIR}/${MASTER_BUILD_DIR_BIN}"
   "${CMAKE_BINARY_DIR}/${MASTER_BUILD_DIR_LIB}"
)
if(CMAKE_INSTALL_RPATH)
  SET(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/${path_executable_to_lib_dir}")
else(CMAKE_INSTALL_RPATH)
  SET(CMAKE_INSTALL_RPATH
"${CMAKE_INSTALL_RPATH}:\$ORIGIN:\$ORIGIN/${path_executable_to_lib_dir}")
endif(CMAKE_INSTALL_RPATH)


That was... ""better"" - dpkg-shlibdeps now bailed out with:

custom CPackDeb.cmake override launched!
CPackDeb: - Generating dependency list
CMake Error at
/mnt/nfs/build/source/CMake/cmake/Modules/overrides/CPackDeb_le_2_8_3/CPackDeb.cmake:202
(MESSAGE):
  CPackDeb: dpkg-shlibdeps: dpkg-shlibdeps: warning: $ORIGIN is used in RPATH
  of ./usr/lib/opus-7.0.122.1123/lib/libCtrlColorfan.so and the corresponding
  directory could not be identified due to lack of DEBIAN sub-directory in
  the root of package's build tree

  dpkg-shlibdeps: warning: $ORIGIN is used in RPATH of
  ./usr/lib/opus-7.0.122.1123/lib/libCtrlColorfan.so and the corresponding
  directory could not be identified due to lack of DEBIAN sub-directory in
  the root of package's build tree

  dpkg-shlibdeps: error: couldn't find library libopusport.so.0 needed by
  ./usr/lib/opus-7.0.122.1123/lib/libCtrlColorfan.so (ELF format:
  'elf32-i386'; RPATH: ':$ORIGIN:$ORIGIN/../lib').

  Note: libraries are not searched in other binary packages that do not have
  any shlibs or symbols file.

  To help dpkg-shlibdeps find private libraries, you might need to set
  LD_LIBRARY_PATH.


This is because CPACK_TEMPORARY_DIRECTORY
(${CMAKE_BINARY_DIR}/_CPack_Packages/Linux/DEB/<PACKAGE_NAME>/) is prepared to
contain a debian/ subdir but _NOT_ a DEBIAN/ subdir.

A comment at "Packaging and Installing a Java Program..."
http://ubuntuforums.org/archive/index.php/t-1563874.html says
"$ dpkg --build
is the wrong command. it builds a deb file out of a filesystem heirarchy. debian
directories are lower case for packaging, upper case in the final built deb
package, they shouldnt be changed. you should use"...



dpkg-shlibdeps contains:

# find_library ($soname, \@rpath, $format)
sub my_find_library {
    my ($lib, $rpath, $format, $execfile) = @_;
    my $file;

    # Create real RPATH in case $ORIGIN is used
    # Note: ld.so also supports $PLATFORM and $LIB but they are
    # used in real case (yet)
    my $libdir = relative_to_pkg_root($execfile);
    my $origin;
    if (defined $libdir) {
        $origin = "/$libdir";
        $origin =~ s{/+[^/]*$}{};
    }
    my @RPATH = ();
    foreach my $path (@{$rpath}) {
        if ($path =~ /\$ORIGIN|\$\{ORIGIN\}/) {
            if (defined $origin) {
                $path =~ s/\$ORIGIN/$origin/g;
                $path =~ s/\$\{ORIGIN\}/$origin/g;
            } else {
                warning(_g("\$ORIGIN is used in RPATH of %s and the correspondi
ng " .
                "directory could not be identified due to lack of DEBIAN " .
                "sub-directory in the root of package's build tree"),
$execfile);
            }
        }
        push @RPATH, $path;
    }


And Dpkg/Path.pm/get_pkg_root_dir() is:

sub get_pkg_root_dir($) {
    my $file = shift;
    $file =~ s{/+$}{};
    $file =~ s{/+[^/]+$}{} if not -d $file;
    while ($file) {
        return $file if -d "$file/DEBIAN";
        last if $file !~ m{/};
        $file =~ s{/+[^/]+$}{};
    }
    return undef;
}

Note the _upper_-case DEBIAN directory coding there.


On the one hand one could argue that yes, we _are_ still doing packaging and do
_not_ yet have the final package (thus the temp dir needs to have debian/ not
DEBIAN/), but OTOH we _do_ call dpkg-shlibdeps here already and not at package
installation time and it is _not_ happy
(IIRC the usual recommendation/place is to call dpkg-shlibdeps in control files
in the _final_ package, e.g. postinst).

Thus I'm afraid we need to provide both a debian/ and a DEBIAN/ directory, to
account for these inconsistencies in invocation moments of dpkg-shlibdeps.

The file(MAKE_DIRECTORY ...) additions should then probably be prefaced with a
comment like
"When invoking dpkg-shlibdeps on a CMAKE_INSTALL_RPATH that contains (more
flexible) $ORIGIN dependency path references, it will attempt to detect the
package root by looking for a directory named DEBIAN/ (the recommended location
to call dpkg-shlibdeps usually is within control files of the final package, not
the packaging directory, i.e. in that case there _is_ a control file directory
named DEBIAN/ not debian/). Since we previously only supplied the
packaging-directory-side debian/ directory, it couldn't detect package root and
bailed out completely."


By making the necessary directory additions, dpkg-shlibdeps made some progress
(but it's still not working completely due to other issues that I need to work
on now).


Or perhaps this issue should be reported/fixed at dpkg-shlibdeps, too?

Thanks!
====================================================================== 

Issue History 
Date Modified    Username       Field                    Change               
====================================================================== 
2011-08-30 10:34 Andreas Mohr   New Issue                                    
======================================================================




More information about the cmake-developers mailing list