CMake : produce Makefiles in each subdirectory? - cmake

Assuming the following configuration :
parentdir1/parentdir2/myproject
parentdir1/parentdir2/myproject/CMakeLists.txt
parentdir1/parentdir2/myproject/src
parentdir1/parentdir2/myproject/src/dir1
parentdir1/parentdir2/myproject/src/dir2
parentdir1/parentdir2/myproject/src/dir3
Currently, my CMakeLists produces only one Makefile in parentdir1/parentdir2/myproject.
How to produce a Makefile in each subdirectory (to compile the associated directory) ?
Thank you very much.

CMake allows you to have a CMakeLists.txt file in any subdirectory under the root directory of your source tree.
Then use the add_subdirectory command in CMakeLists.txt to add the subdirectories. Then CMake will look for CMakeLists.txt in those subdirectories.
See the documentation for the add_subdirectory command here:
http://cmake.org/cmake/help/cmake-2-8-docs.html#command:add_subdirectory
For more info, check out the CMake FAQ and documentation on www.cmake.org.

Related

How can we refer external cmake file from main CMakeLists.txt file?

Let's say I have some protobuf related cmake code as a library that resides inside CMakeLists.pro file and I need to include this library as a external file configuration. How to do that ?
I think this question is asking how to make cmake modules. IE you have helper code and would like to make it easily available.
A normal top level project has a top level cmake folder. Here is an example of what that would look like.
cmake
tests
src
.gitignore
CMakeLists.txt
README.md
Inside the cmake folder say you have a cmake module called foo.cmake
(It's important to make the file end with .cmake file extension)
Anyway this is what your foo.cmake may look like
# Include guards need at least cmake 3.10
include_guard() # Good practice to use an include_guard()
function(bar)
...
endfunction()
Now in your main cmakelists how do you call this function? Simple.
cmake_minimum_required(VERSION 3.18)
# Add the cmake folder to the cmake module path, this makes it easier to include files
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
# Include foo.cmake
include(foo)
# Call the bar function you defined in foo.cmake
bar()
And that's how you can refer to external cmake file from the main CMakeLists.txt

How to write the CMakeList file

cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(WINDOW CXX)
set(WINDOW_SRCS window.cpp)
add_executable(Window ${WINDOW_SRCS})
set(CMAKE_CXX_STANDARD 14)
find_library(OPENGL_LIB
NAMES lGLEW lglfw3 lGL lrt lm ldl lXrandr lXinerama lXxf86vm lXext lXcursor lXrender lXfixes lX11 lpthread lxcb lXau lXdmcp lXi lSOIL lassimp
PATHS /usr/lib /usr/local/lib
)
if(OPENGL_LIB)
target_link_library(Window ${OPENGL_LIB})
endif()
I am trying to write a CMakeList.txt file. I get an error in the generated Makefile
makefile:1: *** missing separator. Stop.
I've added tabs in the beginning of each line. I can't figure out where is wrong
The problem is that you haven't cleaned CMake generated files from the previous CMake configuration run.
Please remove the CMakeCache.txt file and Makefile and the directory CMakeFiles and if they exists the files cmake_install.cmake and CTestTestfile.cmake.
Now you can rerun the CMake configuration via cmake . again.
Then execute make and it should be ok.
In the answer I haven't attempted to improve your CMakeLists.txt, but just to make the issue you are encountering to go away.
Otherwise, as suggested by #roalz, you could use the find_package() to find OpenGL.
Another "improvement" could be to use out-of-source builds. In this way all the build results will be contained in one directory with no interference with the source tree. In this case, to start from a clean state and rerun the CMake configuration, you will only need to remove that build directory, and not all the single files created around. This is particularly useful for projects that have nested source directories (more than one level).

Confusion on how CMake places binaries

I've recently began experimenting with CMake, and have written a simple Hello, World program in C++.
Here is my directory structure:
CMakeLists.txt
src/
CMakeLists.txt
main.cpp
build/
The top-level CMakeLists.txt reads as follows:
#Require at least CMake version 2.8
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
#set up the project name, version and language to compile in
project(HelloWorld)
#tell CMake that we have some source files located in the src directory
add_subdirectory(src)
And the CMakeLists.txt in /src reads:
add_executable(helloworld
main.cpp)
install(TARGETS helloworld
RUNTIME DESTINATION ../build)
Now, I would expect that these two scripts would cause the makefile to create the helloworld binary in the /build directory, but after running make, it creates the helloworld binary in /build/src.
If I move the add_executable and install function calls into the top-level CMakeLists.txt, then the helloworld binary is placed in /build, not /build/src.
So, as I understand, it places the build in the folder relative to where CMake was invoked. Why does it appear as though install is doing nothing, then?
Additionally, what if I have multiple complex subdirectories?
How should I write out my CMakeLists.txt while avoiding file(GLOB ...)?
For example;
CMakeLists.txt
/build
/src
/class_A
a.hpp
a.cpp
/class_B
b.hpp
b.cpp
/class_CB
cb.hpp
cb.cpp
/class_D
d.hpp
d.cpp
Would I just have a giant list of .cpp files, all with relative paths to each cpp file, and pass that list into the add_executable(executable ${SOURCE_FILES})? Or is there an easier way with using multiple CMakeLists.txt?
You misinterpret the install command. It is used to install your files, for example with make install.
When you configure your project, CMake will mimic the structure of your project. This means all folders are created in the same structure and the binaries appear in the according build directories.
Either place your targets in the main directory, which I would consider bad stile. Better live with build/src or give it a more meaningful name.

CMake and dependencies

I have the following directory structure and library dependencies:
./lib-a
./lib-b (depending on lib-a)
Each directory contains a CMakeLists.txt file for generating its own library.
I am using an out-of-source building policy.
In order to say that lib-b depends on lib-a, I have put the command add_subdirectory(../lib-a lib-a) in ./lib-b/CMakeLists.txt, according to what is taught by the official CMake tutorial. This way I obtain that a subdirectory lib-a is created in ./lib-b/build dir.
This is not the behaviour I desire. What I would like to obtain is CMake making reference to lib-a in generating lib-b and, if lib-a has not been already generated, CMake should generate it inside ./lib-a/build by using the CMakeLists.txt of lib-a (in a behaviour similar to the one of the make tool when dealing with dependencies).
I would also like to add that I am not using a root CMakeLists.txt in my example, but what I would like to have is the lib-b/CMakeLists.txt declaring the dependency on lib-a, thus making lib-a to be compiled, if not already, by using its own lib-a/CMakeLists.txt.
Here is the dirs structure and their contents:
lib-a/
CMakeLists.txt (for compiling lib-a)
src/
test.cpp
include/
test.hpp
lib-b/
main.cpp
CMakeLists.txt (for compiling lib-b; here is the point where I would like to make reference to lib-a, that I need for the generation of lib-b)
lib-b/main.cpp contains also an include of test.hpp of lib-a, because it is using a function of lib-a. This should be taken into consideration in the specification of lib-b/CMakeLists.txt.
What should the content of the two lib-a/CMakeLists.txt and lib-b/CMakeLists.txt files be?
I think you misunderstand the tutorial. The thing that links the libraries together is target_link_library(lib_b lib_a). If the name of the dependency is a library that is part of the build, CMake will magically make the dependencies work. It has nothing to do with subdirectories. In fact, if I have the following directory structure:
./
./a.hpp
./a.cpp
./b.hpp
./b.cpp
./CMakeLists.txt
The following will set the dependencies just fine:
PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
PROJECT(lib_b)
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)
This will work across subdirectory projects as well:
./
./CMakeLists.txt
./lib_a/CMakeLists.txt
./lib_a/a.hpp
./lib_a/a.cpp
./lib_b/CMakeLists.txt
./lib_b/b.hpp
./lib_b/b.cpp
And the list files:
# ./CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
ADD_SUBDIRECTORY(lib_a)
ADD_SUBDIRECTORY(lib_b)
# ./lib_a/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
# ./lib_b/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(lib_b)
INCLUDE_DIRECTORIES(${lib_a_SOURCE_DIR})
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)

Add sources from other paths don't have CMakeLists.txt, and move output files to other path in CMake

My source tree:
/project
/project/src/<my sources>
/project/build/vs2008
/project/build/ubuntu
I want to put my CMakeLists.txt in vs2008 and ubuntu. I can accept put one CMakeLists.txt to each folder and put another global CMakeLists.txt on /project/build, but I just don't want any CMakeLists.txt in /project/src(So I can't use add_subdirectory command). I need my solution files of visual studio in /project/build/vs2008 and Makefile in /project/build/ubuntu. What commands I should know about?
I think there's nothing special you would need to know -- you just need to specify paths to your source files relative to where your CMakeLists.txt is located, and your targets should build the same as if you had placed CMakeLists.txt in your src folder. For example, project/build/ubuntu/CMakeLists.txt could look like this:
set( SrcDir ../../src )
add_executable( MyApp
${SrcDir}/file1.cpp
${SrcDir}/file2.cpp
# and so on
)