CMake Linking RDataFrame

I’ve run into a linking issue when including RootDataFrame as an optional components in our CMake project:

...
[ 75%] Building CXX object source/CMakeFiles/ROOT_Output.dir/ROOT_Output.cpp.o                                                                            
[100%] Linking CXX executable ROOT_Output
Undefined symbols for architecture x86_64:
  "ROOT::VecOps::RVec<double>::RVec()", referenced from:
      ROOT::Internal::RDF::TColumnValue<double, false>::TColumnValue() in ROOT_Output.cpp.o                                                                     
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [source/ROOT_Output] Error 1
make[1]: *** [source/CMakeFiles/ROOT_Output.dir/all] Error 2
make: *** [all] Error 2

The CMake file roughly looks like this:

find_package(ROOT REQUIRED COMPONENTS RootDataFrame)
add_executable(ROOT_Output ROOT_Output.cpp)
target_link_libraries(ROOT_Output ${ROOT_LIBRARIES})

Any suggestions would be appreciated.


ROOT Version: 6.14.04
Platform: macOS 10.13.6
Compiler: Not Provided


I had a similar problem once. Including the ROOTVecOps library solved it.

1 Like

Sure enough adding the ROOTVecOps component solved the problem. (Seems like a bug?)

find_package(ROOT REQUIRED COMPONENTS RootDataFrame RootVecOps)
add_executable(ROOT_Output ROOT_Output.cpp)
target_link_libraries(ROOT_Output ${ROOT_LIBRARIES})

So if you say find_package(ROOT COMPONENTS RootDataFrame) this does not automatically bring in RootVecOps, although the former library depends on the latter.

My cmake-fu is not strong enough to comment on this, so let me ping @amadio :smiley:

Cheers,
Enrico

Could you please try linking as shown below?

target_link_libraries(ROOT_Output PUBLIC ROOTDataFrame)

That led to this:

[ 75%] Linking CXX executable ROOT_Output
ld: library not found for -lROOTDataFrame
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [source/ROOT_Output] Error 1
make[1]: *** [source/CMakeFiles/ROOT_Output.dir/all] Error 2
make: *** [all] Error 2

If I instead use

target_link_libraries(ROOT_Output PUBLIC ${ROOT_LIBRARIES})

I get the same output as above in the initial post.

Here is a full example that works for me:

cmake_minimum_required(VERSION 3.6 FATAL_ERROR)

find_package(ROOT 6.14 REQUIRED COMPONENTS ROOTDataFrame)

include(${ROOT_USE_FILE})

add_executable(my_executable my_executable.cxx)
target_link_libraries(my_executable PUBLIC ROOT::ROOTDataFrame)
1 Like

Hi,

I typically don’t use the include(${ROOT_USE_FILE}) as many project have executable that don’t require ROOT. With and without this call I get the following error during compilation:

$ make
-- Configuring done
CMake Error at CMakeLists.txt:7 (add_executable):
  Target "my_exec" links to target "Vdt::Vdt" but the target was not found.
  Perhaps a find_package() call is missing for an IMPORTED target, or an
  ALIAS target is missing?


-- Generating done
-- Build files have been written to: forum/build
make: *** [cmake_check_build_system] Error 1

Here is the example I’m now building:

cmake_minimum_required(VERSION 3.6 FATAL_ERROR)

find_package(ROOT 6.14 REQUIRED COMPONENTS ROOTDataFrame)

include(${ROOT_USE_FILE})

add_executable(my_exec my_exec.cxx)
target_link_libraries(my_exec PUBLIC ROOT::ROOTDataFrame)

and

#include <ROOT/RDataFrame.hxx>                                                                           

int main(int argc, char* argv[]) {                                                                       
   return 0;                                                                                             
}

If you don’t include the file, then you will be missing necessary settings for linking against ROOT and will need to add them yourself. If you have other binaries that you want to isolate from this, you can concentrate your code that depends on ROOT into a subdirectory and only include the file there.

For Vdt in particular, if built as part of ROOT, it cannot export its target because it would point to the build directory. Please either disable the builtin or use it externally.

We usually use the following to link properly for each executable, is this not sufficient?

target_link_libraries(my_exec ${ROOT_LIBRARIES})
target_include_directories(my_exec PUBLIC ${ROOT_INCLUDE_DIRS})
set_target_properties(my_exec PROPERTIES COMPILE_FLAGS ${ROOT_CXX_FLAGS})

I’m not sure what you mean here, do I need to have CMake take into account how ROOT was built? As you see in the example I posted above I haven’t done anything that seems to deviate from your example, I’m even using the include file and have this error.

${ROOT_LIBRARIES} exists for convenience, it contains a list of things, but not all libraries built by ROOT. It’s better to use specific library targets exported by ROOT, like ROOT::ROOTRDataFrame, as I have shown in my example. If you use those, their dependencies are added automatically, something that doesn’t happen with ${ROOT_LIBRARIES}.

The Vdt error is not related to the include file. As I explained above, for builtins, we cannot export targets, as they would point to the build directory. This is a bug in ROOT. Please just disable Vdt in your build of ROOT until we find a way to fix this problem. I will file a JIRA issue for this in the mean time.

I created ROOT-9751 and pull request #2863, which I hope address this issue when Vdt is builtin in ROOT.

Alright, my pull request is merged. Please let me know if you still have problems after my change. I tested locally and my external program linked with Vdt, even though it was installed along with ROOT as a builtin. I removed the imported target from ROOT.

This resolved the issue. Thanks!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.