Opened 6 years ago

Closed 6 years ago

#12233 closed Bugs (fixed)

boost::regex doesn't compile with clang on windows

Reported by: İsmail Dönmez <ismail@…> Owned by: John Maddock
Milestone: Boost 1.64.0 Component: regex
Version: Boost 1.61.0 Severity: Problem
Keywords: Cc:

Description

Trying to compile a simple example:

#include <boost/regex.hpp>
#include <string>
#include <iostream>

int main()
{
  std::string s = "Boost Libraries";
  boost::regex expr{"\\w+\\s\\w+"};
  std::cout << std::boolalpha << boost::regex_match(s, expr) << '\n';
}

with

latte ~\Desktop > clang-cl /D_CRT_SECURE_NO_WARNINGS /MT -I C:\boost-1.61.0 .\b2.cpp C:\boost-1.61.0\lib64-msvc-14.0\lib
boost_regex-vc140-mt-s-1_61.lib
b2-807015.obj : error LNK2019: unresolved external symbol "public: bool __cdecl boost::re_detail_106100::abstract_protected_call::execute(void)const " (?execute@abstract_protected_call@re_detail_106100@boost@@QEBA_NXZ) referenced in function "private: bool __cdecl boost::re_detail_106100::perl_matcher<class std::_String_const_iterator<class std::_String_val<struct std::_Simple_types<char> > >,class std::allocator<struct boost::sub_match<class std::_String_const_iterator<class std::_String_val<struct std::_Simple_types<char> > > > >,struct boost::regex_traits<char,class boost::w32_regex_traits<char> > >::protected_call(bool (__cdecl boost::re_detail_106100::perl_matcher<class std::_String_const_iterator<class std::_String_val<struct std::_Simple_types<char> > >,class std::allocator<struct boost::sub_match<class std::_String_const_iterator<class std::_String_val<struct std::_Simple_types<char> > > > >,struct boost::regex_traits<char,class boost::w32_regex_traits<char> > >::*)(void))" (?protected_call@?$perl_matcher@V?$_String_const_iterator@V?$_String_val@U?$_Simple_types@D@std@@@std@@@std@@V?$allocator@U?$sub_match@V?$_String_const_iterator@V?$_String_val@U?$_Simple_types@D@std@@@std@@@std@@@boost@@@2@U?$regex_traits@DV?$w32_regex_traits@D@boost@@@boost@@@re_detail_106100@boost@@AEAA_NP8123@EAA_NXZ@Z)
b2.exe : fatal error LNK1120: 1 unresolved externals
clang-cl.exe: error: linker command failed with exit code 1120 (use -v to see invocation)

This is also reproducible with clang.exe. Test system is Windows 10 x64.

Change History (13)

comment:1 by juandent@…, 6 years ago

Hi, I also find unresolved external symbols when I try to link with Boost when compiling with Clang 3.7 with Microsoft CodeGen. Couldn't it be that the Boost libraries were built with the usual Microsoft instead of clang?

Or did you build your Boost libraries with Clang 3.7? If so, can you explain me how? Did you create a VStudio 2015 Update 2 solution to build Boost? Where did you get such solution? If you used CMake to generate VStudio projects, where did you get the CMAkeLists.txt files?

I hope we can find the solution to this together!

Regards, Juan

comment:1 by juandent@…, 6 years ago

Hi, I also find unresolved external symbols when I try to link with Boost when compiling with Clang 3.7 with Microsoft CodeGen. Couldn't it be that the Boost libraries were built with the usual Microsoft instead of clang?

Or did you build your Boost libraries with Clang 3.7? If so, can you explain me how? Did you create a VStudio 2015 Update 2 solution to build Boost? Where did you get such solution? If you used CMake to generate VStudio projects, where did you get the CMAkeLists.txt files?

I hope we can find the solution to this together!

Regards, Juan

comment:1 by juandent@…, 6 years ago

Hi, I also find unresolved external symbols when I try to link with Boost when compiling with Clang 3.7 with Microsoft CodeGen. Couldn't it be that the Boost libraries were built with the usual Microsoft instead of clang?

Or did you build your Boost libraries with Clang 3.7? If so, can you explain me how? Did you create a VStudio 2015 Update 2 solution to build Boost? Where did you get such solution? If you used CMake to generate VStudio projects, where did you get the CMAkeLists.txt files?

I hope we can find the solution to this together!

Regards, Juan

comment:2 by İsmail Dönmez <ismail@…>, 6 years ago

I used the precompiled VC14 binaries with clang 3.9 from trunk. Building boost clang is really a different topic because I think it's currently unsupported. Though clang has full VC++ ABI compatibility which should work in this case too.

All but this one symbol is missing:

public: bool __cdecl boost::re_detail_106100::abstract_protected_call::execute(void)const

comment:3 by John Maddock, 6 years ago

I'm not sure this is ever going to work - you would need to build regex with clang as well.

Note that the regex source is "just a bunch of source files", you can build the source in libs/regex/src/*.cpp using whatever method you wish.

in reply to:  3 comment:4 by anonymous, 6 years ago

Replying to johnmaddock:

I'm not sure this is ever going to work - you would need to build regex with clang as well.

Note that the regex source is "just a bunch of source files", you can build the source in libs/regex/src/*.cpp using whatever method you wish.

Just to be on the same page I don't claim this to be a boost bug, I am just trying to understand how is the boost::re_detail_106100::abstract_protected_call::execute symbol is special since clang can't find it. Any tips for me before I look at the source code?

Thanks!

comment:5 by İsmail Dönmez <ismail@…>, 6 years ago

This works when compiling everything with clang so it's surely a bug in clang's MSVC compat. Please feel free to close this bug, I'll be reporting a clang bug when I find the problem.

comment:6 by John Maddock, 6 years ago

Not necessarily a clang bug - I suspect we don't have MSVC and clang configured in exactly the same way - for that matter I'm not sure we would want to (as it would mean disabling clang features), but unless the two compilers are identically configured in Boost.Config etc you won't get binary-compatible objects.

comment:7 by İsmail Dönmez <ismail@…>, 6 years ago

clang-cl.exe is supposed to be a drop in replacement for cl.exe including binary compatibility. Any difference is a bug. I will update this bug after reporting the relevant clang bug.

comment:8 by John Maddock, 6 years ago

You're missing the point: we don't configure clang and msvc the same so the libraries won't contain the same symbols.

comment:9 by İsmail Dönmez <ismail@…>, 6 years ago

Then as I currently suspect boost "needs" something like BOOST_CLANG_CL akin to BOOST_MSVC which enables clang features + MSVC features supported.

comment:10 by adamf88@…, 6 years ago

Hi eceryone,

I found the same issue. I have boost compiled with MSVC toolset (2010) and I'm trying to link it to project with clang toolset. I have no problems with libraries like boost::filesystem. The regexp is the first one I found problem.

I had some time (it took a while) to debug it, but finally I found the reason (if you want to read it in a nutshell then scroll down to point 5):

  1. The error message says than abstract_protected_call::execute() is missing from regex.cpp in the library. I checked the generated libboost_regex-vc100-mt-gd-1_62.lib file. This is true, this function is missing. But why MSVC compilation works and Clang doesn't ?
  2. To answer the question we have to look around. This function is guarded by define: BOOST_REGEX_HAS_MS_STACK_GUARD. If we get the things together then: on MSVC toolset BOOST_REGEX_HAS_MS_STACK_GUARD is undefined (because in lib is missing) and on clang the symbol is defined (because it looks for this function). Let's check it
  3. The symbol is defined in file regex\config.hxx. (line 370 in boost 1.62.0). For tests I added pragma line above this definition: #pragma message("TEST") then we will get this message on clang build and during regex compilation with MSVC. (So the function execute should be available because the symbol is defined), but:
  4. In line 417 in file config.hpp we can find:
#  ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
#     undef BOOST_REGEX_HAS_MS_STACK_GUARD
#  endif

Lets add #pragma message ("UNDEFINED") and check when it is executed. Finally: MSVC compilation boost::regexp library - we will get message UNDEFINED. So the symbol is undefined and our method is not available in static lib. Clang (test project compilation with regexp) - no message. So symbol BOOST_REGEX_HAS_MS_STACK_GUARD is still defined and clang tries to link this function (execute).

  1. Where is the difference ?

In line 395 (regex/config.hpp) we can find define with statement (this statement enables undef code block execution):

!(defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)

If we build sample project with Clang toolset then BOOST_MSVC is undefined. And it is the reason why the compilation fails. Why this symbol is undefined ? Clang should pretend to be MSVC perfectly ( really ? :) ). To answer this last question we should look into file: "config/select_compiler_config.hpp". Clang on windows defines symbols: clang and _MSC_VER, but the check for clang is before check for MSVC and clang toolset was selected. So boost doesn't define BOOST_MSVC for clang toolset compilation.

Unfortunately clang doesn't pretend to be MSVC perfectly and it caused the error. I hope it will help you to do the fix.

My quick and dirty fix was in select_compiler_config.hpp file by adding on the end of clang toolset checking: && !defined(_MSC_VER). But I didn't run any other tests and I don't know if it doesn't cause any other issues. ( My program now works :) )

Dear boost support: Will you do any fix of this issue in the next versions of boost library ? Do you have any plans to support boost build with clang toolset on windows ?

Regards, Adam

comment:11 by John Maddock, 6 years ago

Milestone: To Be DeterminedBoost 1.64.0
Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.