Linking problem with boost when building cpprest-sdk on MacOs - boost

I'm trying to create an HTTP client for a rest API using the cpprest-sdk library: https://github.com/Microsoft/cpprestsdk
I'm using a MacBook Pro with the latest version of MacOs (10.14.2).
I use brew as a package manager and have installed boost with:
brew install boost
Versions of dependencies:
clang: Apple LLVM version 10.0.0 (clang-1000.11.45.5)
cmake: 3.13.2
boost: stable 1.68.0 (bottled), HEAD
First I tried to follow this:
https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Mac-OS-X
So I also installed cpprestsdk with boost:
boost install cpprestsdk
Then I used the code from the tutorial in one main.cpp:
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
int main(int argc, char* argv[])
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://www.bing.com/"));
// Build request URI and start the request.
uri_builder builder(U("/search"));
builder.append_query(U("q"), U("cpprestsdk github"));
return client.request(methods::GET, builder.to_string());
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
return response.body().read_to_end(fileStream->streambuf());
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
return 0;
}
And I created a CMake build file CMakeLists.txt as they describe in the README of cpprestsdk:
cmake_minimum_required(VERSION 3.13)
project(cpprest-example)
set(CMAKE_CXX_STANDARD 14)
find_package(cpprestsdk REQUIRED)
add_executable(cpprest-example main.cpp)
target_link_libraries(cpprest-example PRIVATE cpprestsdk::cpprest)
First I had a problem with CMake not fining openssl, so I had to add two env parameters like described here:
CMake not able to find OpenSSL library
Then it compiles but then fails during linking, with errors:
Scanning dependencies of target cpprest-example
[ 50%] Building CXX object CMakeFiles/cpprest-example.dir/main.cpp.o
[100%] Linking CXX executable cpprest-example
Undefined symbols for architecture x86_64:
"boost::this_thread::interruption_point()", referenced from:
boost::condition_variable::wait(boost::unique_lock<boost::mutex>&) in main.cpp.o
boost::condition_variable::do_wait_until(boost::unique_lock<boost::mutex>&, boost::detail::real_platform_timepoint const&) in main.cpp.o
"boost::chrono::steady_clock::now()", referenced from:
bool boost::condition_variable::wait_for<long long, boost::ratio<1l, 1000l>, pplx::details::event_impl::wait(unsigned int)::'lambda0'()>(boost::unique_lock<boost::mutex>&, boost::chrono::duration<long long, boost::ratio<1l, 1000l> > const&, pplx::details::event_impl::wait(unsigned int)::'lambda0'()) in main.cpp.o
bool boost::condition_variable::wait_until<boost::chrono::steady_clock, boost::chrono::duration<long long, boost::ratio<1l, 1000000000l> >, pplx::details::event_impl::wait(unsigned int)::'lambda0'()>(boost::unique_lock<boost::mutex>&, boost::chrono::time_point<boost::chrono::steady_clock, boost::chrono::duration<long long, boost::ratio<1l, 1000000000l> > > const&, pplx::details::event_impl::wait(unsigned int)::'lambda0'()) in main.cpp.o
"boost::detail::get_current_thread_data()", referenced from:
boost::detail::interruption_checker::interruption_checker(_opaque_pthread_mutex_t*, _opaque_pthread_cond_t*) in main.cpp.o
"boost::system::detail::system_category_instance", referenced from:
boost::system::system_category() in main.cpp.o
"boost::system::detail::generic_category_instance", referenced from:
boost::system::generic_category() in main.cpp.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[2]: *** [cpprest-example] Error 1
make[1]: *** [CMakeFiles/cpprest-example.dir/all] Error 2
make: *** [all] Error 2
Strange thing is that if I build the cpprestsdk codebase with CMake it works fine and one of the samples is the same code:
https://github.com/Microsoft/cpprestsdk/tree/master/Release/samples/BingRequest
That sample project has then been built successfully and runs fine.
I also tried uninstalling cpprestsdk from brew and did a CMake build of the cloned repository and then "make -j4 && make install". That installs cpprestsdk headers and libraries locally but in the end, results in the same errors.
It looks like it's not finding the boost libraries and I have tried using find_package(BOOST 1.68.0) and similar things but it fails with the same errors.
Can anyone see what I'm doing wrong?

Related

Undefined Boost symbol when linking to pre-compiled QuantLib binaries on MacOS

I am trying to compile some C++ that depends on QuantLib, which in turn depends on Boost. I am working on a MacBook Pro M1 (ARM architecture). I installed Boost and QuantLib using the instructions on this page: https://www.quantlib.org/install/macosx.shtml. I then tried to compile the following source code:
#include <iostream>
#include <ql/quantlib.hpp>
int main(int, char*[])
{
QuantLib::Option::Type OptionType(QuantLib::Option::Call);
std::cout << "Option Type = " << OptionType << std::endl;
return 0;
}
using the following command:
clang++ -std=c++11 ql_ex1.cpp -o build/ql_ex1 $(INC) $(LIB) \
-I/opt/homebrew/Cellar/quantlib/1.23/include -I/opt/homebrew/Cellar/boost/1.76.0/include \
-L/opt/homebrew/Cellar/boost/1.76.0/lib -L/opt/homebrew/Cellar/quantlib/1.23/lib
This gave me the following error message:
Undefined symbols for architecture arm64:
"boost::assertion_failed(char const*, char const*, char const*, long)", referenced from:
long double boost::math::detail::sinpx<long double>(long double) in ql_ex1-044d3e.o
"boost::assertion_failed_msg(char const*, char const*, char const*, char const*, long)", referenced from:
boost::array<long double, 171ul>::operator[](unsigned long) const in ql_ex1-044d3e.o
...
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1
So far I have tried the following approaches,
Install x86 binaries and run clang++ in emulation. I see the same Undefined symbols error.
Try to identify a Boost shared library file that I need to link to. I have not been able to find anything that contains the assertion_failed symbol.
Can someone point me to where (if anywhere) this symbol is defined? It would be useful to know if I am just missing the right compiler options or whether there is a more fundamental issue that needs to be addressed.
I think you're missing a -lQuantLib in your command line? You're telling the compiler where to look for the libraries (the -L switches`) but not which libraries to link.
Also, check whether homebrew also installed a quantlib-config script on your computer. If so, it should provide the switches you need; try running
quantlib-config --cflags
which should output the -I flags specifying the location of the QuantLib headers (and possibly the -std=c++11 flag you're passing manually), and
quantlib-config --libs
which should output the corresponding -L switches as well as the -lQuantLib you missed.
If they work, you can use the command
clang++ ql_ex1.cpp -o build/ql_ex1 $(INC) $(LIB) \
-I/opt/homebrew/Cellar/boost/1.76.0/include \
`quantlib-config --cflags` `quantlib-config --libs`
and let the script fill in the info for you.

libssh symbols not found error gcc

I am trying to build a simple SSH client from Wil Allsopp's pen testing book. Working on Mac OS High Sierra with gcc-4.2 with libssh installed using Homebrew. The simplest version of the code is:
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session;
my_ssh_session = ssh_new();
ssh_free(my_ssh_session);
return 0;
}
However a simple gcc build (gcc -Wall ssh_client.c) produces the following error:
Undefined symbols for architecture x86_64:
"_ssh_free", referenced from:
_main in ssh_client-aa8f09.o
"_ssh_new", referenced from:
_main in ssh_client-aa8f09.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
Can anyone explain these errors and how I can fix them?
Your build line doesn't appear to contain any include and linker flags. I imagine it is picking up the headers but not the library for ssh to link against. Have a look into pkgconfig for an easy way to maintain this.

Undefined reference when linking with googletest

When i try to build googletest (and googlemock) 1.8.0 i get an undefined reference to MakeAndRegisterTestInfo when i try to link with libgtest.a. It works fine with version 1.7.0 with the same cmake/make setup. I guess i could use 1.7.0 but then i need to download and build gmock separately.
CMakeFiles/unittest.dir/test/test_led.cpp.o: In function `__static_initialization_and_destruction_0(int, int)':
test_led.cpp:(.text+0x23d): undefined reference to `testing::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)'
collect2: error: ld returned 1 exit status
make[2]: *** [bin/unittest] Error 1
make[1]: *** [CMakeFiles/unittest.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
Other symbols in the libgtest.a works perfectly fine (example ::testing::InitGoogleTest) but as soon as i try to add a test with the macro TEST_F i get this error.
This is my testcase setup:
#include "gtest/gtest.h"
namespace {
// The fixture for testing (used by TEST_F).
class Foo : public ::testing::Test {
protected:
Foo();
virtual ~Foo() {};
virtual void SetUp();
virtual void TearDown();
};
Foo::Foo() {
};
void Foo::SetUp()
{
};
void Foo::TearDown()
{
};
TEST_F(Foo, Init) {
};
} // namespace
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}
Cmake google test snippet:
It downloads from a local folder. It builds and i get a libgtest.a file.
### Unit test ###
# Google test
ExternalProject_Add(EXT_googletest
PREFIX ${CMAKE_CURRENT_BINARY_DIR}
DOWNLOAD_COMMAND ""
SOURCE_DIR ${CMAKE_SOURCE_DIR}/../external/googletest
BUILD_COMMAND make all
# Disable install step
INSTALL_COMMAND "")
# Create a libgtest target to be used as a dependency by test programs
set(LIBGTEST_STATIC ${CMAKE_CURRENT_BINARY_DIR}/.../googlemock/gtest/libgtest.a)
add_executable(unittest
"test/test_foo.cpp")
target_link_libraries(unittest main_app_lib
${LIBGTEST_STATIC}
${CMAKE_THREAD_LIBS_INIT})
NM output libgtest.a 1.8.0
user#system$ nm .../libgtest.a |grep MakeAndRegisterTestInfo
000000000000743a T _ZN7testing8internal23MakeAndRegisterTestInfoEPKcS2_S2_S2_NS0_12CodeLocationEPKvPFvvES7_PNS0_15TestFactoryBaseE
NM output libgtest.a 1.7.0 (working file)
user#system$ nm .../libgtest.a |grep MakeAndRegisterTestInfo
0000000000005968 T _ZN7testing8internal23MakeAndRegisterTestInfoEPKcS2_S2_S2_PKvPFvvES6_PNS0_15TestFactoryBaseE
Solved:
There was an old version of google test installed on build machine which headers were used by cmake.
#user1178014 answered his own question but since there are no posted answers I am writing it up:
If you downloaded the gtest source directly and used the make install from the downloaded gtest repository it may have installed header files under /usr/local/include/gtest. If you later use apt-get to install the libgtest-dev debian package it installs the header files under /usr/include/gtest. If the version installed from the debian package is newer, your Makefile can pick up the older header files from /usr/include and give you link errors even though you
are correctly linking the new libgtest.a archive.
The solution is to look for /usr/local/include/gtest and /usr/include/gtest to see if they both exist. If they do then delete the older directory. If /usr/include/gtest is the older directory, you may want to remove it by uninstalling the libgtest-dev package.

Linking protocol buffers library in XCode

I want to use Google Protocol Buffers for C++ in XCode.
This is my directory where I have the library: /Developer/Protobuf.
What I did inside this directory, is compiled the .proto and produced the .pb.h & .pb.cc files. After this produced the object file:
clang++ -arch x86_64 -I./src -I./ -c file.pb.cc
Then:
ar -r file.pb.a file.pb.o
In XCode, in Build Phases -> Link Binary With Libraries I have added file.pb.a static library. In Build Settings -> Header Search Paths I have added /Developer/Protobuf/src. In Build Settings -> Librabry Search Paths I have added /Developer/Protobuf. In Build Settings -> User Header Search Paths I have added also /Developer/Protobuf/src.
But when I compiled the project I always get this kind of errors:
Undefined symbols for architecture x86_64:
"google::protobuf::DescriptorPool::generated_pool()", referenced from:
musicbrainz::protobuf_AssignDesc_musicbrainz_2eproto() in musicbrainz.pb.o
"google::protobuf::DescriptorPool::InternalAddGeneratedFile(void const*, int)", referenced from:
musicbrainz::protobuf_AddDesc_musicbrainz_2eproto() in musicbrainz.pb.o
"google::protobuf::MessageFactory::generated_factory()", referenced from:
musicbrainz::protobuf_AssignDesc_musicbrainz_2eproto() in musicbrainz.pb.o
"google::protobuf::MessageFactory::InternalRegisterGeneratedFile(char const*, void (*)(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&))", referenced from:
musicbrainz::protobuf_AddDesc_musicbrainz_2eproto() in musicbrainz.pb.o
.................................................................................
Maybe I am not creating the static library correct ?
First of all, you need to compile the Protocol Buffers static libraries using their makefiles, and then, link in the static libraries into your project. You should not be pulling in their source code into your Xcode project.
When linking the libraries into my project, I had the same 'undefined symbols' errors as you. Based on comment #19 in this discussion, running the following commands when building the Protocol Buffers libraries will make them go away.
$ ./configure CC=clang CXX="clang++ -std=c++11 -stdlib=libc++" CXXFLAGS="-O3" --disable-shared
$ make

imwrite throwing compile error in OpenCV

I have been using OpenCV for a while and also the imwrite function, but unfortunately this is not working any more.
I am running with OpenCV 2.4.3 with following sample code:
imwrite("somepath/somefile.png", myMat);
The error:
Undefined symbols for architecture x86_64:
"cv::imwrite(std::string const&, cv::_InputArray const&, std::__debug::vector<int, std::allocator<int> > const&)", referenced from:
MyProject::this_callback(int, void*) in MyProject.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The error looks somewhat familiar but i cannot determine whats wrong.
Yes, I've thought you were using XCode. I had the same problem. :)
If you change the project setup so that:
you use GNU++11 as C++ language dialect
libstdc++ (GNU C++ standard) as C++ standard library
your linking problem will go away.
I use Apple LLVM 4.1.
When I had this problem, I have tried just adding a new target to one of my old projects I knew, worked. Then I've just made that target a one-source-file program.
This must be a "magic" part of XCode as I think there was a time I could not get the same project working after a restart. :S
I did what Barnabas did and also got the issue on cvdef.h. I was getting desperate so and what I did was just changed the header file.
in /usr/local/cvdef.h line 205:
I changed
include <cstdint>
typedef std::uint32_t uint;
to:
include <tr1/cstdint>
typedef std::tr1::uint32_t uint;
based on this post
I think opencv devs should apply some changes to the code for 64bit..
use something like clang version 3.8.0 (trunk 257459), instead of gcc version 4.9.2 (MacPorts gcc49 4.9.2_1+universal) to compile
for reference, cmd: clang++ -std=c++11 `pkg-config --cflags --libs opencv` code.cpp -o code

Resources