Undefined reference when linking protobuf - c++

I'm working on a Mac. I installed libprotobuf with brew install protobuf --c++11.
17:51 $ brew info protobuf
protobuf: stable 2.6.1 (bottled), devel 3.0.0-beta-4, HEAD
Protocol buffers (Google's data interchange format)
https://github.com/google/protobuf/
/usr/local/Cellar/protobuf/2.6.1 (149 files, 7.0M) *
Built from source on 2016-08-02 at 17:42:15 with: --c++11
libprotobuf.dylib lives in /usr/local/Cellar/protobuf/2.6.1/lib.
I wrote the following dummy app hoping to invoke this constructor:
// test.cc
#include <string>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
int main() {
std::string s{"hello"};
google::protobuf::io::StringOutputStream sos(&s);
}
When I compile the app, I get an undefined reference error:
17:55 $ g++ -L/usr/local/Cellar/protobuf/2.6.1/lib -std=c++14 test.cc -lprotobuf
Undefined symbols for architecture x86_64:
"google::protobuf::io::StringOutputStream::StringOutputStream(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)", referenced from:
_main in ccyQlDM5.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
When I check the .dylib for StringOutputStream, it's a little wonky.
17:56 $ nm /usr/local/Cellar/protobuf/2.6.1/lib/libprotobuf.dylib | c++filt | grep "StringOutputStream(std::"
000000000000e3ac T google::protobuf::io::StringOutputStream::StringOutputStream(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*)
000000000000e398 T google::protobuf::io::StringOutputStream::StringOutputStream(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*)
Why is basic_string namespace-prefixed by ::__1 in my list of symbols for that .dylib? How can I fix this?
If this isn't a problem (perhaps an artifact of unmangling), why am I still receiving an undefined reference to a constructor call I know to be defined?
I'm using gcc 5.3.0 to compile test.cc.

As referenced in the comments, Homebrew was building with clang instead of g++.
I removed the protobuf installed by brew, checked out and built the source, copied the new .dylib to /usr/local/lib and it worked fine.

Related

Linker Command Failed - C++ on OSX

I'm using HDF5 for C++ on mac. I'm compiling my code with g++ -std=c++11 test.cpp. Clang is reporting the following error: clang: error: linker command failed with exit code 1 (use -v to see invocation), with additional info above it being ld: symbol(s) not found for architecture x86_64.
One of the symbol errors are as follows:
"readH5(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from: setupData(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int) in test-9aa0e6.o
Would I be right in thinking there's a 32bit / 64bit dispute with the h5 library?
I'm a computer scientist, but I'm no C++ expert by any stretch, so if answers could be written for C++ beginners I would very much appreciate it.
This error is caused by improper linking at build time.
The linking library needs to be specified.
With a library, we have to tell the compiler where the header files are and then tell the linker where the libraries are located with -l.
Can you try clang++ once?
You should also try:
g++ test.cpp -o test -lhdf5 -I /usr/local/include
g++ test.cpp -o test -lhdf5 -I <hdf5 lib location>

building for macOS-x86_64 but attempting to link with file built for macOS-arm64

I wrote a code using c++ and OpenCV:
#include <iostream>
#include <time.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
int main()
{
...
return 0;
}
then I trying to Running my code on the terminal and build using g++:
g++ $(pkg-config --cflags --libs opencv) -std=c++11 yourFile.cpp -o yourFileProgram
but I get this error:
...
ld: warning: ignoring file /opt/homebrew/Cellar/opencv/4.5.1_2/lib/libopencv_core.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64
ld: warning: ignoring file /opt/homebrew/Cellar/opencv/4.5.1_2/lib/libopencv_photo.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64
Undefined symbols for architecture x86_64:
"cv::Mat::Mat()", referenced from:
_main in cv_test-ff1014.o
"cv::Mat::~Mat()", referenced from:
_main in cv_test-ff1014.o
"cv::Mat::operator=(cv::Mat&&)", referenced from:
_main in cv_test-ff1014.o
"cv::imread(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)", referenced from:
_main in cv_test-ff1014.o
"cv::imwrite(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cv::_InputArray const&, std::__1::vector<int, std::__1::allocator<int> > const&)", referenced from:
_main in cv_test-ff1014.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I had the same problem, and the short answer is that Apple switched to using libc++ instead of libstdc++. If you want to compile it as you mention (via console g++) then the answer is here.
Also, you have mention g++ in tag, but be sure that you understand that gcc is alias of clang, and for using g++ compiler you have to print g++-10.
Way to compile OpenCV whith g++ via terminal as you provide in the example is described here
The best way to include OpenCV lib on macOS is to install via homebrew opencv lib, and just generate CMakeLists.txt. Possible example for it:
cmake_minimum_required(VERSION 3.17)
project(PROJECT_NAME)
find_package(OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
set(CMAKE_CXX_STANDARD 17)
#set(CMAKE_CXX_COMPILER "/usr/local/bin/g++-10" CACHE STRING "C++ compiler" FORCE)
#set(CMAKE_C_COMPILER "/usr/local/bin/gcc-10" CACHE STRING "C compiler" FORCE)
add_executable(PROJECT_NAME main.cpp)
target_link_libraries(PROJECT_NAME ${OpenCV_LIBS} )
Note, that if you will force to use g++-10 (uncomment set structure) then there will be problem like described here.
I think there is no OpenCV update for arm, then just ignore the warning and try something like that.

How to build an Ogre Application with g++ and makefile

I am a beginner in programming and compiling C++. I am currently trying to build a very basic OGRE application on OSX (10.10) using g++ compiler and makefile. My makefile is based on the one provided on cleversoap's github repository. I am also using a prebuilt version of the SDK for OSX.
When I first tried to build the tutorial framework from the OGRE 3D webiste, I ended up with multiple linking errors related to the Ogre objects and functions definitions. I edited the source file leaving only those few lines of code.
#include <OgreRoot.h>
#include <OgreCamera.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>
#include <OgreLogManager.h>
#include <OgreViewport.h>
#include <OgreEntity.h>
#include <OgreWindowEventUtilities.h>
#include <OgrePlugin.h>
int main() {
Ogre::Root* mRoot;
mRoot = new Ogre::Root("", "", "LowLevelOgre.log");
delete mRoot;
}
My compile command resulting of the makefile looks like this:
g++ LowLevelOgre.cpp -o OgreMake.app/Contents/MacOS/OgreMake -arch i386 -I/Developer/SDKs/OgreSDK/include/OGRE -I/Developer/SDKs/OgreSDK/include/OGRE/OSX -I/Developer/SDKs/OgreSDK/include/OIS -I/Developer/SDKs/OgreSDK/boost -L/Developer/SDKs/OgreSDK/lib/release -lOIS -F/System/Library/Frameworks -F/Library/Frameworks -framework Carbon -framework AppKit -framework Foundation -framework IOKit -F/Developer/SDKs/OgreSDK/lib/release -framework Cg -framework Ogre
Even though the linker does not complain about the Ogre.framework, I get this error basically meaning that the Ogre::Root definition is missing. (At least I think)
Undefined symbols for architecture x86_64:
"Ogre::Root::Root(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in main-3183b9.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 1
I cannot seem to find what is causing this linking error. Is there anything I am missing or I may have misunderstood?

Linking C++ library (libtorrent) from Objective-C

I'm trying to use libtorrent library from Xcode 5.0 Objective-C Project without success.
I've built boost 1.54 and libtorrent-rasterbar (latest) from sources using LLVM 5.0, no problems with that. Also, via MacPorts I obtained pkg-config to get the proper cflags for libtorrent-rasterbar library. From my build settings, the output for pkgconfig libs and cflags were:
-DTORRENT_USE_OPENSSL -DWITH_SHIPPED_GEOIP_H
-DBOOST_ASIO_HASH_MAP_BUCKETS=1021
-DBOOST_EXCEPTION_DISABLE -DBOOST_ASIO_ENABLE_CANCELIO
-DBOOST_ASIO_DYN_LINK -DTORRENT_LINKING_SHARED -I/usr/local/include
-I/usr/local/include/libtorrent
-L/usr/local/lib -ltorrent-rasterbar
Naturally, I added those parameters to Xcode "Linker Flags" and "C/C++ Flags" settings.
Unfortunately, I cannot get my called functions to link right. This is a sample class I wrote in a testclass.cpp file:
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/create_torrent.hpp"
void testclass::addFilesFromPath(const char* path)
{
libtorrent::file_storage fs;
libtorrent::add_files(fs, path);
}
Tried to get called from a createpackage.mm file:
testclass* pPackage = new testclass();
testclass->addFilesFromPath([_sessionDir UTF8String]);
The linker cannot found the symbols, output is:
Undefined symbols for architecture x86_64:
"libtorrent::parent_path(std::__1::basic_string, std::__1::allocator > const&)",
referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o
"libtorrent::detail::add_files_impl(libtorrent::file_storage&,
std::__1::basic_string,
std::__1::allocator > const&, std::__1::basic_string, std::__1::allocator > const&,
boost::function, std::__1::allocator >)>, unsigned
int)", referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o
"libtorrent::complete(std::__1::basic_string, std::__1::allocator > const&)",
referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o
"libtorrent::filename(std::__1::basic_string, std::__1::allocator > const&)",
referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
I'm pretty puzzled. Checked that libtorrent-raster bar architecture is x86_64. Also, boost is built OK. I'm new to this C++ / Objetive-C code mixing approach.
Thanks.
EDIT 1:
I've resorted to a minimal sample. Made the following CPP file:
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/create_torrent.hpp"
int main()
{
libtorrent::file_storage fs;
libtorrent::add_files(fs, ".");
}
At command line, tried:
c++ test.cpp $(pkg-config /usr/local/lib/pkgconfig/libtorrent-rasterbar.pc --cflags --libs) -lboost_system
Build is successful. So I wonder how to put all that pkg-config data into the proper target configurations in OSX.
Finally, problem was solved.
Let's check symbols comparing the produced object file and the symbols contained in libtorrent library.
nm createpackage.o|grep 'add_files'
U __ZN10libtorrent6detail14add_files_implERNS_12file_storageERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_N5boost8functionIFbS9_EEEj
00000000000002a0 S __ZN10libtorrent9add_filesERNS_12file_storageERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEj
00000000000018e0 S __ZN10libtorrent9add_filesERNS_12file_storageERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEj.eh
Compare with:
$ nm libtorrent-rasterbar.a | grep 'add_files'
00000000000002f0 T __ZN10libtorrent6detail14add_files_implERNS_12file_storageERKSsS4_N5boost8functionIFbSsEEEj
0000000000006e68 S __ZN10libtorrent6detail14add_files_implERNS_12file_storageERKSsS4_N5boost8functionIFbSsEEEj.eh
The difference as many could imagine seeing that output, it's that i'm using the LLVM Standard C++ library for my .mm files while libtorrent was compiled with GCC Stdlib, that's the reason of different symbols referring to char_traits, basic_string, etc.
So, changing in XCode Build Settings > Standard C++ Library to libstdc++ fixed the problem.

Linking to boost::program_options does not work properly

The following library files exist:
cls /usr/local/Cellar/boost/1.51.0/lib $ ls libboost_program*
libboost_program_options-mt.a libboost_program_options-mt.dylib
I include the following header with #include <boost/program_options.hpp>:
cls /usr/local/Cellar/boost/1.51.0/include $ ls boost/program_options.hpp
boost/program_options.hpp
I try to link the libraries with
-lboost_program_options-mt
-L/usr/local/Cellar/boost/1.51.0/lib
(I assume that the name of the library is derived from the file name minus the "lib" and the file ending. If I try the name boost_program_options (without -mt), I get ld: library not found for -lboost_program_options)
This is my main function using the library:
#include <boost/program_options.hpp>
#include <iostream
int main(int argc, char **argv) {
namespace opts = boost::program_options;
opts::options_description desc("EnsembleClustering options");
desc.add_options()
("hello", "produce greeting");
opts::variables_map vmap;
opts::store(opts::parse_command_line(argc, argv, desc), vmap);
opts::notify(vmap);
if (vmap.count("hello")) {
std::cout << "Hello World" << std::endl;
}
}
Why does this setup give me a symbol(s) not found error?
make all
Building target: EnsembleClustering-DPar
Invoking: MacOS X C++ Linker
/usr/local/bin/g++-4.7 -L"/Users/cls/workspace/STINGER/OpenMP Debug" -L"/Users/cls/workspace/gtest/lib" -L/usr/local/Cellar/log4cxx/0.10.0/lib -L/usr/local/Cellar/boost/1.51.0/lib -fopenmp -std=c++11 -o "EnsembleClustering-DPar" ./src/scoring/EdgeScoring.o ./src/scoring/ModularityScoring.o ./src/overlap/test/OverlapGTest.o ./src/overlap/Overlapper.o ./src/overlap/RegionGrowingOverlapper.o ./src/matching/Matcher.o ./src/matching/Matching.o ./src/matching/ParallelMatcher.o ./src/io/test/InputGTest.o ./src/io/CSVWriter.o ./src/io/GraphFromAdjacencies.o ./src/io/GraphIO.o ./src/io/GraphReader.o ./src/io/METISGraphReader.o ./src/io/METISParser.o ./src/io/METISToGraph.o ./src/graph/test/GraphGTest.o ./src/graph/test/STINGERGTest.o ./src/graph/Graph.o ./src/graph/GraphGenerator.o ./src/ensemble/test/EnsembleGTest.o ./src/ensemble/EnsembleClusterer.o ./src/coarsening/test/CoarseningGTest.o ./src/coarsening/ClusterContracter.o ./src/coarsening/ClusteringProjector.o ./src/coarsening/Contracter.o ./src/coarsening/GraphContraction.o ./src/coarsening/MatchingContracter.o ./src/clustering/test/ClusteringGTest.o ./src/clustering/base/Clustering.o ./src/clustering/base/ClusteringGenerator.o ./src/clustering/base/Modularity.o ./src/clustering/base/QualityMeasure.o ./src/clustering/algo/test/ClusteringAlgoGTest.o ./src/clustering/algo/Clusterer.o ./src/clustering/algo/LabelPropagation.o ./src/clustering/algo/ParallelAgglomerativeClusterer.o ./src/aux/test/AuxGTest.o ./src/aux/Noise.o ./src/aux/RandomInteger.o ./src/aux/RandomProbability.o ./src/aux/Timer.o ./src/EnsembleClustering.o -lSTINGER -lgtest -llog4cxx -lboost_program_options-mt
Undefined symbols for architecture x86_64:
"boost::program_options::detail::cmdline::cmdline(std::__debug::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)", referenced from:
boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*) in EnsembleClustering.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [EnsembleClustering-DPar] Error 1
EDIT: Checking the library files with lipo gives
cls /usr/local/Cellar/boost/1.51.0/lib $ lipo -detailed_info libboost_program_options-mt.a libboost_program_options-mt.dylib
input file libboost_program_options-mt.a is not a fat file
input file libboost_program_options-mt.dylib is not a fat file
Non-fat file: libboost_program_options-mt.a is architecture: x86_64
Non-fat file: libboost_program_options-mt.dylib is architecture: x86_64
I'd like to link the static library.
Read the error message
Undefined symbols for architecture x86_64:
"boost::program_options::detail::cmdline::cmdline(std::__debug::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)", referenced from:
boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*) in EnsembleClustering.o
It very clearly says, missing symbol std::__debug::vector, note that the std::__debug namespace is key here. I suspect you've built your source code using iterator debugging with -D_GLIBCXX_DEBUG but are attempting to link against a library that hasn't, such as boost program options. You didn't show us how you built your translation units, so here is a sscce:
$ g++-4.8 -std=c++11 -O2 -pthread main.cpp -D_GLIBCXX_DEBUG -lboost_program_options && ./a.out
/tmp/cca1jwUx.o: In function `boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*)':
main.cpp:(.text._ZN5boost15program_options25basic_command_line_parserIcEC2EiPKPKc[_ZN5boost15program_options25basic_command_line_parserIcEC5EiPKPKc]+0x319): undefined reference to `boost::program_options::detail::cmdline::cmdline(std::__debug::vector<std::string, std::allocator<std::string> > const&)'
collect2: error: ld returned 1 exit status
There are a few ways to solve this
remove the -DGLIBCXX_DEBUG flag from translation units including the program options headers.
consult your boost package maintainer to see if they offer a version built with -D_GLIBCXX_DEBUG. Some variants on Linux do, you might ask around the MacPorts or brew users mailing lists.
Since you're specifying the location for includes, libraries and providing the appropriate .dylib, the only problem I can think of is that the library that you're linking to doesn't have an x86_64 arch in it.
Try checking the library with either file or lipo. If it doesn't show x86_64, then that's the problem.