Cmake CPM link with GameNetworkingSockets - c++

I am trying to link Valves GameNetworkingSockets with my c++ cmake project, and am having errors (first failed to compile due to missing defines when I was able to include the headers, later errors were due to unrecognized targets...). I am using the CPM module for package installing. Below is my cmake:
# Basic settings
cmake_minimum_required (VERSION 3.14)
project (Valhalla)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(get_cpm)
if (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Release)
endif()
############
# LIBRARIES
############
CPMAddPackage(
NAME gamenetworkingsockets
GITHUB_REPOSITORY ValveSoftware/GameNetworkingSockets
#VERSION 3.11.3
GIT_TAG v1.4.1
DOWNLOAD_ONLY TRUE
OPTIONS
CONFIG REQUIRED
"USE_STEAMWEBRTC ON"
"Protobuf_USE_STATIC_LIBS ON"
)
##add_library(lua STATIC ${Lua_sources})
#add_library(steamnet STATIC ${gamenetworkingsockets_sources})
add_library(gamenetworkingsockets INTERFACE)
target_compile_definitions(gamenetworkingsockets INTERFACE STEAMNETWORKINGSOCKETS_STATIC_LINK)
target_include_directories(gamenetworkingsockets SYSTEM INTERFACE ${gamenetworkingsockets_SOURCE_DIR}/include)
#target_include_directories(gamenetworkingsockets PUBLIC ${gamenetworkingsockets_SOURCE_DIR}/include)
#target_include_directories(gamenetworkingsockets PUBLIC ${gamenetworkingsockets_BINARY_DIR})
#target_compile_definitions(gamenetworkingsockets PUBLIC STEAMNETWORKINGSOCKETS_STATIC_LINK)
#target_include_directories(gamenetworkingsockets SYSTEM INTERFACE ${gamenetworkingsockets_SOURCE_DIR}/include)
#target_include_directories(gamenetworkingsockets SYSTEM INTERFACE ${gamenetworkingsockets_BINARY_DIR}/include)
#target_include_directories(gamenetworkingsockets PRIVATE ${gamenetworkingsockets_INCLUDE_DIR})
#
# Linking
#
add_executable(Valhalla
"src/Main.cpp"
)
target_include_directories(Valhalla PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_features(Valhalla PRIVATE cxx_std_20)
target_link_libraries(Valhalla
#gamenetworkingsockets
#GameNetworkingSockets::shared
#steamnet::steamnet_s
#GameNetworkingSockets::GameNetworkingSockets_s
#GameNetworkingSockets::static
#GameNetworkingSockets::GameNetworkingSockets_s
)
set_target_properties(Valhalla PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/run/
CXX_EXTENSIONS OFF
CXX_STANDARD_REQUIRED ON
)
if (MSVC)
target_compile_options(Valhalla PRIVATE /bigobj "/diagnostics:caret")
endif()
if(MSVC AND CMAKE_BUILD_TYPE MATCHES Release)
set_target_properties(Valhalla PROPERTIES WIN32_EXECUTABLE ON)
endif()
The Cmake above has been stripped to a mostly minimal portion for reproducibility. As you can see, there are many commented-out commands as I have tried to brute force ways of making this work to no avail. I found this Linking with GameNetworkingSockets library on Windows gives "unresolved external" error which doesn't help.
#include <steam/steamnetworkingsockets.h>
int main(int argc, char **argv) {
SteamNetworkingIdentity identity;
identity.ParseString("str:peer-server");
return 0;
}
I have no clue how to interface vcpkg with Cmake from MSVC, and I really do not know how to fix this. Any clues as to how I can get everything to link and eventually compile correctly?

So I found out how to use vcpkg.
Install vcpkg
git clone https://github.com/microsoft/vcpkg
.\vcpkg\bootstrap-vcpkg.bat
Update it with
git pull
Make libraries installed with vcpkg recognizable by msvc
.\vcpkg\vcpkg integrate install
Install GameNetworkingSockets and required Protobuf with
.\vcpkg\vcpkg install GameNetworkingSockets --triplet=x64-windows
.\vcpkg\vcpkg install protobuf --triplet=x64-windows
cmakelists.txt in msvc
# Project
cmake_minimum_required (VERSION 3.14)
project (MyProject)
# Libraries
find_package(protobuf CONFIG REQUIRED)
find_package(GameNetworkingSockets CONFIG REQUIRED)
# Linking
add_executable(${PROJECT_NAME}
"src/Main.cpp"
)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
target_link_libraries(${PROJECT_NAME}
PRIVATE GameNetworkingSockets::static GameNetworkingSockets::GameNetworkingSockets
PRIVATE protobuf::libprotobuf
)
Try this simple script
// main.cpp
#include <steam/steamnetworkingsockets.h>
int main(void) {
SteamNetworkingIdentity identity;
identity.ParseString("str:peer-server");
return 0;
}
The above should compile fine if everything worked

Related

CMake Errors including IXWebSocket in Ubuntu 22 (works on MacOS 12.6)

Context:
I have a cpp program built on MacOS 12.6 with the following CMakeLists.txt file.
cmake_minimum_required(VERSION 3.19.0)
project(cpp-test VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(cpp-test main.cpp)
add_library(test-helpers main.cpp ${PROJECT_SOURCE_DIR}/helpers.hpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
# this is super important in order for cmake to include the vcpkg search/lib paths!
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
# find library and its headers
find_path(IXWEBSOCKET_INCLUDE_DIR ixwebsocket/IXWebSocket.h)
find_library(IXWEBSOCKET_LIBRARY ixwebsocket)
find_package(OpenSSL REQUIRED)
find_package(CURL REQUIRED)
# include headers
include_directories(${IXWEBSOCKET_INCLUDE_DIR} ${CURL_INCLUDE_DIR})
# Cmake will automatically fail the generation if the lib was not found, i.e is set to NOTFOUND
target_link_libraries(
${PROJECT_NAME} PRIVATE
${IXWEBSOCKET_LIBRARY}
OpenSSL::SSL
OpenSSL::Crypto
${CURL_LIBRARIES}
"-framework Foundation"
"-framework Security"
"-lz"
)
This compiles just fine. However, when I try to pull it into my Ubuntu VM and try to build it /build> cmake .., I get the following errors
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of "cpp-test":
"IXWEBSOCKET_INCLUDE_DIR-NOTFOUND"
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of
"test-helpers":
"IXWEBSOCKET_INCLUDE_DIR-NOTFOUND"
-- Generating done
What I have tried...
I have installed vcpkg and created my symlink ln -s /path/to/vcpkg /usr/local/bin/vcpkg.
I have installed ixwebsocket via vcpkg install ixwebsocket, but it seems that the CMAKE_TOOLCHAIN_FILE is not being parsed correctly.
I'm a bit lost, any help would be appreciated
This is not a great answer to the issue, but I ended up resolving it by building ixwebsocket via CMake instead.
It seems that vcpkg was not compatible with the linux distro in my VM.

Including a C++ library into another?

I'm trying to build a c++ library, which will be using itself another library.
I would like to output at the end a single .so file, so it is easily copied and used in any other project.
In this library I am using another library, GLFW.
Now, I can create my library fine, but when I am using it I am getting linking errors, where the GLFW functions are not defined. This makes me think that the GLFW lib is not exported with my library.
I've seen this that seemed to be a solution, but i gave me lot of duplicate symbol errors.
I'm quite a beginner with cmake, so maye there is something obvious I'm not seeing. Here is my CMakeLists.txt :
cmake_minimum_required(VERSION 3.22)
project(MyLib)
set(CMAKE_CXX_STANDARD 23)
# define folders path
get_filename_component(ROOT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
set(HEADER "${ROOT_DIR}/include")
set(SRCS_PATHS "${ROOT_DIR}/src")
set(TESTS_SRC "${ROOT_DIR}/tests")
# add dependencies
set(DEP_HEADERS "${ROOT_DIR}/dependencies/GLFW/include")
# set the project sources and headers files
include_directories(${HEADER})
include_directories(${DEP_HEADERS})
set(SRCS [...])
add_library(MyLib SHARED ${SRCS})
# set the project property linker language
set_target_properties(MyLib PROPERTIES LINKER_LANGUAGE CXX)
# target tests
add_executable(window ${TESTS_SRC}/window.cpp)
target_link_libraries(window MyLib)
I've seen I'm not the only one with this issue, but most of the answers I've tried won't work and lead to the same problem.
From what I can deduce from your CMakeLists.txt, you should do something like this (I don't like vendoring, not an expert of this approach, so maybe there is something more elegant):
cmake_minimum_required(VERSION 3.20)
project(MyLib)
# glfw static PIC
set(CMAKE_POSITION_INDEPENDENT_CODE_SAVED ${CMAKE_POSITION_INDEPENDENT_CODE})
set(BUILD_SHARED_LIBS_SAVED ${BUILD_SHARED_LIBS})
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(dependencies/GLFW EXCLUDE_FROM_ALL)
set(CMAKE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE_SAVED})
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVED})
# MyLib
add_library(MyLib SHARED [...])
target_include_directories(MyLib PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
target_link_libraries(MyLib PRIVATE glfw)
target_compile_features(MyLib PUBLIC cxx_std_23)
# Tests
add_executable(window tests/window.cpp)
target_link_libraries(window PRIVATE MyLib)
target_compile_features(MyLib PRIVATE cxx_std_23)
But honestly it's bad to hardcode all these informations in a CMakeLists, you should have a generic CMakeLists and avoid vendoring:
cmake_minimum_required(VERSION 3.20)
project(MyLib)
# MyLib
find_package(glfw3 REQUIRED)
add_library(MyLib [...])
target_include_directories(MyLib PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
target_link_libraries(MyLib PRIVATE glfw)
target_compile_features(MyLib PUBLIC cxx_std_23)
# Tests
add_executable(window tests/window.cpp)
target_link_libraries(window PRIVATE MyLib)
target_compile_features(MyLib PRIVATE cxx_std_23)
And then you would decide at build time how to build each lib:
// build & install glfw once, as static PIC (glfw is not vendored in MyLib source code here)
cd <glfw_source_dir>
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=<glfw_install_dir>
cmake --build build
cmake --build build --target install
// build MyLib as shared
cd <mylib_source_dir>
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_PREFIX_PATH=<glfw_install_dir>
cmake --build build

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!

CMake user built libraries; cannot specify link libraries for target

I'm building a project in Cpp that will communicate with my Java apps via rabbitmq and post updates to twitter. I'm using a few libraries from github
rabbitmq-c
Rabbit installed to /usr/local/lib64
jansson - json library
I installed this a while back for another project, went to /usr/local/lib
twitcurl - C lib for Twitter API
Got installed to /usr/local/lib
If it matters, I'm using CLion as my IDE, which displays jansson and rabbit under auto-complete when defining includes - so that's picking the libs off my system somehow
e.g.
#include <jansson.h>
#include <amqp.h>
I link them using the target_link_libraries(name libs...) and I see output saying
build$ cmake ..
CMake Error at CMakeLists.txt:30 (target_link_libraries):
Cannot specify link libraries for target "twitcurl" which is not built by
this project.
I set LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
I try to set the CMAKE_LIBRARY_PATH to include usr/local/lib and lib64 but doesn't seem to have any effect. Here's my CMakeLists.txt file
#
# This is a CMake makefile. You can find the cmake utility and
# information about it at http://www.cmake.org
#
cmake_minimum_required(VERSION 2.6)
set(PROJECT_NAME twitterUpdater)
set(SOURCE_FILES main.cpp)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "/usr/local/lib"
"/usr/local/lib64")
project(${PROJECT_NAME})
find_package(X11 REQUIRED)
find_package(OpenCV REQUIRED)
IF (X11_FOUND)
INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR})
LINK_LIBRARIES(${X11_LIBRARIES})
ENDIF ( X11_FOUND )
IF (OpenCV_FOUND)
include_directories(${OpenCV_INCLUDE_DIRS})
link_libraries(${OpenCV_LIBS})
ENDIF(OpenCV_FOUND)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${project_name} twitcurl jansson rabbitmq)
What's confusing me is another project I have uses jansson by simply adding it here TARGET_LINK_LIBRARIES(${project_name} dlib jansson)
What did I miss?? Thanks
CMake variables are case sensitive, thus the variable ${project_name} results in an empty string. Use ${PROJECT_NAME} instead, i.e.:
target_link_libraries(${PROJECT_NAME} twitcurl jansson rabbitmq)
Running CMake with the flag --warn-uninitialized helps you detect mistakes like this.

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)