Linking SFML static libs to project - c++

Good morning! I'm moving from shared SFML libs to static. But I have a lot of errors: g++ couldn't find some libs. I used this tutorial :https://github.com/SFML/SFML/wiki/Tutorial%3A-Build-your-SFML-project-with-CMake . My CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(LastFail)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/libs/)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/libs/)
set(CMAKE_C_COMPILER_INIT g++)
add_definitions(-std=c++1y -w)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2 REQUIRED system window graphics network audio)
include_directories(
include/
libs/include/
)
file(GLOB SRC
"src/*/*.cpp"
"src/*.cpp"
)
add_executable(LastFail ${SRC})
target_link_libraries(LastFail
${CMAKE_SOURCE_DIR}/libs/libjsoncpp.a
${CMAKE_SOURCE_DIR}/libs/libsfml-audio-s.a
${CMAKE_SOURCE_DIR}/libs/libsfml-graphics-s.a
${CMAKE_SOURCE_DIR}/libs/libsfml-network-s.a
${CMAKE_SOURCE_DIR}/libs/libsfml-system-s.a
${CMAKE_SOURCE_DIR}/libs/libsfml-window-s.a
)
set_target_properties(LastFail PROPERTIES
OUTPUT_NAME "LastFail"
CLEAN_DIRECT_OUTPUT 1
)
Small part of my errors:
JoystickImpl.cpp:(.text+0x1166): undefined reference to 'udev_device_get_syspath'
libs/libsfml-window-s.a(JoystickImpl.cpp.o): In function 'sf::priv::JoystickImpl::open(unsigned int)':
JoystickImpl.cpp:(.text+0x19ed): undefined reference to 'udev_device_new_from_syspath'
How do I fix that? I need to do that cross-platform way. Thanks!
Edit:
Of course, I have a directory called libs with all needed libraries.

First, packaging all dependencies with the project itself is generally a bad idea, but for game-like applications there could be exceptions.
In your case, the problem is not within packaged SFML, but libudev library. This library is
Linux-specific (not cross-platform)
Can't be linked statically (well, it probably could, but i bet it is a very bad idea, because library you linked in could be different version that udev daemon running on the host machine)
So, you need to add udev to your target_link_libraries() anyway.

Related

How to build static library with bundled dependencies - CMake

I am currently using CMake to create a static library which utilizes a few of the static libraries from OpenCV 4 ( core imgcodecs video highgui imgproc ). My intention is to be able to bundle all of the required OpenCV static libraries into my own library so that I can distribute it as one library. Additionally, I want for the user of my library to not have to install OpenCV 4 on their system (but do not mind if the user has to do simple installs using apt-get install). I know there are tools for bundling static libraries (such as using ar for linux).
However, where I really am having the issue is with all the dependencies of OpenCV (such as libjpeg, libpng, etc). I don't necessarily mind if these libraries are bundled with mine or linked dynamically as they are relatively easy to install (can be installed with sudo apt-get install, whereas opencv4 needs to be built from source).
What is the best way to go about doing this?
This is my current CMakeLists.txt
It is currently working, but that is because I am using find_package(OpenCV REQUIRED) (which defeats the purpose of what I am trying to do). When I remove that line, the linker complains about not being able to find the OpenCV dependencies.
cmake_minimum_required(VERSION 2.8)
project(myproject)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
list(APPEND LINKER_LIBS opencv_core opencv_highgui opencv_video opencv_imgcodecs libmxnet.so libncnn.a nlohmann_json::nlohmann_json)
file(GLOB SRC${CMAKE_CURRENT_LIST_DIR}/src/*.cpp${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_library(myproject ${SRC})
target_link_libraries(myproject ${LINKER_LIBS} ${OpenMP_CXX_FLAGS})
To elaborate on my question. I build my project which generates libmyproject.a. I then take this library and will eventually extract the symbols from the OpenCV libs (libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a) and add them to my lib (for the time being, I have not yet done this step, which is why in the below example I am linking libopencv_*). I then use my library in a new project, for which the CMakeLists.txt is shown below:
cmake_minimum_required(VERSION 2.8)
project(myproject-driver)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)
add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver myproject libncnn.a ${OpenMP_CXX_FLAGS} libmxnet.so libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a)
Building this generates the following errors:
Linking CXX executable myproject-driver
/usr/bin/ld: /home/nchafni/Cyrus/myproject/lib/libopencv_imgcodecs.a(grfmt_jpeg.cpp.o): undefined reference to symbol 'jpeg_default_qtables##LIBJPEG_8.0'
//usr/lib/x86_64-linux-gnu/libjpeg.so.8: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
How can I fix this. Is there some CMake command which will link all these dependencies for me? Do I need to manually track down each dependency of those libopencv_* libs and link those manually? Once again, this is assuming that the person using libmyproject.a can't use find_package(OpenCV REQUIRED) as it won't be defined as they have not installed OpenCV on their machine.
First of all, don't use the super old and outdated version 2.8 of CMake. CMake 3.x is so much more powerful and pretty straightforward to use.
Some tips for modern CMake.
Don't use file(GLOB), see here why that is.
Don't use directory wide instructions, rather use target instructions, e.g. target_include_directories vs. include_directories.
Don't use string variables like ${<PACKAGE_NAME>_LIBRARIES}, rather use targets, e.g. <Package_NAME>::lib
When using targets instead of string variables, all the properties (including LINK_INTERFACE) of that target will be populated to the library/executable when calling target_link_libraries, so no more include_directories,link_directories, etc.
myproject
cmake_minimum_required(VERSION 3.14)
project(myproject)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
set(SOURCES ...) # list all the source files here
add_library(myproject ${SOURCES})
target_include_directories(myproject PUBLIC # give it a scope
${CMAKE_CURRENT_LIST_DIR}/include
)
target_link_libraries(myproject PUBLIC # give it a scope
opencv_core # using the target, you will get all LINK_LIBRARIES
opencv_highgui
opencv_video
opencv_imgcodecs
libmxnet.so # where is this coming from?
libncnn.a # where is this coming from?
nlohmann_json::nlohmann_json
OpenMP::OpenMP_CXX ## linking against a target, CXX_FLAGS will be populated automatically
)
myprojec-driver
cmake_minimum_required(VERSION 3.14)
project(myproject-driver)
set(CMAKE_CXX_STANDARD 14)
add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver PUBLIC # give it a scope
myproject # gets all dependencies through the LINK_INTERFACE
)

CMake shared library in subdirectory

My problem is relatively simple to explain. I have a CMake project(using CLion) running mainly on Windows.
A main CMakeLists.txt project, linking 2 subdirectories
src/Library shared library
src/Executable executable linking Library
See the project structure below.
# main CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(TestTest)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(src/Library)
add_subdirectory(src/Executable)
# src/Library/CMakeLists.txt
add_subdirectory(include)
add_subdirectory(src)
add_library(TestLib SHARED ${TESTLIB_H_FILES} ${TESTLIB_SRC_FILES} )
target_include_directories(TestLib PUBLIC include)
#src/Executable/CMakeLists.txt
add_subdirectory(src)
add_executable(Executable ${EXECUTABLE_SRC_FILES})
target_link_libraries(Executable PUBLIC TestLib)
My problem is that the executable can't find the shared library at runtime.
I tried to add link_directories( ${CMAKE_CURRENT_BINARY_DIR}/src/Library) but didn't work.
What am I missing?
Please note: I wouldn't like to copy the shared library next to the executable manually/automatically by CMake, since I believe I would loose the debugging "capability" of the shared library. I will be getting the following error message by the GDB: No source file named C:/Users/flatron/CLionProjects/TestTest/src/Library/src/libr‌​ary.cpp.
All suggestions are really welcome and appreciated,
Thank you for your help
I suggest to use the following cmake command:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
This will build all executables and shared libraries into the bin folder.
So there is no need to copy anything by hand.

Unable to link an executable to shared library

I have a cmake project where I am trying to link the executable to the shared library. But it is not getting linked. After searching enough and not finding any useful solutions, I'm posting my question here, please let me know if there are any obvious mistakes as I am not familiar with cmake
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
# Set Project Name
set(PROJECT_NAME myproj)
project(${PROJECT_NAME})
# Tell Cmake to invoke gcc with specific flags. Use c++11 standard.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# Include all headers
include_directories(${PROJECT_SOURCE_DIR}/../public/include)
# Driver Program
file(GLOB_RECURSE SOURCE_FILES
"${PROJECT_SOURCE_DIR}/src/*.cpp"
)
# Dont know what to do about this
#set( CMAKE_SKIP_BUILD_RPATH true)
link_directories(${CMAKE_SOURCE_DIR}/../relative/path/to/sharedlib) #contains libshared.so
# Generate Executable, trying to generate shared library to see if it generates # correct dependencies
# add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
#Link the libraries
target_link_libraries(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/../relative/path/to/sharedlib/libshared.so)
Here is the steps I have tried and some observations.
If I generate a shared library instead of an executable, it is able to find the dependent shared library(i.e libshared.so)
ldd myproj.so
libshared.so => full/path/to/sharedlib/libshared.so (0x00007fa26c263000)
I did not fully understand what it meant, but it is able to find the shared library is what I guessed.
If I try to generate an executable instead of shared library, I see undefined reference errors to the functions within the library.
I tried just target_link_libraries(${PROJECT_NAME} shared) as well and it gave same error.
Any clues as to how can I get the shared library linked to my executable? Thanks

Static linking using cmake

I tried to static linking libstdc++-6 and libgcc_s_seh-1.I'm using Clion who use cmake. I'm using SFML but it's not necessary that it's dynamically linked.
Thanks
cmake_minimum_required(VERSION 2.8.4)
project(Game_Project)
set(EXECUTABLE_NAME "Game_Project")
# Enable debug symbols by default
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows")
endif()
# (you can also set it on the command line: -D CMAKE_BUILD_TYPE=Release)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s")
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/SFML-2.2/cmake/Modules/" ${CMAKE_MODULE_PATH})
set(CMAKE_SOURCE_DIR src)
file(GLOB_RECURSE SRCS src/*.cpp)
#Find any version 2.X of SFML
#See the FindSFML.cmake file for additional details and instructions
set(SFML_ROOT "SFML-2.2")
find_package(SFML 2 REQUIRED system window graphics network audio)
include_directories(${CMAKE_SOURCE_DIR} include)
add_executable(${EXECUTABLE_NAME} ${SRCS})
if(SFML_FOUND)
include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
target_link_libraries(${EXECUTABLE_NAME} ${SFML_DEPENDENCIES})
endif()
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)
If you link dynamically against SFML, which in turn links dynamically against libstdc++, your application will still require the so/dll files for libstdc++ because of SFML.
Think of the SFML.dll as a separate executable. That executable has a dynamic runtime dependency on libstdc++. You cannot get rid of that, because SFML has already been linked and there is no way to have it point to the part of libstdc++ that is statically linked to your executable instead.
The only way to get rid of the dependency is to make sure that all components link statically against the library in their linking phase.
The important thing to note here is that static libraries are of no concern for this. Static libraries never pass through the linker (think of them as a bunch of packed together object files), so it is the top-level executable or dynamic library pulling them in that determines how they link against the standard library.
So if you were to build SFML as a static library instead that is then pulled in by your executable, which is configured to statically link against libstdc++, the problem would disappear as well.

How to compile QtGui example with OpenGL/Angle in CMake?

I am trying to take the Qt example from the Qt-distribution in examples/gui/openglwindow/ and make it compile/run with CMake on Windows. However, when compiling, it fails with a bunch of
“error LNK2019: unresolved external symbol __imp_glClear”
I can fix that by manually adding C:\Qt_install\lib\libGLESv2d.lib to the linker path, however, that’s obviously not how CMake should work.
My CMakeLists is very simple:
PROJECT( oglwin )
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 )
cmake_policy(SET CMP0020 NEW) # for Qt: auto-link to qtmain.lib
set(CMAKE_AUTOMOC ON)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
SET(SOURCE
main.cpp
openglwindow.cpp
)
SET(HEADERS
openglwindow.h
)
ADD_EXECUTABLE( oglwin ${SOURCE} ${HEADERS} )
TARGET_LINK_LIBRARIES( oglwin Qt5::Core Qt5::Gui )
Now as I mentioned before, my expectation would be that this automatically links to libGLESv2.lib (or libGLESv2d.lib), as I am using a Qt-build built with ANGLE.
(For that matter, I guess when on the desktop/opengl build, it should link to GL.lib [or whatever the system openGL lib is called]).
Possibly in my case, it should also link to C:\Qt_install\lib\libEGLd.lib.
There are a few related topics around, for example this:
https://bugreports.qt-project.org/browse/QTBUG-29132
(where it says “fixed”), and one can follow that to gitorious:
https://codereview.qt-project.org/#change,53857
So basically what should happen is that QtGui automatically links to its correct OpenGL back-end, whatever that may be (desktop OpenGL, Angle/GLESv2), it says in the bugreport there that it's able to deduce which back-end to use from the installed Qt distribution.
Apparently what I’m trying to do should work, but it doesn’t. Am I doing something wrong?
The solution was as follows:
It was coupled with a Qt bug that is now fixed, but it was also necessary to add ${Qt5Gui_EGL_LIBRARIES} and ${Qt5Gui_OPENGL_LIBRARIES} to target_link_libraries.
That makes Qt find the correct OpenGL dependency.