Unable to compile simple C++ program with embedded Julia 1.0

Yes, that makes much more sense ;-p…

For my actual application (not this toy I was working with here), I found it easier to follow your option 3 and force my C++ program to link with the libstdc++.so shipped with Julia.

nm -g libjulia.so | grep __cxx11
turns up some hits. So libjulia.so was built with the dual ABI, …_ABI=1. The new option is really the standard now ( gcc 5 and above ).

LLVM is looking for the ABI=1 enabled lib.

So if you did want to include anything from the standard c++ lib in your c++ code when building gcc 4.8.5 on an “older” system like CentOS 7, you should build with D_GLIBCXX_USE_CXX11_ABI=1
I’m not sure how the -std=gnu99 flag affects any of this.

However, my local julia embedding test works ( gcc 4.8.5/CentOS). And this is with the default ABI ( 0 ). I was expecting to see a similar error to the OP. Not sure why it worked. -std=gnu99?

Please… stop advertising for setting the libstdc++ flag, it shouldn’t do anything.

Yes, I never said it wasn’t, but that’s irrelavant. As I said, he is NOT linking against LLVM (i.e. he is not calling any function that’s compiled with the c++11 ABI).

(And as an aside, the versions are not 0 and 1, they are C++11 and pre C++11, the 1 there means enabling, not the version…)

And note that the whole reason I chime in is because I saw misinformation being posted here. Even though this is clearly a c++11 ABI related problem, it is completely different from any one that you’ll find online, mostely because no one else ship a libstdc++ the overwrite the system one.

I laid down my analysis in the first post which should is more of a summary for myself and is probably understandably not very easy to understand for anyone that is not as familiar with the linker. What I also left out is analysis of what isn’t an issue since that’ll be too long if I actually want anyone else to understand it… However, since you keep bringing up setting a compiler flag for a linker issue, I’ll go through why what you are saying isn’t an issue.

And before I can talk about it, there are a few thing that I should introduce first.

Why did libstdc++ (not GCC) introduce the new ABI

The original implementation of the std::string in the pre c++11 libstdc++ is not standard conformant anymore. I’m not sure (and don’t really care) what is exactly the reason (I would guess threading/COW related) but apparently fixing it requires changing the implementation in a way to break the ABI.

What is libstdc++'s solution.

In order to not break old code, the new type is put int the namespace std::__cxx11 rather than std. A precompiler flag is added for libstdc++ is added to select the right implementation that is detected in the libstdc++ header. For the library iteslf, it includes functions (symbols) for both versions so applications can use either of them.

What are the implications and common issues.

Since the stdc++ provides both versions of the symbols, it doesn’t care what version the user want. However, that is NOT the case for application code since they are usually only compiled once. This means that if you are directly calling c++ code compiled with the new ABI, the calling code has to be compiled with the same ABI. It’s important to emphasize that you must be calling it directly or you have to have included the header for it. If that’s not the case, you will never have this issue.

What about setting the flag on old GCC version

GCC version doesn’t really matter (it’ll change the default value and early version won’t support the abi tag). The libstdc++ version does matter. This means that unless your system libstdc++ is >5.0, setting the new abi flag will not do anything. (i.e. your suggesting won’t do anything on his system). I’ll also be a little surprised if old gcc can accept that flag with new libstdc++ though due to the abi tag but there might be some -std version dependent behavior there to get it working.

So what the OP want to do

Changiing the linking command is just a hack. Configureing the system in a way to makke this work would indeed be a better solution. Creating or letting julia provide the unversioned symlink should be a relatively safe option. Unless you are willing to update all the c++ libraries in your system, you should not update the system libstdc++ header or compile anything with the new ABI, you’ll just be introducing code that cannot call each other in that case. Replacing the system libstdc++.so symlink with the julia one should also be relative safe since no one should actually use it other thn linking time, you could run into issues though with symbol versions so I would recommand against it.

3 Likes

You could have elaborated a bit at that point maybe.

I’ve been going on for the same reason as you. It’s not misinformation so much as confusing language, it’s hard to tell what you mean with some of the terse answers you give. I’m not going to go through and dissect this conversation though.

The ABI thing is good to know about if you are building stuff with gcc 4.8.5 in CentOS though. One way to be sure you have a julia build consistent with your OS/build environment is to build julia from source. Which is what we did previously. That was a fairly involved task though, so I was too lazy to do it for 1.0.0.

Apologies for belabouring this thread. I do want to understand this though. I’ll be going through these issues soon enough.

Actually what do you mean here? I assuming “the overwrite” => “then overwrites” or “then overrides”? You suggested overwriting the system libstdc++ as a bad option didn’t you?

So the root of the problem of the problem for OP was having -lstdc++? Which is clearly where an ABI mismatch would happen. That doesn’t appear in the original makefile though.

Say I’m building a C++ program with julia embedded in it with gcc 4.8.5 and an old system libstdc++ ( ABI=0 ). I have to respect the ABI=0 of other libraries I will be linking with, so I need to build with ABI=0 ( is that chosen for me by using gcc 4.8.5? ). Can I link with libjulia.so? Sounds like I can’t.

If I can’t, is my best option to build julia and dependecies from source with the same tool chain as I build my other binaries?

If I build the embedded part as a c lib, I should be able to link to that from the main c++ binary without trouble, no?

I’ll answer my last question. I can’t do this because I have to bring in the libjulia.so at some point dynamically.

As you can tell I’m not the compiler expert at my company.

I read up a bit more on D_GLIBCXX_USE_CXX11_ABI=1. Yeah don’t do that :slight_smile: I now switch to advertising ABI=0 branded code.

We end up rebuilding stuff with D_GLIBCXX_USE_CXX11_ABI=0 but never with ABI=1.

I think I have to build julia from source again. Groan. Hopefully it’s easier with 1.0.0 ( less dependencies ).

That’s intentional. Especially before the OP solved his problem, I only want to make it clear what he should try without going through all the details about the issue that he could have hit in a different situations, including the ones you brought up, which is what most people hit.

Sorry that was “that overrides (for julia)”.

Yes. The point is that -lstdc++ is automatically added if you use g++ as linker to link c++ compiled files. (I actually don’t know how it decided/done and I haven’t got into a situation I needed to yet…)

Yes you can. The new libstdc++ is ABI compatible with the old one, which is why the soname didn’t change. In this case, the only thing you need to make sure is that the newer version is used. If you have a program that already loaded the old libstdc++ and then want to dlopen libjulia though, you’ll be in trouble… The only way I can think of to fix that is to replace the system libstdc++. It is theoretically safe but is not what I would recommand if there’s any other alternatives…

That’s kind of irrelevant. Depending on what you mean by “embedded part” and as “c lib”. Note that I’ve mentioned many times that the OP is not using any C++ API from julia (or any libraries shipped with julia) so in practice it’s already C code. The issue arraises only because of the (implicit or explicit) -lstdc++ but as long as any other part of the code still use c++, the issue is the same.

That sounds about right. I don’t remember if there’s any reason we enabled the new ABI but it seems like a better solution is for julia to ship with the latest libstdc++ but use the old ABI by default. It could still have symbol version problems but it could minimise the problem… It might even be better if we could compile with the oldest version of libstdc++ supported by LLVM but ship the latest one…

This is the case.

Many of the tools we use do exactly this, but this is an agreed upon industry standard. I don’t think it’s necessary for Julia to do this though. Julia should probably do the thing that is most convenient for the most people. Julia source is available so we can build it.

If you did provide two generic linux builds, one with the old ABI as well as your current build, that would help adoption for some.