4

In our project, we decided to use the latest fmt version(6.2.0) in our project and use mainly the printf functionality as we had our logging where we are using printf extensively.

I built the libfmt.a on our Linux box using the CMakeLists.txt included in the fmt package. In my process, I included the libfmt include directory and in the target_link_libraries. In the code I only used #include<fmt/printf.h>. Now when I compile the code, the code gets compiled but at the time of linking, I get the errors: There are many more but the following is the first one and I believe if this gets resolved, rest will be resolved automatically

abc.cpp:(.text._ZN3fmt2V68internal8groupingIcEESsNS1_10locale_refE[_ZN3fmt2v68internal8groupingIcEESsNS1_10locale_refE]+0X20): undefined eference to `std::string fmt::v6::internal::grouping_impl(fmt::v6::internal::locale_ref)'

I did some analysis and found that this function's definition is present in format-inl.h. I tried including it in my code but still the same linking issue.

Now, when I defined the macro FMT_HEADER_ONLY in the code the linking worked.

My question is: When I am linking with the library libfmt.a, its not able to find that function. Why? I do not want to use the header-only version.

Please let me know how to get this fixed.

psingh
  • 47
  • 1
  • 4
  • How do you build your program? What libraries are you linking with? Please create a [mcve] of your `CMakeLists.txt` and [edit] your question to show it. – Some programmer dude May 04 '20 at 14:20
  • Thanks for the comment. I am not able to replicate this issue in a small example. I tried that. My project's process is quite complex and the binary is not getting built due to this linking error, I am not able to pinpoint the code from where this function is getting called. That's why I have posted the question here to check if someone else also faced this issue and might be able to help me. – psingh May 04 '20 at 14:44

1 Answers1

4

The linkage order is important (see https://stackoverflow.com/a/409470/471164). Make sure to pass the library after the source or object files that use it. For example:

git clone https://github.com/fmtlib/fmt.git
cd fmt
make fmt
cat <<EOF > test.cc
#include <fmt/printf.h>

int main() {
  fmt::printf("Hello, %s!", "world");
}
EOF
g++ test.cc -L. -lfmt -Iinclude
./a.out

This example fetches {fmt} from github, compiles it, creates and a small test source, compiles and runs it giving the following output:

Hello, world!

If you pass -lfmt before test.cc you'll get linkage errors.

I recommend using CMake which will take care of the linkage order for you: https://fmt.dev/latest/usage.html#usage-with-cmake

vitaut
  • 49,672
  • 25
  • 199
  • 336
  • Thank you for providing valuable inputs. I forgot to mention, we are using cmake only in our project. I also thought cmake will take care of the linkage automatically. Still, let me try to shuffle the linkages and see if that resolves the issues. – psingh May 05 '20 at 15:22
  • Make sure to add `target_link_libraries(yourtarget fmt)`. – vitaut May 05 '20 at 15:49
  • 1
    Yes, I did that but that did not resolve the issue. If I use the fmt in the header only mode then the compilation works. but fails with linking errors when I link with the libfmt.a – psingh May 05 '20 at 15:56
  • I shuffled the linkages but still not working. Please advice further. – psingh May 06 '20 at 11:23