clarify on CMAKE library installation - c++

The odd is that I can understand CMAKE documents, but I still can not figure out how to use it in a little more complicated scenario.
I want to install a SHARED LIB, to let someone else use it.
I know I can install it with CMAKE install command, but my first question is that my code still works without installing the library. The library is built and put under cmake_build_debug dir.
All I did is:
FILE(GLOB SHAREAD_SRC
${CMAKE_CURRENT_SOURCE_DIR}/Interface/*.cpp
)
set(MY_LIB mylib)
add_library(${MY_LIB} SHARED ${SHAREAD_SRC})
add_executable(run_src src/my_src.cpp ${HEADERS})
target_link_libraries(run_src ${MY_LIB})
I can now include the library's header in my source code and start to use it.
My question is,
in add library command, should I also include my library's header files? Currently i only include the source files to build the library, since whenever I use the library, I know where physically the library headers are(since i made this library), and for those others who also want to use this lib, i would provide them the header and the built lib target, so whereever they want to put them, no problem.
some answers talk about the install command saying that without the header files included in add_library, Why add header files into ADD_LIBRARY/ADD_EXECUTABLE command in CMake, otherwise you won't see headers in IDE-generated project. My headers are in this project, so I don't understand this issue. Why do I need to install this library? What is the purpose of install if the user downloaded my header file and have the built binary?
Thanks for helping! Appreciation in advance.

Except for the mentioned reason that specified files gonna be "visible" in IDE there is one more: explicit better than implicit (yeah Pythonish statement) -- meaning that you give a hint to the reader of your CMakeLists.txt of what exact files your library consists of. And yes, using GLOB for sources is the known bad practice for many reasons -- IRL it's not really hard to maintain the list of sources explicitly and makes your build system less error-prone. In some circumstances, you can gain some more benefits of having headers mentioned explicitly (e.g. using install(TARGET ... PUBLIC_HEADERS ...) but this is the other subject :)
You didn't specify your workflow (how do you build and distribute your project/library). However, the primary goal of install is to form the built image of your project -- i.e. what targets/files/directories gonna be installed and into what directory layout. It's needed to build other projects dependent on yours or produce packages (w/ CPack) to distribute or deploy 'em somewhere.
Also, to let others use your built library in CMake way please read how to make a package section in the manual. So, others can just do find_package(YourProject) and use it (link w/ it via target_link_libraries) -- easy peasy!

Related

How to use cmake to get rapidcheck (property based testing) working in C++?

I'd like to do some property-based testing in a C++ library I'm working on, and was thinking of going with RapidCheck unless somebody has a better idea. (I will need, for example, to generate arbitrary std::set<int>, and if I can place bounds on the range of int in the sets and the size of the sets, all the better.)
All this being said, I'm still a bit of a cmake newb. There appear to be no instructions in RapidCheck except to include it as part of the source code (although downloading it would be better). I have gotten to the point where I can include the headers for RapidCheck in my code, but when I try to build any app using RapidCheck, I'm told that there are symbols from RapidCheck missing or that the rapidcheck library is missing.
I'm assuming that I have to build RapidCheck itself as part of the project to generate the library, but I'm not entirely sure how to do this and it seems difficult to find any examples where this is done.
Does anyone have any suggestions of examples where such things are done so that I can see the string of commands necessary to build a 3rd party API and include the library when building the executables, or - even better - an example of a project using RapidCheck that does exactly this? The lack of documentation on how to set this up is discouraging.
I hope this is not overly vague. To summarize, what I'd like to do from cmake:
Preferably download RapidTest (although including the files directly from the RapidTest project would be fine as well).
Run the required commands and set up the necessary variables to have my test code (in ${PROJECT_SOURCE_DIR}/test) be able to access RapidTest headers.
Generate (if necessary) the RapidTest library and make it so that I can link it to the tests I'm running.
Thanks in advance for any help you might be able to offer!
This is probably not the right way to do this, but maybe it will help:
I was able to get this working by doing the following:
# from within the root of the rapidcheck repo:
$ cmake -DBUILD_SHARED_LIBS=true -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug .
# Leave off the BUILD_SHARED_LIBS flag if you don't need an SO.
$ make
That built: librapidcheck.so and librapidcheck.a, which you can then copy / install as needed.
You'll also need the include directory with the headers for rapidcheck, but that's just in the source tree.
Add the include path to your compile commands using whatever build tool you want, and link with the compiled libraries (the .so and .a)

How to 'install' and use in-house dependencies for other projects with CMake

clarification: If the below setup is a reasaonable way to do it, then my question is mainly, how do I best add the public headers with the .lib when I run ninja install as my solution does not do this currently.
There is a myriad of examples of how to do stuff in different ways, and many seem to contradict eachother to just confuse me even more.
I'm trying to change out a in-house build system and replace it with CMake. The codebase consists of many different components/libraries, like OS/Platform abstraction, networking, functionality etc. Before this was always compiled together as one big codebase, so running clean would remove everything and rebuild all dependencies.
Now it comes to the part where I have trouble understanding on how a modern smart way to do it in CMake is.
Ignoring the fact that a dependency-chain tool on top is needed, my idea was to build the components/libraries in order of libraries with no dependency to the topmost as isolated build runs.
Then each isolated build run would be built with its dependencies, like only the windows API for the OS abstraction library, and then run install and export on it.
Is this the general prefered way, to compile a library to a .lib on windows or .a on linux and export it to a known shared location?
Im guessing it would be required then to copy all public header files for this library to the same location? If so, how is this most correctly done?
If I have my OS abstraction folder structure
OSabstraction/
includes/
OSabstraction/
abstraction.h
src/
abstraction.cpp
CMakeLists.txt
and my CMakeLists is
cmake_minimum_required(VERSION 3.12)
project(OSabstraction LANGUAGES CXX)
add_library(abstraction)
target_sources(abstraction
PRIVATE
src/abstraction.cpp
)
target_include_directories(abstraction
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes/>
$<INSTALL_INTERFACE:include>
)
install(
TARGETS abstraction
EXPORT abstraction-export
ARCHIVE DESTINATION lib
)
How would I best go around to use this library in many other inhouse projects? This library is in practice many times larger, so what would be the correct way to do it for a large project?
edit: I tried to follow Pablo Arias' guide on how to do CMake Right, but I am not sure how the build_interface and install_interface generators work in regards to getting my header files with the export of the .lib file.
Recommended solution is to use a package manager together with CMake.
The link below is a full C++ project setup template which can use the package manager https://conan.io/ to support splitting up dependencies into individual libraries.
https://github.com/trondhe/cmake_template

Adding third-party libs to my CMake Project

I cant seem to wrap my head around a certain train of thoughts and was hoping you guys could help me seeing things more clearly. As I understand the find_package command should be all whats necessary to import third-party dependencies into my projects in modern cmake.
Is it considered good practice to use those commands always in the root CMakeLists.txt of my Project hierarchy that features several subfolders, that are added with add_subdirectory.()? Or should I use find_package in the subdirectory where it is actually needed?
I dont get the difference between Find.cmake and Config.cmake files. I believe Config.cmake files are the result of a library author correctly exporting the targets of his lib while Find.cmake files are like an auxiliary measure if a lib does not provide cmake-support, i.e. do not support clients to use CMake. But CMake itself might offer suitable Find.cmake files for proper adoption. Correct? So when do I have to install and export my lib?
thank your for your help
EDIT:
thank you for your hep Thomas. As a concrete example, I would like to add libQGLViewer as a third-party library to my project. However, the package-manager under Ubuntu 16.04 only offers an older version which depends on Qt4. Still, my project uses Qt5 and so I thought, I just download the lib and build it from source to /opt, no sweat. libQGLViewer uses qmake and so I turned to google and found a FindQGLViewer.cmake file. I copied this file to /usr/share/cmake-3.5/Modules and as I understand, this should render the command find_package(QGLViewer) to complete succesfully upon which the Variables ${QGLViewer_LIBRARIES} etc. are populated. However, it doesnt work and I cant figure out what the problem is, probably due to a general lack of understanding regarding these matters
CMake Warning at /usr/share/cmake 3.5/Modules/FindQGLViewer.cmake:108 (MESSAGE):
Could not find libQGLViewer.so, failed to build?
Call Stack (most recent call first):
CMakeLists.txt:57 (_find_package)
CMakeLists.txt:109 (find_package)
1. This depends on your project structure. If you invoke find_package() before adding any sub-folders, then you will ensure that the package is available to all sub-folders. If you instead invoke find_package() in one of the sub-folders, then that package will only be available after the fact.
If there is a chance that more than one sub-folder will depend on the package and at least one of these sub-folders is always part of the build (i.e. not optional), then the prudent thing to do would be to invoke find_package() at top-level before adding the sub-folders to ensure its availability to all sub-folders that might need it, without having to consider the order in which you add the sub-folders.
2. Your understanding is largely correct. Here is the official explanation. Yes, CMake ships with a number of Find-modules for common libraries, but the list is far from exhaustive even in terms of common libraries.

Good practices when adding downloaded c++ source code to my project

I am trying to use gnuplot++, but this is really a more general question about downloaded source code. I have downloaded the gnuplot++ source code and it consists of multiple .h and .cc files. I would like to use it in othercopy projects in the future so I am reluctant to add all the files into my project directory.
From what I understand gcc will look in /usr/local/include for header files, so I have put the code there for now. But what is the best way to compile and link the code?
Should I use the makefile to include the directory of the source code?
Should I keep it somewhere easy to find like /usr/local/include?
How do I know the best way to compile the code in gnuplot++?
Typically, if the project itself doesn't come with install instructions, I usually add it somewhere "public", e.g. /usr/local/project/{lib,include,src,...} where "project" in this case would be gnuplot++.
In this case, there doesn't appear to be any support for building this into a library, which makes it a little more awkward, as you need the sources included in your project itself. I'd still keep those sources separate, but you may prefer to just put them into a separate directory within the project [or spend an hour or three making a library of it].
For general practice, yes, keep the source for gnuplot++ (or any other similar 3rd-party project) separate from your own application source code. This makes it much easier to manage updates to the 3rd party projects, etc.
Yes, I would use the makefile for your application to also include the path to the headers for gnuplot++ and I would not copy those files directly into /usr/local/include. Instead, I would consider a couple options: do nothing and point your include path in your makefile to the gnuplot++ directory, or put symbolic links in /usr/local/include to point to the gnuplot++ files.
As for the best way to compile gnuplot++, I would have to look at gnuplot++ myself and see what it has to say, perhaps in a README file or similar.
In general, when using third-party libraries, you build and install those libraries according to the installation description that comes with the downloaded source.
If there is no installation guideline, it is typically a set of steps like
./configure
make
make install
Then it is the responsibility of the library to ensure the relevant headers and library files are easily locatable for use in your project.
gnuplot++ is an exception here, because it does not seem to come with its own build structure.
The best advice in cases such as this is to put the source from gnuplot++ in a directory within your project (possibly parallel to your own sources) and include the files in your own build setup.

How to generate CMakeLists.txt?

I need some pointers/advice on how to automatically generate CMakeLists.txt files for CMake. Does anyone know of any existing generators? I've checked the ones listed in the CMake Wiki but unfortunately they are not suitable for me.
I already have a basic Python script which traverses my project's directory structure and generates the required files but it's really "dumb" right now. I would like to augment it to take into account for example the different platforms I'm building for, the compiler\cross-compiler I'm using or different versions of the libraries dependencies I might have. I don't have much\expert experience with CMake and an example I could base my work or an already working generator could be of great help.
I am of the opinion that you need not use an automated script for generating CMakeLists.Txt as it is a very simple task to write one, after you have understood the basic procedure. Yeah I do agree that understanding the procedure to write one as given in CMake Wiki is also difficult as it is too much detailed.
A very basic example showing how to write CMakeLists.txt is shown here, which I think will be of use to everyone, even someone who is going to write CMakeLists.txt for the first time.
Well i dont have much of an experience in Cmake either, but to perform a cross platform make a lot of files need to be written and modified including the CMakeLists.txt file, i suggest that you use this new tool called the ProjectGenerator Tool, its pretty cool, it does all the extra work needed and makes it easy to generate such files for 3'rd party sources with little effort.
Just read the README carefully before using it.
Link:
http://www.ogre3d.org/forums/viewtopic.php?f=1&t=54842
I think that you are doing this upside down.
When using CMake, you are supposed to write the CMakeLists.txt yourself. Typically, you don't need to handle different compilers as CMake has knowledge about them. However, if you must, you can add code in the CMakeFiles to do different things depending on the tool you are using.
CLion is an Integrated development environment that is fully based on CMake project file.
It is able to generate itself the CMakeLists.txt file when using the import project from source
However this is quite probable that you have to edit this file manually as your project grows and for adding external dependency.
I'm maintaining a C++ software environment that has more than 1000 modules (shared, static libraries, programs) and uses more than 20 third parties (boost, openCV, Qt, Qwt...). This software environment hosts many programs (~50), each one picking up some libraries, programs and third parties. I use CMake to generate the makefiles and that's really great.
However, if you write your CMakeLists.txt as it is recommended to do (declare the module as being a library/program, importing source files, adding dependencies...). I agree with celavek: maintaining those CMakeLists.txt files is a real pain:
When you add a new file to a module, you need to update its CMakeLists.txt
When you upgrade a third party, you need to update the CMakeLists.txt of all modules using it
When you add a new dependency (library A now needs library B), you may need to update the CMakeLists.txt of all programs using A
When you want a new global settings to be changed (compiler setting, predefined variable, C++ standard used), you need to update all your CMakeLists.txt
Then, I see two strategies to adress those issues and likely the one mentioned by OP.
1- Have CMakeLists.txt be well written and be smart enough not to have a frozen behaviourto update themselves on the fly. That's what we have in our software environment. Each module has a standardized file organization (sources are in src folder, includes are in inc folder...) and have simple text files to specify their dependencies (with keywords we defined, like QT to say the module needs to link with Qt). Then, our CMakeLists.txt is a two-line file and simply calls a cmake macro we wrote to automatically setup the module. As a MCVE that would be:
CMakeLists.txt:
include( utl.cmake )
add_module( "mylib", lib )
utl.cmake:
macro( add_module name what )
file(GLOB_RECURSE source_files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
if ( what STREQUEL "lib" )
add_library( ${name} SHARED ${source_files} )
elseif ( what STREQUEL "prg" )
add_executable( ${name} ${source_files} )
endif()
# TODO: Parse the simple texts files to add target_link_libraries accordingly
endmacro()
Then, for all situations exposed above, you simply need to update utl.cmake, not the thousand of CMakeLists.txt you have...
Honestly, we are very happy with this approach, the system becomes very easy to maintain and we can easily add new dependencies, upgrade third parties, change some build/dependency strategies...
However, there remains a lot of CMake scripts to be written. And CMake script language sucks...the tool's very powerful, right, but the script's variable scope, the cache, the painful and not so well documented syntax (just to check if a list is empty you must ask for it's size and store this in a variable!), the fact it's not object oriented...make it a real pain to maintain.
So, I'm now convinced the real good approach may be to:
2- completly generate the CMakeLists.txt from a more powerful language like Python. The Python script would do things similar to what our utl.cmake does, instead it would generate a CMakeLists.txt ready to be passed CMake tool (with a format as proposed in HelloWorld, no variable, no function....it would only call standard CMake function).
I doubt such generic tool exists, because it's hard to produce the CMakeLists.txt files that will make everyone happy, you'll have to write it yourself. Note that gen-cmake does that (generates a CMakeLists.txt), but in a very primitive way and it apparently only supports Linux, but it may be a good start point.
This is likely to be the v2 of our software environment...one day.
Note : Additionally, if you want to support both qmake and cmake for instance, a well written Python script could generate both CMakeLists and pro files on demand!
Not sure whether this is a problem original poster faced, but as I see plenty of „just write CMakefile.txt” answers above, let me shortly explain why generating CMakefiles may make sense:
a) I have another build system I am fairly happy with
(and which covers large multiplatform build of big collection
of interconnected shared and static libraries, programs, scripting
language extensions, and tools, with various internal and external
dependencies, quirks and variants)
b) Even if I were to replace it, I would not consider cmake.
I took a look at CMakefiles and I am not happy with the syntax
and not happy with the semantics.
c) CLion uses CMakefiles, and Cmakefiles only (and seems somewhat interesting)
So, to give CLion a chance (I love PyCharm, so it's tempting), but to keep using my build system, I would gladly use some tool which would let me
implement
make generate_cmake
and have all necessary CMakefiles generated on the fly according to the current
info extracted from my build system. I can gladly feed the tool/script with information which sources and headers my app consists of, which libraries and programs it is expected to build, which -I, -L, -D, etc are expected to be set for which component, etc etc.
Well, of course I would be much happier if JetBrains would allow to provide some direct protocol of feeding the IDE with the information it needs
(say, allowed me to provide my own command to compile, to run, and to
emit whatever metadata they really need - I suppose they mainly need incdirs and defines to implement on the fly code analysis, and libpaths to setup LD_LIBRARY_PATH for the debugger), without referring to cmake. CMakefiles as protocol are somewhat complicated.
Maybe this could be helpful:
https://conan.io/
The author has given some speeches about cmake and how to create modular projects using cmake into CPPCon. As far as I know, this tool require cmake, so that I suppose that generate it when you integrate new packages, or create new packages. Recently I read something about how to write a higher level description of the C/C++ project using a YAML file, but not sure if it is part of conan or not (what I read was from the author of conan). I have never used, and it is something pending for me, so that, please if you use it and fit your needs, comment your opinions about it and how it fit your scenario.
I was looking for such a generator but at the end I decided to write my own (partly because I wanted to understand how CMake works):
https://github.com/Aenteas/cmake-generator
It has a couple of additional features such as creating python wrappers (SWIG).
Writing a generator that suits everyone is impossible but I hope it will give you an idea in case you want to make your customized version.