CMake how to set the build directory to be different than source directory
I’m pretty new to CMake, and read a few tutorials on how to use it, and wrote some complicated 50 lines of CMake script in order to make a program for 3 different compilers. This probably concludes all my knowledge in CMake. Now my problem is that I have some source code, whose folder I don’t want to touch/mess with when I make the program. I want that all CMake and make output files and folders to go into ../Compile/ , so I changed a few variables in my CMake script for that, and it worked for sometime when I did something like this on my laptop:
Compile$ cmake ../src Compile$ make
Where with that I had a clean output in the folder I’m in right now, which is exactly what I’m looking for. Now I moved to another computer, and recompiled CMake 2.8.11.2, and I’m almost back to square one! It always compiles the thing into the src folder where my CMakeLists.txt is located. The part where I choose the directory in my CMake script is this:
set(dir $/../Compile/) set(EXECUTABLE_OUTPUT_PATH $ CACHE PATH "Build directory" FORCE) set(LIBRARY_OUTPUT_PATH $ CACHE PATH "Build directory" FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $) set(CMAKE_BUILD_FILES_DIRECTORY $) set(CMAKE_BUILD_DIRECTORY $) set(CMAKE_BINARY_DIR $) SET(EXECUTABLE_OUTPUT_PATH $) SET(LIBRARY_OUTPUT_PATH $lib) SET(CMAKE_CACHEFILE_DIR $)
-- Build files have been written to: /. /src
There’s little need to set all the variables you’re setting. CMake sets them to reasonable defaults. You should definitely not modify CMAKE_BINARY_DIR or CMAKE_CACHEFILE_DIR . What happens if you remove all these set() calls and just do cd Compile; rm -rf *; cmake ../src ?
Basically, as long as you’re outside of the source directory when running CMake, it will not modify the source directory unless your CMakeList explicitly tells it to.
@Angew Thank you for the tip, which is surprising! I removed all those lines and just used cmake ../src and it worked like a charm! This is so surprising because I tried it before when I was first learning CMake and it didn’t work. Please put your answer in an official reply to give you the big fat check mark 🙂
What saved me was @Adam Bowen’s remark that «you cannot create an out-of-source build for a source directory with an in-source build»
6 Answers 6
It sounds like you want an out of source build. There are a couple of ways you can create an out of source build.
- Do what you were doing, run
cd /path/to/my/build/folder cmake /path/to/my/source/folder
which will cause cmake to generate a build tree in /path/to/my/build/folder for the source tree in /path/to/my/source/folder . Once you’ve created it, cmake remembers where the source folder is — so you can rerun cmake on the build tree with
cmake /path/to/my/build/folder
cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
cmake -B/path/to/my/build/folder -H/path/to/my/source/folder
CMake puts all of its outputs in the build tree by default, so unless you are liberally using $ or $ in your cmake files, it shouldn’t touch your source tree.
The biggest thing that can go wrong is if you have previously generated a build tree in your source tree (i.e. you have an in source build). Once you’ve done this the second part of (1) above kicks in, and cmake doesn’t make any changes to the source or build locations. Thus, you cannot create an out-of-source build for a source directory with an in-source build. You can fix this fairly easily by removing (at a minimum) CMakeCache.txt from the source directory. There are a few other files (mostly in the CMakeFiles directory) that CMake generates that you should remove as well, but these won’t cause cmake to treat the source tree as a build tree.
Since out-of-source builds are often more desirable than in-source builds, you might want to modify your cmake to require out of source builds:
# Ensures that we do an out of source build MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG) STRING(COMPARE EQUAL "$" "$" insource) GET_FILENAME_COMPONENT(PARENTDIR $ PATH) STRING(COMPARE EQUAL "$" "$" insourcesubdir) IF(insource OR insourcesubdir) MESSAGE(FATAL_ERROR "$") ENDIF(insource OR insourcesubdir) ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD) MACRO_ENSURE_OUT_OF_SOURCE_BUILD( "$ requires an out of source build." )
The above macro comes from a commonly used module called MacroOutOfSourceBuild . There are numerous sources for MacroOutOfSourceBuild.cmake on google but I can’t seem to find the original and it’s short enough to include here in full.
Unfortunately cmake has usually written a few files by the time the macro is invoked, so although it will stop you from actually performing the build you will still need to delete CMakeCache.txt and CMakeFiles .
You may find it useful to set the paths that binaries, shared and static libraries are written to — in which case see how do I make cmake output into a ‘bin’ dir? (disclaimer, I have the top voted answer on that question. but that’s how I know about it).
Why does cmake create a ‘source’ directory in my build directory?
I also have another CMakeLists.txt in ~/project/source , and its content is:
cmake_minimum_required(VERSION 2.8) include_directories("~/project/includes") add_executable(exec entry.cpp)
Now, I go into the build directory which is empty, and do cmake .. . This works fine. However I then see a ‘source’ directory get created as shown here.
Why is this being created? I do not know what is going on. As I understand it, it should not be doing this, it should give me everything I see here, except for the ‘source’ directory.
1 Answer 1
Inside your build directory, CMake re-creates the whole directory structure of your project. The rational is, to keep the project structure. Image a bigger project with several levels of subfolders and sources, libraries and tests scattered in a meaningful way. To run a test, you follow the structure where the test’s source is located, just in the build directory instead of the source directory.
As your project, at least as far as CMake knows it, is only the source subdirectory, only this folder is created.
If you really have just the source project, I am not sure whether would be better to place the CMake project just inside source .
Thanks for your reply. However, as far as I understood it, the build directory was simply supposed to house the executables once make was run. Why is it re-creating the entire source structure? I dont think it is supposed to do that.
It is supposed to do that, I just was not able to find a good source for this claim. If you have executables in ~/project and in ~/project/source they stay separated in ~/project/build and ~/project/build/source . As I said, if you only have sources in sources you may consider to make it the root directory of your CMake project.
So, let me rephrase. When I run make in the build directory, where will the executable file be created?