Pārlūkot izejas kodu

Merge topic 'ispc_improvements'

a020787a9b ISPC: Support generation for multiple instruction sets
5a1750017e ISPC: Add compiler launcher support

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5173
Brad King 5 gadi atpakaļ
vecāks
revīzija
d0ccc7cf2a
62 mainītis faili ar 633 papildinājumiem un 13 dzēšanām
  1. 1 0
      Help/manual/cmake-properties.7.rst
  2. 1 0
      Help/manual/cmake-variables.7.rst
  3. 21 0
      Help/prop_tgt/ISPC_INSTRUCTION_SETS.rst
  4. 1 1
      Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst
  5. 9 0
      Help/variable/CMAKE_ISPC_INSTRUCTION_SETS.rst
  6. 1 1
      Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
  7. 5 0
      Modules/CMakeISPCInformation.cmake
  8. 2 0
      Source/cmCoreTryCompile.cxx
  9. 55 0
      Source/cmGeneratorTarget.cxx
  10. 9 0
      Source/cmGeneratorTarget.h
  11. 6 0
      Source/cmGlobalNinjaGenerator.cxx
  12. 60 2
      Source/cmLocalGenerator.cxx
  13. 5 0
      Source/cmLocalGenerator.h
  14. 17 3
      Source/cmMakefileTargetGenerator.cxx
  15. 6 1
      Source/cmNinjaNormalTargetGenerator.cxx
  16. 14 1
      Source/cmNinjaTargetGenerator.cxx
  17. 2 0
      Source/cmTarget.cxx
  18. 3 0
      Tests/ISPC/CMakeLists.txt
  19. 22 0
      Tests/ISPC/ChainedStaticLibraries/CMakeLists.txt
  20. 17 0
      Tests/ISPC/ChainedStaticLibraries/extra.cxx
  21. 12 0
      Tests/ISPC/ChainedStaticLibraries/extra.ispc
  22. 15 0
      Tests/ISPC/ChainedStaticLibraries/main.cxx
  23. 12 0
      Tests/ISPC/ChainedStaticLibraries/simple.ispc
  24. 1 0
      Tests/ISPC/Defines/CMakeLists.txt
  25. 20 0
      Tests/ISPC/DynamicLibrary/CMakeLists.txt
  26. 17 0
      Tests/ISPC/DynamicLibrary/extra.cxx
  27. 12 0
      Tests/ISPC/DynamicLibrary/extra.ispc
  28. 15 0
      Tests/ISPC/DynamicLibrary/main.cxx
  29. 12 0
      Tests/ISPC/DynamicLibrary/simple.ispc
  30. 45 0
      Tests/ISPC/ObjectGenex/CMakeLists.txt
  31. 87 0
      Tests/ISPC/ObjectGenex/main.cxx
  32. 12 0
      Tests/ISPC/ObjectGenex/simple.ispc
  33. 3 2
      Tests/ISPC/ObjectLibrary/CMakeLists.txt
  34. 9 2
      Tests/RunCMake/CMakeLists.txt
  35. 1 0
      Tests/RunCMake/CompilerLauncher/ISPC-Build-stdout.txt
  36. 4 0
      Tests/RunCMake/CompilerLauncher/ISPC-common.cmake
  37. 1 0
      Tests/RunCMake/CompilerLauncher/ISPC-env-Build-stdout.txt
  38. 1 0
      Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt
  39. 1 0
      Tests/RunCMake/CompilerLauncher/ISPC-env.cmake
  40. 1 0
      Tests/RunCMake/CompilerLauncher/ISPC-launch-Build-stdout.txt
  41. 3 0
      Tests/RunCMake/CompilerLauncher/ISPC-launch-env.cmake
  42. 3 0
      Tests/RunCMake/CompilerLauncher/ISPC-launch.cmake
  43. 2 0
      Tests/RunCMake/CompilerLauncher/ISPC.cmake
  44. 3 0
      Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
  45. 4 0
      Tests/RunCMake/CompilerLauncher/test.ispc
  46. 11 0
      Tests/RunCMake/install/FILES-EXTRA_ISPC_TARGET_OBJECTS-all-check.cmake
  47. 4 0
      Tests/RunCMake/install/FILES-EXTRA_ISPC_TARGET_OBJECTS.cmake
  48. 5 0
      Tests/RunCMake/install/RunCMakeTest.cmake
  49. 4 0
      Tests/RunCMake/install/obj1.ispc
  50. 4 0
      Tests/RunCMake/install/obj2.ispc
  51. 1 0
      Tests/RunCMake/try_compile/ISPCDuplicateTarget-stderr.txt
  52. 8 0
      Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake
  53. 1 0
      Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja-result.txt
  54. 1 0
      Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja-stderr.txt
  55. 11 0
      Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake
  56. 1 0
      Tests/RunCMake/try_compile/ISPCInvalidTarget-stderr.txt
  57. 7 0
      Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake
  58. 1 0
      Tests/RunCMake/try_compile/ISPCTargets-stderr.txt
  59. 1 0
      Tests/RunCMake/try_compile/ISPCTargets-stdout.txt
  60. 7 0
      Tests/RunCMake/try_compile/ISPCTargets.cmake
  61. 9 0
      Tests/RunCMake/try_compile/RunCMakeTest.cmake
  62. 4 0
      Tests/RunCMake/try_compile/src.ispc

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -259,6 +259,7 @@ Properties on Targets
    /prop_tgt/INTERPROCEDURAL_OPTIMIZATION
    /prop_tgt/IOS_INSTALL_COMBINED
    /prop_tgt/ISPC_HEADER_DIRECTORY
+   /prop_tgt/ISPC_INSTRUCTION_SETS
    /prop_tgt/JOB_POOL_COMPILE
    /prop_tgt/JOB_POOL_LINK
    /prop_tgt/JOB_POOL_PRECOMPILE_HEADER

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -512,6 +512,7 @@ Variables for Languages
    /variable/CMAKE_Fortran_MODDIR_FLAG
    /variable/CMAKE_Fortran_MODOUT_FLAG
    /variable/CMAKE_ISPC_HEADER_DIRECTORY
+   /variable/CMAKE_ISPC_INSTRUCTION_SETS
    /variable/CMAKE_LANG_ANDROID_TOOLCHAIN_MACHINE
    /variable/CMAKE_LANG_ANDROID_TOOLCHAIN_PREFIX
    /variable/CMAKE_LANG_ANDROID_TOOLCHAIN_SUFFIX

+ 21 - 0
Help/prop_tgt/ISPC_INSTRUCTION_SETS.rst

@@ -0,0 +1,21 @@
+ISPC_INSTRUCTION_SETS
+---------------------
+
+.. versionadded:: 3.19
+
+List of instruction set architectures to generate code for.
+
+This property is initialized by the value of the :variable:`CMAKE_ISPC_INSTRUCTION_SETS`
+variable if it is set when a target is created.
+
+The ``ISPC_INSTRUCTION_SETS`` target property must be used when generating for multiple
+instruction sets so that CMake can track what object files will be generated.
+
+Examples
+^^^^^^^^
+
+.. code-block:: cmake
+
+  set_property(TARGET tgt PROPERTY ISPC_INSTRUCTION_SETS avx2-i32x4 avx512skx-i32x835)
+
+Generates code for avx2 and avx512skx target architectures.

+ 1 - 1
Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst

@@ -4,7 +4,7 @@
 .. versionadded:: 3.4
 
 This property is implemented only when ``<LANG>`` is ``C``, ``CXX``,
-``Fortran``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
+``Fortran``, ``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
 
 Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing a command line
 for a compiler launching tool. The :ref:`Makefile Generators` and the

+ 9 - 0
Help/variable/CMAKE_ISPC_INSTRUCTION_SETS.rst

@@ -0,0 +1,9 @@
+CMAKE_ISPC_INSTRUCTION_SETS
+---------------------------
+
+.. versionadded:: 3.19
+
+Default value for :prop_tgt:`ISPC_INSTRUCTION_SETS` property of targets.
+
+This variable is used to initialize the :prop_tgt:`ISPC_INSTRUCTION_SETS` property
+on all targets. See the target property for additional information.

+ 1 - 1
Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst

@@ -6,7 +6,7 @@ CMAKE_<LANG>_COMPILER_LAUNCHER
 Default value for :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property.
 This variable is used to initialize the property on each target as it is
 created.  This is done only when ``<LANG>`` is ``C``, ``CXX``, ``Fortran``,
-``OBJC``, ``OBJCXX``, or ``CUDA``.
+``ISPC``, ``OBJC``, ``OBJCXX``, or ``CUDA``.
 
 This variable is initialized to the :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER`
 environment variable if it is set.

+ 5 - 0
Modules/CMakeISPCInformation.cmake

@@ -32,6 +32,11 @@ if(CMAKE_ISPC_STANDARD_LIBRARIES_INIT)
   mark_as_advanced(CMAKE_ISPC_STANDARD_LIBRARIES)
 endif()
 
+if(NOT CMAKE_ISPC_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_ISPC_COMPILER_LAUNCHER})
+  set(CMAKE_ISPC_COMPILER_LAUNCHER "$ENV{CMAKE_ISPC_COMPILER_LAUNCHER}"
+    CACHE STRING "Compiler launcher for ISPC.")
+endif()
+
 include(CMakeCommonLanguageInclude)
 
 # now define the following rules:

+ 2 - 0
Source/cmCoreTryCompile.cxx

@@ -200,6 +200,7 @@ SETUP_LANGUAGE(swift_properties, Swift);
 std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES";
 std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY";
 std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
+std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS";
 std::string const kCMAKE_LINK_SEARCH_END_STATIC =
   "CMAKE_LINK_SEARCH_END_STATIC";
 std::string const kCMAKE_LINK_SEARCH_START_STATIC =
@@ -716,6 +717,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       vars.insert(kCMAKE_CUDA_ARCHITECTURES);
       vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY);
       vars.insert(kCMAKE_ENABLE_EXPORTS);
+      vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS);
       vars.insert(kCMAKE_LINK_SEARCH_END_STATIC);
       vars.insert(kCMAKE_LINK_SEARCH_START_STATIC);
       vars.insert(kCMAKE_OSX_ARCHITECTURES);

+ 55 - 0
Source/cmGeneratorTarget.cxx

@@ -3302,6 +3302,27 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
   }
 }
 
+void cmGeneratorTarget::AddISPCTargetFlags(std::string& flags) const
+{
+  const std::string& property = this->GetSafeProperty("ISPC_INSTRUCTION_SETS");
+
+  // If ISPC_TARGET is false we don't add any architectures.
+  if (cmIsOff(property)) {
+    return;
+  }
+
+  std::string const& compiler =
+    this->Makefile->GetSafeDefinition("CMAKE_ISPC_COMPILER_ID");
+
+  if (compiler == "Intel") {
+    std::vector<std::string> targets;
+    cmExpandList(property, targets);
+    if (!targets.empty()) {
+      flags += cmStrCat(" --target=", cmWrap("", targets, "", ","));
+    }
+  }
+}
+
 void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
 {
   std::string const& compiler =
@@ -5067,6 +5088,11 @@ void cmGeneratorTarget::GetTargetObjectNames(
     assert(!map_it->second.empty());
     objects.push_back(map_it->second);
   }
+
+  auto ispcObjects = this->GetGeneratedISPCObjects(config);
+  for (std::string const& output : ispcObjects) {
+    objects.push_back(cmSystemTools::GetFilenameName(output));
+  }
 }
 
 bool cmGeneratorTarget::StrictTargetComparison::operator()(
@@ -6038,6 +6064,35 @@ std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCHeaders(
   return iter->second;
 }
 
+void cmGeneratorTarget::AddISPCGeneratedObject(std::vector<std::string>&& objs,
+                                               std::string const& config)
+{
+  std::string config_upper;
+  if (!config.empty()) {
+    config_upper = cmSystemTools::UpperCase(config);
+  }
+  auto iter = this->ISPCGeneratedObjects.find(config_upper);
+  if (iter == this->ISPCGeneratedObjects.end()) {
+    this->ISPCGeneratedObjects.insert({ config_upper, objs });
+  } else {
+    iter->second.insert(iter->second.end(), objs.begin(), objs.end());
+  }
+}
+
+std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCObjects(
+  std::string const& config) const
+{
+  std::string config_upper;
+  if (!config.empty()) {
+    config_upper = cmSystemTools::UpperCase(config);
+  }
+  auto iter = this->ISPCGeneratedObjects.find(config_upper);
+  if (iter == this->ISPCGeneratedObjects.end()) {
+    return std::vector<std::string>{};
+  }
+  return iter->second;
+}
+
 std::string cmGeneratorTarget::GetFrameworkVersion() const
 {
   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);

+ 9 - 0
Source/cmGeneratorTarget.h

@@ -448,6 +448,8 @@ public:
   void AddCUDAArchitectureFlags(std::string& flags) const;
   void AddCUDAToolkitFlags(std::string& flags) const;
 
+  void AddISPCTargetFlags(std::string& flags) const;
+
   std::string GetFeatureSpecificLinkRuleVariable(
     std::string const& var, std::string const& lang,
     std::string const& config) const;
@@ -820,6 +822,11 @@ public:
   std::vector<std::string> GetGeneratedISPCHeaders(
     std::string const& config) const;
 
+  void AddISPCGeneratedObject(std::vector<std::string>&& objs,
+                              std::string const& config);
+  std::vector<std::string> GetGeneratedISPCObjects(
+    std::string const& config) const;
+
 private:
   void AddSourceCommon(const std::string& src, bool before = false);
 
@@ -1000,6 +1007,8 @@ private:
 
   std::unordered_map<std::string, std::vector<std::string>>
     ISPCGeneratedHeaders;
+  std::unordered_map<std::string, std::vector<std::string>>
+    ISPCGeneratedObjects;
 
   bool IsLinkLookupScope(std::string const& n,
                          cmLocalGenerator const*& lg) const;

+ 6 - 0
Source/cmGlobalNinjaGenerator.cxx

@@ -1165,6 +1165,12 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
                          gg->MapToNinjaPath());
           outputDeps.insert(outputDeps.end(), headers.begin(), headers.end());
         }
+        auto objs = depTarget->GetGeneratedISPCObjects(targetConfig);
+        if (!objs.empty()) {
+          std::transform(objs.begin(), objs.end(), objs.begin(),
+                         gg->MapToNinjaPath());
+          outputDeps.insert(outputDeps.end(), objs.begin(), objs.end());
+        }
       }
     };
 

+ 60 - 2
Source/cmLocalGenerator.cxx

@@ -1966,6 +1966,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
           "See CMake issue #20726.");
       }
     }
+  } else if (lang == "ISPC") {
+    target->AddISPCTargetFlags(flags);
   }
   // Add VFS Overlay for Clang compiliers
   if (compiler == "Clang") {
@@ -2428,7 +2430,17 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
 
 void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
 {
-  //
+  std::vector<std::string> enabledLanguages =
+    this->GetState()->GetEnabledLanguages();
+  if (std::find(enabledLanguages.begin(), enabledLanguages.end(), "ISPC") ==
+      enabledLanguages.end()) {
+    return;
+  }
+
+  std::vector<std::string> ispcSuffixes =
+    detail::ComputeISPCObjectSuffixes(target);
+  const bool extra_objects = (ispcSuffixes.size() > 1);
+
   std::vector<std::string> configsList =
     this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
   for (std::string const& config : configsList) {
@@ -2442,7 +2454,8 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
     std::vector<cmSourceFile*> sources;
     target->GetSourceFiles(sources, config);
 
-    // build up the list of ispc headers that this target is generating
+    // build up the list of ispc headers and extra objects that this target is
+    // generating
     for (cmSourceFile const* sf : sources) {
       // Generate this object file's rule file.
       const std::string& lang = sf->GetLanguage();
@@ -2453,6 +2466,11 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
 
         auto headerPath = cmStrCat(perConfigDir, '/', ispcSource, ".h");
         target->AddISPCGeneratedHeader(headerPath, config);
+        if (extra_objects) {
+          std::vector<std::string> objs = detail::ComputeISPCExtraObjects(
+            objectName, perConfigDir, ispcSuffixes);
+          target->AddISPCGeneratedObject(std::move(objs), config);
+        }
       }
     }
   }
@@ -4028,4 +4046,44 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
     target->AddSource(force.NameCMP0049);
   }
 }
+
+std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target)
+{
+  const std::string& targetProperty =
+    target->GetSafeProperty("ISPC_INSTRUCTION_SETS");
+  std::vector<std::string> ispcTargets;
+
+  if (!cmIsOff(targetProperty)) {
+    cmExpandList(targetProperty, ispcTargets);
+    for (auto& ispcTarget : ispcTargets) {
+      // transform targets into the suffixes
+      auto pos = ispcTarget.find('-');
+      auto target_suffix = ispcTarget.substr(0, pos);
+      if (target_suffix ==
+          "avx1") { // when targetting avx1 ISPC uses the 'avx' output string
+        target_suffix = "avx";
+      }
+      ispcTarget = target_suffix;
+    }
+  }
+  return ispcTargets;
+}
+
+std::vector<std::string> ComputeISPCExtraObjects(
+  std::string const& objectName, std::string const& buildDirectory,
+  std::vector<std::string> const& ispcSuffixes)
+{
+  std::vector<std::string> computedObjects;
+  computedObjects.reserve(ispcSuffixes.size());
+
+  auto extension = cmSystemTools::GetFilenameLastExtension(objectName);
+  auto objNameNoExt =
+    cmSystemTools::GetFilenameWithoutLastExtension(objectName);
+  for (const auto& ispcTarget : ispcSuffixes) {
+    computedObjects.emplace_back(
+      cmStrCat(buildDirectory, "/", objNameNoExt, "_", ispcTarget, extension));
+  }
+
+  return computedObjects;
+}
 }

+ 5 - 0
Source/cmLocalGenerator.h

@@ -594,4 +594,9 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
                        bool escapeOldStyle, const char* comment,
                        bool uses_terminal, bool command_expand_lists,
                        const std::string& job_pool, bool stdPipesUTF8);
+
+std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target);
+std::vector<std::string> ComputeISPCExtraObjects(
+  std::string const& objectName, std::string const& buildDirectory,
+  std::vector<std::string> const& ispcSuffixes);
 }

+ 17 - 3
Source/cmMakefileTargetGenerator.cxx

@@ -197,6 +197,17 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
     }
   }
 
+  std::string currentBinDir =
+    this->LocalGenerator->GetCurrentBinaryDirectory();
+
+  // Look for ISPC extra object files generated by this target
+  auto ispcAdditionalObjs =
+    this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
+  for (std::string const& ispcObj : ispcAdditionalObjs) {
+    this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
+      currentBinDir, ispcObj));
+  }
+
   // add custom commands to the clean rules?
   bool clean = cmIsOff(this->Makefile->GetProperty("CLEAN_NO_CUSTOM"));
 
@@ -205,8 +216,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
   std::vector<cmSourceFile const*> customCommands;
   this->GeneratorTarget->GetCustomCommands(customCommands,
                                            this->GetConfigName());
-  std::string currentBinDir =
-    this->LocalGenerator->GetCurrentBinaryDirectory();
   for (cmSourceFile const* sf : customCommands) {
     cmCustomCommandGenerator ccg(*sf->GetCustomCommand(),
                                  this->GetConfigName(), this->LocalGenerator);
@@ -832,7 +841,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
     std::string compilerLauncher;
     if (!compileCommands.empty() &&
         (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
-         lang == "OBJC" || lang == "OBJCXX")) {
+         lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) {
       std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
       cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
       if (cmNonempty(clauncher)) {
@@ -1494,6 +1503,11 @@ void cmMakefileTargetGenerator::WriteObjectsStrings(
   for (std::string const& obj : this->ExternalObjects) {
     helper.Feed(obj);
   }
+  auto ispcAdditionalObjs =
+    this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
+  for (std::string const& obj : ispcAdditionalObjs) {
+    helper.Feed(obj);
+  }
   helper.Done();
 }
 

+ 6 - 1
Source/cmNinjaNormalTargetGenerator.cxx

@@ -911,11 +911,16 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
       linkBuild.ExplicitDeps.push_back(
         this->ConvertToNinjaPath(this->GetSourceFilePath(source)));
     }
-
     linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
   } else {
     linkBuild.ExplicitDeps = this->GetObjects(config);
   }
+
+  std::vector<std::string> extraISPCObjects =
+    this->GetGeneratorTarget()->GetGeneratedISPCObjects(config);
+  std::transform(extraISPCObjects.begin(), extraISPCObjects.end(),
+                 std::back_inserter(linkBuild.ExplicitDeps), MapToNinjaPath());
+
   linkBuild.ImplicitDeps =
     this->ComputeLinkDeps(this->TargetLinkLanguage(config), config);
 

+ 14 - 1
Source/cmNinjaTargetGenerator.cxx

@@ -813,7 +813,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
   std::string compilerLauncher;
   if (!compileCmds.empty() &&
       (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
-       lang == "OBJC" || lang == "OBJCXX")) {
+       lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) {
     std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
     cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
     if (cmNonempty(clauncher)) {
@@ -1398,6 +1398,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
     // Make sure ninja knows how to clean the generated header
     this->GetGlobalGenerator()->AddAdditionalCleanFile(ispcHeader, config);
 
+    auto ispcSuffixes =
+      detail::ComputeISPCObjectSuffixes(this->GeneratorTarget);
+    if (ispcSuffixes.size() > 1) {
+      auto ispcSideEfffectObjects = detail::ComputeISPCExtraObjects(
+        objectName, ispcDirectory, ispcSuffixes);
+
+      for (auto sideEffect : ispcSideEfffectObjects) {
+        sideEffect = this->ConvertToNinjaPath(sideEffect);
+        objBuild.ImplicitOuts.emplace_back(sideEffect);
+        this->GetGlobalGenerator()->AddAdditionalCleanFile(sideEffect, config);
+      }
+    }
+
     vars["ISPC_HEADER_FILE"] =
       this->GetLocalGenerator()->ConvertToOutputFormat(
         ispcHeader, cmOutputConverter::SHELL);

+ 2 - 0
Source/cmTarget.cxx

@@ -367,7 +367,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     initProp("JOB_POOL_COMPILE");
     initProp("JOB_POOL_LINK");
     initProp("JOB_POOL_PRECOMPILE_HEADER");
+    initProp("ISPC_COMPILER_LAUNCHER");
     initProp("ISPC_HEADER_DIRECTORY");
+    initProp("ISPC_INSTRUCTION_SETS");
     initProp("LINK_SEARCH_START_STATIC");
     initProp("LINK_SEARCH_END_STATIC");
     initProp("Swift_LANGUAGE_VERSION");

+ 3 - 0
Tests/ISPC/CMakeLists.txt

@@ -6,7 +6,10 @@ macro (add_ispc_test_macro name)
     PROPERTY LABELS "ISPC")
 endmacro ()
 
+add_ispc_test_macro(ISPC.ChainedStaticLibraries ISPCChainedStaticLibraries)
 add_ispc_test_macro(ISPC.Defines ISPCDefines)
+add_ispc_test_macro(ISPC.DynamicLibrary ISPCDynamicLibrary)
+add_ispc_test_macro(ISPC.ObjectGenex ISPCObjectGenex)
 add_ispc_test_macro(ISPC.ObjectLibrary ISPCObjectLibrary)
 add_ispc_test_macro(ISPC.ResponseAndDefine ISPCResponseAndDefine)
 add_ispc_test_macro(ISPC.StaticLibrary ISPCStaticLibrary)

+ 22 - 0
Tests/ISPC/ChainedStaticLibraries/CMakeLists.txt

@@ -0,0 +1,22 @@
+
+cmake_minimum_required(VERSION 3.18)
+project(ISPCChainedStaticLibraries CXX ISPC)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+  set(CMAKE_ISPC_FLAGS "--arch=x86")
+endif()
+
+
+add_library(ispc_objects1 STATIC extra.ispc extra.cxx)
+add_library(ispc_objects2 STATIC simple.ispc)
+
+set_target_properties(ispc_objects1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
+set_target_properties(ispc_objects1 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16;avx2-i32x4")
+
+set_target_properties(ispc_objects2 PROPERTIES POSITION_INDEPENDENT_CODE ON)
+set_target_properties(ispc_objects2 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16")
+
+target_link_libraries(ispc_objects2 PRIVATE ispc_objects1)
+
+add_executable(ISPCChainedStaticLibraries main.cxx)
+target_link_libraries(ISPCChainedStaticLibraries PUBLIC ispc_objects2)

+ 17 - 0
Tests/ISPC/ChainedStaticLibraries/extra.cxx

@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+#include "extra.ispc.h"
+
+int extra()
+{
+  float vin[16], vout[16];
+  for (int i = 0; i < 16; ++i)
+    vin[i] = i;
+
+  ispc::extra(vin, vout, 16);
+
+  for (int i = 0; i < 16; ++i)
+    printf("%d: extra(%f) = %f\n", i, vin[i], vout[i]);
+
+  return 0;
+}

+ 12 - 0
Tests/ISPC/ChainedStaticLibraries/extra.ispc

@@ -0,0 +1,12 @@
+
+export void extra(uniform float vin[], uniform float vout[],
+                   uniform int count) {
+    foreach (index = 0 ... count) {
+        float v = vin[index];
+        if (v < 3.)
+            v = v * v;
+        else
+            v = sqrt(v);
+        vout[index] = v;
+    }
+}

+ 15 - 0
Tests/ISPC/ChainedStaticLibraries/main.cxx

@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "simple.ispc.h"
+
+int main()
+{
+  float vin[16], vout[16];
+  for (int i = 0; i < 16; ++i)
+    vin[i] = i;
+
+  ispc::simple(vin, vout, 16);
+
+  for (int i = 0; i < 16; ++i)
+    printf("%d: simple(%f) = %f\n", i, vin[i], vout[i]);
+}

+ 12 - 0
Tests/ISPC/ChainedStaticLibraries/simple.ispc

@@ -0,0 +1,12 @@
+
+export void simple(uniform float vin[], uniform float vout[],
+                   uniform int count) {
+    foreach (index = 0 ... count) {
+        float v = vin[index];
+        if (v < 3.)
+            v = v * v;
+        else
+            v = sqrt(v);
+        vout[index] = v;
+    }
+}

+ 1 - 0
Tests/ISPC/Defines/CMakeLists.txt

@@ -1,6 +1,7 @@
 cmake_minimum_required(VERSION 3.18)
 project(ISPCDefines CXX ISPC)
 
+set(CMAKE_ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i16x8;avx1-i32x16;avx2-i32x4;avx512knl-i32x16;avx512skx-i32x8")
 set(CMAKE_ISPC_FLAGS -DM_PI=3.1415926535f)
 add_compile_definitions([==[STRUCT_DEFINE=struct{uniform int a]==])
 

+ 20 - 0
Tests/ISPC/DynamicLibrary/CMakeLists.txt

@@ -0,0 +1,20 @@
+
+cmake_minimum_required(VERSION 3.18)
+project(ISPCDynamicLibrary CXX ISPC)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+  set(CMAKE_ISPC_FLAGS "--arch=x86")
+endif()
+
+
+add_library(ispc_objects1 STATIC extra.ispc extra.cxx)
+add_library(ispc_objects2 SHARED simple.ispc)
+
+set_target_properties(ispc_objects1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
+set_target_properties(ispc_objects1 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16;avx2-i32x4")
+set_target_properties(ispc_objects2 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16")
+
+target_link_libraries(ispc_objects2 PRIVATE ispc_objects1)
+
+add_executable(ISPCDynamicLibrary main.cxx)
+target_link_libraries(ISPCDynamicLibrary PUBLIC ispc_objects2)

+ 17 - 0
Tests/ISPC/DynamicLibrary/extra.cxx

@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+#include "extra.ispc.h"
+
+int extra()
+{
+  float vin[16], vout[16];
+  for (int i = 0; i < 16; ++i)
+    vin[i] = i;
+
+  ispc::extra(vin, vout, 16);
+
+  for (int i = 0; i < 16; ++i)
+    printf("%d: extra(%f) = %f\n", i, vin[i], vout[i]);
+
+  return 0;
+}

+ 12 - 0
Tests/ISPC/DynamicLibrary/extra.ispc

@@ -0,0 +1,12 @@
+
+export void extra(uniform float vin[], uniform float vout[],
+                   uniform int count) {
+    foreach (index = 0 ... count) {
+        float v = vin[index];
+        if (v < 3.)
+            v = v * v;
+        else
+            v = sqrt(v);
+        vout[index] = v;
+    }
+}

+ 15 - 0
Tests/ISPC/DynamicLibrary/main.cxx

@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include "simple.ispc.h"
+
+int main()
+{
+  float vin[16], vout[16];
+  for (int i = 0; i < 16; ++i)
+    vin[i] = i;
+
+  ispc::simple(vin, vout, 16);
+
+  for (int i = 0; i < 16; ++i)
+    printf("%d: simple(%f) = %f\n", i, vin[i], vout[i]);
+}

+ 12 - 0
Tests/ISPC/DynamicLibrary/simple.ispc

@@ -0,0 +1,12 @@
+
+export void simple(uniform float vin[], uniform float vout[],
+                   uniform int count) {
+    foreach (index = 0 ... count) {
+        float v = vin[index];
+        if (v < 3.)
+            v = v * v;
+        else
+            v = sqrt(v);
+        vout[index] = v;
+    }
+}

+ 45 - 0
Tests/ISPC/ObjectGenex/CMakeLists.txt

@@ -0,0 +1,45 @@
+cmake_minimum_required(VERSION 3.18)
+project(ISPCObjectGenex CXX ISPC)
+
+set(CMAKE_ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i16x8;avx1-i32x16;avx2-i32x4;avx512knl-i32x16;avx512skx-i32x8")
+
+add_library(ispc_objects OBJECT
+  simple.ispc
+  )
+target_compile_definitions(ispc_objects PRIVATE
+  $<$<COMPILE_LANG_AND_ID:ISPC,Intel>:M_PI=3.1415926535f>
+)
+set_target_properties(ispc_objects PROPERTIES POSITION_INDEPENDENT_CODE ON)
+if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+  set_source_files_properties(simple.ispc PROPERTIES COMPILE_OPTIONS "--arch=x86")
+endif()
+
+
+#Test ObjectFiles with file(GENERATE)
+file(GENERATE
+     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gen_$<LOWER_CASE:$<CONFIG>/>path_to_objs.h
+     CONTENT [[
+#ifndef path_to_objs
+#define path_to_objs
+
+#include <string>
+
+static std::string obj_paths = "$<TARGET_OBJECTS:ispc_objects>";
+
+#endif
+
+]]
+)
+
+
+add_executable(ISPCObjectGenex main.cxx)
+add_dependencies(ISPCObjectGenex ispc_objects)
+
+list(LENGTH CMAKE_ISPC_INSTRUCTION_SETS numberOfTargets)
+math(EXPR numberOfTargets "${numberOfTargets}+1")
+target_compile_definitions(ISPCObjectGenex PRIVATE
+    "ExpectedISPCObjects=${numberOfTargets}"
+    "CONFIG_TYPE=gen_$<LOWER_CASE:$<CONFIG>>"
+    )
+target_include_directories(ISPCObjectGenex PRIVATE ${CMAKE_CURRENT_BINARY_DIR} )
+target_compile_features(ISPCObjectGenex PRIVATE cxx_std_11)

+ 87 - 0
Tests/ISPC/ObjectGenex/main.cxx

@@ -0,0 +1,87 @@
+#include <stdio.h>
+
+/*
+  Define GENERATED_HEADER macro to allow c++ files to include headers
+  generated based on different configuration types.
+*/
+
+/* clang-format off */
+#define GENERATED_HEADER(x) GENERATED_HEADER0(CONFIG_TYPE/x)
+/* clang-format on */
+#define GENERATED_HEADER0(x) GENERATED_HEADER1(x)
+#define GENERATED_HEADER1(x) <x>
+
+#include GENERATED_HEADER(path_to_objs.h)
+
+#include <vector>
+std::vector<std::string> expandList(std::string const& arg)
+{
+  std::vector<std::string> output;
+  // If argument is empty or no `;` just copy the current string
+  if (arg.empty() || arg.find(';') == std::string::npos) {
+    output.emplace_back(arg);
+    return output;
+  }
+
+  std::string newArg;
+  // Break the string at non-escaped semicolons not nested in [].
+  int squareNesting = 0;
+  auto last = arg.begin();
+  auto const cend = arg.end();
+  for (auto c = last; c != cend; ++c) {
+    switch (*c) {
+      case '\\': {
+        // We only want to allow escaping of semicolons.  Other
+        // escapes should not be processed here.
+        auto cnext = c + 1;
+        if ((cnext != cend) && *cnext == ';') {
+          newArg.append(last, c);
+          // Skip over the escape character
+          last = cnext;
+          c = cnext;
+        }
+      } break;
+      case '[': {
+        ++squareNesting;
+      } break;
+      case ']': {
+        --squareNesting;
+      } break;
+      case ';': {
+        // Break the string here if we are not nested inside square
+        // brackets.
+        if (squareNesting == 0) {
+          newArg.append(last, c);
+          // Skip over the semicolon
+          last = c + 1;
+          if (!newArg.empty()) {
+            // Add the last argument if the string is not empty.
+            output.push_back(newArg);
+            newArg.clear();
+          }
+        }
+      } break;
+      default: {
+        // Just append this character.
+      } break;
+    }
+  }
+  newArg.append(last, cend);
+  if (!newArg.empty()) {
+    // Add the last argument if the string is not empty.
+    output.push_back(std::move(newArg));
+  }
+
+  return output;
+}
+
+int main()
+{
+  // determine that the number of object files specified in obj_paths
+  // is equal to the number of arch's
+
+  std::vector<std::string> paths = expandList(obj_paths);
+  const bool correctSize = (paths.size() == ExpectedISPCObjects);
+
+  return (correctSize) ? 0 : 1;
+}

+ 12 - 0
Tests/ISPC/ObjectGenex/simple.ispc

@@ -0,0 +1,12 @@
+
+export void simple(uniform float vin[], uniform float vout[],
+                   uniform int count) {
+    foreach (index = 0 ... count) {
+        float v = vin[index];
+        if (v < M_PI)
+            v = v * v;
+        else
+            v = sqrt(v);
+        vout[index] = v;
+    }
+}

+ 3 - 2
Tests/ISPC/ObjectLibrary/CMakeLists.txt

@@ -7,11 +7,12 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 4)
   set(CMAKE_ISPC_FLAGS "--arch=x86")
 endif()
 
-add_library(ispc_objects OBJECT simple.ispc extra.ispc)
 
-target_compile_options(ispc_objects PRIVATE "$<$<COMPILE_LANGUAGE:ISPC>:--target=sse2-i32x4>")
+add_library(ispc_objects OBJECT simple.ispc extra.ispc)
 
 set_target_properties(ispc_objects PROPERTIES POSITION_INDEPENDENT_CODE ON)
+set_target_properties(ispc_objects PROPERTIES ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i8x16")
+
 
 add_executable(ISPCObjectLibrary main.cxx extra.cxx)
 target_link_libraries(ISPCObjectLibrary PRIVATE ispc_objects)

+ 9 - 2
Tests/RunCMake/CMakeLists.txt

@@ -387,6 +387,7 @@ function(add_RunCMake_test_try_compile)
       CMAKE_CXX_COMPILER_VERSION
       CMAKE_CXX_STANDARD_DEFAULT
       CMake_TEST_CUDA
+      CMake_TEST_ISPC
       CMake_TEST_FILESYSTEM_1S
       CMAKE_OBJC_STANDARD_DEFAULT
       CMAKE_OBJCXX_STANDARD_DEFAULT
@@ -397,7 +398,7 @@ function(add_RunCMake_test_try_compile)
   endforeach()
   add_RunCMake_test(try_compile)
   set_property(TEST RunCMake.try_compile APPEND
-    PROPERTY LABELS "CUDA")
+    PROPERTY LABELS "CUDA;ISPC")
 endfunction()
 add_RunCMake_test_try_compile()
 
@@ -552,7 +553,10 @@ add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN}
   -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
   -DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}
   -DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT}
+  -DCMake_TEST_ISPC=${CMake_TEST_ISPC}
   )
+set_property(TEST RunCMake.install APPEND
+  PROPERTY LABELS "ISPC")
 
 add_RunCMake_test(file-GET_RUNTIME_DEPENDENCIES
   -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
@@ -630,6 +634,9 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
   if(DEFINED CMake_TEST_CUDA)
     list(APPEND CompilerLauncher_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
   endif()
+  if(DEFINED CMake_TEST_ISPC)
+    list(APPEND CompilerLauncher_ARGS -DCMake_TEST_ISPC=${CMake_TEST_ISPC})
+  endif()
   if(CMAKE_Fortran_COMPILER)
     list(APPEND CompilerLauncher_ARGS -DCMake_TEST_Fortran=1)
   endif()
@@ -638,7 +645,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
   endif()
   add_RunCMake_test(CompilerLauncher)
   set_property(TEST RunCMake.CompilerLauncher APPEND
-    PROPERTY LABELS "CUDA")
+    PROPERTY LABELS "CUDA;ISPC")
   add_RunCMake_test(ctest_labels_for_subprojects)
   add_RunCMake_test(CompilerArgs)
 endif()

+ 1 - 0
Tests/RunCMake/CompilerLauncher/ISPC-Build-stdout.txt

@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*

+ 4 - 0
Tests/RunCMake/CompilerLauncher/ISPC-common.cmake

@@ -0,0 +1,4 @@
+enable_language(ISPC)
+enable_language(CXX)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.cxx test.ispc)

+ 1 - 0
Tests/RunCMake/CompilerLauncher/ISPC-env-Build-stdout.txt

@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*

+ 1 - 0
Tests/RunCMake/CompilerLauncher/ISPC-env-launch-Build-stdout.txt

@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*

+ 1 - 0
Tests/RunCMake/CompilerLauncher/ISPC-env.cmake

@@ -0,0 +1 @@
+include(ISPC-common.cmake)

+ 1 - 0
Tests/RunCMake/CompilerLauncher/ISPC-launch-Build-stdout.txt

@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*

+ 3 - 0
Tests/RunCMake/CompilerLauncher/ISPC-launch-env.cmake

@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(ISPC-env.cmake)

+ 3 - 0
Tests/RunCMake/CompilerLauncher/ISPC-launch.cmake

@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(ISPC.cmake)

+ 2 - 0
Tests/RunCMake/CompilerLauncher/ISPC.cmake

@@ -0,0 +1,2 @@
+set(CMAKE_ISPC_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+include(ISPC-common.cmake)

+ 3 - 0
Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake

@@ -29,6 +29,9 @@ endif()
 if(CMake_TEST_Fortran)
   list(APPEND langs Fortran)
 endif()
+if(CMake_TEST_ISPC)
+  list(APPEND langs ISPC)
+endif()
 if(CMake_TEST_OBJC)
   list(APPEND langs OBJC OBJCXX)
 endif()

+ 4 - 0
Tests/RunCMake/CompilerLauncher/test.ispc

@@ -0,0 +1,4 @@
+
+float func(float a, float b) {
+     return a + b / 2.;
+}

+ 11 - 0
Tests/RunCMake/install/FILES-EXTRA_ISPC_TARGET_OBJECTS-all-check.cmake

@@ -0,0 +1,11 @@
+
+set(objs obj1 obj2)
+set(targets  sse2 sse4 avx avx2)
+foreach(o IN LISTS objs)
+  set(item "objs/${o}\\.ispc\\.(o|obj)")
+  check_installed("${item}")
+  foreach(t IN LISTS targets)
+    set(item "objs/${o}\\.ispc_${t}\\.(o|obj)")
+    check_installed("${item}")
+  endforeach()
+endforeach()

+ 4 - 0
Tests/RunCMake/install/FILES-EXTRA_ISPC_TARGET_OBJECTS.cmake

@@ -0,0 +1,4 @@
+enable_language(ISPC)
+add_library(objs OBJECT obj1.ispc obj2.ispc)
+set_target_properties(objs PROPERTIES ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i16x8;avx1-i32x16;avx2-i32x4")
+install(FILES $<TARGET_OBJECTS:objs> DESTINATION objs)

+ 5 - 0
Tests/RunCMake/install/RunCMakeTest.cmake

@@ -96,6 +96,11 @@ if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}
   run_install_test(FILES-TARGET_OBJECTS)
 endif()
 
+if(CMake_TEST_ISPC)
+  run_install_test(FILES-EXTRA_ISPC_TARGET_OBJECTS)
+endif()
+
+
 run_install_test(TARGETS-InstallFromSubDir)
 run_install_test(TARGETS-OPTIONAL)
 run_install_test(FILES-OPTIONAL)

+ 4 - 0
Tests/RunCMake/install/obj1.ispc

@@ -0,0 +1,4 @@
+
+float func1(float a, float b) {
+     return a + b / 2.;
+}

+ 4 - 0
Tests/RunCMake/install/obj2.ispc

@@ -0,0 +1,4 @@
+
+float func2(float a, float b) {
+     return a + b / 2.;
+}

+ 1 - 0
Tests/RunCMake/try_compile/ISPCDuplicateTarget-stderr.txt

@@ -0,0 +1 @@
+.*Error: Can't compile to multiple variants of avx512skx target!.*

+ 8 - 0
Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake

@@ -0,0 +1,8 @@
+enable_language(ISPC)
+set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16
+                                avx512skx-i32x16)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+  SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+  OUTPUT_VARIABLE out
+  )
+message("try_compile output:\n${out}")

+ 1 - 0
Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja-stderr.txt

@@ -0,0 +1 @@
+.*ninja: error: .* multiple rules generate.*src.ispc_avx512skx.o.*

+ 11 - 0
Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake

@@ -0,0 +1,11 @@
+enable_language(ISPC)
+set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16
+                                avx512skx-i32x16)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+  SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+  OUTPUT_VARIABLE out
+  )
+message("try_compile output:\n${out}")
+if(NOT result)
+  message(FATAL_ERROR "making Ninja and Ninja Multi-Config behave the same")
+endif()

+ 1 - 0
Tests/RunCMake/try_compile/ISPCInvalidTarget-stderr.txt

@@ -0,0 +1 @@
+.*Error: Incorrect targets: avxknl-i32x16.*

+ 7 - 0
Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake

@@ -0,0 +1,7 @@
+enable_language(ISPC)
+set(CMAKE_ISPC_INSTRUCTION_SETS "avxknl-i32x16")
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+  SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+  OUTPUT_VARIABLE out
+  )
+message("try_compile output:\n${out}")

+ 1 - 0
Tests/RunCMake/try_compile/ISPCTargets-stderr.txt

@@ -0,0 +1 @@
+.*Linking ISPC static library*

+ 1 - 0
Tests/RunCMake/try_compile/ISPCTargets-stdout.txt

@@ -0,0 +1 @@
+.*Detecting ISPC compiler ABI info - done.*

+ 7 - 0
Tests/RunCMake/try_compile/ISPCTargets.cmake

@@ -0,0 +1,7 @@
+enable_language(ISPC)
+set(CMAKE_ISPC_INSTRUCTION_SETS avx512knl-i32x16 avx512skx-i32x16)
+try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
+  SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
+  OUTPUT_VARIABLE out
+  )
+message("try_compile output:\n${out}")

+ 9 - 0
Tests/RunCMake/try_compile/RunCMakeTest.cmake

@@ -51,6 +51,15 @@ endif()
 if(CMake_TEST_CUDA)
   run_cmake(CudaStandard)
 endif()
+if(CMake_TEST_ISPC)
+  run_cmake(ISPCTargets)
+  run_cmake(ISPCInvalidTarget)
+  set(ninja "")
+  if(RunCMake_GENERATOR MATCHES "Ninja")
+    set(ninja "Ninja")
+  endif()
+  run_cmake(ISPCDuplicateTarget${ninja})
+endif()
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4)
   run_cmake(CStandardGNU)
 endif()

+ 4 - 0
Tests/RunCMake/try_compile/src.ispc

@@ -0,0 +1,4 @@
+
+float func(float a, float b) {
+     return a + b / 2.;
+}