-
Notifications
You must be signed in to change notification settings - Fork 90
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
Visibility issues when building boost_regex shared on OSX with -fvisibility=hidden -fvisibility-inlines-hidden #49
Comments
I can reproduce this with clang on Ubuntu, but either I'm going nuts or there's something very strange going on with the preprocessor. If we compile the file that instantiates and exports those template instances using the same options that b2 uses, except for preprocessing we get:
Then I can determine that the macro BOOST_REGEX_INSTANTIATE is NOT set inside boost/regex/v4/instantiate.hpp. But the thing is, if I put:
immediately prior to the inclusion of instantiate.hpp inside regex.hpp, then it's clear that the macro IS set immediately prior to the inclusion!! |
I'm not sure I reproduced your test accurately, but adding this |
I'm not sure this is the source of the problem, but I suspect the problem might be because the functions themselves are not marked with visibility attributes, only the explicit template instantiations are (if I'm reading correctly through the macros). Maybe clang doesn't propagate visibility attributes attached to the explicit instantiations. |
After a few experiments it doesn't look like marking the function definitions visible makes any difference. Something strange is going on on the linking stage. For example, in the compiled object files, instances.o contains a visible weak definition of |
OK, the isues I thought I was seeing with the preprocessor were cured by deleting boost/ and running ./b2 headers again. Now if I preprocess with either clang or gcc
Then I see for example:
So that's all OK then. So then I built object files using:
And examined them with nm, and both seems to have public symbols present, GCC compiled obj reports:
While clang has an extra record:
But none the less has the symbol as public/visible. Which pretty much mirrors what you found. There's something very arcane going on, and my attempts to reproduce this with a small test case have all failed so far. |
I give up. Fixed in 40ecdc3 by disabling external templates. |
We did the same thing in our projects. Other tricks did not help. This is probably a clang issue. I do not report it because the behavior is strange but according to the C++ standard it is undefined, so it could be implementation specific. |
Thanks, John. I think it should be reported to clang, otherwise it won't get fixed. As a test case we could point to Boost.Regex prior to 40ecdc3. Even if the standard does not define behavior wrt. shared libraries and visibility, the behavior we observe is certainly not desirable; the compiler should behave more like gcc. |
Ok, I'll try to produce a minimized test case suitable for clang error report in a week or two. On success I'll fill a clang issue and post it here. |
I had another attempt at producing a test case this morning - failed miserably :( |
Submitted clang issue: https://bugs.llvm.org/show_bug.cgi?id=38724 |
We tried to build a fully shared version of Boost for OSX with -fvisibility=hidden -fvisibility-inlines-hidden, however when linking boost_log_setup with boost_regex we got the following linker error:
Undefined symbols for architecture x86_64: "boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::do_assign(char const*, char const*, unsigned int)", referenced from: void boost::log::v2_mt_posix::aux::anonymous::matches_predicate::initializer<char>::operator()<boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > >(boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >&) const in matches_relation_factory.o void boost::log::v2_mt_posix::aux::anonymous::matches_predicate::initializer<wchar_t>::operator()<boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > >(boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >&) const in matches_relation_factory.o "boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::do_assign(wchar_t const*, wchar_t const*, unsigned int)", referenced from: void boost::log::v2_mt_posix::aux::anonymous::matches_predicate::initializer<char>::operator()<boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > > >(boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >&) const in matches_relation_factory.o void boost::log::v2_mt_posix::aux::anonymous::matches_predicate::initializer<wchar_t>::operator()<boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > > >(boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >&) const in matches_relation_factory.o "boost::match_results<char const*, std::__1::allocator<boost::sub_match<char const*> > >::maybe_assign(boost::match_results<char const*, std::__1::allocator<boost::sub_match<char const*> > > const&)", referenced from: boost::re_detail_106501::perl_matcher<char const*, std::__1::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_prefix() in matches_relation_factory.o boost::re_detail_106501::perl_matcher<char const*, std::__1::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_match() in matches_relation_factory.o "boost::match_results<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> > >::maybe_assign(boost::match_results<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> > > const&)", referenced from: boost::re_detail_106501::perl_matcher<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::match_prefix() in matches_relation_factory.o boost::re_detail_106501::perl_matcher<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::match_match() in matches_relation_factory.o "boost::re_detail_106501::perl_matcher<char const*, std::__1::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::construct_init(boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags)", referenced from: boost::re_detail_106501::perl_matcher<char const*, std::__1::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::perl_matcher(char const*, char const*, boost::match_results<char const*, std::__1::allocator<boost::sub_match<char const*> > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags, char const*) in matches_relation_factory.o "boost::re_detail_106501::perl_matcher<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::construct_init(boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > > const&, boost::regex_constants::_match_flags)", referenced from: boost::re_detail_106501::perl_matcher<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::perl_matcher(wchar_t const*, wchar_t const*, boost::match_results<wchar_t const*, std::__1::allocator<boost::sub_match<wchar_t const*> > >&, boost::basic_regex<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > > const&, boost::regex_constants::_match_flags, wchar_t const*) in matches_relation_factory.o ld: symbol(s) not found for architecture x86_64
Upon further investigation it looks like do_assign is not correctly exported from boost_regex, however compiling with define=BOOST_REGEX_NO_EXTERNAL_TEMPLATES fixes this issue.
We looked at the preprocesser output and LLVM output, in the preprocessor output the visibility is set to default, however in the LLVM output the visibility is "weak hidden".
We have no idea if this is a clang bug or a boost bug, hopefully someone can figure out what is going on.
Compiler version:
testPCs-iMac:boost_1_65_1 testpc$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.37)
Target: x86_64-apple-darwin17.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
The text was updated successfully, but these errors were encountered: