Adding include paths and lib files in CMake - c++

Recently, I have begun wanting to learn OpenGl, and in the tutorial they are using a static GLFW library to make the code concise and cross platform, but I use VS code, and they use Visual Studio. I use CMake to link my libraries so how would I do that with a lib file and the .h files respectively?
I thought you could achieve this as so
cmake_minimum_required(VERSION 3.0.0)
project(openGL VERSION 1.0.0)
include_directories(${workspaceFolder}dev\dependencies\GLFW\include)
link_directories(${workspaceFolder}dev\dependencies\GLFW\lib-vc2019)
add_executable(main main.cpp)
target_link_libraries(${workspaceFolder}dev\dependencies\GLFW\include)
but this does not seem to work
If anyone knows how I could complete this, please show me. I have respect for all of you. I am quite a young programmer, but I want to be able to do big things, and I would like to start by working on nice graphical interfaces.

Related

Setting up 3rd party libraries environment for CMake on Windows 10

I'm having problems with the "proper" way of installation third-party libraries for use with CMake projects (C++). For most of the time I haven't been bothering myself with this stuff and just hardcoding library paths in my CMakeLists.txt, but I really want to start using this properly.
I ultimately want to have something where I can just type, for example, find_package(SDL2 REQUIRED) in a project and the library is there, found, and works perfectly.
What I have right now is I have a folder C:\CMakeLibs where I --install all 3rd party libraries, so for example there is C:\CMakeLibs\SDL2 and in it, there are folders like cmake, include, lib, etc. Then I include the folder C:\CMakeLibs\SDL2 in CMAKE_PREFIX_PATH in system environment variables, so that CMake can find the SDL2Config.cmake file and there's no need for any FindSDL2.cmake. This way I can just type following code and it straight works, and is also probably the most portable for open-source projects.
find_package(SDL2 REQUIRED)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE SDL2::SDL2main SDL2::SDL2-static)
My only concern here is that I have to manually add any new libraries to CMAKE_PREFIX_PATH. I'd like just have only C:\CMakeLibs as my CMAKE_PREFIX_PATH and everything working fine. I could technically --install the libraries directly to C:\CMakeLibs but I fear of any possible incompatibilities when having all the different files in one shared folders, it doesn't feel like the best solutions.
I know this question might be one of those "without the best answers/based on opinion". I've been looking for solutions on internet for long time already, ever since I started using CMake, so I decided to just write this post here. I hope I described my problem clearly, English isn't my native language.

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.

Boost Installation in CLion

I am a complete beginner in C++ programming and have been advised to use CLion. I am trying to get the Boost package to work.
I found many posts and tutorials online, however they all skip the basics not known to someone who is not a programmer. Namely, there is no explanation of how to get from the moment you open a new project to using some function from the Boost package?
This is what I found to be lacking from previous answers:
Here we are advised to use live incboost live template, however there is no explanation on where to find it or how to use it.
Here seems like a clear tutorial, however it is aimed at Visual Studio, not CLion.
Here I am not sure what each of those files are and how to adjust them to match my case.
I have downloaded boost_1_70_0 from https://www.boost.org/users/download/ and it is now unzipped and saved in C:\...\boost_1_70_0.
Could someone please explain really simply how to get from a blank project to being able to use functions stored in boost?
Considering you are using CLion and it supports only CMake at this time and you have installed BOOST library in the default directory, then your CMakeLists.txt file should look like this. I have used it in linux operating system but it should be able in Windows too.
cmake_minimum_required(VERSION 3.13)
project(LaserCV)
set(CMAKE_CXX_STANDARD 17)
#local
file(GLOB SOURCES
*.hpp
*.cpp
)
add_executable(LaserCV ${SOURCE_FILES} ${SOURCES})
#add_executable(LaserCV main.cpp)
SET(CMAKE_CXX_FLAGS -pthread)
#boost
find_package(Boost REQUIRED)
target_link_libraries(LaserCV ${Boost_LIBRARIES})
include_directories(${Boost_INCLUDE_DIR})
Then simply include a header file for your wanted boost function, for example:
#include <boost/random.hpp>

How to improve my script and copy program resources on build?

So I got into a problem where I needed to use linux for a while instead of windows, and figured linux doesn't have Visual Studio. I then also realized that I made my project Visual Studio only, which I don't want.
So I looked up some CMake tutorials and try'ed creating some examples that could be loaded in both Visual Studio and CodeBlocks. When I got that to work, I went and code a CMake script for my actual program by piecing together what I learned and what I found in tutorials.
See here:
cmake_minimum_required(VERSION 2.8.9)
add_subdirectory(libraries/glfw)
project (OpenGLEngine3D)
include_directories(libraries/glfw/include)
include_directories(libraries/glm)
include_directories(libraries/glad/include)
include_directories(libraries/whereami/src)
include_directories(libraries/stb)
file(GLOB SOURCES "src/*.cpp" "src/*.h" "libraries/whereami/src/whereami.c" "libraries/glad/src/glad.c")
add_executable(OpenGLEngine3D ${SOURCES})
target_link_libraries(OpenGLEngine3D glfw)
Its dirty(I think) but it works.
So now my first question is, how to improve my CMake script? What is redundant or done in a poor way?
Now my program also requires some resources(like shaders, textures) which I have stored in a directory along with my CMake script, libraries and c++ files.
So my second question is, how would I tell CMake to the ide/compiler to copy the files in a certain directory to the program build directory(where the compiled binaries are) after compiling?(And have it only do it when the files aren't there ofc.)
Thanks!
I recently came across this article, which might be help you with CMake.
Here are a couple suggestions from me:
You're safe to use newer version of CMake. Currently, it's 3.11. There's no point in sticking to old versions.
Consider listing all your sources in a variable (using set command) instead of using file(GLOB). file(GLOB) will be evaluated only once, when generating build files. If you add new sources, you'll have to re-generate it manually, so it doesn't help too much, and is harder to debug (and really, debugging more complex CMake projects can be painful).
Avoid using include_directories (and link_libraries). Prefer using target_include_directories which works per-target. It allows to express dependencies between targets (when you have more than one - which might happen as your project grows)
You might consider using find_package(GLFW), instead of including GLFW in your project. Edit: actually, CMake doesn't came with find module for GLFW, but you can use an external module for this (e. g. this one) as described here.
Edit:
Example below illustrates the idea behind point 2), assuming that sources are placed in "src/" directory on the same level as CMakeLists.txt file:
set(engine_sources
"src/header_1.hpp"
"src/source_1.cpp"
# and so on for reset of files...
)
add_executable(OpenGLEngine3D ${engine_sources})
As for the second question: that's what file(COPY) command is for. Alternatively, you could just leave assets in source directory, and set working directory in IDE.
Side note: if you choose the second options, there appears to be a way to set this from CMake for Visual Studio, by setting VS_DEBUGGER_WORKING_DIRECTORY property:
set_target_properties(OpenGLEngine3D PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
(I haven't checked if this works as expected, as I rarely use VS. I remember looking for something like that in the past, and just recently came across it.)

Convert from Xcode to CMake

I have a C++ project that I initially developed using Xcode on my Mac and I would like to set up the very same project using CMake. The project makes use of some external libraries, including eigen and boost. Xcode has a rather long list of Build Settings, including paths to external libraries, specification of the compiler version, additional linker flags, compiler optimization level, etc... and I am wondering where all of this information goes in the CMakeLists.txt file. I've searched extensively for help on this but have found precious little. I am new to CMake and have never written make files before. If there were a utility that could convert my Xcode project into a CMake project, that would be ideal. But I would be very glad to know of a tutorial on this, or to have some specific guidance. Any help on this would be greatly appreciated.
Conversion Strategy
I am pretty sure that the easiest and fastest way to move to CMake is a mixture of looking at comparable projects that link the same dependencies, and maybe copying a few relative file paths to your source files from XCode.
A well-written CMakeLists.txt that uses Eigen and Boost can be very small (and platform-independent).
One reason for this is CMake has a very different way to use dependencies.
For well-known libraries such as Boost, CMake includes scripts to include headers and link libraries.
Minimal CMakeLists.txt
A minimal example may look like this:
find_package(Eigen3 REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
add_executable(
app
src/main.cpp
)
target_include_directories(
app
${Eigen3_INCLUDE_DIRS}
${Boost_INCLUDE_DIR}
)
target_link_libraries(
app
${Boost_LIBRARIES}
)
Example Projects
For Eigen, there is no such pre-installed script that can be called by find_package.
Here are two real-world example projects that link Eigen and Boost: https://github.com/ompl/ompl/blob/master/CMakeLists.txt
https://github.com/roboticslibrary/rl
Here is an example for a find script for Eigen.
As a piece of advice, some CMake projects are out there are convoluted and use old syntax, newer project files tend to use small letters in commands.
If it happens that directly target linking libraries doesn't work, you'll have to write your own Find*.cmake files by yourself.
Here's a spec of what you should cover to make it (this is just one approach):
Imagine you have a library XYZ:
Your file
FindXYZ.cmake should have as a result a set of variables to use:
XYZ_LIBRARIES
XYZ_INCLUDE_DIR
For example:
set(XYZ_LIBRARIES ${SOME_PATH_TO_LIBRARY1} ${SOME_PATH_TO_LIBRARY2})
find_path(XYZ_INCLUDE_DIR NAMES xyz/xyz.h HINTS ${PLACE_WHERE_INCLUDE_SHOULD_BE}
PATH_SUFFIXES include
)
From your main cmake maybe you 'use' it:
find_package(XYZ REQUIRED)
# Now we use both _INCLUDE_DIR and _LIBRARIES
include_directories(SYSTEM "${XYZ_INCLUDE_DIR}")
# TARGET_NAME is the current target, the 'client' of XYZ
# append XYZ to our list of libraries to link
target_link_libraries(${TARGET_NAME} ${XYZ_LIBRARIES})
I'm surely missing details but that's the general idea. Here are some cmake scripts that I know work in a big project:
Example with OpenSSL
Find:
https://github.com/highfidelity/hifi/blob/Android/cmake/modules/FindOpenSSL.cmake
Client (in this case is a library that indeed needs OpenSSL):
https://github.com/highfidelity/hifi/blob/Android/domain-server/CMakeLists.txt