Commit 5c6c0344 authored by Michael Stürmer's avatar Michael Stürmer Committed by Brad King

C# support: add compiler detection for MSVC

parent 3874843f
Pipeline #38766 passed with stage
set(CMAKE_CSharp_COMPILER "@CMAKE_CSharp_COMPILER@")
set(CMAKE_CSharp_COMPILER_ID "@CMAKE_CSharp_COMPILER_ID@")
set(CMAKE_CSharp_COMPILER_VERSION "@CMAKE_CSharp_COMPILER_VERSION@")
set(CMAKE_CSharp_COMPILER_WORKS "@CMAKE_CSharp_COMPILER_WORKS@")
set(CMAKE_CSharp_COMPILER_ID_RUN "@CMAKE_CSharp_COMPILER_ID_RUN@")
set(CMAKE_CSharp_IGNORE_EXTENSIONS "inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC")
set(CMAKE_CSharp_SOURCE_FILE_EXTENSIONS "cs")
using System;
namespace CSharp
{
public class CSharpApp
{
const string InfoCompiler = "INFO:compiler[Microsoft "
#if PlatformToolsetv100
+ "Visual Studio"
#elif PlatformToolsetv110
+ "Visual Studio"
#elif PlatformToolsetv120
+ "Visual Studio"
#elif PlatformToolsetv140
+ "Visual Studio"
#elif PlatformToolsetv141
+ "Visual Studio"
#else
+ "unknown"
#endif
+ "]";
const string InfoPlatform = "INFO:platform[Windows]";
const string InfoArchitecture = "INFO:arch["
#if Platformx64
+ "x64"
#elif Platformx86
+ "x86"
#elif PlatformxWin32
+ "Win32]"
#else
+ "unknown"
#endif
+ "]";
const string InfoCompilerVersion = "INFO:compiler_version["
#if PlatformToolsetv100
+ "2010"
#elif PlatformToolsetv110
+ "2012"
#elif PlatformToolsetv120
+ "2013"
#elif PlatformToolsetv140
+ "2015"
#elif PlatformToolsetv141
+ "2017"
#else
+ "9999"
#endif
+ "]";
static void Main(string[] args)
{
// we have to print the lines to make sure
// the compiler does not optimize them away ...
System.Console.WriteLine(InfoCompiler);
System.Console.WriteLine(InfoPlatform);
System.Console.WriteLine(InfoArchitecture);
System.Console.WriteLine(InfoCompilerVersion);
}
}
}
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# This file sets the basic flags for the C# language in CMake.
# It also loads the available platform file for the system-compiler
# if it exists.
set(CMAKE_BASE_NAME)
get_filename_component(CMAKE_BASE_NAME "${CMAKE_CSharp_COMPILER}" NAME_WE)
set(CMAKE_BUILD_TYPE_INIT Debug)
set(CMAKE_CSharp_FLAGS_INIT "/define:TRACE /langversion:3 /nowin32manifest")
set(CMAKE_CSharp_FLAGS_DEBUG_INIT "/debug:full /optimize- /warn:3 /errorreport:prompt /define:DEBUG")
set(CMAKE_CSharp_FLAGS_RELEASE_INIT "/debug:none /optimize /warn:1 /errorreport:queue")
set(CMAKE_CSharp_FLAGS_RELWITHDEBINFO_INIT "/debug:full /optimize-")
set(CMAKE_CSharp_FLAGS_MINSIZEREL_INIT "/debug:none /optimize")
set(CMAKE_CSharp_LINKER_SUPPORTS_PDB ON)
set(CMAKE_CSharp_STANDARD_LIBRARIES_INIT "System")
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(CMAKE_CSharp_FLAGS_INIT "/platform:x86 ${CMAKE_CSharp_FLAGS_INIT}")
else()
set(CMAKE_CSharp_FLAGS_INIT "/platform:x64 ${CMAKE_CSharp_FLAGS_INIT}")
endif()
# This should be included before the _INIT variables are
# used to initialize the cache. Since the rule variables
# have if blocks on them, users can still define them here.
# But, it should still be after the platform file so changes can
# be made to those values.
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
# copy the values from the LIBRARY variables
if(NOT CMAKE_MODULE_EXISTS)
set(CMAKE_SHARED_MODULE_CSharp_FLAGS ${CMAKE_SHARED_LIBRARY_CSharp_FLAGS})
set(CMAKE_SHARED_MODULE_CREATE_CSharp_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_CSharp_FLAGS})
endif()
# add the flags to the cache based
# on the initial values computed in the platform/*.cmake files
# use _INIT variables so that this only happens the first time
# and you can set these flags in the cmake cache
set(CMAKE_CSharp_FLAGS_INIT "$ENV{CSharpFLAGS} ${CMAKE_CSharp_FLAGS_INIT}")
# avoid just having a space as the initial value for the cache
if(CMAKE_CSharp_FLAGS_INIT STREQUAL " ")
set(CMAKE_CSharp_FLAGS_INIT)
endif()
set (CMAKE_CSharp_FLAGS "${CMAKE_CSharp_FLAGS_INIT}" CACHE STRING
"Flags used by the C# compiler during all build types.")
if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
set (CMAKE_CSharp_FLAGS_DEBUG "${CMAKE_CSharp_FLAGS_DEBUG_INIT}" CACHE STRING
"Flags used by the C# compiler during debug builds.")
set (CMAKE_CSharp_FLAGS_MINSIZEREL "${CMAKE_CSharp_FLAGS_MINSIZEREL_INIT}" CACHE STRING
"Flags used by the C# compiler during release builds for minimum size.")
set (CMAKE_CSharp_FLAGS_RELEASE "${CMAKE_CSharp_FLAGS_RELEASE_INIT}" CACHE STRING
"Flags used by the C# compiler during release builds.")
set (CMAKE_CSharp_FLAGS_RELWITHDEBINFO "${CMAKE_CSharp_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
"Flags used by the C# compiler during release builds with debug info.")
endif()
if(CMAKE_CSharp_STANDARD_LIBRARIES_INIT)
set(CMAKE_CSharp_STANDARD_LIBRARIES "${CMAKE_CSharp_STANDARD_LIBRARIES_INIT}"
CACHE STRING "Libraries linked by default with all C# applications.")
mark_as_advanced(CMAKE_CSharp_STANDARD_LIBRARIES)
endif()
# set missing flags (if they do not exist). This is needed in the
# unlikely case that you have only C# and no C/C++ targets in your
# project.
if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS)
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_DEBUG)
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_RELEASE)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL)
set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO)
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_DEBUG)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_RELEASE)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_MINSIZEREL)
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "" CACHE STRING "" FORCE)
endif()
if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO)
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE STRING "" FORCE)
endif()
set(CMAKE_CSharp_CREATE_SHARED_LIBRARY "CSharp_NO_CREATE_SHARED_LIBRARY")
set(CMAKE_CSharp_CREATE_SHARED_MODULE "CSharp_NO_CREATE_SHARED_MODULE")
set(CMAKE_CSharp_LINK_EXECUTABLE "CSharp_NO_LINK_EXECUTABLE")
mark_as_advanced(
CMAKE_CSharp_FLAGS
CMAKE_CSharp_FLAGS_RELEASE
CMAKE_CSharp_FLAGS_RELWITHDEBINFO
CMAKE_CSharp_FLAGS_MINSIZEREL
CMAKE_CSharp_FLAGS_DEBUG
)
set(CMAKE_CSharp_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_CSharp_INFORMATION_LOADED 1)
......@@ -15,7 +15,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
function(compiler_id_detection outvar lang)
if (NOT lang STREQUAL Fortran)
if (NOT lang STREQUAL Fortran AND NOT lang STREQUAL CSharp)
file(GLOB lang_files
"${CMAKE_ROOT}/Modules/Compiler/*-DetermineCompiler.cmake")
set(nonlang CXX)
......
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])")
message(FATAL_ERROR
"C# is currently only supported for Microsoft Visual Studio 2010 and later.")
endif()
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
#include(Platform/${CMAKE_SYSTEM_NAME}-Determine-CSharp OPTIONAL)
#include(Platform/${CMAKE_SYSTEM_NAME}-CSharp OPTIONAL)
if(NOT CMAKE_CSharp_COMPILER_NAMES)
set(CMAKE_CSharp_COMPILER_NAMES csc)
endif()
# Build a small source file to identify the compiler.
if(NOT CMAKE_CSharp_COMPILER_ID_RUN)
set(CMAKE_CSharp_COMPILER_ID_RUN 1)
# Try to identify the compiler.
set(CMAKE_CSharp_COMPILER_ID_STRINGS_PARAMETERS ENCODING UTF-16LE)
set(CMAKE_CSharp_COMPILER_ID)
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
CMAKE_DETERMINE_COMPILER_ID(CSharp CSFLAGS CMakeCSharpCompilerId.cs)
execute_process(COMMAND "${CMAKE_CSharp_COMPILER}" "/help" OUTPUT_VARIABLE output)
string(REPLACE "\n" ";" output "${output}")
foreach(line ${output})
string(TOUPPER ${line} line)
string(REGEX REPLACE "^.*COMPILER.*VERSION[^\\.0-9]*([\\.0-9]+).*$" "\\1" version "${line}")
if(version AND NOT "x${line}" STREQUAL "x${version}")
set(CMAKE_CSharp_COMPILER_VERSION ${version})
break()
endif()
endforeach()
message(STATUS "The CSharp compiler version is ${CMAKE_CSharp_COMPILER_VERSION}")
endif()
# configure variables set in this file for fast reload later on
configure_file(${CMAKE_ROOT}/Modules/CMakeCSharpCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeCSharpCompiler.cmake
@ONLY
)
......@@ -164,6 +164,10 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(v Intel)
set(ext vfproj)
set(id_cl ifort.exe)
elseif(lang STREQUAL CSharp)
set(v 10)
set(ext csproj)
set(id_cl csc.exe)
elseif(NOT "${vs_version}" VERSION_LESS 10)
set(v 10)
set(ext vcxproj)
......@@ -447,8 +451,12 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
set(SIMULATE_ID)
set(SIMULATE_VERSION)
file(STRINGS ${file}
CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38
${CMAKE_${lang}_COMPILER_ID_STRINGS_PARAMETERS}
REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
set(COMPILER_ID_TWICE)
# In C# binaries, some strings are found more than once.
list(REMOVE_DUPLICATES CMAKE_${lang}_COMPILER_ID_STRINGS)
foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]")
if(COMPILER_ID)
......
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
if(CMAKE_CSharp_COMPILER_FORCED)
# The compiler configuration was forced by the user.
# Assume the user has configured all compiler information.
set(CMAKE_CSharp_COMPILER_WORKS TRUE)
return()
endif()
include(CMakeTestCompilerCommon)
unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs")
# This file is used by EnableLanguage in cmGlobalGenerator to
# determine that that selected C# compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
if(NOT CMAKE_CSharp_COMPILER_WORKS)
PrintTestCompilerStatus("C#" "${CMAKE_CSharp_COMPILER}")
file(WRITE "${test_compile_file}"
"namespace Test {"
" public class CSharp {"
" static void Main(string[] args) {}"
" }"
"}"
)
try_compile(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_BINARY_DIR} "${test_compile_file}"
OUTPUT_VARIABLE __CMAKE_CSharp_COMPILER_OUTPUT
)
# Move result from cache to normal variable.
set(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_CSharp_COMPILER_WORKS})
unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
if(NOT CMAKE_CSharp_COMPILER_WORKS)
message("forcing compiler works to true (will be removed once C# support is integrated)")
set(CMAKE_CSharp_COMPILER_WORKS 1)
endif()
set(CSharp_TEST_WAS_RUN 1)
endif()
if(NOT CMAKE_CSharp_COMPILER_WORKS)
PrintTestCompilerStatus("C#" "${CMAKE_CSharp_COMPILER} -- broken")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the C# compiler works failed with "
"the following output:\n${__CMAKE_CSharp_COMPILER_OUTPUT}\n\n")
message(FATAL_ERROR "The C# compiler \"${CMAKE_CSharp_COMPILER}\" "
"is not able to compile a simple test program.\nIt fails "
"with the following output:\n ${__CMAKE_CSharp_COMPILER_OUTPUT}\n\n"
"CMake will not be able to correctly generate this project.")
else()
if(CSharp_TEST_WAS_RUN)
PrintTestCompilerStatus("C#" "${CMAKE_CSharp_COMPILER} -- works")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if the C# compiler works passed with "
"the following output:\n${__CMAKE_CSharp_COMPILER_OUTPUT}\n\n")
endif()
# Re-configure to save learned information.
configure_file(
${CMAKE_ROOT}/Modules/CMakeCSharpCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeCSharpCompiler.cmake
@ONLY
)
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeCSharpCompiler.cmake)
endif()
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{CAE07175-D007-4FC3-BFE8-47B392814159}</ProjectGuid>
<RootNamespace>CompilerId@id_lang@</RootNamespace>
<Keyword>Win32Proj</Keyword>
@id_system@
@id_system_version@
@id_WindowsTargetPlatformVersion@
@id_WindowsSDKDesktopARMSupport@
</PropertyGroup>
<PropertyGroup>
@id_PreferredToolArchitecture@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@id_toolset@
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<!-- ============================================================ -->
<!-- == set preprocessor definitions == -->
<!-- ============================================================ -->
<PropertyGroup>
<DefineConstants></DefineConstants>
<UnknownValue>Unknown</UnknownValue>
</PropertyGroup>
<!-- Platform -->
<PropertyGroup Condition="'$(Platform)'!=''">
<DefineConstants>$(DefineConstants);Platform$(Platform)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'==''">
<DefineConstants>$(DefineConstants);Platform$(UnknownValue)</DefineConstants>
</PropertyGroup>
<!-- PlatformToolset -->
<PropertyGroup Condition="'$(PlatformToolset)'!=''">
<DefineConstants>$(DefineConstants);PlatformToolset$(PlatformToolset)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(PlatformToolset)'==''">
<DefineConstants>$(DefineConstants);PlatformToolset$(UnknownValue)</DefineConstants>
</PropertyGroup>
<!-- ============================================================ -->
<PropertyGroup>
<OutputPath Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">.\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="@id_src@" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>cd /D &quot;$(MSBuildToolsPath)&quot;
if not %errorlevel%==0 exit -1
if not exist @id_cl@ exit -2
%40echo CMAKE_@id_lang@_COMPILER=$(MSBuildToolsPath)\@id_cl@</PostBuildEvent>
</PropertyGroup>
</Project>
......@@ -26,6 +26,9 @@ add_CMakeOnly_test(CompilerIdCXX)
if(CMAKE_Fortran_COMPILER)
add_CMakeOnly_test(CompilerIdFortran)
endif()
if(CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][0-9])")
add_CMakeOnly_test(CompilerIdCSharp)
endif()
add_CMakeOnly_test(AllFindModules)
......
cmake_minimum_required(VERSION 3.7.0)
project(CompilerIdCSharp CSharp)
foreach(v
CMAKE_CSharp_COMPILER
CMAKE_CSharp_COMPILER_ID
CMAKE_CSharp_COMPILER_VERSION
)
if(${v})
message(STATUS "${v}=[${${v}}]")
else()
message(SEND_ERROR "${v} not set!")
endif()
endforeach()
# Version numbers may only contain numbers and periods.
if(NOT CMAKE_CSharp_COMPILER_VERSION MATCHES
"^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?$"
)
message(SEND_ERROR "Compiler version is not numeric!")
endif()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment