It absolutely is. ${CMAKE_SOURCE_DIR}
is the source directory of your project, the place your top-level CMakeLists.txt
is located. ${CMAKE_CURRENT_SOURCE_DIRECTORY}
is the directory of the current CMakeLists.txt
file being processed. But they’re all source directories. If you create anything during the build, it should be somewhere inside ${CMAKE_BINARY_DIR}
or ${CMAKE_CURRENT_BINARY_DIR}
.
I know you’re using Visual Studio, which probably has its own weird ideas about where to store build artifacts (Qt Creator does as well), but that’s a tool issue. If you were to go into a terminal session and run this:
$ cd c:\path\to\your\toplevel\source\directory
$ cmake -B build -S . -G "Visual Studio 17 2022"
What would happen is that CMake would set up a directory C:\path\to\your\toplevel\source\directory\build
where all of the generated configuration and build artifacts live.
When it processes the top-level CMakeLists.txt
, both ${CMAKE_BINARY_DIR}
and ${CMAKE_CURRENT_BINARY_DIR}
are set to C:\path\to\your\toplevel\source\directory\build
. Both ${CMAKE_SOURCE_DIR}
and ${CMAKE_CURRENT_SOURCE_DIR}
are set to C:\path\to\your\toplevel\source\directory
.
Then, when it descends into the src
directory due to the add_directory(src)
in the toplevel CMakeLists.txt
, ${CMAKE_SOURCE_DIR}
and ${CMAKE_BINARY_DIR}
stay the same, but ${CMAKE_CURRENT_SOURCE_DIR}
becomes C:\path\to\your\toplevel\source\directory\src
, and ${CMAKE_CURRENT_BINARY_DIR}
becomes C:\path\to\your\toplevel\source\directory\build\src
.
But if you write anything into any _SOURCE_DIR
path, you’re storing it somewhere in the source of your project.
Install destinations
Writing into the source dir can be valid, for install artifacts — you may want to install your program to C:\path\to\your\toplevel\source\directory\bin
(a path outside the build directory). But you should do that by setting the CMAKE_INSTALL_PREFIX
to C:\path\to\your\toplevel\source\directory\bin
(by adding --install-prefix C:\path\to\your\toplevel\source\directory\bin
or -DCMAKE_INSTALL_PREFIX=C:\path\to\your\toplevel\source\directory\bin
to the cmake
command / VS CMake configuration, not by hardcoding it in your CMakeLists.txt
file), then installing the artifacts right in the install directory:
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION "."
LIBRARY DESTINATION "."
ARCHIVE DESTINATION "."
)
install(DIRECTORY
"${CMAKE_SOURCE_DIR}/src/assets/"
DESTINATION "."
)
# This will create "${CMAKE_INSTALL_PREFIX}/themes"
# with the contents of the directory
install(DIRECTORY
"${tgui_SOURCE_DIR}/themes" DESTINATION "."
)
But the uninstalled, debuggable files that CMake creates during the build should be inside the build directory, so that they can be deleted with the build directory, and so that they’ll be recreated with each build, not persist outside the space where it’s unclear which build they’re from or how they were compiled. (In fact, if you add a BYPRODUCTS
argument to add_custom_command()
listing the files created, they’ll be marked as additional build artifacts and deleted when you clean the build directory.)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND
${CMAKE_COMMAND} -E make_directory
"${CMAKE_BINARY_DIR}/bin"
COMMAND
${CMAKE_COMMAND} -E copy
"$<TARGET_FILE:${PROJECT_NAME}>"
"${CMAKE_BINARY_DIR}/bin/"
BYPRODUCTS
"${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:${PROJECT_NAME}>"
)
There’s probably no real reason to do that for the files created with execute_process()
, because they’re static and don’t need to be recreated. But if you think you might be editing those and want them to be recreated during the build, you can do that copying in add_custom_command()
calls with BYPRODUCTS
as well.
Taking a step back
I should’ve mentioned that if your goal is simply to make the ${PROJECT_NAME}
target output debuggable, and it needs additional files in its directory to do so, it might be better/simpler not to copy that file itself, and instead just copy the other files needed into the same directory where it’s built.
In the same CMakeLists.txt
where you create the ${PROJECT_NAME}
target with add_library()
/ add_executable()
, you can copy in all of the required files to that same directory as a post-build step:
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR/assets/"
"${CMAKE_CURRENT_BINARY_DIR}"
COMMAND
${CMAKE_COMMAND} -E copy_directory
"${tgui_SOURCE_DIR}/src/themes"
"${CMAKE_CURRENT_BINARY_DIR}/themes"
BYPRODUCTS
# (List the files copied from
# "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
"${CMAKE_CURRENT_BINARY_DIR}/themes"
)
…If those files are all that’s required, that should make $<TARGET_FILE:${PROJECT_NAME}>
(aka ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe
probably) executable directly from its build location, which is the simplest way to make it debuggable, and avoids making a redundant extra copy of the executable.