fmt
fmt copied to clipboard
undefined symbol: protected: virtual bool __cdecl fmt::v9::format_facet<class std::locale>::do_put --- while linking format-test.exe using clang-msvc
My clang-msvc build has a linking issue on format-test.exe :
[44/60] Linking CXX executable bin\format-test.exe
FAILED: bin/format-test.exe
cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --intdir=test\CMakeFiles\format-test.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100220~1.0\x64\rc.exe --mt=C:\PROGRA~1\LLVM\bin\llvm-mt.exe --manifests -- C:\PROGRA~1\LLVM\bin\lld-link.exe /nologo test\CMakeFiles\format-test.dir\format-test.cc.obj /out:bin\format-test.exe /implib:test\format-test.lib /pdb:bin\format-test.pdb /version:0.0 /INCREMENTAL:NO /subsystem:console test\test-main.lib fmt.lib test\gtest\gtest.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK: command "C:\PROGRA~1\LLVM\bin\lld-link.exe /nologo test\CMakeFiles\format-test.dir\format-test.cc.obj /out:bin\format-test.exe /implib:test\format-test.lib /pdb:bin\format-test.pdb /version:0.0 /INCREMENTAL:NO /subsystem:console test\test-main.lib fmt.lib test\gtest\gtest.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:bin\format-test.exe.manifest" failed (exit code 1) with the following output:
lld-link: error: undefined symbol: protected: virtual bool __cdecl fmt::v9::format_facet<class std::locale>::do_put(class fmt::v9::appender, class fmt::v9::loc_value, struct fmt::v9::basic_format_specs<char> const &) const
>>> referenced by test\CMakeFiles\format-test.dir\format-test.cc.obj:(const fmt::v9::format_facet<class std::locale>::`vftable')
ninja: build stopped: subcommand failed.
This is part of format-test.cc :
class format_facet : public fmt::format_facet<std::locale> {
protected:
struct int_formatter {
fmt::appender out;
template <typename T, FMT_ENABLE_IF(fmt::detail::is_integer<T>::value)>
auto operator()(T value) -> bool {
fmt::format_to(out, "[{}]", value);
return true;
}
template <typename T, FMT_ENABLE_IF(!fmt::detail::is_integer<T>::value)>
auto operator()(T) -> bool {
return false;
}
};
auto do_put(fmt::appender out, fmt::loc_value val,
const fmt::format_specs&) const -> bool override;
};
auto format_facet::do_put(fmt::appender out, fmt::loc_value val,
const fmt::format_specs&) const -> bool {
return val.visit(int_formatter{out});
}
TEST(format_test, format_facet) {
auto loc = std::locale(std::locale(), new format_facet());
EXPECT_EQ(fmt::format(loc, "{:L}", 42), "[42]");
EXPECT_EQ(fmt::format(loc, "{:L}", -42), "[-42]");
}
Not sure why clang-msvc is complaining because the function in question is defined here: https://github.com/fmtlib/fmt/blob/94ceb38a0943c50ea9939050a7f4e8e4c9da43d2/include/fmt/format-inl.h#L144-L145
The linker could not find:
error: undefined symbol: protected: virtual bool __cdecl fmt::v9::format_facet<class std::locale>::do_put(class fmt::v9::appender, class fmt::v9::loc_value, struct fmt::v9::basic_format_specs<char> const &) const
With command:
dumpbin.exe -headers fmt.lib | findstr /c:"sym=" > fmt-exports.txt
I found this line
sym= "protected: virtual bool __cdecl fmt::v9::format_facet<class std::locale>::do_put(class fmt::v9::appender,class fmt::v9::loc_value,struct fmt::v9::basic_format_specs<char> const &)const " (?do_put@?$format_facet@Vlocale@std@@@v9@fmt@@MEBA_NVappender@23@Vloc_value@23@AEBU?$basic_format_specs@D@23@@Z)
It seems right there, how come linker can not find it?
Closing for now since this doesn't look actionable. Feel free to reopen if additional information comes up that indicates that the problem is on the {fmt} side.