openvdb icon indicating copy to clipboard operation
openvdb copied to clipboard

[BUILD] CMake RelWithDebInfo produces invalid TBB library path resulting in an error

Open joshbainbridge opened this issue 4 years ago • 6 comments

Environment

Operating System: Linux CentOS 7.0 (Core) Version / Commit SHA: VDB 9.0 CMake Version: 3.12 Compiler: clang++ 12.0.1

Describe the problem

Recently we updated from OpenVDB 8.0.1 to 9.0.0 and found that our RelWithDebInfo CMake configurations were failing. This was due to the changes in cmake/FindTBB.cmake and output string that is ill configured. The error we get back from Clang is:

error: 'optimized;/path/to/install/lib64/libtbbmalloc.so.2;debug;/path/to/install/lib64/libtbbmalloc_debug.so.2', needed by 'src/some/library.so', missing and no known rule to make it.

It appears that instead of a specific library file being passed as IMPORTED_LOCATION when constructing the TBB CMake IMPORT target, we are instead passing a CMake string with both release and debug library locations. I believe these might be the key lines.

cmake/FindTBB.cmake:288:

set(Tbb_${COMPONENT}_LIBRARY optimized ${Tbb_${COMPONENT}_LIBRARY_RELEASE} debug ${Tbb_${COMPONENT}_LIBRARY_DEBUG})

cmake/FindTBB.cmake:418:

set_target_properties(TBB::${COMPONENT} PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" IMPORTED_LOCATION "${Tbb_${COMPONENT}_LIBRARY}")

My expectation when building a CMake RelWithDebInfo configuration is that my library will be linked against the debug build of TBB, rather than a release build. But release would also not be an issue. As long as one is selected and the build works.

To Reproduce

Steps to reproduce the behavior:

  1. Checkout repo '...'
  2. Run CMake with -D CMAKE_BUILD_TYPE=RelWithDebInfo
  3. Build binary

Additional context

Our downstream project sets the CMAKE_MODULE_PATH to that of the modules included with OpenVDB. As a result we pick up the FindTBB.cmake module. We might be better off with a CMake config if one was installed along with the OpenVDB binary, avoiding this need. It looks like there is already a ticket for this https://github.com/AcademySoftwareFoundation/openvdb/issues/1160

joshbainbridge avatar Nov 25 '21 10:11 joshbainbridge

Hey @joshbainbridge thanks, I can reproduce this - the error only occurs if both release and debug variants are found (otherwise the keywords are omitted). I think we can just change this:

    # Standard location
    set_target_properties(TBB::${COMPONENT} PROPERTIES
      IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
      IMPORTED_LOCATION "${Tbb_${COMPONENT}_LIBRARY}")

to:

    set_target_properties(TBB::${COMPONENT} PROPERTIES
      IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")

Release/Debug variants are set afterwards. RelWithDebugInfo seems to then pick the RELEASE configuration (alluded to in https://cmake.org/cmake/help/latest/command/target_link_libraries.html#command:target_link_libraries). This will need to be changed in all our modules.

Idclip avatar Nov 30 '21 22:11 Idclip

Thanks for confirming @Idclip! So can we expect to see this in a future release, or do you need us to do a PR?

joshbainbridge avatar Dec 02 '21 17:12 joshbainbridge

I'll take a look at this asap. Though I did just find this:

https://gitlab.kitware.com/cmake/cmake/-/issues/20319

Seems that the crux of this is a known problem - although this isn't exactly what you're running in to, removing the default IMPORTED_CONFIGURATION will expose us to this which is essentially "what should CMake do if you're configuring a build type which doesn't have a config". It seems that CMake simply picks the first created configuration in these cases. For more control I think the solution is to use the CMAKE_MAP_IMPORTED_CONFIG_<> variables. So you might be able to get your RelWithDebInfo builds to work with either:

-DCMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO="RelWithDebInfo;Release;"

or

-DCMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO="RelWithDebInfo;Debug;"

https://cmake.org/cmake/help/latest/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.html

As far as I understand it, this tells CMake to prioritise any RelWithDebInfo configurations but also defines a list of fallbacks, Release in the first case Debug in the second. I would hope that this would build VDB with RelWithDebInfo flags and pick the fallback library types for imported dependencies (so the second option would give you your preferred Debug dep behaviour).

I haven't tested this, if you can try this on your end that would be great.

Idclip avatar Dec 02 '21 23:12 Idclip

No problem. I've tested this and can confirm it works. We needed to add:

set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo Release "")

Only Release would compile, trying Debug did not work. We also needed to include "".

Both of these allowed our other modules to still function as before.

Thanks! This is a good solution for us in the interim.

joshbainbridge avatar Dec 03 '21 18:12 joshbainbridge

Only Release would compile, trying Debug did not work

Interesting, was there a specific error you encountered? Even once I've fixed this CMake will prioritise Release so if we can get that option to work with Debug that would be great.

Idclip avatar Dec 05 '21 13:12 Idclip

Hey sorry, been a busy week. I'll look into this and get back to you.

joshbainbridge avatar Dec 08 '21 18:12 joshbainbridge