From 98296b3ed9020a5f8fc3a8ccd0da481ca29c74f7 Mon Sep 17 00:00:00 2001 From: Jose Luis Blanco-Claraco Date: Fri, 28 Aug 2020 08:24:32 +0200 Subject: [PATCH] get rid of yamlcpp build dep --- CMakeLists.txt | 1 - .../robotic-arm-kinematics.cbp | 3 - apps/rosbag2rawlog/CMakeLists.txt | 4 +- cmakemodules/script_show_final_summary.cmake | 1 - cmakemodules/script_yamlcpp.cmake | 31 ---- doc/CrossCompilingMRPT.md | 1 - libs/config/CMakeLists.txt | 3 +- libs/config/src/yaml2config_unittest.cpp | 3 - libs/containers/CMakeLists.txt | 3 - .../containers/include/mrpt/containers/yaml.h | 114 ++++++++++++-- libs/containers/src/yaml.cpp | 139 ++++++------------ libs/obs/CMakeLists.txt | 5 - libs/obs/src/VelodyneCalibration.cpp | 25 ++-- packaging/debian/control.in | 1 - packaging/ubuntu-ppa/control.in | 1 - parse-files/config.h.in | 5 - samples/containers_yaml_example/test.cpp | 8 +- 17 files changed, 165 insertions(+), 183 deletions(-) delete mode 100644 cmakemodules/script_yamlcpp.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5919fd6f13..7f9cd2389e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,7 +272,6 @@ include(cmakemodules/script_triclops.cmake REQUIRED) # Check for PointGreyRes include(cmakemodules/script_videre_svs.cmake REQUIRED) # Support for Videre Design stereo camera: include(cmakemodules/script_wxwidgets.cmake REQUIRED) # Check for wxWidgets + GL include(cmakemodules/script_xsens.cmake REQUIRED) # XSens Motion trackers / IMU drivers -include(cmakemodules/script_yamlcpp.cmake REQUIRED) # Check for YAMLCPP library include(cmakemodules/script_zlib.cmake REQUIRED) # Check for zlib # --------------------------------------------------------------------------- diff --git a/apps/robotic-arm-kinematics/robotic-arm-kinematics.cbp b/apps/robotic-arm-kinematics/robotic-arm-kinematics.cbp index 9f77840ce9..188ceab641 100644 --- a/apps/robotic-arm-kinematics/robotic-arm-kinematics.cbp +++ b/apps/robotic-arm-kinematics/robotic-arm-kinematics.cbp @@ -873,9 +873,6 @@ - - diff --git a/apps/rosbag2rawlog/CMakeLists.txt b/apps/rosbag2rawlog/CMakeLists.txt index 64661d085d..f8b2225023 100644 --- a/apps/rosbag2rawlog/CMakeLists.txt +++ b/apps/rosbag2rawlog/CMakeLists.txt @@ -1,6 +1,5 @@ - -if(NOT (CMAKE_MRPT_HAS_YAMLCPP AND TARGET ros1bridge)) +if(NOT TARGET ros1bridge) return() endif() @@ -22,7 +21,6 @@ target_link_libraries(${PROJECT_NAME} ${rosbag_storage_LIBRARIES} ${cv_bridge_LIBRARIES} ${tf2_LIBRARIES} - ${LIBYAMLCPP_LIBRARIES} ) target_include_directories(${PROJECT_NAME} diff --git a/cmakemodules/script_show_final_summary.cmake b/cmakemodules/script_show_final_summary.cmake index 7d3c0ef910..b8ac236652 100644 --- a/cmakemodules/script_show_final_summary.cmake +++ b/cmakemodules/script_show_final_summary.cmake @@ -138,7 +138,6 @@ SHOW_CONFIG_LINE_SYSTEM("PCAP (Wireshark logs for Velodyne) " CMAKE_MRPT_HAS_LI SHOW_CONFIG_LINE_SYSTEM("SuiteSparse " CMAKE_MRPT_HAS_SUITESPARSE) SHOW_CONFIG_LINE_SYSTEM("tinyxml2 " CMAKE_MRPT_HAS_TINYXML2) SHOW_CONFIG_LINE_SYSTEM("wxWidgets " CMAKE_MRPT_HAS_WXWIDGETS "[Version: ${wxWidgets_VERSION_STRING} ${CMAKE_WXWIDGETS_TOOLKIT_NAME}]") -SHOW_CONFIG_LINE_SYSTEM("yamlcpp (YAML file format) " CMAKE_MRPT_HAS_YAMLCPP "[Version: ${LIBYAMLCPP_VERSION}]") message(STATUS "") message(STATUS " ______________________ GUI LIBRARIES ______________________") diff --git a/cmakemodules/script_yamlcpp.cmake b/cmakemodules/script_yamlcpp.cmake deleted file mode 100644 index 5749c188f9..0000000000 --- a/cmakemodules/script_yamlcpp.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# Check for yaml-cpp libray. -# It has a *-config.cmake files, but they are not present in Ubuntu 12.04 LTS, -# so we use pkg-config there. -# =================================================== -set(CMAKE_MRPT_HAS_YAMLCPP 0) -set(CMAKE_MRPT_HAS_YAMLCPP_SYSTEM 0) - -# DISABLE_YAMLCPP -# --------------------- -option(DISABLE_YAMLCPP "Force not using yamlcpp" "OFF") -mark_as_advanced(DISABLE_YAMLCPP) -if(NOT DISABLE_YAMLCPP) - # Invoke pkg-config for getting the configuration: - if(PKG_CONFIG_FOUND) - PKG_CHECK_MODULES(LIBYAMLCPP QUIET yaml-cpp) - if (LIBYAMLCPP_FOUND) - set(CMAKE_MRPT_HAS_YAMLCPP 1) - set(CMAKE_MRPT_HAS_YAMLCPP_SYSTEM 1) - string(REPLACE "." "" CMAKE_MRPT_YAMLCPP_VERSION "${LIBYAMLCPP_VERSION}") - - include_directories(${LIBYAMLCPP_INCLUDE_DIRS}) - if($ENV{VERBOSE}) - message(STATUS "LIBYAMLCPP_LIBRARIES : ${LIBYAMLCPP_LIBRARIES}") - message(STATUS "LIBYAMLCPP_INCLUDE_DIRS : ${LIBYAMLCPP_INCLUDE_DIRS}") - message(STATUS "LIBYAMLCPP_VERSION : ${LIBYAMLCPP_VERSION}") - endif() - endif() - endif() - -endif() - diff --git a/doc/CrossCompilingMRPT.md b/doc/CrossCompilingMRPT.md index 79f7e8b2c1..8d4b269f83 100644 --- a/doc/CrossCompilingMRPT.md +++ b/doc/CrossCompilingMRPT.md @@ -38,7 +38,6 @@ cmake -S. -Bbuild-cross-arm \ -DCMAKE_TOOLCHAIN_FILE=doc/toolchain-gcc8-arm.cmake \ -DEIGEN_USE_EMBEDDED_VERSION=ON \ -DDISABLE_ASSIMP=ON \ - -DDISABLE_YAMLCPP=ON \ -DDISABLE_ROS=ON \ -DDISABLE_WXWIDGETS=ON \ -DBUILD_APPLICATIONS=OFF \ diff --git a/libs/config/CMakeLists.txt b/libs/config/CMakeLists.txt index 4082617734..5e67a5b254 100644 --- a/libs/config/CMakeLists.txt +++ b/libs/config/CMakeLists.txt @@ -14,6 +14,5 @@ define_mrpt_lib( ) if(BUILD_mrpt-config) - target_link_libraries(config PRIVATE ${LIBYAMLCPP_LIBRARIES}) - target_include_directories(config PRIVATE ${LIBYAMLCPP_INCLUDE_DIRS}) + endif() diff --git a/libs/config/src/yaml2config_unittest.cpp b/libs/config/src/yaml2config_unittest.cpp index 5bf5d17bb1..a69fc57cb5 100644 --- a/libs/config/src/yaml2config_unittest.cpp +++ b/libs/config/src/yaml2config_unittest.cpp @@ -8,7 +8,6 @@ +------------------------------------------------------------------------+ */ #include -#if MRPT_HAS_YAMLCPP #include #include @@ -71,5 +70,3 @@ TEST(ini2yaml, parse) // Note: we don't compare the exact strings since order of keys may vary (?) EXPECT_EQ(sampleCfgTxt_as_yaml_correct.size(), c.getContentAsYAML().size()); } - -#endif // MRPT_HAS_YAMLCPP diff --git a/libs/containers/CMakeLists.txt b/libs/containers/CMakeLists.txt index b7fc38d1ea..e14d624fad 100644 --- a/libs/containers/CMakeLists.txt +++ b/libs/containers/CMakeLists.txt @@ -13,9 +13,6 @@ set_property(GLOBAL PROPERTY mrpt_containers_UNIT_TEST_EXTRA_DEPS mrpt-random mr if(BUILD_mrpt-containers) - target_link_libraries(containers PRIVATE ${LIBYAMLCPP_LIBRARIES}) - target_include_directories(containers PRIVATE ${LIBYAMLCPP_INCLUDE_DIRS}) - if (TARGET mrpt_libfyaml) target_link_libraries(containers PRIVATE mrpt_libfyaml) endif() diff --git a/libs/containers/include/mrpt/containers/yaml.h b/libs/containers/include/mrpt/containers/yaml.h index 934c2884e1..193951339c 100644 --- a/libs/containers/include/mrpt/containers/yaml.h +++ b/libs/containers/include/mrpt/containers/yaml.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,6 @@ // forward declarations // clang-format off -// For YAMLCPP import: -namespace YAML { class Node; } // For auxiliary proxies: namespace mrpt::containers { class yaml; namespace internal { @@ -237,6 +236,19 @@ class yaml */ static yaml FromStream(std::istream& i); + /** Parses a text as YAML or JSON (autodetected) and stores the contents + * into this document. + * + * \exception std::exception Upon I/O or format errors + */ + void loadFromFile(const std::string& fileName); + + /** Parses the filename as YAML or JSON (autodetected) and returns a + * document. + * \exception std::exception Upon I/O or format errors. + */ + static yaml FromFile(const std::string& fileName); + /** Parses the stream as YAML or JSON (autodetected) and stores the contents * into this document. * @@ -245,12 +257,18 @@ class yaml void loadFromStream(std::istream& i); /** Builds an object copying the structure and contents from an existing - * YAMLCPP Node. Requires mrpt built against yamlcpp. */ - static yaml FromYAMLCPP(const YAML::Node& n); + * YAMLCPP Node. Requires user to #include yamlcpp from your calling program + * (does NOT requires yamlcpp while compiling mrpt itself). + * + * \tparam YAML_NODE Must be `YAML::Node`. Made a template just to avoid + * build-time depedencies. + */ + template + static yaml FromYAMLCPP(const YAML_NODE& n); - /** Imports the structure and contents from an existing - * YAMLCPP Node. Requires mrpt built against yamlcpp. */ - void loadFromYAMLCPP(const YAML::Node& n); + /** \overload (loads an existing YAMLCPP into this) */ + template + void loadFromYAMLCPP(const YAML_NODE& n); /** @} */ @@ -263,8 +281,8 @@ class yaml * returns true for null(empty) nodes. */ bool empty() const; - /** For map or sequence nodes, clears all elements. - * \exception std::exception If called on a null or scalar node. */ + /** Resets to empty (can be called on a root node or any other node to clear + * that subtree only). */ void clear(); bool isNullNode() const; @@ -428,6 +446,7 @@ class yaml { return internal::implAsGetter(*this); } + /** Returns a ref to the existing or new value of the given type. If types * do not match, the old content will be discarded and a new variable * created into this scalar node. @@ -695,6 +714,83 @@ void yaml::internalPushBack(const T& v) seq.emplace_back().d.emplace().emplace(v); } +template +yaml yaml::FromYAMLCPP(const YAML_NODE& n) +{ + const auto invalidDbl = std::numeric_limits::max(); + + if (n.IsSequence()) + { + yaml ret = yaml(Sequence()); + + for (const auto& e : n) + { + if (e.IsNull()) + { + sequence_t& seq = + std::get(ret.dereferenceProxy()->d); + seq.push_back(node_t()); + } + else if (e.IsScalar()) + { + if (double v = e.template as(invalidDbl); + v != invalidDbl) + ret.push_back(v); + else + ret.push_back(e.template as()); + } + else + { + // Recursive: + ret.push_back(yaml::FromYAMLCPP(e)); + } + } + return ret; + } + else if (n.IsMap()) + { + yaml ret = yaml(yaml::Map()); + + for (const auto& kv : n) + { + const auto& key = kv.first.template as(); + const auto& val = kv.second; + + if (val.IsNull()) + { + map_t& m = std::get(ret.dereferenceProxy()->d); + m[key]; + } + else if (val.IsScalar()) + { + if (double v = val.template as(invalidDbl); + v != invalidDbl) + ret[key] = v; + else + ret[key] = val.template as(); + } + else + { + // Recursive: + ret[key] = yaml::FromYAMLCPP(val); + } + } + return ret; + } + else + { + THROW_EXCEPTION( + "FromYAMLCPP only supports root YAML as sequence " + "or map"); + } +} + +template +void yaml::loadFromYAMLCPP(const YAML_NODE& n) +{ + *this = yaml::FromYAMLCPP(n); +} + } // namespace mrpt::containers namespace mrpt::containers::internal diff --git a/libs/containers/src/yaml.cpp b/libs/containers/src/yaml.cpp index 7a74d7e14a..2a6aeea1d3 100644 --- a/libs/containers/src/yaml.cpp +++ b/libs/containers/src/yaml.cpp @@ -13,14 +13,11 @@ #include #include +#include #include #include #include -#if MRPT_HAS_YAMLCPP -#include -#endif - #if MRPT_HAS_FYAML #include #endif @@ -238,16 +235,7 @@ bool yaml::empty() const void yaml::clear() { auto n = dereferenceProxy(); - if (std::holds_alternative(n->d)) - return std::get(n->d).clear(); - - if (std::holds_alternative(n->d)) - return std::get(n->d).clear(); - - THROW_EXCEPTION_FMT( - "clear() called on a node of type '%s': only available for maps or " - "sequences.", - n->typeName().c_str()); + *n = node_t(); } yaml& yaml::operator=(bool v) { return implOpAssign(v); } @@ -400,7 +388,8 @@ bool yaml::internalPrintAsYAML( } bool yaml::internalPrintAsYAML( const yaml::sequence_t& v, std::ostream& o, int indent, bool first, bool di, - const std::optional& rightComment, bool needsSpace) + const std::optional& rightComment, + [[maybe_unused]] bool needsSpace) { if (di) o << "[printSequence] size=" << v.size() << "\n"; @@ -412,7 +401,7 @@ bool yaml::internalPrintAsYAML( o << "\n"; indent += 2; - needsSpace = false; + // needsSpace = false; } const std::string sInd(indent, ' '); @@ -425,7 +414,8 @@ bool yaml::internalPrintAsYAML( } bool yaml::internalPrintAsYAML( const yaml::map_t& m, std::ostream& o, int indent, bool first, bool di, - const std::optional& rightComment, bool needsSpace) + const std::optional& rightComment, + [[maybe_unused]] bool needsSpace) { if (di) o << "[printMap] size=" << m.size() << "\n"; @@ -764,6 +754,43 @@ yaml yaml::FromStream(std::istream& i) MRPT_END } +// Replicated from mrpt::io to avoid dependency to that module: +static std::string local_file_get_contents(const std::string& fileName) +{ + // Credits: https://stackoverflow.com/a/2602258/1631514 + // Note: Add "binary" to make sure the "tellg" file size matches the actual + // number of read bytes afterwards: + std::ifstream t(fileName, std::ios::binary); + if (!t.is_open()) + THROW_EXCEPTION_FMT( + "file_get_contents(): Error opening for read file `%s`", + fileName.c_str()); + + t.seekg(0, std::ios::end); + std::size_t size = t.tellg(); + std::string buffer(size, ' '); + t.seekg(0); + t.read(&buffer[0], size); + return buffer; +} + +void yaml::loadFromFile(const std::string& fileName) +{ + MRPT_START + clear(); + this->loadFromText(local_file_get_contents(fileName)); + MRPT_END +} + +yaml yaml::FromFile(const std::string& fileName) +{ + MRPT_START + yaml doc; + doc.loadFromFile(fileName); + return doc; + MRPT_END +} + void yaml::loadFromStream(std::istream& i) { MRPT_START @@ -779,84 +806,6 @@ void yaml::loadFromStream(std::istream& i) MRPT_END } -yaml yaml::FromYAMLCPP(const YAML::Node& n) -{ -#if MRPT_HAS_YAMLCPP - const auto invalidDbl = std::numeric_limits::max(); - - if (n.IsSequence()) - { - yaml ret = yaml(Sequence()); - - for (const auto& e : n) - { - if (e.IsNull()) - { - sequence_t& seq = - std::get(ret.dereferenceProxy()->d); - seq.push_back(node_t()); - } - else if (e.IsScalar()) - { - if (double v = e.as(invalidDbl); v != invalidDbl) - ret.push_back(v); - else - ret.push_back(e.as()); - } - else - { - // Recursive: - ret.push_back(yaml::FromYAMLCPP(e)); - } - } - return ret; - } - else if (n.IsMap()) - { - yaml ret = yaml(yaml::Map()); - - for (const auto& kv : n) - { - const auto& key = kv.first.as(); - const auto& val = kv.second; - - if (val.IsNull()) - { - map_t& m = std::get(ret.dereferenceProxy()->d); - m[key]; - } - else if (val.IsScalar()) - { - if (double v = val.as(invalidDbl); v != invalidDbl) - ret[key] = v; - else - ret[key] = val.as(); - } - else - { - // Recursive: - ret[key] = yaml::FromYAMLCPP(val); - } - } - return ret; - } - else - { - THROW_EXCEPTION( - "FromYAMLCPP only supports root YAML as sequence " - "or map"); - } - -#else - THROW_EXCEPTION("MRPT was built without yaml-cpp"); -#endif -} - -void yaml::loadFromYAMLCPP(const YAML::Node& n) -{ - *this = yaml::FromYAMLCPP(n); -} - bool yaml::hasComment() const { const node_t* n = dereferenceProxy(); diff --git a/libs/obs/CMakeLists.txt b/libs/obs/CMakeLists.txt index f539658786..da963111f9 100644 --- a/libs/obs/CMakeLists.txt +++ b/libs/obs/CMakeLists.txt @@ -42,11 +42,6 @@ define_mrpt_lib( ) if(BUILD_mrpt-obs) - if (CMAKE_MRPT_HAS_YAMLCPP) - # ${LIBYAMLCPP_INCLUDE_DIRS} - target_link_libraries(obs PRIVATE ${LIBYAMLCPP_LIBRARIES}) - endif() - # tinyxml2 as system lib: if (TARGET imp_tinyxml2) target_link_libraries(obs PRIVATE imp_tinyxml2) diff --git a/libs/obs/src/VelodyneCalibration.cpp b/libs/obs/src/VelodyneCalibration.cpp index 98c166ce9c..85037bcdb4 100644 --- a/libs/obs/src/VelodyneCalibration.cpp +++ b/libs/obs/src/VelodyneCalibration.cpp @@ -8,7 +8,8 @@ +------------------------------------------------------------------------+ */ #include "obs-precomp.h" // Precompiled headers - +// +#include #include #include #include @@ -19,9 +20,6 @@ #include #include -#if MRPT_HAS_YAMLCPP -#include -#endif #if MRPT_HAS_TINYXML2 #include #endif @@ -239,15 +237,15 @@ bool VelodyneCalibration::loadFromXMLFile( bool VelodyneCalibration::loadFromYAMLText(const std::string& str) { -#if MRPT_HAS_YAMLCPP try { - YAML::Node root = YAML::Load(str); + mrpt::containers::yaml root = mrpt::containers::yaml::FromFile(str); // Clear previous contents: clear(); - const auto num_lasers = root["num_lasers"].as(0); + const auto num_lasers = + root.getOrDefault("num_lasers", 0); ASSERT_(num_lasers > 0); this->laser_corrections.resize(num_lasers); @@ -255,9 +253,11 @@ bool VelodyneCalibration::loadFromYAMLText(const std::string& str) auto lasers = root["lasers"]; ASSERT_EQUAL_(lasers.size(), num_lasers); - for (auto item : lasers) + for (auto it : lasers.asSequence()) { - const auto id = item["laser_id"].as(9999999); + auto& item = it.asMap(); + + const auto id = item["laser_id"].as(); ASSERT_(id < num_lasers); PerLaserCalib& plc = laser_corrections[id]; @@ -288,14 +288,10 @@ bool VelodyneCalibration::loadFromYAMLText(const std::string& str) << "\n"; return false; } -#else - THROW_EXCEPTION("This method requires building MRPT with YAML-CPP."); -#endif } bool VelodyneCalibration::loadFromYAMLFile(const std::string& filename) { -#if MRPT_HAS_YAMLCPP try { std::ifstream f(filename); @@ -315,9 +311,6 @@ bool VelodyneCalibration::loadFromYAMLFile(const std::string& filename) << "\n"; return false; } -#else - THROW_EXCEPTION("This method requires building MRPT with YAML-CPP."); -#endif } bool VelodyneCalibration::empty() const { return laser_corrections.empty(); } diff --git a/packaging/debian/control.in b/packaging/debian/control.in index 1110692a3d..f96150588d 100644 --- a/packaging/debian/control.in +++ b/packaging/debian/control.in @@ -31,7 +31,6 @@ Build-Depends: debhelper (>= 12), liboctomap-dev, libqt5opengl5-dev, libjsoncpp-dev, - libyaml-cpp-dev, libtinyxml2-dev, libcv-bridge-dev, libgeometry-msgs-dev, diff --git a/packaging/ubuntu-ppa/control.in b/packaging/ubuntu-ppa/control.in index d490e7a588..95bbcb5da8 100644 --- a/packaging/ubuntu-ppa/control.in +++ b/packaging/ubuntu-ppa/control.in @@ -34,7 +34,6 @@ Build-Depends: debhelper (>= 9), qtbase5-dev, libqt5opengl5-dev, libjsoncpp-dev, - libyaml-cpp-dev, libtinyxml2-dev, dh-python, libcv-bridge-dev, diff --git a/parse-files/config.h.in b/parse-files/config.h.in index f2c72a3ed8..1a9ea203ae 100644 --- a/parse-files/config.h.in +++ b/parse-files/config.h.in @@ -195,11 +195,6 @@ ${CMAKE_MRPT_BUILD_SHARED_LIB} #define MRPT_HAS_NIDAQMXBASE ${CMAKE_MRPT_HAS_NIDAQMXBASE} #define MRPT_HAS_NIDAQMX ${CMAKE_MRPT_HAS_NIDAQMX} -/** Do we have yaml-cpp? */ -#define MRPT_HAS_YAMLCPP ${CMAKE_MRPT_HAS_YAMLCPP} -#define MRPT_HAS_YAMLCPP_SYSTEM ${CMAKE_MRPT_HAS_YAMLCPP_SYSTEM} -#define MRPT_YAMLCPP_VERSION 0x0${CMAKE_MRPT_YAMLCPP_VERSION} - /** Do we have libfyaml? */ #define MRPT_HAS_FYAML ${CMAKE_MRPT_HAS_LIBFYAML} diff --git a/samples/containers_yaml_example/test.cpp b/samples/containers_yaml_example/test.cpp index 05a085d7c3..6e777d8799 100644 --- a/samples/containers_yaml_example/test.cpp +++ b/samples/containers_yaml_example/test.cpp @@ -31,9 +31,11 @@ void YamlTest_1() p["books"].push_back(10.0); std::cout << "K=" << p["K"] << " N=" << p["N"] << "\n"; - std::cout << "name=" << p["name"] - << " bar=" << p.getOrDefault("bar", "default") - << "\n"; + std::cout << "name=" << p["name"] << "\n"; + + // Get a value, or default if not found. + // YAMLCPP equivalent: p["bar"].as("none") + std::cout << "bar=" << p.getOrDefault("bar", "none") << "\n"; // Iterate a dictionary: for (const auto& kv : p.asMap())