Merge pull request #2271 from ben-clayton/fold-hlsl

Untangle build target cyclic dependencies (approach #2)
diff --git a/SPIRV/CInterface/spirv_c_interface.cpp b/SPIRV/CInterface/spirv_c_interface.cpp
new file mode 100644
index 0000000..c88b808
--- /dev/null
+++ b/SPIRV/CInterface/spirv_c_interface.cpp
@@ -0,0 +1,110 @@
+/**
+    This code is based on the glslang_c_interface implementation by Viktor Latypov
+**/
+
+/**
+BSD 2-Clause License
+
+Copyright (c) 2019, Viktor Latypov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#include "glslang/Include/glslang_c_interface.h"
+
+#include "SPIRV/GlslangToSpv.h"
+#include "SPIRV/Logger.h"
+#include "SPIRV/SpvTools.h"
+
+typedef struct glslang_program_s {
+    glslang::TProgram* program;
+    std::vector<unsigned int> spirv;
+    std::string loggerMessages;
+} glslang_program_t;
+
+static EShLanguage c_shader_stage(glslang_stage_t stage)
+{
+    switch (stage) {
+    case GLSLANG_STAGE_VERTEX:
+        return EShLangVertex;
+    case GLSLANG_STAGE_TESSCONTROL:
+        return EShLangTessControl;
+    case GLSLANG_STAGE_TESSEVALUATION:
+        return EShLangTessEvaluation;
+    case GLSLANG_STAGE_GEOMETRY:
+        return EShLangGeometry;
+    case GLSLANG_STAGE_FRAGMENT:
+        return EShLangFragment;
+    case GLSLANG_STAGE_COMPUTE:
+        return EShLangCompute;
+    case GLSLANG_STAGE_RAYGEN_NV:
+        return EShLangRayGen;
+    case GLSLANG_STAGE_INTERSECT_NV:
+        return EShLangIntersect;
+    case GLSLANG_STAGE_ANYHIT_NV:
+        return EShLangAnyHit;
+    case GLSLANG_STAGE_CLOSESTHIT_NV:
+        return EShLangClosestHit;
+    case GLSLANG_STAGE_MISS_NV:
+        return EShLangMiss;
+    case GLSLANG_STAGE_CALLABLE_NV:
+        return EShLangCallable;
+    case GLSLANG_STAGE_TASK_NV:
+        return EShLangTaskNV;
+    case GLSLANG_STAGE_MESH_NV:
+        return EShLangMeshNV;
+    default:
+        break;
+    }
+    return EShLangCount;
+}
+
+void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage)
+{
+    spv::SpvBuildLogger logger;
+    glslang::SpvOptions spvOptions;
+    spvOptions.validate = true;
+
+    const glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage));
+
+    glslang::GlslangToSpv(*intermediate, program->spirv, &logger, &spvOptions);
+
+    program->loggerMessages = logger.getAllMessages();
+}
+
+size_t glslang_program_SPIRV_get_size(glslang_program_t* program) { return program->spirv.size(); }
+
+void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int* out)
+{
+    memcpy(out, program->spirv.data(), program->spirv.size() * sizeof(unsigned int));
+}
+
+unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program)
+{
+    return program->spirv.data();
+}
+
+const char* glslang_program_SPIRV_get_messages(glslang_program_t* program)
+{
+    return program->loggerMessages.empty() ? nullptr : program->loggerMessages.c_str();
+}
diff --git a/SPIRV/CMakeLists.txt b/SPIRV/CMakeLists.txt
index 8451446..5e90086 100644
--- a/SPIRV/CMakeLists.txt
+++ b/SPIRV/CMakeLists.txt
@@ -6,7 +6,8 @@
     SpvPostProcess.cpp
     doc.cpp
     SpvTools.cpp
-    disassemble.cpp)
+    disassemble.cpp
+    CInterface/spirv_c_interface.cpp)
 
 set(SPVREMAP_SOURCES
     SPVRemapper.cpp
diff --git a/glslang/CInterface/glslang_c_interface.cpp b/glslang/CInterface/glslang_c_interface.cpp
index c4c24a9..54283e6 100644
--- a/glslang/CInterface/glslang_c_interface.cpp
+++ b/glslang/CInterface/glslang_c_interface.cpp
@@ -32,9 +32,6 @@
 
 #include "glslang/Include/glslang_c_interface.h"
 
-#include "SPIRV/GlslangToSpv.h"
-#include "SPIRV/Logger.h"
-#include "SPIRV/SpvTools.h"
 #include "StandAlone/DirStackFileIncluder.h"
 #include "StandAlone/ResourceLimits.h"
 #include "glslang/Include/ShHandle.h"
@@ -401,36 +398,6 @@
     return p;
 }
 
-void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage)
-{
-    spv::SpvBuildLogger logger;
-    glslang::SpvOptions spvOptions;
-    spvOptions.validate = true;
-
-    const glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage));
-
-    glslang::GlslangToSpv(*intermediate, program->spirv, &logger, &spvOptions);
-
-    program->loggerMessages = logger.getAllMessages();
-}
-
-size_t glslang_program_SPIRV_get_size(glslang_program_t* program) { return program->spirv.size(); }
-
-void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int* out)
-{
-    memcpy(out, program->spirv.data(), program->spirv.size() * sizeof(unsigned int));
-}
-
-unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program)
-{
-    return program->spirv.data();
-}
-
-const char* glslang_program_SPIRV_get_messages(glslang_program_t* program)
-{
-    return program->loggerMessages.empty() ? nullptr : program->loggerMessages.c_str();
-}
-
 void glslang_program_delete(glslang_program_t* program)
 {
     if (!program)
diff --git a/glslang/CMakeLists.txt b/glslang/CMakeLists.txt
index a0259a3..606bbdc 100644
--- a/glslang/CMakeLists.txt
+++ b/glslang/CMakeLists.txt
@@ -82,11 +82,32 @@
 
 glslang_pch(SOURCES MachineIndependent/pch.cpp)
 
+if(ENABLE_HLSL)
+    list(APPEND SOURCES
+        ../hlsl/hlslAttributes.cpp
+        ../hlsl/hlslParseHelper.cpp
+        ../hlsl/hlslScanContext.cpp
+        ../hlsl/hlslOpMap.cpp
+        ../hlsl/hlslTokenStream.cpp
+        ../hlsl/hlslGrammar.cpp
+        ../hlsl/hlslParseables.cpp)
+
+    list(APPEND HEADERS
+        ../hlsl/hlslAttributes.h
+        ../hlsl/hlslParseHelper.h
+        ../hlsl/hlslTokens.h
+        ../hlsl/hlslScanContext.h
+        ../hlsl/hlslOpMap.h
+        ../hlsl/hlslTokenStream.h
+        ../hlsl/hlslGrammar.h
+        ../hlsl/hlslParseables.h)
+endif(ENABLE_HLSL)
+
 add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS})
 set_property(TARGET glslang PROPERTY FOLDER glslang)
 set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON)
 target_link_libraries(glslang OGLCompiler OSDependent)
-target_include_directories(glslang PUBLIC 
+target_include_directories(glslang PUBLIC
     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
     $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
 
@@ -94,10 +115,6 @@
     set_target_properties(glslang PROPERTIES PREFIX "")
 endif()
 
-if(ENABLE_HLSL)
-    target_link_libraries(glslang HLSL)
-endif()
-
 if(WIN32)
     source_group("Public" REGULAR_EXPRESSION "Public/*")
     source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*")
diff --git a/hlsl/CMakeLists.txt b/hlsl/CMakeLists.txt
index ae0d4d4..d086631 100644
--- a/hlsl/CMakeLists.txt
+++ b/hlsl/CMakeLists.txt
@@ -1,25 +1,10 @@
-set(SOURCES
-    hlslAttributes.cpp
-    hlslParseHelper.cpp
-    hlslScanContext.cpp
-    hlslOpMap.cpp
-    hlslTokenStream.cpp
-    hlslGrammar.cpp
-    hlslParseables.cpp)
 
-set(HEADERS
-    hlslAttributes.h
-    hlslParseHelper.h
-    hlslTokens.h
-    hlslScanContext.h
-    hlslOpMap.h
-    hlslTokenStream.h
-    hlslGrammar.h
-    hlslParseables.h)
+# The HLSL source is directly embedded into the glslang target when ENABLE_HLSL
+# is set.
+# The HLSL target is now just a stub that exists for backwards compatibility for
+# projects that referenced this target.
 
-glslang_pch(SOURCES pch.cpp)
-
-add_library(HLSL ${LIB_TYPE} ${SOURCES} ${HEADERS})
+add_library(HLSL ${LIB_TYPE} "stub.cpp")
 set_property(TARGET HLSL PROPERTY FOLDER hlsl)
 set_property(TARGET HLSL PROPERTY POSITION_INDEPENDENT_CODE ON)
 
@@ -27,10 +12,6 @@
     set_target_properties(HLSL PROPERTIES PREFIX "")
 endif()
 
-if(WIN32)
-    source_group("Source" FILES ${SOURCES} ${HEADERS})
-endif(WIN32)
-
 if(ENABLE_GLSLANG_INSTALL)
     if(BUILD_SHARED_LIBS)
         install(TARGETS HLSL EXPORT HLSLTargets
diff --git a/hlsl/stub.cpp b/hlsl/stub.cpp
new file mode 100644
index 0000000..c53b939
--- /dev/null
+++ b/hlsl/stub.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2020 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//    Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above
+//    copyright notice, this list of conditions and the following
+//    disclaimer in the documentation and/or other materials provided
+//    with the distribution.
+//
+//    Neither the name of Google, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+// The HLSL source is directly embedded into the glslang target when ENABLE_HLSL
+// is set.
+// The HLSL target is now just a stub that exists for backwards compatibility
+// for projects that referenced this target. As a target requires at least one
+// source file to build, this file acts as that stub.