creating a static library and linking using Cmake - c++

I have a application which need to use two libraries (pugixml and lua) and need to be an multi-platform build capable. I am trying to use Cmake for this. Since I have three different solution (two for creating static libraries and one solution which actually uses that libraries). So far what I do is run Cmake for those two libraries and copy those static libraries manually to the lib folder into application and run cmake again.
I need to reduce the three step and make it as a single step so that I can handle the multi-platform build in a single shot.
I need to know, should we need to create a dynamic link library or shared library or static library for these kind of operation?
And need help on how to do it. I tried creating the source folder of pugixml and copy the cpp/hpp/h file and wrote a cmakelists file like
set(HEADERS pugixml.hpp pugiconfig.hpp)
set(SOURCES ${HEADERS} pugixml.cpp)
add_library(pugixmlLib STATIC ${SOURCES})
target_link_libraries(pugixmlLib pugixml)
On the solution I could see my application project and pugixml project, but on my application project linker property I could find pugixml library.

Related

How to make a lib before making the program in CMAKE?

I would like to be able to dynamically compile a library that will be used by my project before compiling my project.
I am setting up a Vulkan project in C++ (with Clion) and would like it to be multi-platforms, I am using GLFW3.3 to make that happen.
Instead of building my library for each platform and putting the libs and .h in a folder that will be linked through the CMakeLists.txt, I would like to be able to CMAKE+make the library, then put the lib and .h where they need to be and then start compiling my program that will be using those.
GLFW has a working CMakeLists.txt (I manage to make it manually through the console) but I don't know how to tell CMAKE to make it etc.
I am used to using CMake to define path to libs and includes but my last project what also multi-platforms and I didn't like the way I handled the library (build manually etc).
So I am looking for a way in CMake to do everything at once even if it will take time to do so but I have no idea how that works.
Take a look at how Glitter does it:
option(GLFW_BUILD_DOCS OFF)
option(GLFW_BUILD_EXAMPLES OFF)
option(GLFW_BUILD_TESTS OFF)
add_subdirectory(Glitter/Vendor/glfw)
target_link_libraries(${PROJECT_NAME} ... glfw)
They just include the CMakeLists.txt file that GLFW provides and depend on it for the main target.

cmake use library target in added executable

I have started a new c++ project which has several executables and a relatively large amount of shared code.
root
CMakeLists.txt
Common
Application1
Application2
....
So the multiple applications all get compiled with their unittests without issues. But since they depend on the shared code in Common I have the recompile the shared code for each project once I update something there.
So I am wondering if it would be possible to add the library target. And build that first. And then I link my code to that library.
This seems like a relatively normal thing to do but I can't find anything about it on google.
Any help is appreciated.
Yes this is possible.
You have to add a CMakeLists file to the Common folder and in it you compile it as a library
# Add required source files.
add_library(Common ...)
# Include required header files. They must be public to be recognized where they are needed.
target_include_directories(Common PUBLIC ...)
Then in the project's CMakeLists you use:
add_subdirectory(Common) // Will call the other CMakelists
...
# Link to the required libraries.
target_link_libraries(Application Common)

decoupling app and libraries in CMake project

I had a project that was configured to be:
CMake Project
static Lib A src (depends on B)
static Lib B src (depends on Qt)
App src (statically links with LibA)
Each of these folders had its own CMakeLists.txt but all were part of the same CMake project. Things were working fine.
Then for the purpose of more easily separating the library source and the app source into different source code repositories, I started to learn about the creation of CMake packages and performing find_package on LibA. I rearranged things so that now the libraries are their own CMake project, which requires I run "cmake --build . --target install" to put the packages in a common area (not in the build folder).
The app similarly became its own CMake package, and I thought I would only need to find_package(LibA). It turned out I also needed to find_package on LibB because there was one header that the App needed. But the unexpected part is that the App needed to find_package on Qt5Widgets, Qt5Core, and Qt5Gui just as LibB did. That's the part that I don't quite understand. When everything was one giant project, the App's CMakeLists.txt only needed to link against LibA. Was all of the other stuff just taken care of without me knowing? Am I naive to think that performing find_package on LibA and LibB would somehow cause the Qt libs to be linked in to the App as well?
This might be a lousy question, because I have things working again. I just want to make sure I understand the why.
Using static libraries in C++ does not pull in their dependencies, so they have to be specified explicitly while linking the executable (as compared to dynamic ones).
A static library is essentially a pre-compiled archive of functions (an object file), which get linked into your applications by your C++ linker in a similar way as any other object file would. As such, it does not include information about its dependencies.
A shared (dynamic) library is a more complex (and generic) thing, allowing to load and link code run-time. This is done by a dynamic linker, which will also bring it any dependencies of the loaded library recursively.
For this reason, if you want to avoid specifying the dependencies explicitly, a dynamic library might be a better choice (it might be a better choice for a variety of other reasons as well :) ).

Create standalone executable with CMake

I need to build a standalone executable. The main problem is that this project relies on dll which I previously built on my system.
When I create the executable there should not be a dependence from these dll so I need to know if I can include them somehow in the program. To compile I'm currently using CMake which I believe is the best solution, but I haven't figured a way to accomplish this task yet.
Right now in my CMakeLists.txt file I do the following:
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(myexe myexe.cxx)
target_link_libraries(myexe
${ITK_LIBRARIES} )
I omitted some instructions to focus on what's most important. When I compile it, it correctly works but it is not standalone as it still keeps using the dll (also tried with .a) installed on my system.
Thanks
A DLL is by nature dynamically linked to at runtime. Your only option is to use a static library (.lib on windows .

Linking a static library to a shared library in cmake

I have been working on a fun project (a game engine) for awhile now and figured i could make it more portable and easy to compile across platforms if I use cmake. Right now i have it set up like so, with a main executable and then a bunch of shared libraries that the executable is linked to. I've found all the material needed to produce the libraries and the executable, and linking those to the executable, but what of linking a dependency like a static library or another shared library to one of the libraries i produce? Here is a visual
Sentiment (name of project)
-Root (all the interfaces and components of the engine. main.cpp is here
-Sentiment_OGL4Renderer (the files for the Renderer library)
-Sentiment_SFMLGui (the files for the Gui library)
-Sentiment_TestGame (the code for a game)
now i want all of these, the executable and the shared libraries built and put into the bin folder in the top level directory. What i found suggested online for a setup like this was to make cmakelists.txt files in each folder, and then one in the root, for each project. What i have thus far is this.
#Sentiment
cmake_minimum_required(VERSION 2.6)
project(Sentiment)
set(RENDERER Sentiment_OGL4Renderer)
set(GUI Sentiment_SFMLGui)
set(GAME Test_Game)
add_definitions(-DBUILD_DLL)
list( APPEND CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
set(EXECUTABLE_OUTPUT_PATH "${Sentiment_SOURCE_DIR}/bin")
set(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}")
link_directories("${LIBRARY_OUTPUT_PATH}")
add_subdirectory("${RENDERER}")
add_subdirectory("${GUI}")
add_subdirectory("${GAME}")
add_subdirectory(Root)
in root
project(Sentiment_exe)
link_directories("${Sentiment_SOURCE_DIR}/bin")
AUX_SOURCE_DIRECTORY(. new_source_list)
add_executable("${CMAKE_PROJECT_NAME}" ${new_source_list})
target_link_libraries("${CMAKE_PROJECT_NAME}" "${LIBRARY_OUTPUT_PATH}/${RENDERER}" "${LIBRARY_OUPUT_PATH}/${GUI}" "${LIBRARY_OUTPUT_PATH}/${GAME}" "${ADDITIONAL_DEPENDENCIES}")
in Sentiment_OGL4Renderer
project(Sentiment_OGL4-3Renderer)
include_directories(${Sentiment_SOURCE_DIR})
add_definitions(-DGLEW_STATIC)
add_library(Sentiment_OGL4-3Renderer SHARED Sentiment_OGL4Renderer.cpp GL/glew.cpp)
in Sentiment_SFMLGui
project(Sentiment_SFMLGui)
include_directories(${Sentiment_SOURCE_DIR})
add_library(Sentiment_SFMLGui SHARED Sentiment_SFMLGui.cpp)
in Sentiment_TestGame
project(Sentiment_Game)
include_directories(${Sentiment_SOURCE_DIR})
add_library(Sentiment_Game SHARED Game.cpp)
As you can tell there are a lot of third party libraries, and i tried various methods of linking, like with target_link_libraries, and i cannot for the life of me figure how to link an external library to the ones i've made. First off, the renderer uses GLEW but it needs no external dependency so ignore that. Then it needs OpenGL32.lib and Gdi32.lib from the windows sdk (only for windows). As for SFML, i've got the DLL's in the bin folder which need to be linked, (can easily get the .so's when working in linux and can distribute with the final product if I ever choose to do so). I need these all linked as dependencies to the libraries i create, but nothing seems to work. The project is all c++ and I am currently using mingw32 to compile it. I'm brand new to cmake so please be gentle if it is really simple.
To link external libraries, best practice is to use or create FindModule for given external library.
CMake comes with numerous modules that aid in finding various well-known libraries and packages.
The list of standard modules is in the official documentation
In case there is no standard module for your external library, you should write your own.
The OpenGL library has standard module FindOpenGL:
find_package (OpenGL)
if (OPENGL_FOUND)
include_directories(${OPENGL_INCLUDE_DIR})
target_link_libraries (Sentiment_OGL4-3Renderer ${OPENGL_gl_LIBRARY})
endif (OPENGL_FOUND)