16

I'm using cmake to compile a C++ project, and I want cmake to generate all the output files(metafiles like Makefile used to create binaries) in the build folder. I've checked all the answers in How do I make cmake output into a 'bin' dir?, none of them worked for me(suprisingly!). Files are generated in the root folder instead of in the build folder, what's wrong here? I guess I must have missed something.

Code Structure

➜  cmake-test tree .
.
├── CMakeLists.txt
└── hello.cpp

0 directories, 2 files

CMakeLists.txt

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.11)

# Project's name
project(hello)

# Set the output folder where your program will be created
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# The following folder will be included
include_directories("${PROJECT_SOURCE_DIR}")

add_executable(hello ${PROJECT_SOURCE_DIR}/hello.cpp)

Build Commands and Outputs

➜  cmake-test cmake .

-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/searene/CLionProjects/cmake-test

➜  cmake-test ls

bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt  hello.cpp  Makefile

cmake version

➜  cmake-test cmake --version

cmake version 3.11.4

CMake suite maintained and supported by Kitware (kitware.com/cmake).

OS

Linux

Searene
  • 25,920
  • 39
  • 129
  • 186
  • Just to let everyone be sure, you want Cmake to output binaries in build when you cmake install (a copy) or you want the binaries to always be outputed to build ? Also build is generally used for build metafiles, and bin for binaries. :3 – Alceste_ Aug 26 '18 at 02:27
  • The usual way to do this, rather than changing variables to set the path, is simply to create the output directory, change to it, and run cmake from there. So instead of `cmake .` you usually have `cmake ..` or similar. – John Zwinck Aug 26 '18 at 02:31
  • @Alceste_ I want the metafiles to be located in the `build` directory, i.e. those files generated by running `cmake .`. – Searene Aug 26 '18 at 02:33
  • @JohnZwinck Yes, that really worked! But I don't want to change directories all the time, I just want to run `cmake .` in the root directory, and then, the output files can be generated in the `build` folder. – Searene Aug 26 '18 at 02:34
  • mkdir build && cd build && cmake .. where CMakeLists.txt remains in the root directory. – Alceste_ Aug 26 '18 at 02:34
  • The easiest way would be to alias that. :P – Alceste_ Aug 26 '18 at 02:35
  • @Alceste_ Is there any way to do this without changing directories? I thought those variables in CMakeLists.txt should be able to do that, but they didn't work. – Searene Aug 26 '18 at 02:36

3 Answers3

27

The usual way to do this, rather than changing variables to set the path, is simply to create the output directory, change to it, and run cmake from there. So instead of cmake . you usually have cmake .. or similar.

I understand the initial impulse to say "But I expect my build system to write output somewhere else." But CMake is not usually used in the way you were initially expecting, and other people who run your CMake build won't expect what you were expecting, so it's probably best to just use the built-in, default behavior, which is to put the output wherever cmake was run.

Put another way: You are fighting against the tool. Don't do that.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    The last part is a pretty important point we tend to forget way too often. If you really need to work with the behavior described in the question use an alias so you won't be anoying other people while having a perfect environment for yourself. – Alceste_ Aug 26 '18 at 02:38
  • Thanks, I finally got it. I misunderstood the question in https://stackoverflow.com/questions/6594796/how-do-i-make-cmake-output-into-a-bin-dir, I thought we had the same question, but we didn't. He was asking for the location of the binaries and I was asking for the location of the metafiles used to build binaries. No wonder none of those answers worked for me. If that's the conventional behavior, then I'll abide by it. Thanks! – Searene Aug 26 '18 at 02:43
18

Disclaimer: I recommend going with @john-zwinck's answer.

By default, cmake uses the current working directory as build directory and whatever path you provide as source directory. So the normal way of achieving your goal is

  • create the build directory (mkdir build)
  • go there (cd build)
  • call cmake with the source dir as argument (cmake path/to/source)

BUT there is another way, as far as I know not documented in the cmake docs and only kept for compatibility reasons or internal usage, that some people are using. The -B and -H flags

cmake -Hpath/to/source -Bpath/to/build

or even from the source dir

cmake . -Bbuild

Important: no space after -B.

pseyfert
  • 3,263
  • 3
  • 21
  • 47
6

CMake 3.19.1 (not sure how about older ones) has following option (from docs):

cmake [<options>] -S <path-to-source> -B <path-to-build>

Uses as the build tree and as the source tree. The specified paths may be absolute or relative to the current working directory. The source tree must contain a CMakeLists.txt file. The build tree will be created automatically if it does not already exist. For example:

cmake -S src -B build