Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake on Windows - missing linker symbols #481

Closed
stalek71 opened this issue Sep 8, 2021 · 11 comments
Closed

CMake on Windows - missing linker symbols #481

stalek71 opened this issue Sep 8, 2021 · 11 comments

Comments

@stalek71
Copy link

stalek71 commented Sep 8, 2021

When I use work.exec_prepared1 method on linux it can be build without any problems. When I build the same project on Windows (using CMake with Microsoft Visual C++ 2019) it complains about missing symbols like below:

 error LNK2019: unresolved external symbol "public: static char * __cdecl pqxx::string_traits<signed char>::into_buf(char *,char *,signed char const &)"
 error LNK2019: unresolved external symbol "public: static unsigned __int64 __cdecl pqxx::string_traits<signed char>::size_buffer(signed char const &)"

Is it possible to fix it without waiting for a new version (by providing some template specializations)?

I tried to add something like below, but it didn't work. The message related to it is below the def...

template
unsigned __int64 __cdecl pqxx::string_traits<signed char>::size_buffer(signed char const &) noexcept;
pqxx/strconv.hxx(194): warning C4661: 'size_t pqxx::string_traits<signed char>::size_buffer(const TYPE &) noexcept': no suitable definition provided for explicit template instantiation request
@jtv
Copy link
Owner

jtv commented Sep 8, 2021

There really isn't supposed to be a pqxx::string_traits<signed char>. The reason is that a signed char can reasonably mean either "a very small integer" or "a single-byte character." (Same for char and unsigned char by the way.)

So the real question is: what code is looking for that specialisation? Is it possible that you were passing an unsigned char parameter to the prepared statement?

@jtv
Copy link
Owner

jtv commented Sep 9, 2021

Ahem. I meant: is it possible that you were passing a signed char to the prepared statement? Perhaps some standard type that one compiler typedefs to signed char but the other compiler treats as a separate type, or typedefs to a different one?

@stalek71
Copy link
Author

stalek71 commented Sep 9, 2021

This is a code fragment that causes the issue. The interesting fact is when I use inline value it needs five symbols instead of 2 (like in case of std::string var)...

int PostgresStorage::CreateSerie(const std::string &name, int8_t pointType) const
{
    // Start transaction
    pqxx::work work(*connPtr_);
    // auto CREATE_SERIE_STMT = "create_serie"; <- It's const char*
    auto row = work.exec_prepared1(CREATE_SERIE_STMT, name, pointType);
    //auto row = work.exec_prepared1(CREATE_SERIE_STMT, (unsigned char*)"", pointType);
    work.commit();

    return row[0].as<int>();
}

For uchar case it shows such symbols:

[build] TimeSeriesStorage.lib(PostgresStorage.cpp.obj) : error LNK2019: unresolved external symbol "public: static bool __cdecl pqxx::nullness<unsigned char *,void>::is_null(unsigned char * const &)" (?is_null@?$nullness@PEAEX@pqxx@@SA_NAEBQEAE@Z) referenced in function "bool __cdecl pqxx::is_null<unsigned char *>(unsigned char * const &)" (??$is_null@PEAE@pqxx@@YA_NAEBQEAE@Z)
[build] TimeSeriesStorage.lib(PostgresStorage.cpp.obj) : error LNK2019: unresolved external symbol "public: static char * __cdecl pqxx::string_traits<unsigned char *>::into_buf(char *,char *,unsigned char * const &)" (?into_buf@?$string_traits@PEAE@pqxx@@SAPEADPEAD0AEBQEAE@Z) referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl pqxx::to_string<unsigned char *>(unsigned char * const &)" (??$to_string@PEAE@pqxx@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBQEAE@Z)
[build] TimeSeriesStorage.lib(PostgresStorage.cpp.obj) : error LNK2019: unresolved external symbol "public: static unsigned __int64 __cdecl pqxx::string_traits<unsigned char *>::size_buffer(unsigned char * const &)" (?size_buffer@?$string_traits@PEAE@pqxx@@SA_KAEBQEAE@Z) referenced in function "unsigned __int64 __cdecl pqxx::size_buffer<unsigned char *>(unsigned char * const &)" (??$size_buffer@PEAE@pqxx@@YA_KAEBQEAE@Z)
[build] TimeSeriesStorage.lib(PostgresStorage.cpp.obj) : error LNK2019: unresolved external symbol "public: static char * __cdecl pqxx::string_traits<signed char>::into_buf(char *,char *,signed char const &)" (?into_buf@?$string_traits@C@pqxx@@SAPEADPEAD0AEBC@Z) referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl pqxx::to_string<signed char>(signed char const &)" (??$to_string@C@pqxx@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBC@Z)
[build] TimeSeriesStorage.lib(PostgresStorage.cpp.obj) : error LNK2019: unresolved external symbol "public: static unsigned __int64 __cdecl pqxx::string_traits<signed char>::size_buffer(signed char const &)" (?size_buffer@?$string_traits@C@pqxx@@SA_KAEBC@Z) referenced in function "unsigned __int64 __cdecl pqxx::size_buffer<signed char>(signed char const &)" (??$size_buffer@C@pqxx@@YA_KAEBC@Z)
[build] tests\Storage\TimeSeries\TimeSeriesStorageTests.exe : fatal error LNK1120: 5 unresolved externals

@stalek71
Copy link
Author

stalek71 commented Sep 9, 2021

I tried to build it on Arch linux (Manjaro) also and it fails as well.
I have no baseline set for vcpkg so it uses the latest version of libpqxx (7.6)

[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /home/alek/Projects/mesh.saas/out/build/linux-base
[build] [1/3] Linking CXX executable tests/Storage/TimeSeries/TimeSeriesStorageTests
[build] FAILED: tests/Storage/TimeSeries/TimeSeriesStorageTests 
[build] : && /usr/bin/g++ -g  tests/Storage/TimeSeries/CMakeFiles/TimeSeriesStorageTests.dir/Source/main.cpp.o tests/Storage/TimeSeries/CMakeFiles/TimeSeriesStorageTests.dir/Source/TimeSeriesStorageTests.cpp.o -o tests/Storage/TimeSeries/TimeSeriesStorageTests  src/Libraries/Common/libCommon.a  src/Libraries/Storage/TimeSeries/libTimeSeriesStorage.a  vcpkg_installed/x64-linux/debug/lib/libgtestd.a  vcpkg_installed/x64-linux/debug/lib/libgmockd.a  vcpkg_installed/x64-linux/debug/lib/libpqxx-7.6.a  vcpkg_installed/x64-linux/debug/lib/libpq.a  vcpkg_installed/x64-linux/debug/lib/libpq.a  vcpkg_installed/x64-linux/debug/lib/libpgport.a  vcpkg_installed/x64-linux/debug/lib/libpgcommon.a  vcpkg_installed/x64-linux/debug/lib/libssl.a  vcpkg_installed/x64-linux/debug/lib/libcrypto.a  -ldl  vcpkg_installed/x64-linux/debug/lib/libgtestd.a  -lpthread && :
[build] /usr/bin/ld: src/Libraries/Storage/TimeSeries/libTimeSeriesStorage.a(PostgresStorage.cpp.o): in function `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > pqxx::to_string<signed char>(signed char const&)':
[build] /home/alek/Projects/mesh.saas/out/build/linux-base/vcpkg_installed/x64-linux/include/pqxx/internal/conversions.hxx:1100: undefined reference to `pqxx::string_traits<signed char>::into_buf(char*, char*, signed char const&)'
[build] /usr/bin/ld: src/Libraries/Storage/TimeSeries/libTimeSeriesStorage.a(PostgresStorage.cpp.o): in function `unsigned long pqxx::size_buffer<signed char>(signed char const&)':
[build] /home/alek/Projects/mesh.saas/out/build/linux-base/vcpkg_installed/x64-linux/include/pqxx/strconv.hxx:370: undefined reference to `pqxx::string_traits<signed char>::size_buffer(signed char const&)'
[build] collect2: error: ld returned 1 exit status
[build] [2/3] Linking CXX executable src/Services/CalculationSvc/CalculationSvc
[build] [3/3] Linking CXX executable src/Services/Storage/TimeSeriesStorageSvc/TimeSeriesStorageSvc
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1

vcpkg config has no any special deps:

{
  "name": "mesh",
  "version-string": "0.0.1",
  "dependencies": [
    "gtest",
    "grpc",
    "protobuf",
    "openssl",
    "libpq",
    "libpqxx"
  ],
  "overrides": [
  ]
}

I was building it using g++ in version 11.1.0. Build options are like below (tested also with 17 and exts):

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

@jtv
Copy link
Owner

jtv commented Sep 9, 2021

So yes, standard type that gets typedef'ed to signed char. In this case, int8_t. Try widening pointType to, say, short:

auto row = work.exec_prepared1(CREATE_SERIE_STMT, name, short(pointType));

@stalek71
Copy link
Author

stalek71 commented Sep 9, 2021

I was able to build it on Linux as well as on Windows also. I will check docker image yet (two stage build based on alpine/musl), but it should be ok also... Thanks for the hint!
Btw: why it doesn't work with signed char as a param?

@jtv
Copy link
Owner

jtv commented Sep 9, 2021

Good question! The problem with signed/unsigned char is that it's open to two very different interpretations: "a character" or "a small integer." That ambiguity is, I think, trouble waiting to happen. When you convert it to a string, should it come out as text, or as a number? Bear in mind that for various reasons, existing codebases sometimes use signed char or unsigned char for bytes in a string.

If you'd asked me 20 years ago whether signed char should come out as text or as a number, I would probably have said "it makes a bit more sense to treat it as text." But I wasn't certain enough to build that choice into libpqxx. And today I'm glad, because int8_t is clearly an integer, and your compiler implements it as a signed char.

It's probably worth building in a trick to make this situation produce a more helpful error message.

@stalek71
Copy link
Author

stalek71 commented Sep 9, 2021

Yes, it's a bit problematic. Probably some trait should be added to spec yet as char type is treated as num here instead of "character based data class":
https://en.cppreference.com/w/cpp/types/is_integral

@jtv
Copy link
Owner

jtv commented Sep 9, 2021

In any case... did the short(...) help?

@stalek71
Copy link
Author

stalek71 commented Sep 9, 2021

Yes, thanks. It resolved the issue.

@jtv
Copy link
Owner

jtv commented Sep 9, 2021

I'll merge a fix for a better error message, and that will automatically close this ticket. Thanks for reporting.

@jtv jtv closed this as completed in 4b3d89f Sep 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants