简体   繁体   中英

Producing a library with a recent gcc and consuming it with an older gcc - Why are there issues despite the same C++ version?

Don't ask me why I am doing what I am doing... that would be a long story. For now, the purpose of this post is to learn and to understand why things don't work the way I expect. Possibly my expectations are wrong?

  • So initially I build my own SystemC 2.3.3 library from source using a recent compiler, say gcc 10.2.0 . However, to preserve backwards compatibility with older gccs, I request C++11:

     ./configure CXXFLAGS="-DSC_CPLUSPLUS=201103L"
  • Next I want to build an application using an older gcc that supports C++11 (and the same ABI), say gcc 8.2.0 , :

     g++ -std=c++11 sc_main.cpp -I/path/to/systemc/include -L/path/to/systemc/lib -lsystemc -lm -o sim

To my surprise, link fails:

libsystemc.so: undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()

In effect, comparing the outputs of

nm --demangle `/path/to/gcc/10.2.0/bin/g++ --print-file-name libstdc++.so` | grep "std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::"

and

nm --demangle `/path/to/gcc/8.2.0/bin/g++ --print-file-name libstdc++.so` | grep "std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::"

reveals some differences. Indeed, the former contains std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream() whereas the latter doesn't.

Is this expected? Does it mean that in general, it is necessary but not sufficient for the producer and the consumer of a library to use the same C++ version (and the same ABI)? Or is there something else going on that I don't understand?

Does it mean that in general, it is necessary but not sufficient for the producer and the consumer of a library to use the same C++ version (and the > same ABI)?

Correct. Backwards/forwards compatibility is not defined just by the C++ language version used when compiling source code. Backwards/forwards compatibility is a complicated topic of its own. But I'll just give a simple contrived, example that illustrates some underlying concepts.

Let's simplify what a std::string is. It's basically a pointer, and the number of characters in the string:

namespace std {

    class string {
         char *chars;
         size_t nchars;
    public:
         // Constructors and other methods.
    };
}

The real std::string is somewhat more complicated (and would use symbol names that are reserved for C++ implementations, but that's immaterial). This is just a simplified illustration. std::string existed even before C++11. So, things roll along, over the years, and your C++ compiler has been updated to C++20. For whatever reason its C++ library decided to change this class slightly:

namespace std {

    class string {
         size_t nchars;
         char *chars;
    public:
         // Constructors and other methods.
    };
}

At this point you can choose to instruct your new C++ compiler to compile only at the C++11 language revision. This will allow only C++11 language features. However the resulting binary code still will not be binary-compatible with code that was built by an older version of the C++ compiler, which was compiled with an incompatible class layout.

In general: in order for C++ code built by a new compiler to be binary compatible with code built by an older compiler, an explicit compilation/configuration option would be needed. It's certainly possible that this is this might be the option that specifies the general C++ language version, but just doing that is not generally sufficient. All that does is instruct the compiler which language version to use for compiling the C++ code. Newer language versions obsolete/deprecate features from earlier versions, and the purpose of the language option is to allow source code written for an earlier version of the C++ standard to be compiled, by the current C++ compiler. This is not the same thing as backwards/forwards compatibility.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM