[filesystem] 1.49 linking with c++0x

Given: // cp.cpp #include <boost/filesystem.hpp> int main( int argc, char** argv ) { if( argc < 3 ) return -1; boost::filesystem::copy_file( argv[1], argv[2] ); return 0; } g++ -o cp cp.cpp -std=c++0x -I /usr/local/include /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_system.a Undefined symbols for architecture x86_64: "boost::filesystem3::detail::copy_file(boost::filesystem3::path const&, boost::filesystem3::path const&, boost::filesystem3::copy_option, boost::system::error_code*)", referenced from: boost::filesystem3::copy_file(boost::filesystem3::path const&, boost::filesystem3::path const&) in ccUAyvBD.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status If I remove the -std=c++0x flag then it links just fine. g++ --version g++ (MacPorts gcc47 4.7.0_3) 4.7.0 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Dan

Given:
// cp.cpp #include <boost/filesystem.hpp> int main( int argc, char** argv ) { if( argc < 3 ) return -1; boost::filesystem::copy_file( argv[1], argv[2] ); return 0; }
g++ -o cp cp.cpp -std=c++0x -I /usr/local/include /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_system.a
Undefined symbols for architecture x86_64: "boost::filesystem3::detail::copy_file(boost::filesystem3::path const&, boost::filesystem3::path const&, boost::filesystem3::copy_option, boost::system::error_code*)", referenced from: boost::filesystem3::copy_file(boost::filesystem3::path const&, boost::filesystem3::path const&) in ccUAyvBD.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status
If I remove the -std=c++0x flag then it links just fine.
g++ --version g++ (MacPorts gcc47 4.7.0_3) 4.7.0 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This is a case where I compiled boost with a different version of g++ (or perhaps without c++0x support??) resulting in binary incompatibility when the BOOST_SCOPED_ENUM is used in the header of a compiled library. This seems like a bad API choice as it requires all programs that use boost::filesystem::copy_file to use the same version of G++ with the same compile options. In this case, the library should (in theory) implement both the scoped enum and unscoped enum implementation so that I can mix and match C++03 code with C++0x code without having two different versions of boost::filesystem. The problem appears to also exist in 1.50 upon inspecting the code. My work arounds are to disable SCOPED_ENUM in my build process or to use the boost::filesystem::copy instead of boost::filesystem::copy_file...
Dan

On 11.07.2012 20:05, Daniel Larimer wrote:
This is a case where I compiled boost with a different version of g++ (or perhaps without c++0x support??) resulting in binary incompatibility when the BOOST_SCOPED_ENUM is used in the header of a compiled library.
This seems like a bad API choice as it requires all programs that use boost::filesystem::copy_file to use the same version of G++ with the same compile options. In this case, the library should (in theory) implement both the scoped enum and unscoped enum implementation so that I can mix and match C++03 code with C++0x code without having two different versions of boost::filesystem.
You cannot safely mix and match C++03 and C++11 code with GCC no matter what libraries you use. The standard library itself breaks binary compatibility between the two versions. Boost builds on the standard library. So no change in Filesystem is going to rescue binary compatibility for you. Sebastian

On Thursday 12 July 2012 10:21:12 Sebastian Redl wrote:
On 11.07.2012 20:05, Daniel Larimer wrote:
This is a case where I compiled boost with a different version of g++ (or perhaps without c++0x support??) resulting in binary incompatibility when the BOOST_SCOPED_ENUM is used in the header of a compiled library.
This seems like a bad API choice as it requires all programs that use boost::filesystem::copy_file to use the same version of G++ with the same compile options. In this case, the library should (in theory) implement both the scoped enum and unscoped enum implementation so that I can mix and match C++03 code with C++0x code without having two different versions of boost::filesystem.
You cannot safely mix and match C++03 and C++11 code with GCC no matter what libraries you use. The standard library itself breaks binary compatibility between the two versions. Boost builds on the standard library. So no change in Filesystem is going to rescue binary compatibility for you.
But you can build and link both C++03 and C++11 programs against libstdc++, can't you? So it must either contain both ABIs or have some compatibility layer. Why is it not possible to use both ABIs then? BTW, I filed a ticket for this problem earlier: https://svn.boost.org/trac/boost/ticket/6779

Le 12/07/12 12:01, Andrey Semashev a écrit :
On Thursday 12 July 2012 10:21:12 Sebastian Redl wrote:
This is a case where I compiled boost with a different version of g++ (or perhaps without c++0x support??) resulting in binary incompatibility when the BOOST_SCOPED_ENUM is used in the header of a compiled library.
This seems like a bad API choice as it requires all programs that use boost::filesystem::copy_file to use the same version of G++ with the same compile options. In this case, the library should (in theory) implement both the scoped enum and unscoped enum implementation so that I can mix and match C++03 code with C++0x code without having two different versions of boost::filesystem. You cannot safely mix and match C++03 and C++11 code with GCC no matter what libraries you use. The standard library itself breaks binary compatibility between the two versions. Boost builds on the standard
On 11.07.2012 20:05, Daniel Larimer wrote: library. So no change in Filesystem is going to rescue binary compatibility for you. But you can build and link both C++03 and C++11 programs against libstdc++, can't you? So it must either contain both ABIs or have some compatibility layer. Why is it not possible to use both ABIs then?
BTW, I filed a ticket for this problem earlier:
Hi, This is a severe issue that Boost.Thread should share since the introduction of scoped enums. Is there a way to solve it, other than using always the emulation? Is this kind of errors limited to scoped enums or there are other C++11 emulated Boost constructions that have different ABI with c++03 and C++11? I'm thinking to constexpr, noexcept, ... Best, Vicente

On 12.07.2012 12:01, Andrey Semashev wrote:
On Thursday 12 July 2012 10:21:12 Sebastian Redl wrote:
You cannot safely mix and match C++03 and C++11 code with GCC no matter what libraries you use. The standard library itself breaks binary compatibility between the two versions. Boost builds on the standard library. So no change in Filesystem is going to rescue binary compatibility for you. But you can build and link both C++03 and C++11 programs against libstdc++, can't you? So it must either contain both ABIs or have some compatibility layer. Why is it not possible to use both ABIs then?
Just did a bit of searching and found that the GCC developers actually delayed the ABI split so far, so it was actually possible to have compatible 03 and 11 versions, except that a breakage now slipped into 4.7 (apparently earlier than indented). The reason why you can still use the same libstdc++ is that the breakage is in std::list, and there is no precompiled std::list code in the dynamic library. http://docs.redhat.com/docs/en-US/Red_Hat_Developer_Toolset/1/html/1.0_Relea... Sebastian

On Jul 12, 2012, at 7:55 AM, Sebastian Redl wrote:
On 12.07.2012 12:01, Andrey Semashev wrote:
On Thursday 12 July 2012 10:21:12 Sebastian Redl wrote:
You cannot safely mix and match C++03 and C++11 code with GCC no matter what libraries you use. The standard library itself breaks binary compatibility between the two versions. Boost builds on the standard library. So no change in Filesystem is going to rescue binary compatibility for you. But you can build and link both C++03 and C++11 programs against libstdc++, can't you? So it must either contain both ABIs or have some compatibility layer. Why is it not possible to use both ABIs then?
Just did a bit of searching and found that the GCC developers actually delayed the ABI split so far, so it was actually possible to have compatible 03 and 11 versions, except that a breakage now slipped into 4.7 (apparently earlier than indented). The reason why you can still use the same libstdc++ is that the breakage is in std::list, and there is no precompiled std::list code in the dynamic library.
http://docs.redhat.com/docs/en-US/Red_Hat_Developer_Toolset/1/html/1.0_Relea...
This is very interesting and something I did not know would be a problem. This is almost as bad as 32 vs 64 bit libs and the library name should include the c++ version it works with. If you are using 3rd party libs that you cannot rebuild for c++11 then you a SOL. Considering the ABI hasn't broken yet for GCC or (VS2010??), I would think boost should avoid breaking the boost ABI as well based upon a simple compile flag. I would expect a failure earlier in the build process that clearly states that I am 'using the wrong header'... or 'boost was not built with c++11 feature X enabled'. This could be solved by providing an implementation for both the versions of the few methods with broken ABI... create two files: copy_file_03.cpp copy_file_11.cpp Compile them with different flags, and then link them both into the boost::filesystem library. Now you have one library that will work both ways without having to worry about 'duplicate symbols' created by trying to link two versions of boost_filesystem into the same exe simply to resolve one method. At the very least these issues need to be clearly documented and a policy put in place for when, how, and why a boost library will break its ABI for C++11.
Sebastian
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thu, Jul 12, 2012 at 9:32 PM, Daniel Larimer <dlarimer@gmail.com> wrote:
Considering the ABI hasn't broken yet for GCC or (VS2010??), I would think boost should avoid breaking the boost ABI as well based upon a simple compile flag.
I would expect a failure earlier in the build process that clearly states that I am 'using the wrong header'... or 'boost was not built with c++11 feature X enabled'.
This could be solved by providing an implementation for both the versions of the few methods with broken ABI... create two files:
copy_file_03.cpp copy_file_11.cpp
Compile them with different flags, and then link them both into the boost::filesystem library. Now you have one library that will work both ways without having to worry about 'duplicate symbols' created by trying to link two versions of boost_filesystem into the same exe simply to resolve one method.
At the very least these issues need to be clearly documented and a policy put in place for when, how, and why a boost library will break its ABI for C++11.
Are you volunteering:-? --Beman

On 13.07.2012 13:22, Beman Dawes wrote:
On Thu, Jul 12, 2012 at 9:32 PM, Daniel Larimer <dlarimer@gmail.com> wrote:
Considering the ABI hasn't broken yet for GCC or (VS2010??), I would think boost should avoid breaking the boost ABI as well based upon a simple compile flag.
As an aside, VS2010 doesn't have a C++03 mode (it always enables all the 11 features it has), and Visual Studio breaks standard library ABI on every version. So that's not a concern there.
Sebastian

[Sebastian Redl]
As an aside, VS2010 doesn't have a C++03 mode (it always enables all the 11 features it has), and Visual Studio breaks standard library ABI on every version. So that's not a concern there.
Correct. Modes Are Evil (TM) and we love breaking binary compatibility between major versions (we guarantee that it'll be preserved by hotfixes and service packs). Stephan T. Lavavej Visual C++ Libraries Developer
participants (6)
-
Andrey Semashev
-
Beman Dawes
-
Daniel Larimer
-
Sebastian Redl
-
Stephan T. Lavavej
-
Vicente J. Botet Escriba