22

I have a source directory with a folder called "phantom-dir/" where I put all generated files I don't need. I want to put all generated files by CMake inside this phantom directory (together with other generated and "ugly" files).

A mini example:

$ mkdir cmake-test
$ cd cmake-test
$ echo 'message("Hello World!")' > CMakeLists.txt
$ cmake . | grep "Hello"
Hello World!
$ tree
.
├── CMakeCache.txt
├── CMakeFiles
│   ├── CMakeCCompiler.cmake
│   ├── cmake.check_cache
│   ├── CMakeCXXCompiler.cmake
│   ├── CMakeDetermineCompilerABI_C.bin
│   ├── CMakeDetermineCompilerABI_CXX.bin
│   ├── CMakeDirectoryInformation.cmake
│   ├── CMakeOutput.log
│   ├── CMakeSystem.cmake
│   ├── CMakeTmp
│   ├── CompilerIdC
│   │   ├── a.out
│   │   └── CMakeCCompilerId.c
│   ├── CompilerIdCXX
│   │   ├── a.out
│   │   └── CMakeCXXCompilerId.cpp
│   ├── Makefile2
│   ├── Makefile.cmake
│   ├── progress.marks
│   └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
└── Makefile

4 directories, 20 files

By default, all CMake files (CMakeCache.txt, cmake_install.cmake, Makefile, CMakeFiles) are written in the working directory. But, I want something like that:

$ mkdir cmake-test
$ cd cmake-test
$ mkdir phantom-dir
$ echo 'message("Hello World!")' > CMakeLists.txt
$ // editing CMakeLists.txt to set some cmake variables.
$ cmake . | grep "Hello"
Hello World!
$ tree
.
├── phantom-dir
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   │   ├── CMakeCCompiler.cmake
│   │   ├── cmake.check_cache
│   │   ├── CMakeCXXCompiler.cmake
│   │   ├── CMakeDetermineCompilerABI_C.bin
│   │   ├── CMakeDetermineCompilerABI_CXX.bin
│   │   ├── CMakeDirectoryInformation.cmake
│   │   ├── CMakeOutput.log
│   │   ├── CMakeSystem.cmake
│   │   ├── CMakeTmp
│   │   ├── CompilerIdC
│   │   │   ├── a.out
│   │   │   └── CMakeCCompilerId.c
│   │   ├── CompilerIdCXX
│   │   │   ├── a.out
│   │   │   └── CMakeCXXCompilerId.cpp
│   │   ├── Makefile2
│   │   ├── Makefile.cmake
│   │   ├── progress.marks
│   │   └── TargetDirectories.txt
│   ├── cmake_install.cmake
├── CMakeLists.txt
└── Makefile

4 directories, 20 files

That means: the Makefile in the current directory (to make, "cmake . && make"), but the remaining generated files inside the "phantom" directory.

I know I can make it with:

$ cd phantom-dir/
$ cmake ../

But it's a little tiresome for me to do it each time I want to re-compiling or remake cmake, above all taking into account that I'm modifying many times my CMakeLists.txt.

Which variables I have to set in the CMakeLists.txt file in order to achieve it?

ABu
  • 10,423
  • 6
  • 52
  • 103
  • We wrote a script that does all the directory changes for us. Ie: `build.sh compile` and `build.sh configure` which would do the directory change, make or cmake, and make install. – tpg2114 Dec 04 '12 at 21:17
  • 1
    The problem with your method is: the code (the build process) isn't any more cross-platform. Then, I will need an script for each known platform. Perhaps a CMake file executing it in script mode (-D) will be an equivalent solution, but this solution isn't elegant (in my point of view). – ABu Dec 04 '12 at 21:24
  • 1
    We did a python script not a bash script, so it is still cross-platform. But that's why it was just a comment and not an answer, I know it doesn't address exactly what you asked :) – tpg2114 Dec 04 '12 at 21:25
  • Why don't you build "out-of-source"? In other words, create a build-directory adjacent to your source and from there call "cmake ../Source"? – André Dec 04 '12 at 21:46
  • 2
    I explain it at the end of my question: that implies to move in this "build directory" each time I have to compile or rebuild the project, and when I have to do it many times, it becomes a little tiresome. – ABu Dec 04 '12 at 22:02
  • Did you ever find a better solution? The fact so many people have asked for a way to configure the `CMakeFiles` output dir and yet there doesn't seem to be a way is somewhat frustrating – Steve Lorimer Aug 18 '16 at 19:51
  • It just goes to show that CMake is a sub-par build system. – C.J. Oct 26 '18 at 22:04
  • 1
    +1 for the `tree` command... in almost two decades of UNIX, it's the first time I see it - unbelievable! :-) – andreee Apr 21 '20 at 11:47

1 Answers1

40

You could make use of the undocumented CMake options -H and -B to avoid leaving your source dir. -H specifies the path to the main CMakeLists.txt file, and -B specifies the path to your desired build directory.

cmake -H. -Bphantom-dir

Note that these are undocumented and so I suppose could change at any time the Kitware guys feel like.

To build your project without leaving your source dir, you can make use of the (official) option --build This is a cross-platform way to invoke your chosen build tool, and you can pass whatever flags you want to this tool. e.g.

cmake --build phantom-dir -- -j3
Antonio
  • 19,451
  • 13
  • 99
  • 197
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • Oh thanks! I guess it's impossible to make it by means of "set" commands inside the CMakeLists.txt file, isn't it? – ABu Dec 04 '12 at 23:21
  • @Peregring-lk - I would think so. I guess you could create an alias for "cmake -H. -Bphantom-dir" to save a bit of effort. – Fraser Dec 04 '12 at 23:23
  • 7
    @Kenny because this is what CMake is about, I guess (a half-documented, moving-target 12-ways-to-do-anything) :) – mlvljr May 14 '15 at 19:02
  • 2
    `-H` doesn't serve this purpose anymore (it prints help). I am not sure if `-B` still exists. – Antonio May 10 '16 at 15:23
  • 1
    See also http://stackoverflow.com/questions/31090821/what-does-the-h-option-means-for-cmake for info on the `-H` option and an excursion into the CMake source code to find it. – Colin D Bennett Sep 28 '16 at 15:55
  • `-H` seems to bring up `help` in `3.9.4`. `-B` seems to still have the same effect though. – datatype_void Oct 18 '17 at 13:25
  • 6
    Small hint for the `-H` option: note the difference between `cmake -H` and `cmake -H.` - the first one will just print the help, whilst the second one sets the home directory to current working dir – shybovycha Nov 01 '17 at 03:09