Why is this happening with cmake - c++

I am working on a c++ project and I am using cmake as the build system, so my workflow here is make changes to code. then,
rm -r build
mkdir build
cd build
cmake -G "Unix Makefiles" ..
make
Now I added glew as a dependency to the project, so whenever I try to run make I get an error saying SDL.h not found(this was working before).After sometime I decided to check CMakeCache.txt.opened it using vim then :wq that's all I did now if I run make, my project is building successfully, I am not sure why this is happening, Can anyone tell me why?
ps: added gif of this event, check it out to get a clear picture
(the code i am working on is linked as well, this exact issue is in this commit "dd4452b45c733e0612bc5f3c632e9d1a08be8072")
link to gif
link to code

variables in cmake are limited to the scope of the directory they are in plus their subdirectories.
This, calling find_module() in the gamelib subdirectory does not find that module for use in the main directory.
The preferred way to propagate include directory dependencies is to add them to the target (in the gamelib directory), like this:
target_include_directories(gamelib BEFORE PRIVATE
$<BUILD_INTERFACE:${SDL2_INCLUDE_DIR}>
$<BUILD_INTERFACE:${GLEW_INCLUDE_DIR}>
)
target_include_directories(gamelib SYSTEM BEFORE PUBLIC
$<BUILD_INTERFACE:${SDL2_INCLUDE_DIR}>
$<BUILD_INTERFACE:${GLEW_INCLUDE_DIR}>
)
then you don't need to even mention them in any executable that uses gamelib.

Related

Can someone expand what is meant by 'configure' and 'build' with CMake files

I am downloading this code from GitHub (subdivision-regression), and am getting stuck following the instructions:
To build doosabin_regression:
Run CMake with an out of source build.
Set COMMON_CPP_INCLUDE_DIR to the full path to rstebbing/common/cpp.
Set DOOSABIN_INCLUDE_DIR to the full path to rstebbing/subdivision/cpp/doosabin/include.
Set Ceres_DIR to the directory containing CeresConfig.cmake.
Set GFLAGS_INCLUDE_DIR, GFLAGS_LIBRARY and RAPID_JSON_INCLUDE_DIR. (Add -std=c++11 to CMAKE_CXX_FLAGS if compiling with gcc.)
Configure.
Build.
I have edited the CMakeLists.txt file to put the correct paths in. I then created a new directory called subdivision-regression-bin and ran:
cmake ../subdivision-regression/src
It completes this and displays:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hert5584/RStebbing/subdivision-regression-bin
However, when I try and run the example code, it cannot find the files listed in CMakeLists.txt (I know they are the right paths as otherwise CMake does not run).
I have tried running:
sudo make install
But get the following error:
make: *** No rule to make target 'install'. Stop.
Any ideas why this isn't working? Have the above steps Configured and Built the files?
The ordered CMake idiom to understand is:
The Configure step
The Generate step (This is often subsumed in the Configure step, and not mentioned explicitly, as in this case.)
The Build step (in which you actually compile/link your code into libraries/executables)
Take a look at this resource for information about the configure and generate stages.
You didn't appear to perform the steps to set CMake cache variables. For these you have to use CMake command line options (-D specifically). So run CMake as something like this instead to set all six variables:
cmake -DCOMMON_CPP_INCLUDE_DIR=/rstebbing/common/cp -DDOOSABIN_INCLUDE_DIR=...[More CMake Cache variables]... ../subdivision-regression/src
For building, try just running make without sudo or install:
make

Enable cmake options/flag after making the file

I don't have much knowledge about cmake. I installed a package libfreenect2 following the instructions on their github page. The instructions were as follows-
Clone the repository. And follow the cmake step:
cd ..
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2
make
make install
However, after installing I realised the program/package that required libfreenect2 as a dependency required me to use:
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2 -DENABLE_CXX11=ON
You may have noticed, it required me to use an extra flag -DENABLE_CXX11=ON. How can I fix this? How can I set ENABLE_CXX11=ON after the whole make process has been completed? By the way what does -D do? (are these -DXXX things called options or flag)
In case your answer is to repeat the whole process again then kindly guide me through the step by step process of deleting the correct files. I don't want to delete other dependencies.
Here are some other stackoverflow answers relating to cmake-
set cmake option(), cmake option to include a directory, What does cmake do
SOLUTION - I used the accepted solution to enable the flag. Even though it worked for my problem (libfreenect2) still it will be amazing if someone could provide an answer which doesn't involve reinstalling.
My warm suggestion would be to repeat the process with that option ON.
First you should delete what was previously generated.
The sequence of commands to follow is the following:
rm -rf build
rm -rf $HOME/freenect2
just to be entirely sure you start from a "clean state".
I don't see the need to do rm -rf $HOME/freenect2 as that files/dir will be overwritten by the new install, but shouldn't hurt.
You can also try the suggestion in the SO post mentioned in one of the comments.
Then repeat the process from the root dir of libfreenect2:
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2 -DENABLE_CXX11=ON
make
make install
Alternatively, if you're entirely sure that you will build libfreenect2 always with that option ENABLE_CXX11=ON, you could explicitely set it ON once and for all in the CMakeLists.txt of libfreenect2, specifically changing the line:
OPTION(ENABLE_CXX11 "Enable C++11 support" OFF)
into
OPTION(ENABLE_CXX11 "Enable C++11 support" ON)
In this last case, you will just need to do
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2
make
make install
of course after you've cleaned as explained at the beginning.
About -D for CMake, it allows you to pass options. Directly from the documentation:
-D <var>:<type>=<value>
Create a cmake cache entry.
When cmake is first run in an empty build tree, it creates a
CMakeCache.txt file and populates it with customizable settings for
the project. This option may be used to specify a setting that takes
priority over the project’s default value. The option may be repeated
for as many cache entries as desired.
So if there's some project default options that one wants to change/overwrite than it can be done with this.

Compile a single file under CMake project?

I'm developing a C++ project which is going to be enclosed on a bigger one.
I've seen that on the bigger project (is a Qt application and it's being generated from qmake) I am able to compile a single file from the linux command line, just entering the relative path to the specific file as an argument to make.
On the other hand, I'm using CMake for my own project. When I modify some code for a compilation unit and I have to modify its header file, I have to wait a long time to compile its dependencies and then its own source file. But there are some situations in which I would prefer to check whether the source code in the *.cc file is compilable without errors.
Is there a way to generate a Makefile from CMake the way qmake does this? Switching to qmake is not an option anymore.
You do not have to add extra custom targets to your CMake scripts, as the Makefiles generated by CMake already contain .o targets for each .cc file. E.g. if you have a source file called mySourceFile.cc, there will be a Makefile in your build directory that defines a target called <Some Path>/mySourceFile.cc.o. If you cd into your build directory, you can use grep or ack-grep to locate the Makefile that defines this target, then cd into that Makefile's directory and build it.
E.g. suppose the command ack-grep mySourceFile.cc.o prints something like:
foo/bar/Makefile
119:x/y/z/mySourceFile.o: x/y/z/mySourceFile.cc.o
123:x/y/z/mySourceFile.cc.o:
124: # recipe for building target
Then you can build mySourceFile.cc.o by doing:
cd foo/bar && make x/y/z/mySourceFile.cc.o
CMake doesn't have a generic built-in way of doing this (it's an open issue), but if you're using the Ninja generator, you can can use a special Ninja syntax for building just the direct outputs of a given source file. For example, to compile just foo.o you would use:
ninja /path/to/foo.cpp^
Not out-of-the box. CMake does not expose those "internal" makefile rules in the main makefile.
You can do this only if you consider what kind of file structure CMake uses internally. You can e.g. for compiling a single .obj files using CMake generated makefiles call
make -f CMakeFiles/myProg.dir/build.make CMakeFiles/myProg.dir/main.cc.obj
when you have something like
cmake_minimum_required(VERSION 3.1)
project(myProg CXX)
file(WRITE "main.cc" "int main()\n{\nreturn 0;\n}")
add_executable(myProg main.cc)
To build src/foo.cpp alone:
cmake --build . --target src/foo.cpp.o
No, CMake does not offer built-in support to compile single files.
You have to add a target for each object file, maybe by a function iterating over all files of a directory.
Others have suggested ways to find the target name (ending in .cpp.o) from the .cpp filename, but if you already know the name of a target that will trigger compilation of the .cpp file and you're using ninja this suggestion should be easier.
First build the target:
ninja TriggersCppCompilationLib
Assuming your file was changed or was not yet built, ninja will print the full target name. When you see the name come up, hit enter so it is not overwritten. Then simply copy the name from the terminal (e.g. using tmux copy mode).

Build folder and makefile

The question comes from my puzzlement when compiling a makefile for Deep Learning framework Caffe on Ubuntu, but it relates, I believe, to a more general phenomenon of the nature of compiling a C++ makefile.
After "make all", the resulting files from the compilation were put in a hidden folder: .build_release, not in the respective folders where the cpp files are.
Then when I tried to run the following lines:
./data/mnist/get_mnist.sh
./examples/mnist/create_mnist.sh
I was getting an error that the system does not find the file:
./create_mnist.sh: 16: ./create_mnist.sh: build/examples/mnist/convert_mnist_data.bin: not found
But the file actually existed in the .build_release folder.
What happened and how to fix this problem?
The issue is not with make, you simply need to follow the instructions carefully. The BUILD_DIR is specified by Makefile.config. By default this folder is named build. Once you followed the compilation instructions:
cp Makefile.config.example Makefile.config
# Adjust Makefile.config (for example, if using Anaconda Python)
make all
make test
make runtest
Navigate to build:
cd build
./data/mnist/get_mnist.sh
./examples/mnist/create_mnist.sh

How do I tell cmake where to output its build data?

How do I tell cmake where it should output its build data?
Let's say I have a dir with the source code called src/,
and then since cmake outputs a lot of files I would like him to put all of that in
a dir called build/.
BUT I would like him to put the generated Makefile in the project root,
so I don't have to go into the build dir to build the application.
Is this possible with cmake?
I have managed to get the cmake out put if I fun cmake in the build dir like this:
cd build/
cmake ../src/
make
./hello
But it would be nice to stay in the project root and type something like this
cmake
make
./hello
I guess that I need to put a CMakeList.txt in the project root with some magic commands telling him where he could put the object files and where he can find the source code.
Thanks
Update:
Since my question is a little bit vague.
After I have run the cmake commands this is how I would like my tree to look like:
src/CMakeLists.txt
src/hello.c
src/hello.h
build/CMakeCache.txt
build/CMakeFiles/
build/cmake_install.cmake
CMakeLists.txt
Makefile
So the question is how should the CMakeLists.txt look like in this setup.
CMakeLists.txt
src/CMakeLists.txt
But maybe that is not possible?
BUT I would like him to put the generated Makefile in the project root, so I don't have to go into the build
dir to build the application.
cmake not designed for that, as I know,
BUT you can stay in the project root and type:
make -C build
./hello
with custom build rules or set_target_properties,
you can force cmake to put result executable to
sources directory or you can use
./build/hello
Type "cd build && cmake .." you need only once,
after that make will automaticaly start cmake, if something
changed.
cmake wants you to have a fresh build directory.
Okay, i get what you want. I think, you can achieve this with some machinery in CMakeLists.txt. Of course, it's not option if you are not project developer.
In root CMakeLists.txt you can add file(WRITE ...) command, which would write Makefile into ${CMAKE_SOURCE_DIR}. This Makefile would contain these commands for every target:
<target>:
cd ${CMAKE_BUILD_DIR} && ${CMAKE_MAKE_PROGRAM} <target>
So, now you can run make from source dir and it will build your project in build dir.
Simply use
cmake .
make
in your src directory. The (.) dot on unix systems addresses the current directory. Keep in mind doing so is actually not recommended since there will be a lot of build files in your src directory you'll have to clean up afterwards or at release time.