CLIUtils / CLI11

CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.
https://cliutils.github.io/CLI11/book/
Other
3.31k stars 349 forks source link

linker error when CLI.hpp not included #1064

Open cconverse711 opened 1 month ago

cconverse711 commented 1 month ago

Using version 2.4.2, I get a linker error when trying to build the following code:

#include <CLI/App.hpp>

int main(int argc, char **argv) {
    CLI::App app("");
    return 0;
}

Error:

/usr/bin/ld: CMakeFiles/app.dir/app.cpp.o: warning: relocation against `_ZTVN3CLI10ConfigBaseE' in read-only section `.text._ZN3CLI3AppC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_PS0_[_ZN3CLI3AppC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_PS0_]'
/usr/bin/ld: CMakeFiles/app.dir/app.cpp.o: in function `CLI::ConfigBase::~ConfigBase()':
app.cpp:(.text._ZN3CLI10ConfigBaseD2Ev[_ZN3CLI10ConfigBaseD5Ev]+0x7): undefined reference to `vtable for CLI::ConfigBase'
/usr/bin/ld: CMakeFiles/app.dir/app.cpp.o: in function `CLI::ConfigBase::~ConfigBase()':
app.cpp:(.text._ZN3CLI10ConfigBaseD0Ev[_ZN3CLI10ConfigBaseD5Ev]+0x7): undefined reference to `vtable for CLI::ConfigBase'
/usr/bin/ld: CMakeFiles/app.dir/app.cpp.o: in function `CLI::App::App(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, CLI::App*)':
app.cpp:(.text._ZN3CLI3AppC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_PS0_[_ZN3CLI3AppC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_PS0_]+0x227): undefined reference to `vtable for CLI::Formatter'
/usr/bin/ld: app.cpp:(.text._ZN3CLI3AppC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_PS0_[_ZN3CLI3AppC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_PS0_]+0x461): undefined reference to `vtable for CLI::ConfigBase'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/app.dir/build.make:97: app] Error 1
make[1]: *** [CMakeFiles/Makefile2:139: CMakeFiles/app.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

This seems similar to #316 , as the error can be resolved by adding #include <CLI/CLI.hpp>, however the linking failure is still somewhat unexpected. Generally I try to follow the "include what you use" rule, so that's why I was including App.hpp directly -- is CLI.hpp the only official include "entrypoint" of the library?

phlptp commented 1 month ago

For this to work you would need to be linking with the static library, which is not built by default. Just including that header would be missing many of the definitions as seen from the linker errors.

A majority of time, I use the single header version to keep things very simple and contained, but either CLI/CLI.hpp or building the static library (usually through CMake, but other means are also possible), also should work fine.

cconverse711 commented 1 month ago

Got it, that makes sense. I recently switched form using the static library version to the conan package which is header only. It still seems somewhat problematic that including a public header that's not named as a forward header would cause such linker errors. Is it possible to easily prevent the linker errors by adjusting the includes in that file, or some way to provide an compiler error message that suggests the workaround?

phlptp commented 1 month ago

The file that includes the necessary includes is CLI/CLI.hpp. All the files in the library would need to be included as App_inl.hpp needs definitions for them all to function. So if you want to use the static library then just including App.hpp is fine, but if you want to use the header only then you need to use CLI.hpp as you then need all the definitions available in your compilation unit.