Linux: a C++ library fails to link after recompiling - c++

I had a https://github.com/simongog/sdsl-lite library installed on a remote Linux server. What I did was to create lib, include directories inside my home directory and then run the script as ./install.sh /my/home/dir, as indeed explained on the above page. I was able to do it once and successfully linked it to my other programs by using a CMakeLists.txt file as the one similar to the following:
cmake_minimum_required(VERSION 2.8)
set (CMAKE_CXX_STANDARD 14)
macro(use_cxx14)
if (CMAKE_VERSION VERSION_LESS "3.1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -mcmodel=large")
endif ()
else ()
set (CMAKE_CXX_STANDARD 14)
endif ()
endmacro(use_cxx14)
use_cxx14()
# Locate GTest
link_directories(/my/home/dir/)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /my/home/dir/)
list(APPEND CMAKE_PREFIX_PATH "/my/home/dir/")
list(APPEND CMAKE_LIBRARY_PATH /my/home/dir/lib/)
INCLUDE_DIRECTORIES(/my/home/dir/include)
LINK_DIRECTORIES(/my/home/dir/lib)
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests rs_bitvector_test.cpp)
# SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
# SET(BUILD_SHARED_LIBRARIES OFF)
# SET(CMAKE_EXE_LINKER_FLAGS "-static")
target_link_libraries(runTests sdsl ${GTEST_LIBRARIES} pthread)
(the server was missing C++14 but the name remains, although really I use the C++11 option)
Now I've changed a source file inside the previously downloaded location of the library and recompiled it. And now linking stopped working. What could be the reason? During re-compilation, the remote server kept telling me about some "modification time in the future" and "build may be incomplete". Is that the reason? What can be done?
EDIT: based off the suggestions in the comments, I removed the build directory (analog of make clean) and replaced it with that from the directory of the original bundle. Now, the timstamps issue is gone, but the linking still fails.

Funnily, after noticing that sdsl detected g++ 7.3 during installation while cmake was compiling using 4.8, I used https://cmake.org/Wiki/CMake_FAQ#How_do_I_use_a_different_compiler.3F to set the compiler to g++ 7.3 (using Method 3 in the above link), and it finally worked (still some issues with GTest, but it is OK).

Related

Encounter issue with `find_package` command in Visual Studio CMake

I'm operating under a new learning curve here with c++ and using CMake in Visual Studio. Here is the partial code up until the point where I receive the error:
project(libfranka
VERSION 0.8.0
LANGUAGES CXX
)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(MSVC)
add_compile_options(/W0)
else()
add_compile_options(-Wall -Wextra)
endif()
set(THIRDPARTY_SOURCES_DIR "${CMAKE_SOURCE_DIR}/3rdparty" CACHE PATH
"Directory for third-party sources")
## Dependencies
find_package(Poco REQUIRED COMPONENTS Net Foundation)
find_package(Eigen3 REQUIRED)
Once it hits the first find_package is where I encounter the error:
Here is the code within FindPoco.cmake.
find_package(Poco COMPONENTS ${Poco_FIND_COMPONENTS} CONFIG QUIET)
if(Poco_FOUND)
return()
endif()
find_path(Poco_INCLUDE_DIR Poco/Poco.h)
mark_as_advanced(FORCE Poco_INCLUDE_DIR)
foreach(component ${Poco_FIND_COMPONENTS})
set(component_var "Poco_${component}_LIBRARY")
find_library(${component_var} Poco${component})
mark_as_advanced(FORCE ${component_var})
if(${component_var})
set(Poco_${component}_FOUND TRUE)
list(APPEND Poco_LIBRARIES ${component})
if(NOT TARGET Poco::${component})
add_library(Poco::${component} SHARED IMPORTED)
set_target_properties(Poco::${component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${Poco_INCLUDE_DIR}
IMPORTED_LOCATION ${${component_var}}
)
endif()
endif()
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Poco
FOUND_VAR Poco_FOUND
REQUIRED_VARS Poco_INCLUDE_DIR Poco_LIBRARIES
VERSION_VAR Poco_VERSION
HANDLE_COMPONENTS
)
I installed poco using vcpkg in a directory titled vcpkg. Within the vcpkg directory is the libfranka directory, which houses the CMakeLists.txt file that I compile in Visual Studio. Here is an image of that directory:
Finally, here is the tutorial that I am using: https://frankaemika.github.io/docs/installation_windows.html#building-from-source
EDIT:
Per the link I followed the instructions for solving the build dependencies and here is an image of that:
Then I ran the CMakeLists.txt again and in the CMake Settings this is what I see:
Note also that I ran through the install of poco again and I noticed this and am unsure if it could be the source of the problem or if it means nothing (again, this was the out put after running vcpkg install poco):
After this I still receive the same error.
Does anyone see what it is that I am doing incorrectly?
Thank you!

Can't use protobuf in cmakelists.txt

I am trying to run the example given in protobuf repo here, the c++ version. I have successfully installed the library and am able to run the Makefile. But on running the CMakeLists.txt, I get this error:
CMake Error at CMakeLists.txt:9 (find_package):
Could not find a package configuration file provided by "protobuf" with any
of the following names:
protobufConfig.cmake
protobuf-config.cmake
Add the installation prefix of "protobuf" to CMAKE_PREFIX_PATH or set
"protobuf_DIR" to a directory containing one of the above files. If
"protobuf" provides a separate development package or SDK, be sure it has
been installed.
-- Configuring incomplete, errors occurred!
See also "/home/cortana/Projects/CppProjects/proto/build/CMakeFiles/CMakeOutput.log".
See also "/home/cortana/Projects/CppProjects/proto/build/CMakeFiles/CMakeError.log".
I have updated my LD_LIBRARY_PATH but this error is still there. How do I remove this error?
EDIT:
CMakeLists.txt:
# Minimum CMake required
cmake_minimum_required(VERSION 2.8.12)
# Project
project(protobuf-examples)
include(FindProtobuf)
# Find required protobuf package
find_package(protobuf CONFIG REQUIRED)
if(protobuf_VERBOSE)
message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
endif()
set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
${THIRDPARTY_DIR}/protobuf-3.1.0
)
include_directories(${ProtobufIncludePath})
# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
if(MSVC AND protobuf_MSVC_STATIC_RUNTIME)
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach()
endif()
foreach(example add_person list_people)
set(${example}_SRCS ${example}.cc)
set(${example}_PROTOS addressbook.proto)
#Code Generation
if(protobuf_MODULE_COMPATIBLE) #Legacy Support
protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
else()
foreach(proto_file ${${example}_PROTOS})
get_filename_component(proto_file_abs ${proto_file} ABSOLUTE)
get_filename_component(basename ${proto_file} NAME_WE)
set(generated_files ${basename}.pb.cc ${basename}.pb.h)
list(APPEND ${example}_SRCS ${generated_files})
add_custom_command(
OUTPUT ${generated_files}
COMMAND protobuf::protoc
ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs}
COMMENT "Generating ${generated_files} from ${proto_file}"
VERBATIM
)
endforeach()
endif()
#Executable setup
set(executable_name ${example}_cpp)
add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS})
if(protobuf_MODULE_COMPATIBLE) #Legacy mode
target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
else()
target_link_libraries(${executable_name} protobuf::libprotobuf)
endif()
endforeach()
EDIT 2:
After trying for 2 hours, I couldn't fix the CMakeLists.txt provided by google examples. I wrote this basic one and it works for me:
PROJECT(protopuff)
CMAKE_MINIMUM_REQUIRED (VERSION 3.5)
SET(CMAKE_CXX_FLAGS "-g -Wall -Werror -std=c++11")
INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER addressbook.proto)
ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}_add add_person.cc)
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}_list list_people.cc)
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME}_add proto ${PROTOBUF_LIBRARY})
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME}_list proto ${PROTOBUF_LIBRARY})
Your problem is here:
find_package(protobuf CONFIG REQUIRED)
The name should start with uppercase: Protobuf. And that is the reason why your version is working; because in there, you have used correct case (last code snippet line 6):
find_package(Protobuf REQUIRED)
Here cmake documentation for find_package
The command searches for a file called <name>Config.cmake or <lower-case-name>-config.cmake for each name specified.
in this thread fraser solved the problem but if you need to develop according to protobuf CMake config and find_package command in CMake for finding protobuf libraries. your protobuf library must be compiled with CMake and do not use configure routine .
after compile protobuf with CMake , a config file named protobuf-config.cmake will be generated into the prefix/lib/CMake/protobuf directory.
The CmakeList.txt that is provided by the OP works on Linux but it does NOT work on Windows.
There is a way to make the actual CMakeList.txt work without any changes. The problem is that it requires the CONFIG parameter and that part is not documented anywhere. We need to provide the path to that config using -Dprotobuf_DIR parameter while generating the project.
On Windows, wherever you have installed protobuf, it will have bin, cmake, include, lib folders. We need to give the path of this cmake folder as an argument, like following:
cmake -G "Visual Studio 16 2019" -A x64 -B _build2 -Dprotobuf_DIR=C:/protobuf/install/cmake
This will build a solution file in the current directory.

Linking with cmake, icc and pthreads (linux)

I am trying to compile a simple test project with the Intel C++ Compiler, CMake, and std::threads support.
If I do :
icpc -std=c++11 -lpthread source/main.cpp
Then the build and the program work fine.
But with CMake I get an error:
CMake Error at CMakeLists.txt:21 (TARGET_LINK_LIBRARIES):
Cannot specify link libraries for target "test" which is not built by
this project.
CMakeLists.txt is:
project(test)
set (CMAKE_CXX_FLAGS "-std=c++11")
set(SOURCE_LIST "source/main.cpp")
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
add_executable (${PROJECT_NAME} ${SOURCE_LIST})
I am building in an environment set by the script supplied by icc (compilervars.sh) and CMake is called with the -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc options. It works if I'm not using threads.
What is wrong with my use of CMake?
Thanks!
Looking back the documentation for target_link_libraries, a target must be declared before being used:
The named <target> must have been created in the current directory by a command such as add_executable() or add_library().
BTW as stated in this answer, you should not set CMAKE_CXX_FLAGS explicitly, and prefer setting CMAKE_CXX_STANDARD and related variables:
project(test)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(SOURCE_LIST "source/main.cpp")
add_executable(${PROJECT_NAME} ${SOURCE_LIST})
target_link_libraries(${PROJECT_NAME} pthread)
The order is wrong: first declare your executable and let CMake know that it exists
add_executable (${PROJECT_NAME} ${SOURCE_LIST})
and afterwards add the link libraries
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
From target_link_libraries's documentation:
The named must have been created in the current directory by a command such as add_executable() or add_library()

CMake third party library undefined reference

I already read and searched a lot (e.g. 1 2 3, several docs for CMake, similar projects, etc. to find a solution but I have not been able to solve my problem. I am relatively new to Cmake and Linux (Ubuntu 14.04).
I want to use libsbp (https://github.com/swift-nav/libsbp) to write a program in C++ to communicate with a GPS module. I cloned the repository and installed the C-Library. So now in /usr/local/lib there are two files: libsbp.so and libsbp-static.a and the headers are in /usr/local/include/libsbp
In my own project I include the headers with #include "libsbp/sbp.h" which also works.
Now the Problem: if I want to use a method from libsbp e.g. sbp_state_init(&s); I get undefined reference to "sbp_state_init(sbp_state_t*)"
The relevant part of my Cmake for my own project:
link_directories(/usr/local/lib)
add_executable(main ${QT_SOURCES} ${QT_HEADER_HPP})
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)
As I said before, I tried some things:
find_library(SBP_LIB sbp /usr/local/lib) -> same error
same goes for using libsbp in target_link_libraries or searching for it
link_directory(/usr/local/lib)
trying different paths, even moveing libsbp.so into the project directory and "finding" it with ${CMAKE_CURRENT_SOURCE_DIR}
Maybe you can help me!
edit:
this is the CMakeList.txt from the libsbp/c/src directory
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif (NOT DEFINED BUILD_SHARED_LIBS)
file(GLOB libsbp_HEADERS "${PROJECT_SOURCE_DIR}/include/libsbp/*.h")
include_directories("${PROJECT_SOURCE_DIR}/CBLAS/include")
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
include_directories("${PROJECT_SOURCE_DIR}/lapacke/include")
include_directories("${PROJECT_SOURCE_DIR}/include/libsbp")
set(libsbp_SRCS
edc.c
sbp.c
)
add_library(sbp-static STATIC ${libsbp_SRCS})
install(TARGETS sbp-static DESTINATION lib${LIB_SUFFIX})
if(BUILD_SHARED_LIBS)
add_library(sbp SHARED ${libsbp_SRCS})
install(TARGETS sbp DESTINATION lib${LIB_SUFFIX})
else(BUILD_SHARED_LIBS)
message(STATUS "Not building shared libraries")
endif(BUILD_SHARED_LIBS)
install(FILES ${libsbp_HEADERS} DESTINATION include/libsbp)
this is the CMakeList.txt from /libsbp/c/
cmake_minimum_required(VERSION 2.8.9)
project(libsbp)
# Setup flags for Code Coverage build mode
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C++ compiler for building with code coverage."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C compiler for building with code coverage."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used for linking binaries with code coverage."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the shared libraries linker during builds with code coverage."
FORCE )
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
# Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE )
# Set project version using Git tag and hash.
execute_process(
COMMAND git describe --dirty --tags --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_VERSION_FOUND
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)
# Set project version explicitly for release tarballs.
#set(VERSION foo)
message(STATUS "libsbp version: ${VERSION}")
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Some compiler options used globally
set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}")
add_subdirectory(src)
add_subdirectory(docs)
add_subdirectory(test)
It seems that your program uses C++ and the library is written in C.
Symbols in C and C++ are encoded differently (mangled). When including C headers from C++ you need to tell the compiler. This can be done by declaring the symbols extern "C".
extern "C" {
#include <libsbp/sbp.h>
}
Some libraries already include this in their headers, but not sbp.
You have (at least) two possibilities:
Installing the library (this is what you did)
Integrating the library in your CMake project
When installing the library, the target_link_libraries command needs to be modified slightly:
find_library(SBP_LIB sbp /usr/local/lib)
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} ${SBP_LIB})
When you integrate the library in your CMake project, you can directly use the following command without using find_library. This works, because the library is known to CMake since it is built within the current project.
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)

translate g++ code to clion environment

I am new in clion. on gcc i always use:
g++ bin/obj/main.o -o bin/main -lboost_filesystem -lboost_system -lcrypto
How to do it in clion?
It seems my CMakeList does not work:
cmake_minimum_required(VERSION 3.1)
project(motion_simulation)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(motion_simulation ${SOURCE_FILES})
link_libraries(lboost_filesystem)
link_libraries(lboost_system)
link_libraries(lcrypto)
Try including the keyword "CMake" into your search next time. This question is actually not CLion specific because CLion actually uses CMake as buildsystem.
CMake is very well documented, and you should be able to find a lot of answers regarding your problem.
You could first try to get rid of that "l":
link_libraries(boost_filesystem)
If that doesn't work you should take a look how the find_package() command works. http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries
And here is a detailed explanation how to find Boost libs and include directory.
http://www.cmake.org/cmake/help/v3.0/module/FindBoost.html
As you are using CMake 3.1 you can use some more advanced features of CMake.
With CMAKE_CXX_STANDARD you can select which C++ version you want to use and CMake will select the corresponding compiler flags (see docs).
link_libraries is one possibility, but it has to be called before add_executable or add_library. The alternative is target_link_libraries which links only to a single target, but can also manage transitive dependencies (docs).
CMake comes with find_package modules for OpenSSL and Boost to find dependencies and with the option REQUIRED, you can ensure that they are found on the system. Boost also supports COMPONENTS to select which libraries you need.
In case you ever work on a system, where OpenSSL and Boost are not installed in /usr/, you can already use target_include_directories to specify where the headers for your executable is found. Like target_link_libraries, target_include_directories can work with transitive dependencies, in this case PRIVATE.
cmake_minimum_required(VERSION 3.1)
project(motion_simulation)
set(CMAKE_CXX_STANDARD 11)
find_package(Boost REQUIRED COMPONENTS filesystem system)
find_package(OpenSSL REQUIRED)
set(SOURCE_FILES main.cpp)
add_executable(motion_simulation ${SOURCE_FILES})
target_include_directories(motion_simulation PRIVATE ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR})
target_link_libraries( motion_simulation PRIVATE ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES})