aurzenligl / prophy

prophy: fast serialization protocol
MIT License
13 stars 8 forks source link

static const int2type<discriminator_id> objects are not defined #27

Open R2RT opened 5 years ago

R2RT commented 5 years ago

Hey,

I'll base on https://prophy.readthedocs.io/en/latest/examples.html code:

In generated .hpp file there are multiple static const objects declared:

static const prophy::detail::int2type<discriminator_id> discriminator_id_t;
static const prophy::detail::int2type<discriminator_keys> discriminator_keys_t;
static const prophy::detail::int2type<discriminator_nodes> discriminator_nodes_t;

But they are never defined in any .cpp file. Reasonable usage for constructor dispatch I've seen is e.g. Token t{Token::discriminator_keys_t, Keys{...}} and it kinda works with GCC, as overall these discriminators are stateless. EDIT: Usage from example: Object{{Token::discriminator_keys_t, {1, 2, 3}}, {1, 2, 3, 4, 5}, {'\x0e'}}

But it causes linkage errors when shared objects are used with clang++. I can come up with example project if necessary. It is enough to create test.so file and list missing symbols in so file with nm -C -u test.so though.

I've tried constexpring them, but clang still expected their definitions. I guess they should be defined in corresponding .cpp file

aurzenligl commented 5 years ago

That might happen when code is compiled without optimization - -O0: https://stackoverflow.com/a/5392050/7249587 https://stackoverflow.com/a/8016853/7249587 I wasn't able to reproduce the problem though, would you care to make a small reproduction project?

R2RT commented 5 years ago

Hey, I almost forgot about this issue, but here you are: issue.zip

It wasn't this easy to reproduce, as chain of 2 shared library was required. I've also presented minimal example of the issue in simplified-case.cpp file. You can follow its logic in this SO question I asked once I found the issue: https://stackoverflow.com/q/55251540/5945883

And yes, it occurs only with -O0, debug build

issue.zip contains lazily written CMakeLists.txt, so you have to do is unpack in repository root directory it and run build.sh script.

Once you do you should get kind of following output:

$: ~/prophy/cxx-issue$ ./build.sh 
-- The CXX compiler identification is Clang 7.0.1
-- Check for working CXX compiler: ~/bin/clang++
-- Check for working CXX compiler: ~/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: ~/prophy/cxx-issue/build
[ 11%] Generating values.ppf.cpp, values.ppf.hpp
Scanning dependencies of target values
[ 22%] Building CXX object CMakeFiles/values.dir/values.ppf.cpp.o
[ 33%] Linking CXX shared library libvalues.so
[ 33%] Built target values
Scanning dependencies of target useprophy
[ 44%] Building CXX object CMakeFiles/useprophy.dir/useprophy.cpp.o
[ 55%] Linking CXX shared library libuseprophy.so
[ 55%] Built target useprophy
Scanning dependencies of target simplified-case
[ 66%] Building CXX object CMakeFiles/simplified-case.dir/simplified-case.cpp.o
[ 77%] Linking CXX shared library libsimplified-case.so
[ 77%] Built target simplified-case
Scanning dependencies of target main
[ 88%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable main
/usr/bin/ld: libuseprophy.so: undefined reference to `prophy::generated::Token::discriminator_keys_t'
/usr/bin/ld: libsimplified-case.so: undefined reference to `A::x'
clang: error: linker command failed with exit code 1 (use -v to see invocation)