leethomason / tinyxml2

TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs.
zlib License
5.09k stars 1.83k forks source link

CMake error: Could not find a package configuration file provided by "TinyXML2" with any of the following names: TinyXML2Config.cmake tinyxml2-config.cmake #930

Open ElectricRCAircraftGuy opened 1 year ago

ElectricRCAircraftGuy commented 1 year ago

I am trying to build a CMake package which requires tinyxml2, but am unable to get it to work. Error:

CMake Error at CMakeLists.txt:9 (find_package):
  By not providing "FindTinyXML2.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "TinyXML2",
  but CMake did not find one.

  Could not find a package configuration file provided by "TinyXML2" with any
  of the following names:

    TinyXML2Config.cmake
    tinyxml2-config.cmake

  Add the installation prefix of "TinyXML2" to CMAKE_PREFIX_PATH or set
  "TinyXML2_DIR" to a directory containing one of the above files.  If
  "TinyXML2" provides a separate development package or SDK, be sure it has
  been installed.

The package I am building is host-rospack, built via Buildroot.

I have tried installing TinyXML2 in 3 ways, none of which work to make Cmake find it!:

  1. Via apt on ubuntu 22.04:
    sudo apt update
    sudo apt install libtinyxml2-dev
    sudo apt install libtinyxml-dev
  2. Via make
    git clone https://github.com/leethomason/tinyxml2.git
    cd tinyxml2/
    make
    sudo make install
  3. Via vcpkg, as described here:
    git clone https://github.com/Microsoft/vcpkg.git
    cd vcpkg
    ./bootstrap-vcpkg.sh
    ./vcpkg integrate install
    ./vcpkg install tinyxml2

How do I install tinyxml2 in such a way that my CMake package which requires it (rospack in my case) can find it?

ElectricRCAircraftGuy commented 1 year ago

Follow-up question I just asked: https://stackoverflow.com/q/75076697/4561887

stefanaerospace commented 1 year ago

https://github.com/leethomason/tinyxml2/pull/851

Maybe that will help you? I am trying to create a git project on how to get started with writing xmls using this tool and burned a good chunk of my Sunday wrestling with Cmake issues. Seems like find_package is broken again. It isn't able to find "shared" libraries and so it kills itself.

Following the directions from the above PR this is my new error

`$ cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/tinyxml2-quickstart/tinyxml2

CMake Error at CMakeLists.txt:3 (find_package): Found package configuration file:

/home/stefan/tinyxml2-quickstart/tinyxml2/cmake/tinyxml2-config.cmake

but it set tinyxml2_FOUND to FALSE so package "tinyxml2" is considered to be NOT FOUND. Reason given by package:

tinyxml2 shared libraries were requested but not found.`

@leethomason @alexreinking Here is my repo, hopefully I just goofed a cmake detail. But even when I go the add_subdir/target_linked_lib route it doesn't properly link tinyxml2 in a way that xml.cpp can access it. https://github.com/stefanaerospace/tinyxml2-quickstart

alexreinking commented 1 year ago

@stefanaerospace

You're calling find_package before project. That might not be the problem, but it is definitely a problem.

stefanaerospace commented 1 year ago

@alexreinking Good catch, no that doesn't seem to change the error message. Updated.

alexreinking commented 1 year ago

@stefanaerospace - I'm looking at your repository more closely now and it seems you've confused find_package and add_subdirectory.

You are calling find_package(tinyxml2 REQUIRED) which means that you need to have built and installed tinyxml2 somewhere (likely to a local prefix). This is my preferred way of doing things as it plays nicely with vcpkg, Conan, and common patterns for managing repositories of source/libraries. For example:

$ export CMAKE_GENERATOR=Ninja
$ export CMAKE_BUILD_TYPE=Release
$ export CMAKE_PREFIX_PATH=$PWD/local
$ cmake -S tinyxml2 -B build/tinyxml2 -DCMAKE_INSTALL_PREFIX=${CMAKE_PREFIX_PATH}
$ cmake --build build/tinyxml2 --target install
...
$ cmake -S . -B build/tinyxml2-quickstart
[ should find tinyxml2 now ]
$ cmake --build build/tinyxml2-quickstart

However, your instructions indicate that you would like to vendor tinyxml2 by including it in your build directly. The quickest way of resolving this would be to use add_subdirectory(tinyxml2) on your git submodule. Alternatively, you could use FetchContent, which I think would be better, since CMake 3.24+ supports overriding FetchContent calls with find_package. So instead of find_package(tinyxml2 REQUIRED), you would write:

include(FetchContent)

FetchContent_Declare(
  tinyxml2
  GIT_REPOSITORY https://github.com/leethomason/tinyxml2.git
  GIT_TAG        e05956094c27117f989d22f25b75633123d72a83 # master as of Jan 14, 2023
  FIND_PACKAGE_ARGS
)

FetchContent_MakeAvailable(tinyxml2)

Anyway, I don't think this is a bug in tinyxml2 or its build.

yinghaoyu commented 1 year ago

I have same problem.

find_package(TinyXML2 REQUIRED)
if(TinyXML2_FOUND)
  include_directories(${TinyXML2_INCLUDE_DIRS})
endif()
alexreinking commented 1 year ago

@yinghaoyu - that code is plain wrong. First of all, we always use the lowercase tinyxml2. We don't set TinyXML2_INCLUDE_DIRS and even if we did, that wouldn't be enough; tinyxml2 is not header-only. The only supported way of using tinyxml2 through CMake is to link to the imported target tinyxml2::tinyxml2.

Also, since you have passed REQUIRED to find_package, the check if(TinyXML2_FOUND) will always be true, so including it is useless.

Here is a correct build using tinyxml2:

cmake_minimum_required(VERSION 3.15)
project(example)

find_package(tinyxml2 REQUIRED)

add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE tinyxml2::tinyxml2)
W0WSS commented 1 year ago

Hi, is there an updated solution to this problem?

W0WSS commented 1 year ago

@ElectricRCAircraftGuy Hi, have you solved your problem yet?

stefanaerospace commented 1 year ago

I haven't gotten back to this to resolve it yet. Probably will next weekend.

yinghaoyu commented 1 year ago

I had taken advice from gpt4.0.

include_directories(/path/to/tinyxml2/include)
link_directories(/path/to/tinyxml2/lib)
ElectricRCAircraftGuy commented 1 year ago

@ElectricRCAircraftGuy Hi, have you solved your problem yet?

@W0WSS , No, and I can't anymore. I no longer have access to the computer nor code base which had the issues.

ElectricRCAircraftGuy commented 1 year ago

In general, I do highly recommend ChatGPT and Bing's chat AI though. They're both super great and have helped me with a ton of coding problems, debugging, etc.

They don't replace a human. But a human is so much more capable and productive with them.

alexreinking commented 1 year ago

As the developer of the CMake integration for this library, I can say absolutely that GPT's suggestion is wrong. No library should be linked to that way, at least not since CMake 2.8.10, almost a decade ago. Libraries that make you do that are ill-behaved. Don't listen to LLMs. LLMs are misleading and provide an absolutely false sense of confidence about bad code.

If you post clear steps to reproduce the issue, I will be happy to help you debug.

stefanaerospace commented 1 year ago

@alexreinking

Thanks for the suggestion! I think my bit of example code works now (for my future reference if nothing else). I didn't know about FetchContent before, this is way better than using submodules imo.

For those that want a bit of starter code to integrate tinyxml2 into an existing project: https://github.com/stefanaerospace/tinyxml2-quickstart

Ryanf55 commented 11 months ago

The debian package distributed on Ubuntu 22 is missing the CMake configuration file necessary for find_package to work.

Here's the file contents for the two packages:

ryan@B650-970:~/Dev/ros2_ws$ sudo dpkg -L libtinyxml2-9
/.
/usr
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libtinyxml2.so.9.0.0
/usr/share
/usr/share/doc
/usr/share/doc/libtinyxml2-9
/usr/share/doc/libtinyxml2-9/changelog.Debian.gz
/usr/share/doc/libtinyxml2-9/copyright
/usr/lib/x86_64-linux-gnu/libtinyxml2.so.9
ryan@B650-970:~/Dev/ros2_ws$ sudo dpkg -L libtinyxml2-dev
/.
/usr
/usr/include
/usr/include/tinyxml2.h
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/pkgconfig
/usr/lib/x86_64-linux-gnu/pkgconfig/tinyxml2.pc
/usr/share
/usr/share/doc
/usr/share/doc/libtinyxml2-dev
/usr/share/doc/libtinyxml2-dev/copyright
/usr/lib/x86_64-linux-gnu/libtinyxml2.so
/usr/share/doc/libtinyxml2-dev/changelog.Debian.gz

apt info for libtinyxml2-dev

ryan@B650-970:~/Dev/ros2_ws$ sudo apt info libtinyxml2-dev
Package: libtinyxml2-dev
Version: 9.0.0+dfsg-3
Priority: extra
Section: universe/libdevel
Source: tinyxml2
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Chow Loong Jin <hyperair@debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 92.2 kB
Depends: libtinyxml2-9 (= 9.0.0+dfsg-3)
Homepage: http://www.grinninglizard.com/tinyxml2/
Download-Size: 18.6 kB
APT-Manual-Installed: yes
APT-Sources: http://us.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages
Description: TinyXML2 library - header and static library
 This package contains the header file and a static version of the
 TinyXML2 library.
 .
 TinyXML2 is a simple and small C++ XML parser that can be easily integrating
 into other programs. It reads XML and creates C++ objects representing the XML
 document. The objects can be manipulated, changed, and saved again as XML.
 .
 TinyXML2 supersedes the previous TinyXML library, with various improvements:
  - Fewer memory allocations (1% - 10% compared to TinyXML)
  - Uses less memory (about 40% of that used by TinyXML)
  - Faster
  - No STL requirement
  - More modern C++, including a proper namespace
  - Proper and useful handling of whitespace

Package info for libtinyxml2-9

  ryan@B650-970:~/Dev/ros2_ws$ sudo apt info libtinyxml2-9
Package: libtinyxml2-9
Version: 9.0.0+dfsg-3
Priority: optional
Section: universe/libs
Source: tinyxml2
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Chow Loong Jin <hyperair@debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 122 kB
Depends: libc6 (>= 2.14), libgcc-s1 (>= 3.0), libstdc++6 (>= 5)
Homepage: http://www.grinninglizard.com/tinyxml2/
Task: kubuntu-desktop, kubuntu-full, ubuntustudio-desktop, ubuntu-mate-desktop
Download-Size: 32.5 kB
APT-Manual-Installed: no
APT-Sources: http://us.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages
Description: C++ XML parsing library
 This package contains the shared version of the TinyXML2 library.
 .
 TinyXML2 is a simple and small C++ XML parser that can be easily integrating
 into other programs. It reads XML and creates C++ objects representing the XML
 document. The objects can be manipulated, changed, and saved again as XML.
 .
 TinyXML2 supersedes the previous TinyXML library, with various improvements:
  - Fewer memory allocations (1% - 10% compared to TinyXML)
  - Uses less memory (about 40% of that used by TinyXML)
  - Faster
  - No STL requirement
  - More modern C++, including a proper namespace
  - Proper and useful handling of whitespace

For find_package to work, there needs to be either a cmake CONFIG or MODULE mode script supplied as part of the debian package. CONFIG modes are recommended currently.

Currently, a user will face the following errror when they try to consume tinyxml as a package rather than directly in their source tree through submodule/fetchcontent.

 CMake Error at CMakeLists.txt:27 (find_package):
  By not providing "Findtinyxml2.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "tinyxml2",
  but CMake did not find one.

  Could not find a package configuration file provided by "tinyxml2" with any
  of the following names:

    tinyxml2Config.cmake
    tinyxml2-config.cmake

  Add the installation prefix of "tinyxml2" to CMAKE_PREFIX_PATH or set
  "tinyxml2_DIR" to a directory containing one of the above files.  If
  "tinyxml2" provides a separate development package or SDK, be sure it has
  been installed.

Do you want help getting this supported?

Ryanf55 commented 11 months ago

Compiling from source on master hash c2d30872e20621955ca7feb9168bad996d591a19, I can see that a CMake config file is correctly being generated in the install tree. To me, this is a packaging bug in Ubuntu/Debian. Is anyone familiar or in contact with the maintainers of those packages?

cmake -S . -B build
cmake --build build
cmake --install build --prefix install 
find install -type f -name *-config.cmake 
>>> install/lib/cmake/tinyxml2/tinyxml2-config.cmake

This isn't currently reported. https://launchpad.net/ubuntu/+source/tinyxml2/+bugs

Edit: Someone already filed a patch, but for some reason there hasn't been a new release. https://git.launchpad.net/ubuntu/+source/tinyxml2/commit/?id=8ec400cc2fe03ce9760c01fdde017b75b2aeed59

That said, the path is not the same as installed above. https://git.launchpad.net/ubuntu/+source/tinyxml2/tree/debian/libtinyxml2-dev.install#n4

Perhaps that's causing it not to install? Or, perhaps because that patch doesn't seem to be part of the jammy package yet. Unclear why it's not backported to jammy yet. I've requested the update here: https://answers.launchpad.net/ubuntu/+source/tinyxml2/+question/708581