Bundling opencv as a static library gives thousands of undefined references - c++

I have a library that I am trying to link with openCV (and I think I did successfully) into one big dynamic library. I then try and add an executable and link everything together to test the library and I get 2000-3000 errors each saying
In function `________________`: undefined reference to `________`
some examples are:
/path/to/libs/libopencv_features2d.a(matchers.cpp.o): In function `cv::FlannBasedMatcher::read(cv::FileNode const&)':
matchers.cpp:(.text._ZN2cv17FlannBasedMatcher4readERKNS_8FileNodeE+0x227): undefined reference to `cv::flann::IndexParams::setAlgorithm(int)'
/path/to/libs/libopencv_videoio.a(cap_gstreamer.cpp.o)` In function `CvCapture_GStreamer::getProperty(int) const':
cap_gstreamer.cpp:(.text._ZNK19CvCapture_GStreamer11getPropertyEi+0x8b): undefined reference to `gst_element_query_position'
/path/to/lib/libopencv_core.a(stat.cpp.o): In function `cv::norm(cv::_InputArray const&, int, cv::_InputArray const&)':
stat.cpp:(.text._ZN2cv4normERKNS_11_InputArrayEiS2_+0x1d27): undefined reference to `ippicviNorm_L1_32f_C1MR'
stat.cpp:(.text._ZN2cv4normERKNS_11_InputArrayEiS2_+0x1dab): undefined reference to `ippicviNorm_L1_8u_C1MR'
My cmake file which runs:
project(SDK-build)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(MYLIB_SRC
file1.cpp
file2.cpp
file3.cpp
)
add_library(gesture SHARED ${MYLIB_SRC})
cmake_policy(SET CMP0015 NEW)
link_directories(./opencvlib-wgstreamer)
set(OPENCV_LIBS
libopencv_calib3d.a
libopencv_core.a
libopencv_features2d.a
libopencv_highgui.a
libopencv_imgcodecs.a
libopencv_imgproc.a
libopencv_ml.a
libopencv_objdetect.a
libopencv_photo.a
libopencv_video.a
libopencv_videoio.a
)
set(TEST_SRC
test.cpp
)
add_executable(gesture_test ${TEST_SRC})
#build library
#target_link_libraries(gesture -Wl,-whole-archive ${OPENCV_LIBS} -Wl,--no-whole-archive)
#build library with executable
target_link_libraries(gesture_test gesture -Wl,-whole-archive ${OPENCV_LIBS} -Wl,--no-whole-archive)
When I use the first target_link_libraries, everything builds and make has no problem executing, but linking with the file with main() causes the massive confusion. Any suggestions I've been banging my head over this for hours. I also tried several combinations of compiling opencv, using both WITH_IPP=ON, WITH_IPP=OFF, and WITH_GSTREAMER_ON

You have to specify the libraries in the correct order.
See here for more information.
Edit I see you are using -Wl-whole-archive which I believe is an other possible way to fix the problem, so maybe I'm wrong

Related

Building gRPC and openssl as dependency with cmake for msys2/mingw64 fails with undefined references

I'm trying to build the grpc helloworld example with changed file tree structure and my own CMakeLists.txt with msys2/mingw64. I want to build grpc from sources as a static library using add_subdirectory and build grpc's dependencies recursevily from sources as well.
Doing that I was getting linking errors with undefined references. After some research it seems that boringssl has problems with building in msys2/mingw64 or at least the way boringssl is included in grpc's repo isn't compatible with msys2/mingw64.
Since the grpc package in msys2 is built using openssl as dependency I decided to build openssl from sources during the build and let grpc statically link to that. I hope it is enough to just clone grpc without the boringssl submodule.
I was able to succesfully link and run the example when openssl was linked dynamically to libssl.dll.a. However when I try to link to static openssl build I'm getting undefined references errors again.`grpc_test2_server.exe
This are the linking errors I'm getting:
cmd.exe /C "cd . && C:\msys64\mingw64\bin\c++.exe -g #CMakeFiles\grpc_test2_server.rsp -o grpc_test2_server.exe -Wl,--out-implib,libgrpc_test2_server.dll.a -Wl,--major-image-version,0,--minor-image-version,0 && cd ."
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(b_addr.o): in function `addr_strings':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_addr.c:208: undefined reference to `__imp_getnameinfo'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_addr.c:220: undefined reference to `gai_strerrorW'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(b_addr.o): in function `BIO_lookup_ex':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_addr.c:731: undefined reference to `gai_strerrorW'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(b_sock.o): in function `BIO_sock_error':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_sock.c:99: undefined reference to `__imp_getsockopt'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(b_sock.o): in function `BIO_gethostbyname':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_sock.c:113: undefined reference to `__imp_gethostbyname'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(b_sock2.o): in function `BIO_listen':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_sock2.c:217: undefined reference to `__imp_getsockopt'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(b_sock2.o): in function `BIO_accept_ex':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/crypto/bio/b_sock2.c:290: undefined reference to `__imp_accept'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_get_prov_info':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1281: undefined reference to `__imp_CertGetCertificateContextProperty'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1289: undefined reference to `__imp_CertGetCertificateContextProperty'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_cert_get_fname':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1329: undefined reference to `__imp_CertGetCertificateContextProperty'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1335: undefined reference to `__imp_CertGetCertificateContextProperty'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_open_store':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1400: undefined reference to `__imp_CertOpenStore'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_list_certs':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1432: undefined reference to `__imp_CertFreeCertificateContext'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1435: undefined reference to `__imp_CertEnumCertificatesInStore'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1443: undefined reference to `__imp_CertCloseStore'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_find_cert':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1455: undefined reference to `__imp_CertFindCertificateInStore'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1459: undefined reference to `__imp_CertEnumCertificatesInStore'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_find_key':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1559: undefined reference to `__imp_CertFreeCertificateContext'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1561: undefined reference to `__imp_CertCloseStore'
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1593: undefined reference to `__imp_CertFreeCertificateC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: third-party/openssl/lib/libcrypto.a(e_capi.o): in function `capi_load_ssl_client_cert':
C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1720: undefined reference to `__imp_CertEnumCertificatesInStore'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1740: undefined reference to `__imp_CertDuplicateCertificateContext'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1754: undefined reference to `__imp_CertFreeCertificateContext'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\PatVax\Workspace\cpp\grpc_test2\build-debug\third-party\openssl_build/../../../third-party/openssl/engines/e_capi.c:1756: undefined reference to `__imp_CertCloseStore'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.`
And this is my CMakeLists.txt that I'm currently using:
cmake_minimum_required(VERSION 3.24)
project(grpc_test2 C CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_STANDARD 17)
set(BUILD_SHARED_LIBS OFF)
set(gRPC_BUILD_SHARED_LIBS OFF)
set(gRPC_BUILD_GRPC_CSHARP_EXT OFF)
set(gRPC_BUILD_GRPC_PHP_EXT OFF)
set(gRPC_BUILD_GRPC_PYTHON_EXT OFF)
set(gRPC_BUILD_GRPC_NODE_EXT OFF)
set(gRPC_BUILD_GRPC_RUBY_EXT OFF)
set(gRPC_BUILD_GRPC_OBJC_EXT OFF)
set(gRPC_BUILD_GRPC_OBJC_PLUGIN OFF)
set(_gRPC_BASELIB_LIBRARIES libws2_32 libcrypt32)
include(ProcessorCount)
ProcessorCount(N)
set(OPENSSL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/openssl)
set(OPENSSL_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/third-party/openssl_build)
set(OPENSSL_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/third-party/openssl)
set(OPENSSL_INCLUDE_DIR ${OPENSSL_INSTALL_DIR}/include)
set(MSYS_SHELL ${MSYS2_ROOT}/msys2_shell.cmd)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(OPENSSL_CONFIGURE_COMMAND ${MSYS_SHELL} -mingw64 -no-start -here -defterm -c
"${OPENSSL_SOURCE_DIR}/Configure --prefix=${OPENSSL_INSTALL_DIR} --openssldir=${OPENSSL_INSTALL_DIR} --release -static no-shared mingw64")
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(OPENSSL_CONFIGURE_COMMAND ${MSYS_SHELL} -mingw64 -no-start -here -defterm -c
"${OPENSSL_SOURCE_DIR}/Configure --prefix=${OPENSSL_INSTALL_DIR} --openssldir=${OPENSSL_INSTALL_DIR} --debug -static no-shared mingw64")
else()
set(OPENSSL_CONFIGURE_COMMAND ${MSYS_SHELL} -mingw64 -no-start -here -defterm -c
"${OPENSSL_SOURCE_DIR}/Configure --prefix=${OPENSSL_INSTALL_DIR} --openssldir=${OPENSSL_INSTALL_DIR} -static no-shared mingw64")
endif()
add_custom_target(OpenSSL_Configured
COMMAND ${OPENSSL_CONFIGURE_COMMAND}
WORKING_DIRECTORY ${OPENSSL_BINARY_DIR}
BYPRODUCTS ${OPENSSL_BINARY_DIR}/Makefile
DEPENDS ${OPENSSL_SOURCE_DIR}/Configure
COMMENT "OpenSSL is configuring")
add_custom_target(OpenSSL_Built
COMMAND ${MSYS_SHELL} -mingw64 -no-start -here -defterm -c "make -j${N}"
WORKING_DIRECTORY ${OPENSSL_BINARY_DIR}
BYPRODUCTS ${OPENSSL_BINARY_DIR}/libssl.a ${OPENSSL_BINARY_DIR}/libcrypto.a
DEPENDS OpenSSL_Configured
COMMENT "OpenSSL is building")
add_custom_target(OpenSSL_Installed
COMMAND ${MSYS_SHELL} -mingw64 -no-start -here -defterm -c "make install"
WORKING_DIRECTORY ${OPENSSL_BINARY_DIR}
BYPRODUCTS ${OPENSSL_INSTALL_DIR}/lib/libssl.a ${OPENSSL_INSTALL_DIR}/lib/libcrypto.a ${OPENSSL_INSTALL_DIR}/lib/libssl.dll.a ${OPENSSL_INSTALL_DIR}/lib/libcrypto.dll.a ${OPENSSL_INSTALL_DIR}/lib/libssl.dll ${OPENSSL_INSTALL_DIR}/lib/libcrypto.dll
DEPENDS OpenSSL_Built
COMMENT "OpenSSL is installing")
add_custom_target(OpenSSL DEPENDS OpenSSL_Installed COMMENT "OpenSSL is ready")
file(MAKE_DIRECTORY ${OPENSSL_INCLUDE_DIR})
add_library(OpenSSL::SSL STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::SSL PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libssl.a)
set_property(TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(OpenSSL::SSL OpenSSL)
add_library(OpenSSL::Crypto STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::Crypto PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libcrypto.a)
set_property(TARGET OpenSSL::Crypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(OpenSSL::Crypto OpenSSL)
add_library(ssl STATIC IMPORTED GLOBAL)
set_property(TARGET ssl PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libssl.a)
set_property(TARGET ssl PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(ssl OpenSSL)
add_library(crypto STATIC IMPORTED GLOBAL)
set_property(TARGET crypto PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libcrypto.a)
set_property(TARGET crypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(crypto OpenSSL)
set(_gRPC_SSL_LIBRARIES ssl crypto)
set(_gRPC_SSL_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR})
add_subdirectory(third-party/grpc ${CMAKE_CURRENT_BINARY_DIR}/third-party/grpc)
get_filename_component(hw_proto "${CMAKE_CURRENT_SOURCE_DIR}/protobufs/helloworld.proto" ABSOLUTE)
get_filename_component(hw_proto_path "${hw_proto}" PATH)
find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc")
set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h")
set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc")
set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h")
add_custom_command(
OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}"
COMMAND protobuf::protoc
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${hw_proto_path}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${hw_proto}"
DEPENDS "${hw_proto}")
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
add_library(hw_grpc_proto
${hw_grpc_srcs}
${hw_grpc_hdrs}
${hw_proto_srcs}
${hw_proto_hdrs})
target_link_libraries(hw_grpc_proto grpc++ grpc++_reflection libprotobuf)
add_executable(${CMAKE_PROJECT_NAME}_server server.cpp)
add_executable(${CMAKE_PROJECT_NAME}_client client.cpp)
target_link_libraries(${CMAKE_PROJECT_NAME}_server grpc++ grpc++_reflection libprotobuf hw_grpc_proto)
target_link_libraries(${CMAKE_PROJECT_NAME}_client grpc++ grpc++_reflection libprotobuf hw_grpc_proto)
My directory structure looks like the following:
grpc is cloned with all submodules without boringssl
openssl is cloned with all submodules
protobufs contains the .proto files that are being compiled during the build process
Contents of the .cpp files are identical to those in the helloworld example in the grpc repo
What could be the reason of my problems? Am I missing something? Thanks in advance.
EDIT3: I've actually realized a big blunder here. You can't link against the ws2_32.lib as it was built with MSVC and not MinGW. However the issue to your problem stems from here.
I feel like a donkey, but apparently newer versions of MSYS2/MinGW should be able to link against these static libraries. So the following solution is worth a try.
EDIT: After some digging in I think I found the reason why MSVC is supported and mingw is not. The reason why you're having issues is because they are most likely using #pragma to link their libraries (this is a MSVC specific feature).
Try additionaly linking to this library: ws2_32 (maybe the 64 bit version is called ws2_64) - (more precisely you want to link against winsock2 64 bit version)
EDIT2: They are all named ws2_32 and the #pragma picks the right one for you, i.e. the only thing different is the path to the correct SDK
Based on this official github issue. The GRPC team does not support MinGW for Windows builds.
They describe the same issue that you are describing and they also have a suggestion on how to fix boringssl to work i.e.
By applying this patch and
by building boringssl with the following define OPENSSL_NO_ASM.
Long story short, I would switch to MSVC on Windows if I were you - I don't see a reason why not to use it if your target platform is Windows anyway.
EDIT: However if you are still persistent on using MinGW then maybe to maybe get you closer to how to fix your issue I would maybe point out that gai_strerrorW is a function defined in ws2tcpip.h

CMake 'undefined reference' error with CERN-ROOT

I'm writing a small addition to CERN ROOT and now can't get rid of 'undefined reference' errors on every function from ROOT that I use (and my classes too). Can't find a way to fix this, so looking for help here.
My OS is Linux Mint 19. I use g++ as my c++ compiler, however, I tried clang++ and there was no difference.
I downloaded sources of ROOT from their github and built it now on my computer. Output of root --version is this:
ROOT Version: 6.19/01
Built for linuxx8664gcc on Sep 29 2019, 14:25:35
From heads/master#v6-19-01-1167-gbec9f2d1f7
This is the structure of my project:
ParentFolder
--CMakeLists.txt
--General
----include/...
----source/...
----CMakeLists.txt
----LinkDef.h
--Test
----include/...
----source/...
----CMakeLists.txt
Important lines from top level CMakeLists.txt are:
find_package(ROOT REQUIRED)
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
include(${ROOT_USE_FILE})
add_subdirectory("./General")
add_subdirectory("./Test")
From Test/CmakeLists.txt:
add_executable(Test source/test_main.cpp)
target_include_directories(Test PUBLIC "./include")
target_link_libraries(Test PUBLIC General GTest::GTest GTest::Main ${ROOT_LIBRARIES})
From General/CmakeLists.txt:
file(GLOB_RECURSE SOURCES . source/*.cpp)
ROOT_GENERATE_DICTIONARY(GeoManagerExtractor LINKDEF LinkDef.h)
add_library(General SHARED ${SOURCES} GeoManagerExtractor.cxx)
target_link_libraries(General ${ROOT_LIBRARIES})
target_include_directories(General PUBLIC "./include")
Here are first few lines produced by CMake (while using clang++)
CMakeFiles/Test.dir/source/test_main.cpp.o: In function `main':
test_main.cpp:(.text+0x37): undefined reference to `TGeoManager::Import(char const*, char const*, char const*)'
test_main.cpp:(.text+0x3f): undefined reference to `gGeoManager'
test_main.cpp:(.text+0x8c): undefined reference to `gGeoManager'
CMakeFiles/Test.dir/source/test_main.cpp.o: In function `TGeoManagerExporter::~TGeoManagerExporter()':
test_main.cpp:(.text._ZN19TGeoManagerExporterD2Ev[_ZN19TGeoManagerExporterD2Ev]+0xa): undefined reference to `vtable for TGeoManagerExporter'
../General/libGeneral.so: undefined reference to `ROOT::GenerateInitInstance(TGeoManagerExporter const*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Here are a few lines from test_main.cpp:
TGeoManager::Import("../root_tests/geofile_full.root");
if (gGeoManager == nullptr) {
std::cerr << "Can't find TGeoManager in file" << std::endl;
return 0;
}
UPD: Forgot to mention, that in order to create my CMakeLists.txt files I used these two sources:
https://root.cern.ch/how/integrate-root-my-project-cmake
https://cliutils.gitlab.io/modern-cmake/chapters/packages/ROOT.html
I have managed to compile my project.
As it turned out, .so file that contains TGeoManager implementation was not included in ROOT_LIBRARIES(thanks, Kamil Cuk for bringing my attention to this variable) by the script provided by ROOT developers. It was hard to find as this class was working properly in Cling(c++ interpreter included with ROOT) and this class is almost the only one from ROOT that I use in the project, so I assumed, that the whole ROOT library was not linking properly. After I found this issue, I fixed my CMake files like this (this is from General/CmakeLists.txt):
file(GLOB_RECURSE SOURCES2 . $ENV{ROOTSYS}/lib/*.so)
add_library(General SHARED ${SOURCES} ${SOURCES2} GeoManagerExtractor.cxx)
This eliminates all of the "undefined reference to 'gGeoManager'" and alike, but "undefined reference to `vtable for TGeoManagerExporter'" (TGeoManagerExporter is my own class) stays. However, I figured out that this error is caused by a reflection feature, so as a temporary solution I just don't activate it. I'll post a comment here if I solve this problem.

C++ undefined reference for libtins library

I installed the libtins package for C++, by building it as described and adding #include <tins/tins.h> to the header of the example file. I ran ldconfig but building always throws a Undefined reference error:
CMakeFiles/lts.dir/main.cpp.o: In function `main':
/home/patrick/ClionProjects/lts/main.cpp:6: undefined reference to `Tins::EthernetII::EthernetII(Tins::HWAddress<6ul, unsigned char> const&, Tins::HWAddress<6ul, unsigned char> const&)'
/home/patrick/ClionProjects/lts/main.cpp:7: undefined reference to `Tins::IPv4Address::IPv4Address(char const*)'
/home/patrick/ClionProjects/lts/main.cpp:7: undefined reference to `Tins::IPv4Address::IPv4Address(char const*)'
/home/patrick/ClionProjects/lts/main.cpp:7: undefined reference to `Tins::IP::IP(Tins::IPv4Address, Tins::IPv4Address)'
/home/patrick/ClionProjects/lts/main.cpp:8: undefined reference to `Tins::TCP::TCP(unsigned short, unsigned short)'
/home/patrick/ClionProjects/lts/main.cpp:10: undefined reference to `Tins::PDU::inner_pdu(Tins::PDU*)'
/home/patrick/ClionProjects/lts/main.cpp:12: undefined reference to `Tins::PDU::inner_pdu(Tins::PDU*)'
CMakeFiles/lts.dir/main.cpp.o: In function `Tins::EthernetII::~EthernetII()':
/usr/local/include/tins/ethernetII.h:46: undefined reference to `vtable for Tins::EthernetII'
/usr/local/include/tins/ethernetII.h:46: undefined reference to `Tins::PDU::~PDU()'
collect2: error: ld returned 1 exit status
make[3]: *** [lts] Error 1
I am using CLion as IDE and the following cmake file:
cmake_minimum_required(VERSION 3.5)
project(lts)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -ltins")
set(SOURCE_FILES main.cpp)
add_executable(lts ${SOURCE_FILES})
Any Idea what could be the problem?
There's a couple of things to address in your question. First, let CMake find the location of the libtins library for you, then use target_link_libraries() to add it to your lts executable. In the CMake sample in your question, you are specifying library options in the compiler flags variable (CMAKE_CXX_FLAGS). The other thing is to also let CMake handle setting the appropriate compiler flags for C++11 instead of manually adding them to CMAKE_CXX_FLAGS (which would only take care of the compiler part but not the linker). The following should do what you want in a robust, platform independent way:
cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(lts)
find_library(TINS_LIBRARY tins)
set(SOURCE_FILES main.cpp)
add_executable(lts ${SOURCE_FILES})
target_link_libraries(lts "${TINS_LIBRARY}")
I recommend you read the CMake docs for find_library() and target_link_libraries() to understand what those commands do. For the C++11 stuff, I recommend this blog article for a more cohesive explanation than what the CMake docs give you (disclosure: I wrote the article).
The CMake variable CMAKE_CXX_FLAGS is for the compiler flags, not for libraries.
To add a library you should use target_link_libraries:
target_link_libraries(lts tins)
If you want all targets to link to the same library, you should add it to the list CMAKE_STANDARD_LIBRARIES.
A small tip on debugging these kind of things: Either set CMAKE_VERBOSE_MAKEFILE or use make VERBOSE=1 to inhibit the normal CMake build output, and instead display the normal make output, which will show you all commands make runs, and all flags and options used for each and every program. That way you will be able to see the -ltins flag being passed as a compiler flag, but not as a linker flag or library.
The compiler should -ltins. Refer to CMake manual on how to add library dependencies.
From the Download page of libtins:
In order to link your application with libtins on GCC or clang, use the -ltins flag
Simply add the following line in your CMake file:
target_link_libraries(PROJECT_NAME -ltins)

How do I use a static library (in my case assimp) without the source files

I have a libassimp.a file and the header files. How can I use the library?
I'm adding the header files to my project with set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${ASSIMP_INCLUDE_DIR}"). With ASSIMP_INCLUDE_DIR being ../contrib/assimp/include.
Now when I use some class in my main.cpp it gives me errors about undefined references to some funtions, because obviously I don't have the source files.
When I add the libassimp.a to my compile flags I get the following errors when using make:
make[3]: *** No rule to make target `../contrib/assimp/lib/libassimp.a',
...
main.cpp:7:32: fatal error: assimp/Importer.hpp: No such file or directory
....
Linking CXX static library libassimp.a
I don't understand these messages. Maybe they are there because it's trying to access libassimp.a before it's actually there? Is this some kind of concurrency problem?
Anyways, if I call make again then I get different errors, namely a bunch of undefined references to things I am not using, e.g.
../contrib/assimp/lib/libassimp.a(AssbinLoader.cpp.o): In function `Assimp::AssbinImporter::InternReadFile(std::string const&, aiScene*, Assimp::IOSystem*)':
AssbinLoader.cpp:(.text+0x2a49): undefined reference to `uncompress'
EDIT:
I am compiling with CMake like this:
target_link_libraries(monoRenderer [some other libraries] ${ASSIMP_STATIC_LIB})
ASSIMP_STATIC_LIB is the path to libassimp.a.
EDIT2:
I reduced my CMake file to this:
cmake_minimum_required(VERSION 2.8.12)
project(monoRenderer)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
file(GLOB_RECURSE CXX_SRCS src/*.cpp)
file(GLOB_RECURSE C_SRCS src/*.c)
file(GLOB_RECURSE HPP_HDRS src/*.hpp)
file(GLOB_RECURSE H_HDRS src/*.h)
set(SRCS "${C_SRCS};${CXX_SRCS}")
set(HDRS "${H_HDRS};${HPP_HDRS}")
include_directories(${PROJECT_SOURCE_DIR}/contrib/assimp/include)
add_executable(monoRenderer ${SRCS} ${HDRS})
target_link_libraries(monoRenderer ${PROJECT_SOURCE_DIR}/contrib/assimp/lib/libassimp.a)
The header files are in contrib/assimp/include and the libassmip.a is in contrib/assimp/lib. It still doesn't work, same errors as before.
My main.cpp looks like this:
#include <assimp/Importer.hpp>
#include <cstdlib>
int main() {
Assimp::Importer importer;
return EXIT_SUCCESS;
}
EDIT3:
I think it has something to do with zlib, since all the errors seem to have that in common I think:
undefined reference to `uncompress'
undefined reference to `inflateInit2_'
undefined reference to `inflate'
undefined reference to `inflateEnd'
undefined reference to `inflateReset'
undefined reference to `inflateSetDictionary'
undefined reference to `get_crc_table'
undefined reference to `crc32'
As you stated yourself you are encountering problems with zlib. You have to add all dependencies from your static library yourself, e.g.:
target_link_libraries(monoRenderer z)
Since you stated that your header are located in contrib/assimp/include you might want to change your include in main.cpp to
#include <Importer.hpp>

'undefined reference to' with cmake

So, I am trying to write an applet for school, and part of it requires using cmake. I have two different classes contained in their own files, and I use them as part of the main class. I have included their headers as such in the main project header:
#include /path/to/header/1.h
#include /path/to/header/2.h
The problem I have is that when I run make after I've run cmake, I get undefined reference errors for any instance in which I try to use one of the two libraries. I know that it has to do with linker errors, but since I'm new to cmake, I'm not exactly sure what the proper way to use TARGET_LINK_LIBRARIES would be.
EDIT
After linking/associating my libraries, I have the following:
CMakeLists.txt:
# A name for the project
project(plasma-engine-gdrive)
# Find the required libaries
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS}, -std=c++0x)
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
${KDE4_INCLUDES}
./include
./lib
)
set (GOOGLE_LIBS include/atom_helper.h include/util/string_utils.h include/client/doc_list_service.h include/client/service.h)
set (GOOGLE_SRCS include/atom_helper.cc include/util/string_utils.cc include/client/doc_list_service.cc include/client/service.cc)
# We add our source code here
set(gdrive_engine_SRCS gdriveengine.cpp)
add_library (DataWrapper include/DataWrapper.cpp include/DataWrapper.h)
add_library (GData ${GOOGLE_SRCS} ${GOOGLE_LIBS})
# Now make sure all files get to the right place
kde4_add_plugin(plasma_engine_gdrive ${gdrive_engine_SRCS})
target_link_libraries(plasma_engine_gdrive
GData
DataWrapper
${KDE4_KDECORE_LIBS}
${KDE4_PLASMA_LIBS})
install(TARGETS plasma_engine_gdrive
DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES plasma-engine-gdrive.desktop
DESTINATION ${SERVICES_INSTALL_DIR})
There are also too many errors to put here. Here's a few:
/usr/include/c++/4.6/bits/stl_map.h:467: undefined reference to `Glib::ustring::ustring()'
lib/libGData.a(atom_helper.o): In function `pair<Glib::ustring, Glib::ustring, void>':
/usr/include/c++/4.6/bits/stl_pair.h:132: undefined reference to `Glib::ustring::ustring(Glib::ustring const&)'
/usr/include/c++/4.6/bits/stl_pair.h:132: undefined reference to `Glib::ustring::ustring(Glib::ustring const&)'
lib/libGData.a(atom_helper.o): In function `pair<Glib::ustring, Glib::ustring>':
/usr/include/c++/4.6/bits/stl_pair.h:137: undefined reference to `Glib::ustring::ustring(Glib::ustring const&)'
/usr/include/c++/4.6/bits/stl_pair.h:137: undefined reference to `Glib::ustring::ustring(Glib::ustring const&)'
I was working with some others and I got it compiled!
All I really needed was to provide the name of the library and put it into target_link_libraries like so:
target_link_libraries(plasma_engine_gdrive
DataWrapper
GData
xml++-2.6
curl
glibmm-2.4
${KDE4_KDECORE_LIBS}
${KDE4_PLASMA_LIBS})
My dad, being completely unfamiliar with CMake, went and dug out the link.txt within the CMake build structure. There, he just added the following after the -o flag:
-lxml++-2.6
-lcurl
-lglibmm-2.4
When I saw that, I thought I might try to do that linking through CMakeLists.txt -- and it worked.