CoderCal
CoderCal

Reputation: 191

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

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!

Upvotes: 10

Views: 15593

Answers (3)

Timbergus
Timbergus

Reputation: 3253

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.

Upvotes: 3

Clare Macrae
Clare Macrae

Reputation: 3799

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.

Upvotes: 1

vitaut
vitaut

Reputation: 55605

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

Upvotes: 6

Related Questions