From 3d085cd74ec5a86aaaa6c4fc6239937d568a59bc Mon Sep 17 00:00:00 2001 From: Martin Pecka Date: Wed, 8 Jun 2022 12:18:07 +0200 Subject: [PATCH] Noetic and TF2 support --- CMakeLists.txt | 51 ++++++++++++++++++++++---------- cmake/detect_tf_pip.cmake | 25 +++++++++++++++- cmake/tensorflow-extras.cmake.in | 10 +++++-- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c69c1e..bce45b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,14 @@ -cmake_minimum_required(VERSION 2.8.3) +cmake_minimum_required(VERSION 3.8.0) project(tensorflow_ros_cpp) find_package(catkin REQUIRED) # variables affecting the search for the tensorflow library +if("$ENV{ROS_PYTHON_VERSION}" STREQUAL "2") + set(TF_LIBRARY_VERSION 1 CACHE STRING "Whether to search for Tensorflow 1.x or 2.x") +else() + set(TF_LIBRARY_VERSION 2 CACHE STRING "Whether to search for Tensorflow 1.x or 2.x") +endif() set(FORCE_TF_PIP_SEARCH OFF CACHE BOOL "Whether to search for pip-installed Tensorflow even on systems using C++11 ABI") set(DISABLE_TF_PIP_SEARCH OFF CACHE BOOL "Whether to skip search for pip-installed Tensorflow") set(FORCE_TF_BAZEL_SEARCH OFF CACHE BOOL "Whether to search for bazel-compiled Tensorflow even if tensorflow was already found") @@ -12,7 +17,7 @@ set(FORCE_TF_CATKIN_SEARCH OFF CACHE BOOL "Whether to search for tensorflow_catk set(DISABLE_TF_CATKIN_SEARCH OFF CACHE BOOL "Whether to skip search for tensorflow_catkin") # variables affecting pip search -set(TF_PYTHON_VERSION 2.7 CACHE STRING "Python version to be used for searching for Tensorflow") +set(TF_PYTHON_VERSION $ENV{ROS_PYTHON_VERSION} CACHE STRING "Python version to be used for searching for Tensorflow") set(TF_PYTHON_LIBRARY "" CACHE STRING "Python development library of the interpreter used for the found tensorflow. Use only when find_package finds wrong version of PythonLibs, which might be the case if you want to use Tensorflow from Python3.") set(TF_PIP_EXECUTABLE pip${TF_PYTHON_VERSION} CACHE STRING "Path to pip executable used for searching for tensorflow") set(TF_PIP_DISABLE_SEARCH_FOR_GPU_VERSION OFF CACHE BOOL "If ON, tensorflow-gpu will be ignored during the search") @@ -24,13 +29,21 @@ set(TF_BAZEL_SRC_DIR "${CATKIN_DEVEL_PREFIX}/../tensorflow-include-base" CACHE S set(TF_BAZEL_USE_SYSTEM_PROTOBUF OFF CACHE BOOL "Whether to use system-installed protobuf includes or those distributed with Tensorflow") +message("-- tensorflow_ros_cpp is searching for TensorFlow ${TF_LIBRARY_VERSION}.x library") message("-- tensorflow_ros_cpp is probing the system") # check for a modern c++ compiler, since tensorflow needs support for the c++11 standard include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -if(NOT COMPILER_SUPPORTS_CXX11) - message(FATAL_ERROR "You must use a compiler that supports the c++11 standard, e.g. GCC 4.9.") +if("${TF_LIBRARY_VERSION}" STREQUAL "1") + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + if(NOT COMPILER_SUPPORTS_CXX11) + message(FATAL_ERROR "You must use a compiler that supports the c++11 standard, e.g. GCC 4.9.") + endif() +else() + CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14) + if(NOT COMPILER_SUPPORTS_CXX14) + message(FATAL_ERROR "You must use a compiler that supports the c++14 standard, e.g. GCC 8.") + endif() endif() # detect if the system uses C++11 ABI @@ -41,10 +54,20 @@ execute_process( ) if("${DETECT_CXX11_ABI_RESULT}" STREQUAL "0") set(SYSTEM_USES_CXX11_ABI 1 CACHE BOOL "Whether the system uses C++11 ABI") - message("-- - The system uses C++11 ABI, the use of tensorflow from pip is possible, but problematic; consider compiling tensorflow yourself") + message("-- - The system uses C++11 ABI.") + if("${TF_LIBRARY_VERSION}" STREQUAL "1") + message("-- -- The use of tensorflow from pip is possible, but problematic; consider compiling tensorflow yourself") + else() + message("-- -- You can use tensorflow from pip without problems.") + endif() else() set(SYSTEM_USES_CXX11_ABI 0 CACHE BOOL "Whether the system uses C++11 ABI") - message("-- - The system doesn't use C++11 ABI, you can use tensorflow from pip without problems") + message("-- - The system doesn't use C++11 ABI.") + if("${TF_LIBRARY_VERSION}" STREQUAL "1") + message("-- -- You can use tensorflow from pip without problems.") + else() + message("-- -- The use of tensorflow from pip is possible, but problematic; consider compiling tensorflow yourself") + endif() endif() # start the search @@ -63,21 +86,17 @@ set(tensorflow_ros_cpp_USES_CXX11_ABI ${SYSTEM_USES_CXX11_ABI}) # 1. PIP -if((NOT ${SYSTEM_USES_CXX11_ABI} OR ${FORCE_TF_PIP_SEARCH}) AND NOT ${DISABLE_TF_PIP_SEARCH}) +if(((NOT ${SYSTEM_USES_CXX11_ABI} AND "${TF_LIBRARY_VERSION}" STREQUAL "1") OR (${SYSTEM_USES_CXX11_ABI} AND "${TF_LIBRARY_VERSION}" STREQUAL "2") OR ${FORCE_TF_PIP_SEARCH}) AND NOT ${DISABLE_TF_PIP_SEARCH}) message("-- - Trying to find Tensorflow installed by pip") include(cmake/detect_tf_pip.cmake) - - # pip-installed tensorflow is always built without C++11 ABI - if(${TENSORFLOW_FOUND}) - set(tensorflow_ros_cpp_USES_CXX11_ABI 0) - endif() - else() if(${DISABLE_TF_PIP_SEARCH}) message("-- - Not searching for Tensorflow installed by pip, it is disabled.") - else() + elseif("${TF_LIBRARY_VERSION}" STREQUAL "1") message("-- - Not searching for Tensorflow installed by pip since the system uses C++11 ABI. Set FORCE_TF_PIP_SEARCH to force the search.") + else() + message("-- - Not searching for Tensorflow installed by pip since the system does not use C++11 ABI. Set FORCE_TF_PIP_SEARCH to force the search.") endif() endif() @@ -129,7 +148,7 @@ else() message("-- The found Tensorflow library is compiled without CUDA support.") endif() -set(tensorflow_ros_cpp_CMAKE_CXX_FLAGS_PRIVATE "-D_GLIBCXX_USE_CXX11_ABI=${tensorflow_ros_cpp_USES_CXX11_ABI}") +set(tensorflow_ros_cpp_CMAKE_CXX_FLAGS_PRIVATE "-D_GLIBCXX_USE_CXX11_ABI=${tensorflow_ros_cpp_USES_CXX11_ABI} -DTF_LIBRARY_VERSION=${TF_LIBRARY_VERSION}") catkin_package( INCLUDE_DIRS ${tensorflow_ros_cpp_INCLUDE_DIRS} diff --git a/cmake/detect_tf_pip.cmake b/cmake/detect_tf_pip.cmake index 45f81b0..ea01d94 100644 --- a/cmake/detect_tf_pip.cmake +++ b/cmake/detect_tf_pip.cmake @@ -157,6 +157,20 @@ execute_process( COMMAND nm -CD ${TENSORFLOW_ORIG_LIBRARY} OUTPUT_VARIABLE NM_OUTPUT ) + +if(${NM_OUTPUT} MATCHES "TF_Tensor::~TF_Tensor") + set(TF_LIBRARY_DETECTED_VERSION 1) + message("-- -- The Tensorflow library is version 1.x.") +else() + set(TF_LIBRARY_DETECTED_VERSION 2) + message("-- -- The Tensorflow library is version 2.x.") +endif() + +if(NOT "${TF_LIBRARY_VERSION}" STREQUAL "${TF_LIBRARY_DETECTED_VERSION}") + message(WARNING "-- -- Detected TF library version ${TF_LIBRARY_DETECTED_VERSION} does not match the requested version ${TF_LIBRARY_VERSION}") + return() +endif() + if(${NM_OUTPUT} MATCHES "cudaError") set(HAS_TENSORFLOW_GPU 1) message("-- -- The Tensorflow library is compiled with CUDA support.") @@ -165,6 +179,14 @@ else() message("-- -- The Tensorflow library is compiled without CUDA support.") endif() +if(${NM_OUTPUT} MATCHES "__cxx11") + set(TF_LIBRARY_USES_CXX11_ABI 1) + message("-- -- The Tensorflow library uses C++11 ABI.") +else() + set(TF_LIBRARY_USES_CXX11_ABI 0) + message("-- -- The Tensorflow library does not use C++11 ABI.") +endif() + set(TENSORFLOW_LIBRARIES _pywrap_tensorflow) set(TENSORFLOW_TARGETS ${TENSORFLOW_LIBRARY} ${TENSORFLOW_LIBRARY2}) @@ -221,7 +243,7 @@ if (EXISTS ${TENSORFLOW_PATH}/include/external/nsync/public) list(APPEND TENSORFLOW_INCLUDE_DIRS ${TENSORFLOW_PATH}/include/external/nsync/public) endif() -if(${SYSTEM_USES_CXX11_ABI}) +if(NOT "${TF_LIBRARY_USES_CXX11_ABI}" STREQUAL "${SYSTEM_USES_CXX11_ABI}") message(WARNING "-- -- Tensorflow library and system C++ ABI differ. You should consider building Tensorflow yourself. In case you still want to use the python TF library, itcan only be used from targets that do not link to any system libraries that have a C++ API (e.g. a method with std::string argument). Your library using Tensorflow must expose all methods using a C API, or a limited C++ API with only primitive data types (numerics, arrays, chars, but not std::vectors or std::strings). See the kinetic-devel branch of github.com/tradr-project/tensorflow_ros_test for an example.") endif() @@ -229,3 +251,4 @@ set(TENSORFLOW_FOUND 1) set(TENSORFLOW_FOUND_BY "pip") set(tensorflow_ros_cpp_INCLUDE_DIRS ${TENSORFLOW_INCLUDE_DIRS}) set(tensorflow_ros_cpp_LIBRARIES ${TENSORFLOW_LIBRARIES}) +set(tensorflow_ros_cpp_USES_CXX11_ABI ${TF_LIBRARY_USES_CXX11_ABI}) diff --git a/cmake/tensorflow-extras.cmake.in b/cmake/tensorflow-extras.cmake.in index 207cba8..00863bb 100644 --- a/cmake/tensorflow-extras.cmake.in +++ b/cmake/tensorflow-extras.cmake.in @@ -1,8 +1,14 @@ -set(CMAKE_CXX_FLAGS "-std=c++11 -Wl,--no-as-needed ${CMAKE_CXX_FLAGS}") +if(@TF_LIBRARY_VERSION@ STREQUAL "1") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wl,--no-as-needed ${CMAKE_CXX_FLAGS}") +else() + set(CMAKE_CXX_FLAGS "-Wl,--no-as-needed ${CMAKE_CXX_FLAGS}") +endif() # Whether the found TF library uses C++11 ABI or not set(tensorflow_ros_cpp_USES_CXX11_ABI @tensorflow_ros_cpp_USES_CXX11_ABI@) +set(tensorflow_ros_cpp_TF_LIBRARY_VERSION @TF_LIBRARY_VERSION@) + # Flags to be added via target_compile_definitions(target PRIVATE ...) to targets that link to TF in case TF is linked # as a target-private dependency (e.g. when working around the C++ ABI problems). -set(tensorflow_ros_cpp_CMAKE_CXX_FLAGS_PRIVATE @tensorflow_ros_cpp_CMAKE_CXX_FLAGS_PRIVATE@) \ No newline at end of file +set(tensorflow_ros_cpp_CMAKE_CXX_FLAGS_PRIVATE @tensorflow_ros_cpp_CMAKE_CXX_FLAGS_PRIVATE@)