How do I make CMake output into a 'bin' dir?
As in Oleg's answer, I believe the correct variable to set is CMAKE_RUNTIME_OUTPUT_DIRECTORY. We use the following in our root CMakeLists.txt:
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
You can also specify the output directories on a per-target basis:
set_target_properties( targets...
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
In both cases you can append _[CONFIG]
to the variable/property name to make the output directory apply to a specific configuration (the standard values for configuration are DEBUG
, RELEASE
, MINSIZEREL
and RELWITHDEBINFO
).
How to make cmake output to the build directory?
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.
CMake output/build directory
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
. Treat these as read-only.
First remove the existing problematic cache file from the src directory:
cd src
rm CMakeCache.txt
cd ..
Then remove all the set()
commands and do:
cd Compile && rm -rf *
cmake ../src
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 do so.
Once you have this working, you can look at where CMake puts things by default, and only if you're not satisfied with the default locations (such as the default value of EXECUTABLE_OUTPUT_PATH
), modify only those you need. And try to express them relative to CMAKE_BINARY_DIR
, CMAKE_CURRENT_BINARY_DIR
, PROJECT_BINARY_DIR
etc.
If you look at CMake documentation, you'll see variables partitioned into semantic sections. Except for very special circumstances, you should treat all those listed under "Variables that Provide Information" as read-only inside CMakeLists.
CMake output directory by platform
One way would be to set the bin directories for the project:
math(EXPR platform_bits "${CMAKE_SIZEOF_VOID_P} * 8")
set(platform_dir ${CMAKE_SYSTEM_NAME}${platform_bits}-${CMAKE_CXX_COMPILER_ID}${CMAKE_CXX_COMPILER_VERSION})
foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
foreach(var CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config} CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config} CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config})
set(${var} "${CMAKE_BINARY_DIR}/${platform_dir}-${config}")
string(TOLOWER "${${var}}" ${var})
endforeach()
endforeach()
This won't give you the exact directory names you are looking for, but is a good start. You can look at the CMake variables list for a list of platform specific configuration information. You would then need to apply some logic that will transform the CMake defined values into the specific ones you are looking for.
how to make Cmake output relative path?
(1)Solution to the first problem:Add the following code to your outermost CMakeLists.txt:
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_SOURCE_DIR}/custom_output.sh")
The global RULE_LAUNCH_COMPILE property is set to a custom launch script named custom_output.sh which needs to be added to the root of the CMake source tree:
#!/bin/bash
# shell script invoked with the following arguments
# $(CXX) $(CXX_DEFINES) $(CXX_FLAGS) -o OBJECT_FILE -c SOURCE_FILE
# extract parameters
SOURCE_FILE="${@: -1:1}"
OBJECT_FILE="${@: -3:1}"
# invoke compiler
{ "$@" 2> >(sed 's@^/mnt/d/demo/@@'|sed "s/warning/${esc}[32m&${esc}[0m/g"|sed "s/error/${esc}[31m&${esc}[0m/g" >&3); } 3>&2
it would output stderr messages also on stderr and transform it to relative path.Where "/mnt/d/demo/" is the string to be deleted. What to delete depends on the source code relative path.
(2)You can use the following command from gdb for remapping to solve the second problem:
set substitute-path old_path new_path
You need add follow code to you launch.json
"customLaunchSetupCommands": [
{
"text": "set substitute-path /mnt/d d:/",
"description": "change directory to workspace",
"ignoreFailures": false
}
]
If you debug with Cortex Debug you should add follw code to you launch.json
"postLaunchCommands": ["set substitute-path /mnt/d d:/"]
CMake: write executables to multiple subdirectories
You may set CMAKE_RUNTIME_OUTPUT_DIRECTORY
variable as many times as you want. Each setting will affect only on the executables created since that setting until the next one.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Futher executables will be placed under 'bin/'
add_executable(my_program <sources>...)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/tests)
# Futher executables will be placed under 'bin/tests/' instead
add_executable(test1 <sources>...)
add_executable(test2 <sources>...)
If you are creating the tests in the separate CMakeLists.txt
, the settings can be made modular:
CMakeLists.txt:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Futher executables will be placed under 'bin/'
add_executable(my_program <sources>...)
add_subdirectory(tests)
tests/CMakeLists.txt:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/tests)
# Executables created below will be placed under 'bin/tests/' instead
add_executable(test1 <sources>...)
add_executable(test2 <sources>...)
Actually, when you call add_executable
, it just uses the current value of the CMAKE_RUNTIME_OUTPUT_DIRECTORY
variable. This fact can be found in the documentation about RUNTIME_OUTPUT_DIRECTORY
target property, which is affected by the variable.
Related Topics
Why Can't I Compile an Unordered_Map With a Pair as Key
How Does Generic Lambda Work in C++14
Explicit Specialization in Non-Namespace Scope
Why Is Address Zero Used For the Null Pointer
How to Pass a Member Function Pointer
How to Forward Declare an Inner Class
How to Assert That a Constexpr If Else Clause Never Happen
Forward Declaration of a Typedef in C++
Printing 1 to 1000 Without Loop or Conditionals
Is Ncurses Available For Windows
Do Rvalue References to Const Have Any Use
How to Take a Screenshot in a Windows Application
Catching Access Violation Exceptions
How to Return Local Array in C++
Constants and Compiler Optimization in C++
C++ Redefinition Header Files (Winsock2.H)
"Invalid Use of Incomplete Type" Error With Partial Template Specialization