Feedback on clang change (#53194)

Marcus Calhoun-Lopez mcalhoun at macports.org
Fri Feb 3 11:48:20 UTC 2017


> On Feb 1, 2017, at 2:37 PM, Mojca Miklavec <mojca at macports.org> wrote:
> 
> So basically you need this to be able to compile binaries and
> libraries against the same stdlib, where you need gcc6 for one and
> clang for the other and the trick with D_GLIBCXX_USE_CXX11_ABI=0 is
> not sufficient?
The proposal is mostly about respecting the value of cxx_stdlib.
If cxx_stdlib is set to libstdc++ (the default prior to OS X Mavericks) and C++11 is required, the only options
are GCC or  clang with the proposed patch.
Since GCC doesn’t always interact well with the system libraries, that leaves the proposed patch.

Example:
    Octave has a dependency on GraphicsMagick.
    If cxx_stdlib is set to libstdc++, GraphicsMagick includes /usr/include/c++/4.2.1/string and links against /usr/lib/libstdc++.6.dylib.
    So far, no problems.
    Octave requires C++11 and and can not use GCC (it can but requires jumping through a few hoops).
    That leaves clang using MacPorts libstdc++.
    Even with the proposed patch, it would not work initially.
    You get errors like
        undefined symbols:
            "Magick::Image::ping(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)"
    /usr/include/c++/4.2.1/string and /opt/local/include/gcc6/c++/string have different naming schemes since the GCC internal representation of strings (and lists) are different.
    Prior to GCC 5.1, strings were Copy-On-Write, which is incompatible with the C++11 standard.
    Setting _GLIBCXX_USE_CXX11_ABI=0 forces /opt/local/include/gcc6/c++/string to use the old (technically C++11 incompatible) Copy-On-Write
    representation of strings that is compatible with /usr/include/c++/4.2.1/string and /usr/lib/libstdc++.6.dylib.

I am not sure if that answers your question or is even understandable.

>> My point of reference: https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/using_dual_abi.html
>> The following code is what I wrote to test various combinations.
>> The -D_GLIBCXX_USE_CXX11_ABI=0 forces the new libstdc++ string and list implementations to be compatible with the old libstdc++ string and list implementations.
>> 
>> main.cxx:
>>    #include "f1.hxx"
>>    int main() { f1("Hi There"); }
>> 
>> f1.hxx:
>>    #include <string>
>>    void f1(const std::string& string);
>> 
>> f1.cxx
>>    #include "f1.hxx"
>>    #include <iostream>
>>    void f1(const std::string& string) { std::cout << string << "\n"; }
>> 
>> /opt/local/bin/g++-mp-6 -c -D_GLIBCXX_USE_CXX11_ABI=0 f1.cxx
>> /usr/bin/clang++ -c -stdlib=libstdc++ -std=c++11 main.cxx
>> /usr/bin/clang++ -stdlib=libstdc++ *.o
>> ./a.out
>> /opt/local/bin/g++-mp-6 *.o
>> ./a.out
> 
> So just to make sure: is this orthogonal to the current discussion?
> That is: assuming you use
>    clang++ -stdlib=macports-libstdc++ ...
Sorry, that was not clear.
This is *not* orthogonal.
Substitute “clang++ -stdlib=macports-libstdc++” for “/opt/local/bin/g++-mp-6” and the point remains.

> What is then the situation with respect to compatibility? Does that
> mean that binaries compiled with "clang++ -stdlib=macports-libstdc++"
> will (only) be compatible with other libraries built with gcc6 (or
> with the same method), but incompatible with binaries built against
> libc++ and /usr/lib/libstdc++.dylib?
As I understand the situation:
    “clang++ -stdlib=macports-libstdc++” and
    “/opt/local/bin/g++-mp-6”
    are compatible with each other but *not* with anything else.

    “clang++ -stdlib=macports-libstdc++ -D_GLIBCXX_USE_CXX11_ABI=0,”
    /opt/local/bin/g++-mp-6 -D_GLIBCXX_USE_CXX11_ABI=0,”  and
    /usr/bin/clang++ -stdlib=libstdc++
    are also compatible with each other but not with anything else.

>> When the patched clang is called, the header files of gcc6 are used and the libraries from libgcc are linked in.
> 
> But the libraries are only linked into the compiled binary, not into
> clang, right?
That is correct.
The clang compiler itself never uses anything from GCC.

> And the header files are only used when maports-libstc++ is requested, I assume?
That is also correct.
The GCC header files are only included if maports-libstdc++ is requested.

> Are there any negative consequences if the user:
> - installs clang (with support for macports-libstdc++)
> - doesn't compile any binary against maports-libstc++
> - uninstals libgcc
> Would the compiler crash or stop working?
All binaries compiled in this manner would be unaffected.
“clang++ -stdlib=libstdc++” and “clang++ -stdlib=libc++” would continue to work just fine.
“clang -stdlib=maports-libstdc++” would attempt to use the clang header files while linking against /usr/lib/libstdc++.6.dylib.
In theory, we could add some checks to in the clang patch, but I did not bother since gcc6 was a library dependency.

> With all that, having one special subport of just the latest clang
> (with some special name) that would perhaps even compile against
> libstdc++ by default doesn't sound such a bad idea either.

In researching this option, I also found that the following base code would have to be modified:
    portconfigure::configure_get_compiler
    portconfigure::configure_start
    portconfigure::compiler_port_name
They are small changes, but, all things considered, the variant option might be easier.
At the very least, the variant option makes the overall proposal easier to isolate from other ports.

-Marcus


More information about the macports-dev mailing list