Linking against the correct libc++ with Xcode 9.0 - xcode

I have a library that is written in a mixture of Fortran and C++. It also uses MPI at the Fortran layer. Let's say a user wants to link a new c++ program against my library. From what I've found on the internet, the best way to do this is to have them compile their code with a C++ compiler, and link against my library using the mpif90 fortran wrapper. This is to make sure you link against the correct version of MPI. But in order to make this all work, you also have to link against libc++ explicitly because otherwise your c++ program won't work. So, for example:
mpic++ their_code.cc -c
mpif90 their_code.o -o program.exe -lmylib -lstdc++
This approach has worked fine for me across many platforms and compilers (gnu, intel, etc). It also worked for clang, until the release of Xcode 9.0, which broke this process. The compiler errors appear to be related to incompatibility in the c++ standard library, because it only breaks when I call functions that pass std::string. In the Xcode release notes it says:
Projects created using this Xcode release use the new libc++ implementation of the standard C++ library. The libc++ library is available only on iOS 5.0 and later and OS X 10.7 and later. 12221787
To enable deployment on earlier releases of iOS and OS X in your project, set the C++ Standard Library build setting to libstdc++ (Gnu C++ standard library).
This leads me to believe I need to modify how I link against libc++. You can reproduce this issue with the following code (assuming you have upgraded Xcode to version 9).
main.cc:
#include<string>
using namespace std;
void fun_str(string s);
void fun_num(int n);
int main() {
string my_str = "test";
int my_num = 1;
fun_str(my_str);
fun_num(my_num);
return 0;
}
fun.cc:
#include <string>
using namespace std;
void fun_str(string s) {}
void fun_num(int n) {}
Makefile:
test: main.o fun.o
mpif90 main.o fun.o -o program.exe -lstdc++
main.o: main.cc
mpic++ main.cc -c
fun.o: fun.cc
mpic++ fun.cc -c
Notice how if you remove all the references to strings, it does compile correctly. But if not, you get the following error:
mpic++ main.cc -c
mpic++ fun.cc -c
mpif90 main.o fun.o -o program.exe -lstdc++
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
_main in main.o
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in main.o
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
Additionally, if you switch to GNU by setting the environment variable OMPI_CXX to g++-7, it also compiles without a hitch. So this is definitely just a Clang issue, that only showed up in the new version. Any help would be greatly appreciated :)!

I fixed this on my own, but using -lc++ instead of -lstdc++. It seems that libstdc++ is depreciated with clang.

Related

SFML, GCC, and undefined symbol for sf::String

I have gcc 8.1.0 installed through homebrew on macOS 10.13.4. I installed sfml 2.4.2_1 through homebrew as well. When I compile this file:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode().getDesktopMode(), "My Window");
while (window.isOpen())
{
sf::Event event;
while(window.pollEvent(event))
{
window.clear();
if (event.type == sf::Event::Closed)
{
window.close();
}
}
}
return 0;
}
with g++-8 sfmltest.cpp -o sfmltest -lsfml-system -lsfml-graphics -lsfml-window -lsfml-audio -lsfml-network
I get an undefined reference to sf::String:
Undefined symbols for architecture x86_64:
"sf::String::String(char const*, std::locale const&)", referenced from:
_main in cciQ649w.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
I realize that I shouldn't need all of those libraries. I was including them hoping to get rid of the undefined symbols error. If I compile the same file with the same libraries using clang++, everything compiles just fine.
My guess is that homebrew is using clang to compile and install sfml and that the produced abi is incompatible with gcc. Can anyone confirm this? Is this something that I can fix? It's no problem to use clang++ for me. I would prefer to use g++ just because I want to.

FFMPEG library usage for own C++ project

I would like to create my own project using FFMPEG to build a player, but creating a new file to include ffmpeg library seems not easy. I have configure the ffmpeg and make build.
./configure
./make
The ffmpeg hello world program (myffmpeg.c):
#include <libavformat/avformat.h>
int main(int argc, char *argv[]) {
av_register_all();
return 0;
}
but it shows
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
Undefined symbols for architecture x86_64:
"av_register_all()", referenced from:
_main in myffmpeg-61ec1b.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation
When I try to link the allformats.o file, which has av_register_all function inside. I got:
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
Undefined symbols for architecture x86_64:
"_av_register_input_format", referenced from:
_register_all in allformats.o
"_av_register_output_format", referenced from:
_register_all in allformats.o
"_avcodec_register_all", referenced from:
_register_all in allformats.o
"_ff_a64_muxer", referenced from:
_register_all in allformats.o
...
"_ff_yuv4mpegpipe_muxer", referenced from:
_register_all in allformats.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It should be my bad Makefile knowledge, could anyone give me some hint on how to call ffmpeg library functions? Or even how to modify the Makefile to build my own program? Thanks!
*Update:
It could be my compiling command problem, is it the way to compile?
g++ myffmpeg.c
maybe the problem is that c++ is decorating functions. So the same function compiled with C compiler and C++ looks different to linker. try this:
extern "C"
{
#include <libavformat/avformat.h>
}
this code means that you told your compiler to not decorate functions in that file.
I think I could answer myself.
g++ -o main.o main.c `pkg-config --cflags --libs libavformat`
I don't know the reason now, it is from https://soledadpenades.com/2009/11/24/linking-with-ffmpegs-libav/
We still need the extern, see answer below.

Compiling minimal project with SFML 2.1 on mac os x

I'm trying to compile minimal project with SFML on mac os x. I'm using the following command:
g++ -o rj -framework SFML -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system main.cpp
with following code:
# include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "test");
return 0;
}
and getting an error:
Undefined symbols for architecture x86_64:
"sf::String::String(char const*, std::__1::locale const&)", referenced from:
_main in main-15430b.o
ld: symbol(s) not found for architecture x86_64
What am i doing wrong?
The problem solved by installing the clang version of library.

OpenCV Unresolved symbols - name mangling mismatch - xcode

I built the i386 flavor of OpenCV locally on my Macbook running Lion, by using
cmake -G "Unix Makefiles" -D CMAKE_OSX_ARCHITECTURES=i386 -D CMAKE_C_FLAGS=-m32 -D CMAKE_CXX_FLAGS=-m32 ..
make -j8
sudo make install
Libraries built and published fine, and I've added them to my xcode project.
However, there are link errors when building my test app, and they seem to be name mangling issues.
Undefined symbols for architecture i386:
"cv::namedWindow(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)", referenced from:
_main in main.o
"cv::imread(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)", referenced from:
_main in main.o
"cv::imshow(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cv::_InputArray const&)", referenced from:
_main in main.o
Taking cv::imread as an example, it is exported from libopencv_highgui.dylib with the name:
00007510 (__TEXT,__text) external __ZN2cv6imreadERKSsi
while main.o is referencing the symbol
U __ZN2cv6imreadERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEi
On the other hand, function __ZN2cv7waitKeyEi from the same dylib links fine.
Both the test app and the framework are for i386 arch.
Any ideas what might be causing this issue?
I've had the same problem. I think the issue could be that if you have used the MacPorts to compile your OpenCV libraries, they probably got built by the GCC according to it's Portfile. I switched the compiler used in the XCode (Apple LLVM 4.1) to the LLVM GCC 4.2 and now it works.
Hope it helps.
I just had the same problem and fixed it by using libstdc++ as the C++ standard library. It was defaulted to libc++
Under Project Build settings -> APPLE LLVM compiler 4.2 - Language -> C++ Standard Library

Awesomium on Mac OS X

Have anyone used to do with Awesomium framework on Mac OSX? I try to create a sample project and add code in main.m, but it has error
Undefined symbols for architecture i386:
"Awesomium::WebCoreConfig::setCustomCSS(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Do you have any ideas for this error?
main.m is an Objective-C source file and std::__1::basic_string, std::__1::allocator > const& is a C++ class.
Change the name of main.m to main.mm, making it a Objective-C++ source file and try again.
Awesomium is 32 bit only (a current limitation of chromium) while Apple's compiler defaults to 64 bits these days.
You have to compile your app using -m32 (or if using Xcode setting the architecture to 32 bit only as in the link the OP posted)
Example:
clang -m32 awe_test.cpp -o test -framework Awesomium -F$(DIR_WHERE_I_HAVE_AWESOMIUM) -I$(DIR_WHERE_I_HAVE_AWESOMIUM)

Resources