summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst30
-rw-r--r--Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst95
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake20
-rw-r--r--Modules/CMakeFindBinUtils.cmake19
-rw-r--r--Modules/FindLua.cmake1
-rw-r--r--Modules/FindwxWidgets.cmake2
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h12
-rw-r--r--Source/cmGeneratorExpressionParser.cxx7
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx34
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx6
-rw-r--r--Source/cmNinjaTargetGenerator.cxx22
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx99
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h2
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx48
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h2
-rw-r--r--Source/cmake.cxx8
-rw-r--r--Tests/CMakeLists.txt5
-rw-r--r--Tests/CSharpLinkFromCxx/.gitattributes1
-rw-r--r--Tests/CSharpLinkFromCxx/CMakeLists.txt19
-rw-r--r--Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs16
-rw-r--r--Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs12
-rw-r--r--Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp15
-rw-r--r--Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp16
-rw-r--r--Tests/CompileFeatures/default_dialect.c2
-rw-r--r--Tests/RunCMake/XcodeProject/RunCMakeTest.cmake14
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt1
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake4
-rw-r--r--Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt2
31 files changed, 368 insertions, 151 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4d2a9a..6623959 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -310,6 +310,8 @@ endmacro()
# Simply to improve readability of the main script.
#-----------------------------------------------------------------------
macro (CMAKE_BUILD_UTILITIES)
+ find_package(Threads)
+
#---------------------------------------------------------------------
# Create the kwsys library for CMake.
set(KWSYS_NAMESPACE cmsys)
diff --git a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst
index f522c6b..7d3dfd1 100644
--- a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst
+++ b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst
@@ -3,15 +3,29 @@ AUTOGEN_TARGET_DEPENDS
Target dependencies of the corresponding ``_autogen`` target.
-Targets which have their :prop_tgt:`AUTOMOC` target ``ON`` have a
-corresponding ``_autogen`` target which is used to autogenerate generate moc
-files. As this ``_autogen`` target is created at generate-time, it is not
-possible to define dependencies of it, such as to create inputs for the ``moc``
-executable.
+Targets which have their :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` property
+``ON`` have a corresponding ``_autogen`` target which is used to auto generate
+``moc`` and ``uic`` files. As this ``_autogen`` target is created at
+generate-time, it is not possible to define dependencies of it,
+such as to create inputs for the ``moc`` or ``uic`` executable.
-The ``AUTOGEN_TARGET_DEPENDS`` target property can be set instead to a list of
-dependencies for the ``_autogen`` target. The buildsystem will be generated to
-depend on its contents.
+The :prop_tgt:`AUTOGEN_TARGET_DEPENDS` target property can be set instead to a
+list of dependencies of the ``_autogen`` target. Dependencies can be target
+names or file names.
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
+
+Use cases
+^^^^^^^^^
+
+If :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` depends on a file that is either
+
+- a :prop_sf:`GENERATED` non C++ file (e.g. a :prop_sf:`GENERATED` ``.json``
+ or ``.ui`` file) or
+- a :prop_sf:`GENERATED` C++ file that isn't recognized by :prop_tgt:`AUTOMOC`
+ and :prop_tgt:`AUTOUIC` because it's skipped by :prop_sf:`SKIP_AUTOMOC`,
+ :prop_sf:`SKIP_AUTOUIC`, :prop_sf:`SKIP_AUTOGEN` or :policy:`CMP0071` or
+- a file that isn't in the target's sources
+
+it must added to :prop_tgt:`AUTOGEN_TARGET_DEPENDS`.
diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
index b738ecf..69957bf 100644
--- a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
+++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
@@ -1,21 +1,27 @@
AUTOMOC_DEPEND_FILTERS
----------------------
-Filter definitions used by :prop_tgt:`AUTOMOC` to extract file names from
-source code as additional dependencies for the ``moc`` file.
-
-This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON``
-for this target.
+Filter definitions used by :prop_tgt:`AUTOMOC` to extract file names from a
+source file that are registered as additional dependencies for the
+``moc`` file of the source file.
Filters are defined as ``KEYWORD;REGULAR_EXPRESSION`` pairs. First the file
content is searched for ``KEYWORD``. If it is found at least once, then file
names are extracted by successively searching for ``REGULAR_EXPRESSION`` and
taking the first match group.
-Consider a filter extracts the file name ``DEP`` from the content of a file
-``FOO``. If ``DEP`` changes, then the ``moc`` file for ``FOO`` gets rebuilt.
-The file ``DEP`` is searched for first in the vicinity
-of ``FOO`` and afterwards in the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+The file name found in the first match group is searched for
+
+- first in the vicinity of the source file
+- and afterwards in the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+
+If any of the extracted files changes, then the ``moc`` file for the source
+file gets rebuilt even when the source file itself doesn't change.
+
+If any of the extracted files is :prop_sf:`GENERATED` or if it is not in the
+target's sources, then it might be necessary to add it to the
+``_autogen`` target dependencies.
+See :prop_tgt:`AUTOGEN_TARGET_DEPENDS` for reference.
By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from
:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default.
@@ -24,22 +30,75 @@ See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
-Example
-^^^^^^^
+Example 1
+^^^^^^^^^
-Consider a file ``FOO.hpp`` holds a custom macro ``OBJ_JSON_FILE`` and we
-want the ``moc`` file to depend on the macro`s file name argument::
+A header file ``my_class.hpp`` uses a custom macro ``JSON_FILE_MACRO`` which
+is defined in an other header ``macros.hpp``.
+We want the ``moc`` file of ``my_class.hpp`` to depend on the file name
+argument of ``JSON_FILE_MACRO``::
+ // my_class.hpp
class My_Class : public QObject
{
Q_OBJECT
- OBJ_JSON_FILE ( "DEP.json" )
+ JSON_FILE_MACRO ( "info.json" )
+ ...
+ };
+
+In ``CMakeLists.txt`` we add a filter to
+:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` like this::
+
+ list( APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
+ "JSON_FILE_MACRO"
+ "[\n][ \t]*JSON_FILE_MACRO[ \t]*\\([ \t]*\"([^\"]+)\""
+ )
+
+We assume ``info.json`` is a plain (not :prop_sf:`GENERATED`) file that is
+listed in the target's source. Therefore we do not need to add it to
+:prop_tgt:`AUTOGEN_TARGET_DEPENDS`.
+
+Example 2
+^^^^^^^^^
+
+In the target ``my_target`` a header file ``complex_class.hpp`` uses a
+custom macro ``JSON_BASED_CLASS`` which is defined in an other header
+``macros.hpp``::
+
+ // macros.hpp
...
+ #define JSON_BASED_CLASS(name, json) \
+ class name : public QObject \
+ { \
+ Q_OBJECT \
+ Q_PLUGIN_METADATA(IID "demo" FILE json) \
+ name() {} \
};
+ ...
+
+::
-Then we might use :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` to
-define a filter like this::
+ // complex_class.hpp
+ #pragma once
+ JSON_BASED_CLASS(Complex_Class, "meta.json")
+ // end of file
- set(CMAKE_AUTOMOC_DEPEND_FILTERS
- "OBJ_JSON_FILE" "[\n][ \t]*OBJ_JSON_FILE[ \t]*\\([ \t]*\"([^\"]+)\""
+Since ``complex_class.hpp`` doesn't contain a ``Q_OBJECT`` macro it would be
+ignored by :prop_tgt:`AUTOMOC`. We change this by adding ``JSON_BASED_CLASS``
+to :variable:`CMAKE_AUTOMOC_MACRO_NAMES`::
+
+ list(APPEND CMAKE_AUTOMOC_MACRO_NAMES "JSON_BASED_CLASS")
+
+We want the ``moc`` file of ``complex_class.hpp`` to depend on
+``meta.json``. So we add a filter to
+:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`::
+
+ list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
+ "JSON_BASED_CLASS"
+ "[\n^][ \t]*JSON_BASED_CLASS[ \t]*\\([^,]*,[ \t]*\"([^\"]+)\""
)
+
+Additionally we assume ``meta.json`` is :prop_sf:`GENERATED` which is
+why we have to add it to :prop_tgt:`AUTOGEN_TARGET_DEPENDS`::
+
+ set_property(TARGET my_target APPEND PROPERTY AUTOGEN_TARGET_DEPENDS "meta.json")
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index cf502f6..5ddd64f 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -66,12 +66,20 @@ else()
# The order is 95 or newer compilers first, then 90,
# then 77 or older compilers, gnu is always last in the group,
# so if you paid for a compiler it is picked by default.
- set(CMAKE_Fortran_COMPILER_LIST
- ftn
- ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 pgfortran lf95 xlf95
- fort flang gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77
- frt pgf77 xlf fl32 af77 g77 f77 nag
- )
+ if(CMAKE_HOST_WIN32)
+ set(CMAKE_Fortran_COMPILER_LIST
+ ifort pgf95 pgfortran lf95 fort
+ flang gfortran gfortran-4 g95 f90 pgf90
+ pgf77 g77 f77 nag
+ )
+ else()
+ set(CMAKE_Fortran_COMPILER_LIST
+ ftn
+ ifort ifc efc pgf95 pgfortran lf95 xlf95 fort
+ flang gfortran gfortran-4 g95 f90 pgf90
+ frt pgf77 xlf g77 f77 nag
+ )
+ endif()
# Vendor-specific compiler names.
set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77)
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index ece0547..1b6823c 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -19,6 +19,25 @@
# on UNIX, cygwin and mingw
+if(CMAKE_LINKER)
+ # we only get here if CMAKE_LINKER was specified using -D or a pre-made CMakeCache.txt
+ # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+ # find the linker in the PATH if necessary
+ get_filename_component(_CMAKE_USER_LINKER_PATH "${CMAKE_LINKER}" PATH)
+ if(NOT _CMAKE_USER_LINKER_PATH)
+ find_program(CMAKE_LINKER_WITH_PATH NAMES ${CMAKE_LINKER} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+ if(CMAKE_LINKER_WITH_PATH)
+ set(CMAKE_LINKER ${CMAKE_LINKER_WITH_PATH})
+ get_property(_CMAKE_LINKER_CACHED CACHE CMAKE_LINKER PROPERTY TYPE)
+ if(_CMAKE_LINKER_CACHED)
+ set(CMAKE_LINKER "${CMAKE_LINKER}" CACHE STRING "Default Linker" FORCE)
+ endif()
+ unset(_CMAKE_LINKER_CACHED)
+ endif()
+ unset(CMAKE_LINKER_WITH_PATH CACHE)
+ endif()
+endif()
+
# if it's the MS C/CXX compiler, search for link
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC"
OR "x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xMSVC"
diff --git a/Modules/FindLua.cmake b/Modules/FindLua.cmake
index b59b9b3..7eba206 100644
--- a/Modules/FindLua.cmake
+++ b/Modules/FindLua.cmake
@@ -122,6 +122,7 @@ endif ()
if (NOT LUA_VERSION_STRING)
foreach (subdir IN LISTS _lua_include_subdirs)
unset(LUA_INCLUDE_PREFIX CACHE)
+ unset(LUA_INCLUDE_PREFIX)
find_path(LUA_INCLUDE_PREFIX ${subdir}/lua.h
HINTS
ENV LUA_DIR
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index e21ec38..965948e 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -837,7 +837,7 @@ else()
# extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES)
string(REGEX MATCHALL "-L[^;]+"
wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARIES}")
- string(REPLACE "-L" ""
+ string(REGEX REPLACE "-L([^;]+)" "\\1"
wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARY_DIRS}")
DBG_MSG_V("wxWidgets_LIBRARIES=${wxWidgets_LIBRARIES}")
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index e7c0732..a0010a2 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -765,6 +765,7 @@ target_link_libraries(CMakeLib cmsys
${CMAKE_LIBUV_LIBRARIES}
${CMAKE_LIBRHASH_LIBRARIES}
${CMake_KWIML_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 1477f0d..f1fdb60 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 11)
-set(CMake_VERSION_PATCH 20180220)
+set(CMake_VERSION_PATCH 20180226)
#set(CMake_VERSION_RC 1)
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 92dac79..0561799 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <string>
+#include <utility>
#include <vector>
struct cmGeneratorExpressionContext;
@@ -64,17 +65,16 @@ private:
struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
GeneratorExpressionContent(const char* startContent, size_t length);
- void SetIdentifier(
- std::vector<cmGeneratorExpressionEvaluator*> const& identifier)
+
+ void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
{
- this->IdentifierChildren = identifier;
+ this->IdentifierChildren = std::move(identifier);
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> const&
- parameters)
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters)
{
- this->ParamChildren = parameters;
+ this->ParamChildren = std::move(parameters);
}
Type GetType() const override
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index 278de04..7b4dc7b 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stddef.h>
+#include <utility>
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
const std::vector<cmGeneratorExpressionToken>& tokens)
@@ -92,7 +93,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
- content->SetIdentifier(identifier);
+ content->SetIdentifier(std::move(identifier));
result.push_back(content);
return;
}
@@ -198,8 +199,8 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
GeneratorExpressionContent* content =
new GeneratorExpressionContent(startToken->Content, contentLength);
- content->SetIdentifier(identifier);
- content->SetParameters(parameters);
+ content->SetIdentifier(std::move(identifier));
+ content->SetParameters(std::move(parameters));
result.push_back(content);
}
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index a4570e1..fa7dc51 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -737,26 +737,24 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
cmGeneratorTarget const* gt)
{
- // check to see if this is a C# build
- std::set<std::string> languages;
- {
- // Issue diagnostic if the source files depend on the config.
- std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
- return false;
- }
- // Only "real" targets are allowed to be C# targets.
- if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) {
- return false;
- }
+ // C# targets can be defined with add_library() (using SHARED or STATIC) and
+ // also using add_executable(). We do not treat imported C# targets the same
+ // (these come in as UTILITY)
+ if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ gt->GetType() != cmStateEnums::EXECUTABLE) {
+ return false;
}
- gt->GetLanguages(languages, "");
- if (languages.size() == 1) {
- if (*languages.begin() == "CSharp") {
- return true;
- }
+
+ // Issue diagnostic if the source files depend on the config.
+ std::vector<cmSourceFile*> sources;
+ if (!gt->GetConfigCommonSourceFiles(sources)) {
+ return false;
}
- return false;
+
+ std::set<std::string> languages;
+ gt->GetLanguages(languages, "");
+ return languages.size() == 1 && languages.count("CSharp") > 0;
}
bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 2a38599..d3f5aac 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -459,7 +459,11 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// Add ZERO_CHECK
bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
- if (regenerate) {
+ bool generateTopLevelProjectOnly =
+ mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+ bool isTopLevel =
+ !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid();
+ if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
this->CreateReRunCMakeFile(root, gens);
std::string file =
this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index f4faf47..e18959b 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -856,9 +856,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
+
if (!this->NeedDepTypeMSVC(language)) {
- vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- objectFileName + ".d", cmOutputConverter::SHELL);
+ bool replaceExt(false);
+ if (!language.empty()) {
+ std::string repVar = "CMAKE_";
+ repVar += language;
+ repVar += "_DEPFILE_EXTENSION_REPLACE";
+ replaceExt = this->Makefile->IsOn(repVar);
+ }
+ if (!replaceExt) {
+ // use original code
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".d", cmOutputConverter::SHELL);
+ } else {
+ // Replace the original source file extension with the
+ // depend file extension.
+ std::string dependFileName =
+ cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL);
+ }
}
this->ExportObjectCompileCommand(
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 92d67db..c7b60b9 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -856,10 +856,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences()
{
- for (std::vector<TargetsFileAndConfigs>::iterator i =
- this->TargetsFileAndConfigsVec.begin();
- i != this->TargetsFileAndConfigsVec.end(); ++i) {
- TargetsFileAndConfigs const& tac = *i;
+ for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
this->WriteString("<Import Project=\"", 3);
(*this->BuildFileStream) << tac.File << "\" ";
(*this->BuildFileStream) << "Condition=\"";
@@ -894,10 +891,9 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
}
if (!references.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::iterator ri = references.begin();
- ri != references.end(); ++ri) {
+ for (std::string const& ri : references) {
this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\">\n";
this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
this->WriteString("</Reference>\n", 2);
}
@@ -910,13 +906,11 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
{
this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
+ for (std::string const& c : this->Configurations) {
this->WriteString("<ProjectConfiguration Include=\"", 2);
- (*this->BuildFileStream) << *i << "|" << this->Platform << "\">\n";
+ (*this->BuildFileStream) << c << "|" << this->Platform << "\">\n";
this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream) << *i << "</Configuration>\n";
+ (*this->BuildFileStream) << c << "</Configuration>\n";
this->WriteString("<Platform>", 3);
(*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
<< "</Platform>\n";
@@ -927,10 +921,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("PropertyGroup", *i, 1,
+ for (std::string const& c : this->Configurations) {
+ this->WritePlatformConfigTag("PropertyGroup", c, 1,
" Label=\"Configuration\"", "\n");
if (this->ProjectType != csproj) {
@@ -977,12 +969,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
if (this->MSTools) {
if (!this->Managed) {
- this->WriteMSToolConfigurationValues(*i);
+ this->WriteMSToolConfigurationValues(c);
} else {
- this->WriteMSToolConfigurationValuesManaged(*i);
+ this->WriteMSToolConfigurationValuesManaged(c);
}
} else if (this->NsightTegra) {
- this->WriteNsightTegraConfigurationValues(*i);
+ this->WriteNsightTegraConfigurationValues(c);
}
this->WriteString("</PropertyGroup>\n", 1);
@@ -1132,10 +1124,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands()
this->CSharpCustomCommandNames.clear();
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- this->WriteCustomCommand(*si);
+ for (cmSourceFile const* si : customCommands) {
+ this->WriteCustomCommand(si);
}
// Add CMakeLists.txt file with rule to re-run CMake for user convenience.
@@ -1154,9 +1144,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand(
if (this->SourcesVisited.insert(sf).second) {
if (std::vector<cmSourceFile*> const* depends =
this->GeneratorTarget->GetSourceDepends(sf)) {
- for (std::vector<cmSourceFile*>::const_iterator di = depends->begin();
- di != depends->end(); ++di) {
- this->WriteCustomCommand(*di);
+ for (cmSourceFile const* di : *depends) {
+ this->WriteCustomCommand(di);
}
}
if (cmCustomCommand const* command = sf->GetCustomCommand()) {
@@ -1179,10 +1168,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// VS 10 will always rebuild a custom command attached to a .rule
// file that doesn't exist so create the file explicitly.
if (source->GetPropertyAsBool("__CMAKE_RULE")) {
- if (!cmSystemTools::FileExists(sourcePath.c_str())) {
+ if (!cmSystemTools::FileExists(sourcePath)) {
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(sourcePath);
- cmSystemTools::MakeDirectory(path.c_str());
+ cmSystemTools::MakeDirectory(path);
cmsys::ofstream fout(sourcePath.c_str());
if (fout) {
fout << "# generated from CMake\n";
@@ -1216,20 +1205,17 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
this->WriteString("</None>\n", 2);
this->WriteString("</ItemGroup>\n", 1);
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- cmCustomCommandGenerator ccg(command, *i, lg);
+ for (std::string const& c : this->Configurations) {
+ cmCustomCommandGenerator ccg(command, c, lg);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg));
// input files for custom command
std::stringstream inputs;
inputs << cmVS10EscapeXML(source->GetFullPath());
- for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (std::string const& d : ccg.GetDepends()) {
std::string dep;
- if (lg->GetRealDependency(*d, *i, dep)) {
+ if (lg->GetRealDependency(d, c, dep)) {
ConvertToWindowsSlash(dep);
inputs << ";" << cmVS10EscapeXML(dep);
}
@@ -1237,15 +1223,14 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// output files for custom command
std::stringstream outputs;
const char* sep = "";
- for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
- std::string out = *o;
+ for (std::string const& o : ccg.GetOutputs()) {
+ std::string out = o;
ConvertToWindowsSlash(out);
outputs << sep << cmVS10EscapeXML(out);
sep = ";";
}
if (this->ProjectType == csproj) {
- std::string name = "CustomCommand_" + *i + "_" +
+ std::string name = "CustomCommand_" + c + "_" +
cmSystemTools::ComputeStringMD5(sourcePath);
std::string inputs_s = inputs.str();
std::string outputs_s = outputs.str();
@@ -1253,10 +1238,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
script = cmVS10EscapeQuotes(script);
inputs_s = cmVS10EscapeQuotes(inputs_s);
outputs_s = cmVS10EscapeQuotes(outputs_s);
- this->WriteCustomRuleCSharp(*i, name, script, inputs_s, outputs_s,
+ this->WriteCustomRuleCSharp(c, name, script, inputs_s, outputs_s,
comment);
} else {
- this->WriteCustomRuleCpp(*i, script, inputs.str(), outputs.str(),
+ this->WriteCustomRuleCpp(c, script, inputs.str(), outputs.str(),
comment);
}
}
@@ -1314,8 +1299,8 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath(
{
return forceRelative
? cmSystemTools::RelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str())
- : path.c_str();
+ this->LocalGenerator->GetCurrentBinaryDirectory(), path)
+ : path;
}
static void ConvertToWindowsSlash(std::string& s)
@@ -1341,10 +1326,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->GeneratorTarget->GetAllConfigSources();
std::set<cmSourceGroup*> groupsUsed;
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- std::string const& source = si->Source->GetFullPath();
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+ std::string const& source = si.Source->GetFullPath();
cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source, sourceGroups);
groupsUsed.insert(sourceGroup);
@@ -1376,9 +1359,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
"xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
this->WriteString(project_defaults.c_str(), 0);
- for (ToolSourceMap::const_iterator ti = this->Tools.begin();
- ti != this->Tools.end(); ++ti) {
- this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
+ for (auto const& ti : this->Tools) {
+ this->WriteGroupSources(ti.first.c_str(), ti.second, sourceGroups);
}
// Added files are images and the manifest.
@@ -1510,7 +1492,7 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
}
void cmVisualStudio10TargetGenerator::WriteGroupSources(
- const char* name, ToolSources const& sources,
+ std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>& sourceGroups)
{
this->WriteString("<ItemGroup>\n", 1);
@@ -1847,7 +1829,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
if (this->LocalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS10 &&
- cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
+ cmSystemTools::FileIsFullPath(sourceFile)) {
// Normal path conversion resulted in a full path. VS 10 (but not 11)
// refuses to show the property page in the IDE for a source file with a
// full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
@@ -2168,7 +2150,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
*source);
}
clOptions.AddIncludes(includeList);
- clOptions.SetConfiguration(config.c_str());
+ clOptions.SetConfiguration(config);
clOptions.PrependInheritedString("AdditionalOptions");
clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", lang);
@@ -3451,6 +3433,17 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmComputeLinkInformation::Item const& l : libs) {
+ // Do not allow C# targets to be added to the LIB listing. LIB files are
+ // used for linking C++ dependencies. C# libraries do not have lib files.
+ // Instead, they compile down to C# reference libraries (DLL files). The
+ // `<ProjectReference>` elements added to the vcxproj are enough for the
+ // IDE to deduce the DLL file required by other C# projects that need its
+ // reference library.
+ if (l.Target &&
+ cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(l.Target)) {
+ continue;
+ }
+
if (l.IsPath) {
std::string path =
this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index adef127..124db4e 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -153,7 +153,7 @@ private:
void WriteEvent(const char* name,
std::vector<cmCustomCommand> const& commands,
std::string const& configName);
- void WriteGroupSources(const char* name, ToolSources const& sources,
+ void WriteGroupSources(std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>&);
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index ccbff83..fb74fda 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -152,9 +152,8 @@ bool cmVisualStudioGeneratorOptions::IsManaged() const
bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
// Look for the a _UNICODE definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_UNICODE") {
+ for (std::string const& di : this->Defines) {
+ if (di == "_UNICODE") {
return true;
}
}
@@ -163,9 +162,8 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode() const
bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
// Look for the a _SBCS definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_SBCS") {
+ for (std::string const& di : this->Defines) {
+ if (di == "_SBCS") {
return true;
}
}
@@ -227,7 +225,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// It translates to -arch=<virtual> -code=<real>.
cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
}
- for (auto const& c : codes) {
+ for (std::string const& c : codes) {
std::string entry = arch_name + "," + c;
result.push_back(entry);
}
@@ -237,7 +235,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// -gencode=<arch>,<code>
// -gencode=<arch>,[<code1>,<code2>]
// -gencode=<arch>,"<code1>,<code2>"
- for (auto const& e : gencode) {
+ for (std::string const& e : gencode) {
std::string entry = e;
cmSystemTools::ReplaceString(entry, "arch=", "");
cmSystemTools::ReplaceString(entry, "code=", "");
@@ -285,7 +283,7 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
uacExecuteLevelMap["highestAvailable"] = "HighestAvailable";
uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator";
- for (auto const& subopt : subOptions) {
+ for (std::string const& subopt : subOptions) {
std::vector<std::string> keyValue;
cmsys::SystemTools::Split(subopt, keyValue, '=');
if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) {
@@ -332,9 +330,8 @@ void cmVisualStudioGeneratorOptions::Parse(const char* flags)
// Process flags that need to be represented specially in the IDE
// project file.
- for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end();
- ++ai) {
- this->HandleFlag(ai->c_str());
+ for (std::string const& ai : args) {
+ this->HandleFlag(ai.c_str());
}
}
@@ -437,7 +434,8 @@ cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
return value;
}
-void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
+void cmVisualStudioGeneratorOptions::SetConfiguration(
+ const std::string& config)
{
this->Configuration = config;
}
@@ -566,31 +564,27 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
const char* indent)
{
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
+ for (auto const& m : this->FlagMap) {
fout << indent;
if (!this->Configuration.empty()) {
this->TargetGenerator->WritePlatformConfigTag(
- m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
+ m.first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
} else {
- fout << "<" << m->first << ">";
+ fout << "<" << m.first << ">";
}
const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i);
+ for (std::string const& i : m.second) {
+ fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(i);
sep = ";";
}
- fout << "</" << m->first << ">\n";
+ fout << "</" << m.first << ">\n";
}
} else {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent << m->first << "=\"";
+ for (auto const& m : this->FlagMap) {
+ fout << indent << m.first << "=\"";
const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i);
+ for (std::string const& i : m.second) {
+ fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(i);
sep = ";";
}
fout << "\"\n";
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 2dffe9b..2c56d42 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -91,7 +91,7 @@ public:
const char* suffix,
const std::string& lang);
void OutputFlagMap(std::ostream& fout, const char* indent);
- void SetConfiguration(const char* config);
+ void SetConfiguration(const std::string& config);
private:
cmLocalVisualStudioGenerator* LocalGenerator;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5620723..f4f4a15 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2387,17 +2387,17 @@ int cmake::Build(const std::string& dir, const std::string& target,
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
}
- std::unique_ptr<cmGlobalGenerator> gen(
- this->CreateGlobalGenerator(cachedGenerator));
- if (!gen.get()) {
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator);
+ if (!gen) {
std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator
<< "\"\n";
return 1;
}
+ this->SetGlobalGenerator(gen);
const char* cachedGeneratorInstance =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
if (cachedGeneratorInstance) {
- cmMakefile mf(gen.get(), this->GetCurrentSnapshot());
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
return 1;
}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 62157bb..0ce6d72 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -348,6 +348,7 @@ if(BUILD_TESTING)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
+ ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
endif()
ADD_TEST_MACRO(COnly COnly)
@@ -1445,6 +1446,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProject")
set_tests_properties(ExternalProject PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(NAME ExternalProjectSubdir
@@ -1484,6 +1486,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal")
set_tests_properties(ExternalProjectLocal PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(ExternalProjectUpdateSetup ${CMAKE_CTEST_COMMAND}
@@ -1499,6 +1502,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
set_tests_properties(ExternalProjectUpdateSetup PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(NAME ExternalProjectUpdate
@@ -1513,6 +1517,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
set_tests_properties(ExternalProjectUpdate PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT}
WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate
DEPENDS ExternalProjectUpdateSetup )
diff --git a/Tests/CSharpLinkFromCxx/.gitattributes b/Tests/CSharpLinkFromCxx/.gitattributes
new file mode 100644
index 0000000..57a39049
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/.gitattributes
@@ -0,0 +1 @@
+UsefulManagedCppClass.* -format.clang-format
diff --git a/Tests/CSharpLinkFromCxx/CMakeLists.txt b/Tests/CSharpLinkFromCxx/CMakeLists.txt
new file mode 100644
index 0000000..9a1a993
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Take a C# shared library and link it to a managed C++ shared library
+cmake_minimum_required(VERSION 3.10)
+project (CSharpLinkFromCxx CXX CSharp)
+
+add_library(CSharpLibrary SHARED UsefulCSharpClass.cs)
+
+# we have to change the default flags for the
+# managed C++ project to build
+string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+
+# The C# project is a dependency of the C++/CLI project
+add_library(ManagedCppLibrary SHARED UsefulManagedCppClass.cpp UsefulManagedCppClass.hpp)
+target_compile_options(ManagedCppLibrary PRIVATE "/clr")
+target_link_libraries(ManagedCppLibrary PUBLIC CSharpLibrary)
+
+# Main executable for the test framework
+add_executable(CSharpLinkFromCxx CSharpLinkFromCxx.cs)
+target_link_libraries(CSharpLinkFromCxx PRIVATE ManagedCppLibrary)
diff --git a/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs b/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs
new file mode 100644
index 0000000..31a74eb
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs
@@ -0,0 +1,16 @@
+using System;
+using CSharpLibrary;
+
+namespace CSharpLinkFromCxx
+{
+ internal class CSharpLinkFromCxx
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Starting test for CSharpLinkFromCxx");
+
+ var useful = new UsefulManagedCppClass();
+ useful.RunTest();
+ }
+ }
+}
diff --git a/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs b/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs
new file mode 100644
index 0000000..749e57d
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace CSharpLibrary
+{
+ public class UsefulCSharpClass
+ {
+ public string GetSomethingUseful()
+ {
+ return "Something Useful";
+ }
+ }
+}
diff --git a/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp
new file mode 100644
index 0000000..9468812
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp
@@ -0,0 +1,15 @@
+#include "UsefulManagedCppClass.hpp"
+
+namespace CSharpLibrary
+{
+ UsefulManagedCppClass::UsefulManagedCppClass()
+ {
+ auto useful = gcnew UsefulCSharpClass();
+ m_usefulString = useful->GetSomethingUseful();
+ }
+
+ void UsefulManagedCppClass::RunTest()
+ {
+ Console::WriteLine("Printing from Managed CPP Class: " + m_usefulString);
+ }
+}
diff --git a/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp
new file mode 100644
index 0000000..def7cea
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp
@@ -0,0 +1,16 @@
+using namespace System;
+
+namespace CSharpLibrary
+{
+ public ref class UsefulManagedCppClass
+ {
+ public:
+
+ UsefulManagedCppClass();
+ void RunTest();
+
+ private:
+
+ String^ m_usefulString;
+ };
+}
diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c
index 4debd94..2b4627c 100644
--- a/Tests/CompileFeatures/default_dialect.c
+++ b/Tests/CompileFeatures/default_dialect.c
@@ -1,6 +1,6 @@
#if DEFAULT_C11
-#if __STDC_VERSION__ != 201112L
+#if __STDC_VERSION__ < 201112L
#error Unexpected value for __STDC_VERSION__.
#endif
#elif DEFAULT_C99
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index 64a07f0..5eff6b9 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -236,3 +236,17 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 8)
deploymeny_target_test(${SDK})
endforeach()
endif()
+
+function(XcodeDependOnZeroCheck)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeDependOnZeroCheck-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ run_cmake(XcodeDependOnZeroCheck)
+ run_cmake_command(XcodeDependOnZeroCheck-build ${CMAKE_COMMAND} --build . --target parentdirlib)
+ run_cmake_command(XcodeDependOnZeroCheck-build ${CMAKE_COMMAND} --build . --target subdirlib)
+endfunction()
+
+XcodeDependOnZeroCheck()
diff --git a/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt
new file mode 100644
index 0000000..92c9a29
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt
@@ -0,0 +1 @@
+BUILD AGGREGATE TARGET ZERO_CHECK
diff --git a/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake
new file mode 100644
index 0000000..d759a65
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake
@@ -0,0 +1,4 @@
+set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY TRUE)
+project(XcodeDependOnZeroCheck CXX)
+add_subdirectory(zerocheck)
+add_library(parentdirlib foo.cpp)
diff --git a/Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt b/Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt
new file mode 100644
index 0000000..4adde99
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt
@@ -0,0 +1,2 @@
+project(subproject)
+add_library(subdirlib ../foo.cpp)