How to use the fmt library without getting "Undefined symbols for architecture x86_64"
Asked Answered
K

3

10

I'm trying to use the fmt (https://github.com/fmtlib/fmt) formatting header library in my c++ project.

I've added the path to the core header file at the top of my main file like so:

#include "../third_party/fmt/core.h"

but when I try to call any function like:

string message = fmt::format("The answer is {}", 42);

I get the following error:

Undefined symbols for architecture x86_64:
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > fmt::v5::internal::vformat<char>(fmt::v5::basic_string_view<char>, fmt::v5::basic_format_args<fmt::v5::buffer_context<char>::type>)", referenced from:
      std::__1::basic_string<std::__1::enable_if<internal::is_string<char [17]>::value, fmt::v5::internal::char_t<char [17]>::type>::type, std::__1::char_traits<std::__1::enable_if<internal::is_string<char [17]>::value, fmt::v5::internal::char_t<char [17]>::type>::type>, std::__1::allocator<std::__1::enable_if<internal::is_string<char [17]>::value, fmt::v5::internal::char_t<char [17]>::type>::type> > fmt::v5::format<char [17], int>(char const (&) [17], int const&) in main.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]: *** [main] Error 1
make[1]: *** [CMakeFiles/main.dir/all] Error 2
make: *** [all] Error 2

I'm not sure how to use this as this is how I have used other header libraries in the past such as cxxopts. Any help would be appreciated!

Khania answered 15/6, 2019 at 8:20 Comment(5)
not to ask the obvious but did you define FMT_HEADER_ONLY?Wilkey
asking the obvious is always a good ideaElectrum
Please produce a minimal reproducible example. Not just one line of code. A (very) short but complete program, along with your compiler flags, is a must.Superpower
@Wilkey Nope I didn't. Rookie with this stuff. I didn't actually see that needed to be defined in the documentation. I see there's a line in the github readme about it though. Is this common for header libraries? Thanks for the help!Khania
@Khania yes, header-only libraries commonly use preprocessor definitions for configuration or to basically even compile. Either for all translation-units or sometimes they require the definition to be only done inside one translation unit (where the implementation will reside).Wilkey
P
6

You should link with the fmt library or use the optional header-only mode.

For example, if you have the file test.cc:

#include <fmt/core.h>

int main() {
  fmt::print("The answer is {}.", 42);
}

You can compile and link it with gcc:

g++ -std=c++11 test.cc -lfmt
Propeller answered 23/6, 2019 at 14:41 Comment(3)
Could you mind giving some snippets on how to use optional header-only mode? I want to use fmt::format("The answer is {}", 42); Following the link you provide I still do not have much idea on how to use header-only mode.. Do you mean that we can do gcc -I[the directory to header files] src/format.cc my-test.cpp for the "optional header-only mode" ? where my-test.cpp includes fmt/core.h, fmt/format.h, fmt/format-inl.h.Psephology
Usage is almost identical, the only difference is that you should include fmt/format.h instead of fmt/core.h.Propeller
Additionally, I had to #define FMT_HEADER_ONLYBriefcase
G
3

I'm working on Mac, and I did not realize that you can install the library using brew. It appears at the end of the page. I have been dealing with symbol errors all evening, and I'm not sure that all my problems were related to the build process. The compiling process was also not working properly.

The paths where the library is installed are: /usr/local/include and /usr/local/lib.

I'm using g++-11 to build my project and this instruction works for me:

g++-11 -std=c++20 -I/usr/local/include -L/usr/local/lib -lfmt main.cpp -o main

The only problem is that it works partially. It works fine with print:

fmt::print("Don't {}!\n", "panic");

But it breaks using format:

fmt::format("Don't {}!\n", "panic");

I'm missing something, but I'm not sure what.

By the way, if you are using VSCode, you can create a c_cpp_properties.json into your .vscode folder and add the include path for the headers.

{
  "includePath": [
    [...],
    "/usr/local/include/"
  ],
}

Not sure if this is related to your case, but I hope it helps.

Grapefruit answered 25/9, 2021 at 21:1 Comment(0)
A
1

From a comment in @vitaut's answer, if you change your #include line from this:

#include "../third_party/fmt/core.h"

to this:

#include "../third_party/fmt/format.h"

it will cause the code to be compiled in "header-only mode", and you won't need to change your build process to compile and link in the {fmt} library.

Alumina answered 2/6, 2021 at 10:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.