CMake hardcodes system library path in text files

0 views
Skip to first unread message

David Froger

unread,
Aug 26, 2015, 8:55:22 AM8/26/15
to co...@continuum.io
Hello,

I'm trying to package ITK libraries [0] on Centos 5.11 [1], and then link an
executable with these libraries on Ubuntu 14.04 .

ITK is built with CMake, which generates and install configuration files used
latter by CMake to link with ITK libraries, like with pkg-config.

Problem is that path to system libraries (/usr/lib64/libdl.so,
/usr/lib64/libm.so, /usr/lib64/librt.so) are hardcoded in these configuration
files, but these libraries are found on Ubuntu 14.04 in /lib/x86_64-linux-gnu or
/usr/lib/x86_64-linux-gnu.

I'm looking for a solution:

- at the end of build.sh, replace all paths like /usr/lib64/libm.so with
libm.so?
- make conda-build automatically do this?
- maybe there is a CMake option to do it?
- using RPATHs http://conda.pydata.org/docs/building/meta-yaml.html#rpaths?

Does anyone already solved this kind of problem?

Thanks,
David

Small example to reproduce the problem
======================================

ITK is a big project, here is a minimal example to reproduce the problem:

https://github.com/dfroger/gravitation

The conda package 'gravitation' built on Centos 5.11 contains among other these
files:
- lib/libgravation.so
- include/gravitation/gravitation.hxx
- share/gravitation/GRAVITATION_LIBRARY-noconfig.cmake This file contains
information for CMake to link with lib/libgravitation.so, and contains
a reference to ""/usr/lib64/libm.so".

The conda package 'gravitation' is then installed on Ubuntu 14.04, and I want
to link the file example/main.cxx with lib/libgravitation.so

The CMakeLists.txt is:

cmake_minimum_required(VERSION 2.8)
cmake_policy(VERSION 2.8)
project(GRAVITATION)
set(version 0.1.0)

find_package(gravitation REQUIRED)

include_directories(${GRAVITATION_INCLUDE_DIRS})

# Create executable.
add_executable(gravitation-example main.cxx)
target_link_libraries(gravitation-example ${GRAVITATION_LIBRARIES})

Configure:

$ mkdir build
$ cd build
$ cmake ..

This creates a file build/CMakeFiles/gravitation-example.dir/build.make
containing the rule:

gravitation-example: /usr/lib64/libm.so

Build:
$ make

this causes the error:
make[2]: *** No rule to make target `/usr/lib64/libm.so', needed by `gravitation-example'. Stop.

Indeed, on Ubuntu 14.04, m library is found at /lib/x86_64-linux-gnu/libm.so.6
or /usr/lib/x86_64-linux-gnu/libm.so

Links
=====

[0] https://github.com/heimdali/heimdali/tree/2d9f12c7db78d7b8b25d7b573880497dbb8e032b/conda-recipe/itk
[1] https://github.com/dfroger/conda-build-env/tree/a878cc82a2d77c353a15c5e11e34505caa383e26

Stuart Berg

unread,
Aug 27, 2015, 10:58:39 AM8/27/15
to David Froger, conda
Hi David,

I don't know the exact answer to your question, so hopefully someone else can chime in.  Here's what advice I can offer:

I'm trying to package ITK libraries [0] on Centos 5.11 [1], and then link an
executable with these libraries on Ubuntu 14.04 .

Note that my recipe only builds a small subset of ITK, just the "segmentation" group and "convolution" module. (I use -DITK_BUILD_DEFAULT_MODULES=0, and then select the specific modules I need.)

I build it on CentOS-5.11, and you can try it your self via:
conda install -c ilastik itk-seg-conv-only
 

ITK is built with CMake, which generates and install configuration files used
latter by CMake to link with ITK libraries, like with pkg-config.

Problem is that path to system libraries (/usr/lib64/libdl.so,
/usr/lib64/libm.so, /usr/lib64/librt.so) are hardcoded in these configuration
files, but these libraries are found on Ubuntu 14.04 in /lib/x86_64-linux-gnu or
/usr/lib/x86_64-linux-gnu.
 
You'll notice that my libITK*.so files *do not* include absolute links to libm.so (and none of them link against librt at all, probably because I'm not building everything).  I'm not sure why mine use relative so-names and your build uses absolute names.  One difference between your recipe and mine is the detect_binary_files_with_prefix setting:
https://github.com/ilastik/ilastik-build-conda/blob/master/itk-seg-conv-only/meta.yaml#L12

...but I don't see why that would be responsible for the difference we're seeing in the .so files.


I'm looking for a solution:

  - at the end of build.sh, replace all paths like /usr/lib64/libm.so with
    libm.so?
  - make conda-build automatically do this?
  - maybe there is a CMake option to do it?

Hopefully a conda developer can offer advice about one of these three options.
I don't think this can help you here.  If the soname in your library is already hard-linked as an absolute path, then adding an RPATH to search can't help.  RPATHs can only help if the soname is *relative*, in which case the loader will search the RPATH directories.
 
HTH,
Stuart

David Froger

unread,
Aug 27, 2015, 12:57:50 PM8/27/15
to Stuart Berg, conda
Hi Stuart,

Quoting Stuart Berg (2015-08-27 16:58:38)
> Hi David,
>
> I don't know the exact answer to your question, so hopefully someone else can
> chime in.  Here's what advice I can offer:
>
>
> I'm trying to package ITK libraries [0] on Centos 5.11 [1], and then link
> an
> executable with these libraries on Ubuntu 14.04 .
>
>
> FWIW, my recipe for ITK can be found here:
> https://github.com/ilastik/ilastik-build-conda/tree/master/itk-seg-conv-only

Thanks for your help!

> You'll notice that my libITK*.so files *do not* include absolute links to
> libm.so (and none of them link against librt at all, probably because I'm not
> building everything).  I'm not sure why mine use relative so-names and your
> build uses absolute names. 

Actually, my libITK*.so files do not include absolute links to libm.so, and
/usr/lib/x86_64-linux-gnu/libm.so is used as expected.

Problem is in ITK config files, for example,
lib/cmake/ITK-4.7ITKTargets-release.cmake contains:

# Import target "ITKIOHDF5" for configuration "Release"
set_property(TARGET ITKIOHDF5 APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(ITKIOHDF5 PROPERTIES
IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5_cpp.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so;ITKIOImageBase;/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5_cpp.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so"
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libITKIOHDF5-4.7.so.1"
IMPORTED_SONAME_RELEASE "libITKIOHDF5-4.7.so.1"
)

I think I only have the problem with the configuration of the HDF5 ITK module.

By the way, I have another problem with my ITK package: On Ubuntu 14.04, I can
link with ITK libraries with /usr/bin/gcc (after fixing my first problem
replacing /usr/lib64/libm.so with libm.so, etc), but when I use gcc from 'conda
install -c asmeurer gcc=4.8.5', CMake does not put flags -L, -Wl,-rpath and
-Wl,-rpath-link, and for example 'libitkgdcmjpeg8-4.7.so.1' needed by
libitkgdcmMSFF-4.7.so is not found by ld. But no ideas why...

Aaron Meurer

unread,
Aug 27, 2015, 1:29:22 PM8/27/15
to Stuart Berg, David Froger, conda
That setting tells conda to replace hard-coded prefixes in binary
files. With it active, if there are hard-coded prefixes, they should
be set to the install prefix of whatever environment you installed the
package in (you can also check the info/has_prefix file of the package
to see what files have the prefix baked into them).

Aaron Meurer

>
> ...but I don't see why that would be responsible for the difference we're
> seeing in the .so files.
>
>
>> I'm looking for a solution:
>>
>> - at the end of build.sh, replace all paths like /usr/lib64/libm.so with
>> libm.so?
>>
>> - make conda-build automatically do this?
>> - maybe there is a CMake option to do it?
>
>
> Hopefully a conda developer can offer advice about one of these three
> options.
>
>>
>> - using RPATHs
>> http://conda.pydata.org/docs/building/meta-yaml.html#rpaths?
>
>
> I don't think this can help you here. If the soname in your library is
> already hard-linked as an absolute path, then adding an RPATH to search
> can't help. RPATHs can only help if the soname is *relative*, in which case
> the loader will search the RPATH directories.
>
> HTH,
> Stuart
>
> --
> You received this message because you are subscribed to the Google Groups
> "conda - Public" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to conda+un...@continuum.io.
> To post to this group, send email to co...@continuum.io.
> Visit this group at http://groups.google.com/a/continuum.io/group/conda/.

Stuart Berg

unread,
Aug 27, 2015, 1:43:13 PM8/27/15
to David Froger, conda
Hi David,

Actually, my libITK*.so files do not include absolute links to libm.so, and
/usr/lib/x86_64-linux-gnu/libm.so is used as expected.

OK, Thanks for the explanation.  I clearly did not read your first email very carefully -- I was answering the wrong question entirely :-/
 

Problem is in ITK config files, for example,
lib/cmake/ITK-4.7ITKTargets-release.cmake contains:

    # Import target "ITKIOHDF5" for configuration "Release"
    set_property(TARGET ITKIOHDF5 APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
    set_target_properties(ITKIOHDF5 PROPERTIES
      IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5_cpp.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so;ITKIOImageBase;/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5_cpp.so;/opt/anaconda1anaconda2anaconda3/lib/libhdf5.so;/usr/lib64/librt.so;/opt/anaconda1anaconda2anaconda3/lib/libz.so;/usr/lib64/libdl.so;/usr/lib64/libm.so"
      IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libITKIOHDF5-4.7.so.1"
      IMPORTED_SONAME_RELEASE "libITKIOHDF5-4.7.so.1"
      )

I think I only have the problem with the configuration of the HDF5 ITK module.

Now I understand that the problem is with the text files in ${PREFIX}/lib/cmake/ITK-4.7/.  If I had to guess, I'd say the problem is that the ITKIOHDF5 cmake files are somehow hard-coding a dependency on /usr/lib64/libm.so instead of add_target_link_libraries(m), or something like that.

One option is to debug the ITKIOHDF5 cmake scripts themselves.  But I think your idea to add some special post-processing to build.sh to replace /usr/lib64/libm.so with "m" sounds like a reasonable workaround.

 
By the way, I have another problem with my ITK package: On Ubuntu 14.04, I can
link with ITK libraries with /usr/bin/gcc (after fixing my first problem
replacing /usr/lib64/libm.so with libm.so, etc), but when I use gcc from 'conda
install -c asmeurer gcc=4.8.5', CMake does not put flags -L, -Wl,-rpath and
-Wl,-rpath-link, and for example 'libitkgdcmjpeg8-4.7.so.1' needed by
libitkgdcmMSFF-4.7.so is not found by ld. But no ideas why...

Interesting.  I don't know why there would be a difference in behavior between /usr/bin/gcc and asmeurer's gcc binary.  But in any case, if you know the flags that you need, you can just add them to your cmake command via -DCMAKE_SHARED_LINKER_FLAGS and -DCMAKE_EXE_LINKER_FLAGS.

HTH,
Stuart

David Froger

unread,
Aug 27, 2015, 3:57:17 PM8/27/15
to Stuart Berg, conda
> One option is to debug the ITKIOHDF5 cmake scripts themselves.  But I think
> your idea to add some special post-processing to build.sh to replace /usr/lib64
> /libm.so with "m" sounds like a reasonable workaround.

I can reproduce on a small example, without HDF5, just m:
https://github.com/dfroger/gravitation

> By the way, I have another problem with my ITK package: On Ubuntu 14.04, I
> can
> link with ITK libraries with /usr/bin/gcc (after fixing my first problem
> replacing /usr/lib64/libm.so with libm.so, etc), but when I use gcc from
> 'conda
> install -c asmeurer gcc=4.8.5', CMake does not put flags -L, -Wl,-rpath and
> -Wl,-rpath-link, and for example 'libitkgdcmjpeg8-4.7.so.1' needed by
> libitkgdcmMSFF-4.7.so is not found by ld. But no ideas why...
>
>
> Interesting.  I don't know why there would be a difference in behavior between
> /usr/bin/gcc and asmeurer's gcc binary.  But in any case, if you know the flags
> that you need, you can just add them to your cmake command via
> -DCMAKE_SHARED_LINKER_FLAGS and -DCMAKE_EXE_LINKER_FLAGS.

I can reproduce on this small example:
https://github.com/dfroger/secondary_dep

but don't found the explanation for now...
Reply all
Reply to author
Forward
0 new messages