Visual Studio: Add support for configuration-dependent sources
Take the following CMakeLists.txt
:
cmake_minimum_required(VERSION 2.9)
project(Sample)
file(WRITE main.cpp "int main() {}")
file(WRITE Release.cpp "")
file(WRITE Debug.cpp "")
add_executable(Sample
main.cpp
$<$<CONFIG:Debug>:Debug.cpp>
$<$<CONFIG:Release>:Release.cpp>
)
Now execute it by doing the following from the directory where it is:
cmake -E remove_directory build
cmake -E make_directory build
cmake -E chdir build cmake ../
With my CMake 3.9.3 it produces the following output:
-- Building for: Visual Studio 15 2017
-- The C compiler identification is MSVC 19.14.26433.0
-- The CXX compiler identification is MSVC 19.14.26433.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.14.26428/bin/Hostx86/x86/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.14.26428/bin/Hostx86/x86/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.14.26428/bin/Hostx86/x86/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.14.26428/bin/Hostx86/x86/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
-- Generating done
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
CMake Error in CMakeLists.txt:
Target "Sample" has source files which vary by configuration. This is not
supported by the "Visual Studio 15 2017" generator.
Config "Debug":
C:/Sample/build/main.cpp
C:/Sample/build/Debug.cpp
C:/Sample/CMakeLists.txt
Config "Release":
C:/Sample/build/main.cpp
C:/Sample/build/Release.cpp
C:/Sample/CMakeLists.txt
-- Build files have been written to: C:/Sample/build
As can be seen the same issue is reported many times. Yet it doesn't seem to be a real issue with Visual Studio. Generated solution and project files are all fine and build OK with command:
cmake -E chdir build cmake --build .
The generated solution and projects behave in Visual Studio as expected. Source files use "Exclude From Build" property to be included/excluded depending on current configuration. In fact, this is quite nice feature as it shows all files in the project but marks ones that are not used in current configuration.
I tried to analyze this issue. This is what I found out.
The behavior is expected. In fact, it is tested for with Tests/RunCMake/TargetSources/RunCMakeTest.cmake
which invokes (for Visual Studio and Xcode) ConfigNotAllowed.cmake
and expecting output from ConfigNotAllowed-stderr.txt
.
Error itself is generated by cmGeneratorTarget::GetConfigCommonSourceFiles
in Source/cmGeneratorTarget.cxx
. However, there is no direct condition there - it doesn't seem there is any check if the generator actually supports this or not. Perhaps such check is done on a higher level - I don't know the code enough to verify it.
To sum up, generator behavior seems wrong here. Visual Studio does support such scenarios. In fact, it supports them quite nicely in a natural way (for itself). There is no reason to generate errors. And even less so to generate so many of them. Can this be corrected?