ADD_CUSTOM_TARGET(debug
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
COMMENT "Creating the executable in the debug mode.")
ADD_CUSTOM_TARGET(release
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
COMMENT "Creating the executable in the release mode.")
# instead of calling the following in build subdir, as we used to:
# cmake.exe ../ -DCMAKE_BUILD_TYPE=Debug -G "MSYS Makefiles"
# now we want to try something like:
# cmake.exe ../ -DCMAKE_BUILD_TYPE=SingleBuildDir -G "MSYS Makefiles"
# ... and then have `make debug` build in build/Debug, and `make release` build in build/Release
# see https://stackoverflow.com/questions/10083427/can-cmake-generate-a-single-makefile-that-supports-both-debug-and-release
cmake_minimum_required(VERSION 3.13)
# https://stackoverflow.com/questions/18968979/how-to-make-colorized-message-with-cmake
#if(NOT WIN32) # well, get rid of this, as it detects MINGW bash as WIN32 too
string(ASCII 27 Esc)
set(ColourReset "${Esc}[m")
set(ColourBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
#endif()
if (NOT(EXISTS "${CMAKE_SOURCE_DIR}/main.c" AND NOT IS_DIRECTORY "${CMAKE_SOURCE_DIR}/main.c"))
message("${Cyan}Creating ${CMAKE_SOURCE_DIR}/main.c${ColourReset}")
# https://stackoverflow.com/questions/7637539/how-to-split-strings-across-multiple-lines-in-cmake
# https://stackoverflow.com/questions/69574555/cmake-filegenerate-output-output-file-how-to-write-content-on-multiple
# https://stackoverflow.com/questions/67674998/cmakelists-create-string-with-new-lines
# https://stackoverflow.com/questions/26193171/cmake-how-to-create-a-file-with-make-command # example for file(write
FILE(WRITE ${CMAKE_SOURCE_DIR}/main.c
"#include <stdio.h>\n"
"\n"
"int main() {\n"
" printf(\"Hello from test_cmake_singlebuilddir main.exe!\\n\");\n"
" return 0;\n"
"}\n"
)
endif() # NOT(EXISTS "${CMAKE_SOURCE_DIR}/main.c"
# NOTE: apparently, project command MUST be first;
# else the `make debug` might fail with "Error: could not find CMAKE_PROJECT_NAME in Cache"
# (via [Error could not find CMAKE_PROJECT_NAME in Cache · Issue #90 · facebookresearch/habitat-sim · GitHub](https://github.com/facebookresearch/habitat-sim/issues/90))
project(test_singlebuilddir C)
message("${Cyan}Current CMAKE_BUILD_TYPE mode: ${CMAKE_BUILD_TYPE}${ColourReset}")
if(CMAKE_BUILD_TYPE STREQUAL "SingleBuildDir")
message("${Yellow}Create subdirectories in build (${CMAKE_BINARY_DIR}): ./Debug, ./Release${ColourReset}")
# https://stackoverflow.com/questions/3702115/creating-a-directory-in-cmake
# "CMAKE_BINARY_DIR is defined and cached based on the directory that you run the cmake command" SO:10083427
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Debug)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Release)
message("${Yellow}Creating top-level makefile${ColourReset}") # SO:10083427
message("${Yellow}Initialize Debug directory${ColourReset}")
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} -DCMAKE_BUILD_TYPE=Debug -G "${CMAKE_GENERATOR}"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debug
)
message("${Yellow}Add debug build target${ColourReset}")
ADD_CUSTOM_TARGET(debug
COMMAND ${CMAKE_COMMAND} --build . --target all
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debug
COMMENT "Creating the executable in the debug mode."
)
message("${Yellow}Initialize Release directory${ColourReset}")
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} -DCMAKE_BUILD_TYPE=Release -G "${CMAKE_GENERATOR}"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Release
)
message("${Yellow}Add release build target${ColourReset}")
ADD_CUSTOM_TARGET(release
COMMAND ${CMAKE_COMMAND} --build . --target all
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Release
COMMENT "Creating the executable in the release mode."
)
# if we ended up here, exit early; no real cmake command for that:
# https://stackoverflow.com/questions/57192628/can-i-stop-cmake-processing-without-an-error
# ... but try return?:
return() # seems to work!
endif() # CMAKE_BUILD_TYPE STREQUAL "SingleBuildDir"
message("${Cyan}Proceed with rest of CMakeLists.txt - actual project setup ...${ColourReset}")
#project(test_singlebuilddir C) # if here, "Error: could not find CMAKE_PROJECT_NAME in Cache"
set(CMAKE_C_STANDARD 11)
message("${Cyan}PROJECT_NAME is '${PROJECT_NAME}'${ColourReset}")
set(${PROJECT_NAME}_sources
main.c
)
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_sources})
$ # in the directory where CMakeLists.txt is:
$ mkdir build
$ cd build
$ # check state of this and parent folder
$ ls -la ..
total 20K
drwxr-xr-x 1 user None 0 Oct 6 19:14 ./
drwxr-xr-x 1 user None 0 Oct 6 17:40 ../
drwxr-xr-x 1 user None 0 Oct 6 19:14 build/
-rw-r--r-- 1 user None 4.8K Oct 6 18:59 CMakeLists.txt
$ ls -la .
total 4.0K
drwxr-xr-x 1 user None 0 Oct 6 19:14 ./
drwxr-xr-x 1 user None 0 Oct 6 19:14 ../
$ # run cmake
$ cmake ../ -DCMAKE_BUILD_TYPE=SingleBuildDir -G "MSYS Makefiles"
Creating C:/test_cmake_singlebuilddir/main.c
-- The C compiler identification is GNU 13.2.0
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Current CMAKE_BUILD_TYPE mode: SingleBuildDir
Create subdirectories in build (C:/test_cmake_singlebuilddir/build): ./Debug, ./Release
Creating top-level makefile
Initialize Debug directory
-- The C compiler identification is GNU 13.2.0
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Current CMAKE_BUILD_TYPE mode: Debug
Proceed with rest of CMakeLists.txt - actual project setup ...
PROJECT_NAME is 'test_singlebuilddir'
-- Configuring done
-- Generating done
-- Build files have been written to: C:/test_cmake_singlebuilddir/build/Debug
Add debug build target
Initialize Release directory
-- The C compiler identification is GNU 13.2.0
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
Current CMAKE_BUILD_TYPE mode: Release
Proceed with rest of CMakeLists.txt - actual project setup ...
PROJECT_NAME is 'test_singlebuilddir'
-- Configuring done
-- Generating done
-- Build files have been written to: C:/test_cmake_singlebuilddir/build/Release
Add release build target
-- Configuring done
-- Generating done
-- Build files have been written to: C:/test_cmake_singlebuilddir/build
$ # try it out
$ make debug
make[1]: Entering directory '/c/test_cmake_singlebuilddir/build'
make[2]: Entering directory '/c/test_cmake_singlebuilddir/build'
make[3]: Entering directory '/c/test_cmake_singlebuilddir/build'
Scanning dependencies of target debug
make[3]: Leaving directory '/c/test_cmake_singlebuilddir/build'
make[3]: Entering directory '/c/test_cmake_singlebuilddir/build'
[100%] Creating the executable in the debug mode.
make[4]: Entering directory '/c/test_cmake_singlebuilddir/build/Debug'
make[5]: Entering directory '/c/test_cmake_singlebuilddir/build/Debug'
make[6]: Entering directory '/c/test_cmake_singlebuilddir/build/Debug'
Scanning dependencies of target test_singlebuilddir
make[6]: Leaving directory '/c/test_cmake_singlebuilddir/build/Debug'
make[6]: Entering directory '/c/test_cmake_singlebuilddir/build/Debug'
[ 50%] Building C object CMakeFiles/test_singlebuilddir.dir/main.c.obj
[100%] Linking C executable test_singlebuilddir.exe
make[6]: Leaving directory '/c/test_cmake_singlebuilddir/build/Debug'
[100%] Built target test_singlebuilddir
make[5]: Leaving directory '/c/test_cmake_singlebuilddir/build/Debug'
make[4]: Leaving directory '/c/test_cmake_singlebuilddir/build/Debug'
make[3]: Leaving directory '/c/test_cmake_singlebuilddir/build'
[100%] Built target debug
make[2]: Leaving directory '/c/test_cmake_singlebuilddir/build'
make[1]: Leaving directory '/c/test_cmake_singlebuilddir/build'
$ make release
make[1]: Entering directory '/c/test_cmake_singlebuilddir/build'
make[2]: Entering directory '/c/test_cmake_singlebuilddir/build'
make[3]: Entering directory '/c/test_cmake_singlebuilddir/build'
Scanning dependencies of target release
make[3]: Leaving directory '/c/test_cmake_singlebuilddir/build'
make[3]: Entering directory '/c/test_cmake_singlebuilddir/build'
[100%] Creating the executable in the release mode.
make[4]: Entering directory '/c/test_cmake_singlebuilddir/build/Release'
make[5]: Entering directory '/c/test_cmake_singlebuilddir/build/Release'
make[6]: Entering directory '/c/test_cmake_singlebuilddir/build/Release'
Scanning dependencies of target test_singlebuilddir
make[6]: Leaving directory '/c/test_cmake_singlebuilddir/build/Release'
make[6]: Entering directory '/c/test_cmake_singlebuilddir/build/Release'
[ 50%] Building C object CMakeFiles/test_singlebuilddir.dir/main.c.obj
[100%] Linking C executable test_singlebuilddir.exe
make[6]: Leaving directory '/c/test_cmake_singlebuilddir/build/Release'
[100%] Built target test_singlebuilddir
make[5]: Leaving directory '/c/test_cmake_singlebuilddir/build/Release'
make[4]: Leaving directory '/c/test_cmake_singlebuilddir/build/Release'
make[3]: Leaving directory '/c/test_cmake_singlebuilddir/build'
[100%] Built target release
make[2]: Leaving directory '/c/test_cmake_singlebuilddir/build'
make[1]: Leaving directory '/c/test_cmake_singlebuilddir/build'
$ # check where the produced executables are located:
$ find . -name '*.exe'
./CMakeFiles/3.14.3/CompilerIdC/a.exe
./Debug/CMakeFiles/3.14.3/CompilerIdC/a.exe
./Debug/test_singlebuilddir.exe
./Release/CMakeFiles/3.14.3/CompilerIdC/a.exe
./Release/test_singlebuilddir.exe
3条答案
按热度按时间vq8itlhq1#
据我所知,这不能通过使用一组构建脚本来实现。然而,你可以做的是在你的工作区域有两个子目录:
然后执行:
如有必要,您可以在
build
目录中添加另一个构建脚本,如下所示:xwmevbvl2#
这可以使用
ADD_CUSTOM_TARGET
命令来实现。例如,如果要在makefile中添加调试和发布目标,请将以下内容添加到CMakeLists.txt文件中:然后,在使用cmake进行配置之后,可以在同一目录中运行
make debug
来设置调试目标,并运行make release
来设置发布目标。r6vfmomb3#
感谢@a.sam的回答,我现在可以提供一个独立的工作示例;你可以以后再谢我
:)
本质上,这里我发明了一个
CMAKE_BUILD_TYPE
,它不存在于cmake
中(cmake
不知道它),这里称为SingleBuildDir
,并使用它来区分创建顶级Makefile或调试/发布Makefile。只需保存下面的文件作为
CMakeLists.txt
某处:命令行输出如下:注意我必须传播-g“MSYS 2 Makefiles”,因为我在Windows MSYS 2 bash shell上:
好了-这正是我一直想要的!