Add initial CMakeLists.txt files

Adds CMake support for:
 - Generating the Dawn headers and C++ wrappers
 - libdawn_wire
 - libdawn_native with the Metal backend for now
 - All the examples.

Bug: dawn:333

Change-Id: I6ffbe090b0bd21d6a805c03a507ad51fda0275ca
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15720
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..c33f570
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,142 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.10)
+
+# When upgrading to CMake 3.11 we can remove DAWN_DUMMY_FILE because source-less add_library
+# becomes available.
+# When upgrading to CMake 3.12 we should add CONFIGURE_DEPENDS to DawnGenerator to rerun CMake in
+# case any of the generator files changes.
+
+project(
+    Dawn
+    DESCRIPTION "Dawn, a WebGPU implementation"
+    HOMEPAGE_URL "https://dawn.googlesource.com/dawn"
+    LANGUAGES C CXX
+)
+
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+if(NOT CMAKE_BUILD_TYPE)
+    message(WARNING "CMAKE_BUILD_TYPE not set, forcing it to Debug")
+    set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
+        "Build type (Debug, Release, RelWithDebInfo, MinSizeRel)" FORCE)
+endif()
+
+set(DAWN_BUILD_GEN_DIR "${Dawn_BINARY_DIR}/gen")
+set(DAWN_GENERATOR_DIR "${Dawn_SOURCE_DIR}/generator")
+set(DAWN_SRC_DIR "${Dawn_SOURCE_DIR}/src")
+set(DAWN_INCLUDE_DIR "${DAWN_SRC_DIR}/include")
+set(DAWN_TEMPLATE_DIR "${DAWN_GENERATOR_DIR}/templates")
+set(DAWN_THIRD_PARTY_DIR "${Dawn_SOURCE_DIR}/third_party")
+
+set(DAWN_DUMMY_FILE "${DAWN_SRC_DIR}/Dummy.cpp")
+
+################################################################################
+# Configuration options
+################################################################################
+
+# Default values for the backend-enabling options
+set(ENABLE_D3D12 OFF)
+set(ENABLE_METAL OFF)
+set(ENABLE_OPENGL OFF)
+set(ENABLE_VULKAN OFF)
+if (WIN32)
+    set(ENABLE_D3D12 ON)
+    set(ENABLE_VULKAN ON)
+elseif(APPLE)
+    set(ENABLE_METAL ON)
+elseif(UNIX)
+    set(ENABLE_OPENGL ON)
+    set(ENABLE_VULKAN ON)
+endif()
+
+option(DAWN_ENABLE_D3D12 "Enable compilation of the D3D12 backend" ${ENABLE_D3D12})
+option(DAWN_ENABLE_METAL "Enable compilation of the Metal backend" ${ENABLE_METAL})
+option(DAWN_ENABLE_NULL "Enable compilation of the Null backend" ON)
+option(DAWN_ENABLE_OPENGL "Enable compilation of the OpenGL backend" ${ENABLE_OPENGL})
+option(DAWN_ENABLE_VULKAN "Enable compilation of the Vulkan backend" ${ENABLE_VULKAN})
+option(DAWN_ALWAYS_ASSERT "Enable assertions on all build types" OFF)
+
+option(DAWN_BUILD_EXAMPLES "Enables building Dawn's exmaples" ON)
+
+set(DAWN_GLFW_DIR "${DAWN_THIRD_PARTY_DIR}/glfw" CACHE STRING "Directory in which to find GLFW")
+set(DAWN_GLM_DIR "${DAWN_THIRD_PARTY_DIR}/glm" CACHE STRING "Directory in which to find GLM")
+set(DAWN_GLSLANG_DIR "${DAWN_THIRD_PARTY_DIR}/glslang" CACHE STRING "Directory in which to find GLSLang")
+set(DAWN_JINJA2_DIR "${DAWN_THIRD_PARTY_DIR}/jinja2" CACHE STRING "Directory in which to find Jinja2")
+set(DAWN_SHADERC_DIR "${DAWN_THIRD_PARTY_DIR}/shaderc" CACHE STRING "Directory in which to find shaderc")
+set(DAWN_SPIRV_CROSS_DIR "${DAWN_THIRD_PARTY_DIR}/spirv-cross" CACHE STRING "Directory in which to find SPIRV-Cross")
+set(DAWN_SPIRV_HEADERS_DIR "${DAWN_THIRD_PARTY_DIR}/spirv-headers" CACHE STRING "Directory in which to find SPIRV-Headers")
+set(DAWN_SPIRV_TOOLS_DIR "${DAWN_THIRD_PARTY_DIR}/SPIRV-Tools" CACHE STRING "Directory in which to find SPIRV-Tools")
+
+################################################################################
+# Dawn's public and internal "configs"
+################################################################################
+
+# The public config contains only the include paths for the Dawn headers.
+add_library(dawn_public_config INTERFACE)
+target_include_directories(dawn_public_config INTERFACE
+    "${DAWN_SRC_DIR}/include"
+    "${DAWN_BUILD_GEN_DIR}/src/include"
+)
+
+# The internal config conatins additional path but includes the dawn_public_config include paths
+add_library(dawn_internal_config INTERFACE)
+target_include_directories(dawn_internal_config INTERFACE
+    "${DAWN_SRC_DIR}"
+    "${DAWN_BUILD_GEN_DIR}/src"
+)
+target_link_libraries(dawn_internal_config INTERFACE dawn_public_config)
+
+# Compile definitions for the internal config
+if (DAWN_ALWAYS_ASSERT OR $<CONFIG:Debug>)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_ASSERTS")
+endif()
+if (DAWN_ENABLE_D3D12)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_D3D12")
+endif()
+if (DAWN_ENABLE_METAL)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_METAL")
+endif()
+if (DAWN_ENABLE_NULL)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_NULL")
+endif()
+if (DAWN_ENABLE_OPENGL)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_OPENGL")
+endif()
+if (DAWN_ENABLE_VULKAN)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_VULKAN")
+endif()
+if (UNIX AND NOT APPLE)
+    target_compile_definitions(dawn_internal_config INTERFACE "DAWN_USE_X11")
+endif()
+
+set(CMAKE_CXX_STANDARD "14")
+
+################################################################################
+# Run on all subdirectories
+################################################################################
+
+add_subdirectory(third_party)
+add_subdirectory(src/common)
+add_subdirectory(generator)
+add_subdirectory(src/dawn)
+add_subdirectory(src/dawn_platform)
+add_subdirectory(src/dawn_native)
+add_subdirectory(src/dawn_wire)
+
+if (DAWN_BUILD_EXAMPLES)
+    add_subdirectory(src/utils)
+    add_subdirectory(examples)
+endif()
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..896b87e
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+add_library(dawn_sample_utils STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_sample_utils PRIVATE
+    "SampleUtils.cpp"
+    "SampleUtils.h"
+)
+target_link_libraries(dawn_sample_utils PUBLIC
+    dawn_internal_config
+    dawncpp
+    dawn_proc
+    dawn_common
+    dawn_native
+    dawn_wire
+    dawn_utils
+    glfw
+)
+
+add_executable(CppHelloTriangle "CppHelloTriangle.cpp")
+target_link_libraries(CppHelloTriangle dawn_sample_utils)
+
+add_executable(CHelloTriangle "CHelloTriangle.cpp")
+target_link_libraries(CHelloTriangle dawn_sample_utils)
+
+add_executable(ComputeBoids "ComputeBoids.cpp")
+target_link_libraries(ComputeBoids dawn_sample_utils glm)
+
+add_executable(Animometer "Animometer.cpp")
+target_link_libraries(Animometer dawn_sample_utils)
+
+add_executable(CubeReflection "CubeReflection.cpp")
+target_link_libraries(CubeReflection dawn_sample_utils glm)
diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt
new file mode 100644
index 0000000..c21359c
--- /dev/null
+++ b/generator/CMakeLists.txt
@@ -0,0 +1,116 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+find_package(PythonInterp REQUIRED)
+message(STATUS "Dawn: using python at ${PYTHON_EXECUTABLE}")
+
+# Check for Jinja2
+if (NOT DAWN_JINJA2_DIR)
+    message(STATUS "Dawn: Using system jinja2")
+    execute_process(
+        COMMAND ${PYTHON_EXECUTABLE} -c "import jinja2"
+        RESULT_VARIABLE RET
+    )
+    if (NOT RET EQUAL 0)
+        message(FATAL_ERROR "Dawn: Missing dependencies for code generation, please ensure you have python-jinja2 installed.")
+    endif()
+else()
+    message(STATUS "Dawn: Using jinja2 at ${DAWN_JINJA2_DIR}")
+endif()
+
+# Function to invoke a generator_lib.py generator.
+#  - SCRIPT is the name of the script to call
+#  - ARGS are the extra arguments to pass to the script in addition to the base generator_lib.py arguments
+#  - PRINT_NAME is the name to use when outputting status or errors
+#  - RESULT_VARIABLE will be modified to contain the list of files generated by this generator
+function(DawnGenerator)
+    set(oneValueArgs SCRIPT RESULT_VARIABLE PRINT_NAME)
+    set(multiValueArgs ARGS)
+    cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    # Build the set of args common to all invocation of that generator.
+    set(BASE_ARGS
+        ${PYTHON_EXECUTABLE}
+        ${G_SCRIPT}
+        --template-dir
+        "${DAWN_TEMPLATE_DIR}"
+        --root-dir
+        "${Dawn_SOURCE_DIR}"
+        --output-dir
+        "${DAWN_BUILD_GEN_DIR}"
+        ${G_ARGS}
+    )
+    if (DAWN_JINJA2_DIR)
+        list(APPEND BASE_ARGS --jinja2-path ${DAWN_JINJA2_DIR})
+    endif()
+
+    # Call the generator to get the list of its dependencies.
+    execute_process(
+        COMMAND ${BASE_ARGS} --print-cmake-dependencies
+        OUTPUT_VARIABLE DEPENDENCIES
+        RESULT_VARIABLE RET
+    )
+    if (NOT RET EQUAL 0)
+        message(FATAL_ERROR "Dawn: Failed to get the dependencies for ${G_PRINT_NAME}.")
+    endif()
+
+    # Ask CMake to re-run if any of the dependencies changed as it might modify the build graph.
+    if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0")
+        set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${DEPENDENCIES})
+    endif()
+
+    # Call the generator to get the list of its outputs.
+    execute_process(
+        COMMAND ${BASE_ARGS} --print-cmake-outputs
+        OUTPUT_VARIABLE OUTPUTS
+        RESULT_VARIABLE RET
+    )
+    if (NOT RET EQUAL 0)
+        message(FATAL_ERROR "Dawn: Failed to get the outputs for ${G_PRINT_NAME}.")
+    endif()
+
+    # Add the custom command that calls the generator.
+    add_custom_command(
+        COMMAND ${BASE_ARGS}
+        DEPENDS ${DEPENDENCIES}
+        OUTPUT ${OUTPUTS}
+        COMMENT "Dawn: Generating files for ${G_PRINT_NAME}."
+    )
+
+    # Return the list of outputs.
+    set(${G_RESULT_VARIABLE} ${OUTPUTS} PARENT_SCOPE)
+endfunction()
+
+# Helper function to call dawn_generator.py:
+#  - TARGET is the generator target to build
+#  - PRINT_NAME and RESULT_VARIABLE are like for DawnGenerator
+function(DawnJSONGenerator)
+    set(oneValueArgs TARGET RESULT_VARIABLE)
+    cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    DawnGenerator(
+        SCRIPT "${Dawn_SOURCE_DIR}/generator/dawn_json_generator.py"
+        ARGS --dawn-json
+             "${Dawn_SOURCE_DIR}/dawn.json"
+             --wire-json
+             "${Dawn_SOURCE_DIR}/dawn_wire.json"
+             --targets
+             ${G_TARGET}
+        RESULT_VARIABLE RET
+        ${G_UNPARSED_ARGUMENTS}
+    )
+
+    # Forward the result up one more scope
+    set(${G_RESULT_VARIABLE} ${RET} PARENT_SCOPE)
+endfunction()
diff --git a/generator/generator_lib.py b/generator/generator_lib.py
index 56b3f34..bda4c1e 100644
--- a/generator/generator_lib.py
+++ b/generator/generator_lib.py
@@ -206,22 +206,39 @@
 def run_generator(generator):
     parser = argparse.ArgumentParser(
         description = generator.get_description(),
-        formatter_class = argparse.ArgumentDefaultsHelpFormatter
+        formatter_class = argparse.ArgumentDefaultsHelpFormatter,
     )
 
     generator.add_commandline_arguments(parser);
-    parser.add_argument('-t', '--template-dir', default='templates', type=str, help='Directory with template files.')
+    parser.add_argument('--template-dir', default='templates', type=str, help='Directory with template files.')
     parser.add_argument(kJinja2Path, default=None, type=str, help='Additional python path to set before loading Jinja2')
     parser.add_argument('--output-json-tarball', default=None, type=str, help='Name of the "JSON tarball" to create (tar is too annoying to use in python).')
     parser.add_argument('--depfile', default=None, type=str, help='Name of the Ninja depfile to create for the JSON tarball')
     parser.add_argument('--expected-outputs-file', default=None, type=str, help="File to compare outputs with and fail if it doesn't match")
     parser.add_argument('--root-dir', default=None, type=str, help='Optional source root directory for Python dependency computations')
     parser.add_argument('--allowed-output-dirs-file', default=None, type=str, help="File containing a list of allowed directories where files can be output.")
+    parser.add_argument('--print-cmake-dependencies', default=False, action="store_true", help="Prints a semi-colon separated list of dependencies to stdout and exits.")
+    parser.add_argument('--print-cmake-outputs', default=False, action="store_true", help="Prints a semi-colon separated list of outputs to stdout and exits.")
+    parser.add_argument('--output-dir', default=None, type=str, help='Directory where to output generate files.')
 
     args = parser.parse_args()
 
     renders = generator.get_file_renders(args);
 
+    # Output a list of all dependencies for CMake or the tarball for GN/Ninja.
+    if args.depfile != None or args.print_cmake_dependencies:
+        dependencies = generator.get_dependencies(args)
+        dependencies += [args.template_dir + os.path.sep + render.template for render in renders]
+        dependencies += _compute_python_dependencies(args.root_dir)
+
+        if args.depfile != None:
+            with open(args.depfile, 'w') as f:
+                f.write(args.output_json_tarball + ": " + " ".join(dependencies))
+
+        if args.print_cmake_dependencies:
+            sys.stdout.write(";".join(dependencies))
+            return 0
+
     # The caller wants to assert that the outputs are what it expects.
     # Load the file and compare with our renders.
     if args.expected_outputs_file != None:
@@ -235,6 +252,11 @@
             print("Actual output:\n    " + repr(sorted(actual)))
             return 1
 
+    # Print the list of all the outputs for cmake.
+    if args.print_cmake_outputs:
+        sys.stdout.write(";".join([os.path.join(args.output_dir, render.output) for render in renders]))
+        return 0
+
     outputs = _do_renders(renders, args.template_dir)
 
     # The caller wants to assert that the outputs are only in specific directories.
@@ -257,7 +279,7 @@
                     print('    "{}"'.format(directory))
                 return 1
 
-    # Output the tarball and its depfile
+    # Output the JSON tarball
     if args.output_json_tarball != None:
         json_root = {}
         for output in outputs:
@@ -266,11 +288,14 @@
         with open(args.output_json_tarball, 'w') as f:
             f.write(json.dumps(json_root))
 
-    # Output a list of all dependencies for the tarball for Ninja.
-    if args.depfile != None:
-        dependencies = generator.get_dependencies(args)
-        dependencies += [args.template_dir + os.path.sep + render.template for render in renders]
-        dependencies += _compute_python_dependencies(args.root_dir)
+    # Output the files directly.
+    if args.output_dir != None:
+        for output in outputs:
+            output_path = os.path.join(args.output_dir, output.name)
 
-        with open(args.depfile, 'w') as f:
-            f.write(args.output_json_tarball + ": " + " ".join(dependencies))
+            directory = os.path.dirname(output_path)
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+
+            with open(output_path, 'w') as outfile:
+                outfile.write(output.content)
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
new file mode 100644
index 0000000..2498db6
--- /dev/null
+++ b/src/common/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+add_library(dawn_common STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_common PRIVATE
+    "Assert.cpp"
+    "Assert.h"
+    "BitSetIterator.h"
+    "Compiler.h"
+    "Constants.h"
+    "DynamicLib.cpp"
+    "DynamicLib.h"
+    "GPUInfo.cpp"
+    "GPUInfo.h"
+    "HashUtils.h"
+    "Log.cpp"
+    "Log.h"
+    "Math.cpp"
+    "Math.h"
+    "Platform.h"
+    "Result.cpp"
+    "Result.h"
+    "Serial.h"
+    "SerialMap.h"
+    "SerialQueue.h"
+    "SerialStorage.h"
+    "SwapChainUtils.h"
+    "SystemUtils.cpp"
+    "SystemUtils.h"
+    "vulkan_platform.h"
+    "windows_with_undefs.h"
+    "xlib_with_undefs.h"
+)
+target_link_libraries(dawn_common PRIVATE dawn_internal_config)
+
+# TODO Android Log support
+# TODO Vulkan headers support
diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt
new file mode 100644
index 0000000..9024051
--- /dev/null
+++ b/src/dawn/CMakeLists.txt
@@ -0,0 +1,75 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+###############################################################################
+# Dawn headers
+###############################################################################
+
+DawnJSONGenerator(
+    TARGET "dawn_headers"
+    PRINT_NAME "Dawn headers"
+    RESULT_VARIABLE "DAWN_HEADERS_GEN_SOURCES"
+)
+
+add_library(dawn_headers INTERFACE)
+target_sources(dawn_headers INTERFACE
+    "${DAWN_INCLUDE_DIR}/dawn/dawn_wsi.h"
+    ${DAWN_HEADERS_GEN_SOURCES}
+)
+target_link_libraries(dawn_headers INTERFACE dawn_public_config)
+
+###############################################################################
+# Dawn C++ headers
+###############################################################################
+
+DawnJSONGenerator(
+    TARGET "dawncpp_headers"
+    PRINT_NAME "Dawn C++ headers"
+    RESULT_VARIABLE "DAWNCPP_HEADERS_GEN_SOURCES"
+)
+
+add_library(dawncpp_headers INTERFACE)
+target_sources(dawncpp_headers INTERFACE
+    "${DAWN_INCLUDE_DIR}/dawn/EnumClassBitmasks.h"
+    ${DAWNCPP_HEADERS_GEN_SOURCES}
+)
+target_link_libraries(dawncpp_headers INTERFACE dawn_headers)
+
+###############################################################################
+# Dawn C++ wrapper
+###############################################################################
+
+DawnJSONGenerator(
+    TARGET "dawncpp"
+    PRINT_NAME "Dawn C++ wrapper"
+    RESULT_VARIABLE "DAWNCPP_GEN_SOURCES"
+)
+
+add_library(dawncpp STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawncpp PRIVATE ${DAWNCPP_GEN_SOURCES})
+target_link_libraries(dawncpp PUBLIC dawncpp_headers)
+
+###############################################################################
+# libdawn_proc
+###############################################################################
+
+DawnJSONGenerator(
+    TARGET "dawn_proc"
+    PRINT_NAME "Dawn C++ wrapper"
+    RESULT_VARIABLE "DAWNPROC_GEN_SOURCES"
+)
+
+add_library(dawn_proc STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_proc PRIVATE ${DAWNPROC_GEN_SOURCES})
+target_link_libraries(dawn_proc PUBLIC dawn_headers)
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
new file mode 100644
index 0000000..004c00a
--- /dev/null
+++ b/src/dawn_native/CMakeLists.txt
@@ -0,0 +1,237 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+DawnJSONGenerator(
+    TARGET "dawn_native_utils"
+    PRINT_NAME "Dawn native utilities"
+    RESULT_VARIABLE "DAWN_NATIVE_UTILS_GEN_SOURCES"
+)
+
+add_library(dawn_native STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_native PRIVATE
+    "${DAWN_INCLUDE_DIR}/dawn_native/DawnNative.h"
+    "${DAWN_INCLUDE_DIR}/dawn_native/dawn_native_export.h"
+    ${DAWN_NATIVE_UTILS_GEN_SOURCES}
+    "Adapter.cpp"
+    "Adapter.h"
+    "AttachmentState.cpp"
+    "AttachmentState.h"
+    "BackendConnection.cpp"
+    "BackendConnection.h"
+    "BindGroup.cpp"
+    "BindGroup.h"
+    "BindGroupLayout.cpp"
+    "BindGroupLayout.h"
+    "BindGroupTracker.h"
+    "BuddyAllocator.cpp"
+    "BuddyAllocator.h"
+    "BuddyMemoryAllocator.cpp"
+    "BuddyMemoryAllocator.h"
+    "Buffer.cpp"
+    "Buffer.h"
+    "CachedObject.cpp"
+    "CachedObject.h"
+    "CommandAllocator.cpp"
+    "CommandAllocator.h"
+    "CommandBuffer.cpp"
+    "CommandBuffer.h"
+    "CommandBufferStateTracker.cpp"
+    "CommandBufferStateTracker.h"
+    "CommandEncoder.cpp"
+    "CommandEncoder.h"
+    "CommandValidation.cpp"
+    "CommandValidation.h"
+    "Commands.cpp"
+    "Commands.h"
+    "ComputePassEncoder.cpp"
+    "ComputePassEncoder.h"
+    "ComputePipeline.cpp"
+    "ComputePipeline.h"
+    "Device.cpp"
+    "Device.h"
+    "DynamicUploader.cpp"
+    "DynamicUploader.h"
+    "EncodingContext.cpp"
+    "EncodingContext.h"
+    "Error.cpp"
+    "Error.h"
+    "ErrorData.cpp"
+    "ErrorData.h"
+    "ErrorInjector.cpp"
+    "ErrorInjector.h"
+    "ErrorScope.cpp"
+    "ErrorScope.h"
+    "ErrorScopeTracker.cpp"
+    "ErrorScopeTracker.h"
+    "Extensions.cpp"
+    "Extensions.h"
+    "Fence.cpp"
+    "Fence.h"
+    "FenceSignalTracker.cpp"
+    "FenceSignalTracker.h"
+    "Format.cpp"
+    "Format.h"
+    "Forward.h"
+    "Instance.cpp"
+    "Instance.h"
+    "ObjectBase.cpp"
+    "ObjectBase.h"
+    "PassResourceUsage.h"
+    "PassResourceUsageTracker.cpp"
+    "PassResourceUsageTracker.h"
+    "PerStage.cpp"
+    "PerStage.h"
+    "Pipeline.cpp"
+    "Pipeline.h"
+    "PipelineLayout.cpp"
+    "PipelineLayout.h"
+    "ProgrammablePassEncoder.cpp"
+    "ProgrammablePassEncoder.h"
+    "Queue.cpp"
+    "Queue.h"
+    "RefCounted.cpp"
+    "RefCounted.h"
+    "RenderBundle.cpp"
+    "RenderBundle.h"
+    "RenderBundleEncoder.cpp"
+    "RenderBundleEncoder.h"
+    "RenderEncoderBase.cpp"
+    "RenderEncoderBase.h"
+    "RenderPassEncoder.cpp"
+    "RenderPassEncoder.h"
+    "RenderPipeline.cpp"
+    "RenderPipeline.h"
+    "ResourceHeap.h"
+    "ResourceHeapAllocator.h"
+    "ResourceMemoryAllocation.cpp"
+    "ResourceMemoryAllocation.h"
+    "RingBufferAllocator.cpp"
+    "RingBufferAllocator.h"
+    "Sampler.cpp"
+    "Sampler.h"
+    "ShaderModule.cpp"
+    "ShaderModule.h"
+    "StagingBuffer.cpp"
+    "StagingBuffer.h"
+    "Surface.cpp"
+    "Surface.h"
+    "SwapChain.cpp"
+    "SwapChain.h"
+    "Texture.cpp"
+    "Texture.h"
+    "ToBackend.h"
+    "Toggles.cpp"
+    "Toggles.h"
+    "dawn_platform.h"
+)
+target_link_libraries(dawn_native
+    PUBLIC dawncpp_headers
+    PRIVATE dawn_common
+            dawn_platform
+            dawn_internal_config
+            shaderc_spvc
+            spirv-cross-core
+)
+
+if (DAWN_ENABLE_D3D12)
+    #TODO
+endif()
+
+if (DAWN_ENABLE_METAL)
+    target_sources(dawn_native PRIVATE
+        "${DAWN_INCLUDE_DIR}/dawn_native/MetalBackend.h"
+        "Surface_metal.mm"
+        "metal/BackendMTL.h"
+        "metal/BackendMTL.mm"
+        "metal/BufferMTL.h"
+        "metal/BufferMTL.mm"
+        "metal/CommandBufferMTL.h"
+        "metal/CommandBufferMTL.mm"
+        "metal/CommandRecordingContext.h"
+        "metal/CommandRecordingContext.mm"
+        "metal/ComputePipelineMTL.h"
+        "metal/ComputePipelineMTL.mm"
+        "metal/DeviceMTL.h"
+        "metal/DeviceMTL.mm"
+        "metal/Forward.h"
+        "metal/PipelineLayoutMTL.h"
+        "metal/PipelineLayoutMTL.mm"
+        "metal/QueueMTL.h"
+        "metal/QueueMTL.mm"
+        "metal/RenderPipelineMTL.h"
+        "metal/RenderPipelineMTL.mm"
+        "metal/SamplerMTL.h"
+        "metal/SamplerMTL.mm"
+        "metal/ShaderModuleMTL.h"
+        "metal/ShaderModuleMTL.mm"
+        "metal/StagingBufferMTL.h"
+        "metal/StagingBufferMTL.mm"
+        "metal/SwapChainMTL.h"
+        "metal/SwapChainMTL.mm"
+        "metal/TextureMTL.h"
+        "metal/TextureMTL.mm"
+        "metal/UtilsMetal.h"
+        "metal/UtilsMetal.mm"
+    )
+    target_link_libraries(dawn_native PRIVATE
+        "-framework Cocoa"
+        "-framework IOKit"
+        "-framework IOSurface"
+        "-framework QuartzCore"
+    )
+endif()
+
+if (DAWN_ENABLE_NULL)
+    target_sources(dawn_native PRIVATE
+        "${DAWN_INCLUDE_DIR}/dawn_native/NullBackend.h"
+        "null/DeviceNull.cpp"
+        "null/DeviceNull.h"
+    )
+endif()
+
+if (DAWN_ENABLE_OPENGL)
+    DawnGenerator(
+        SCRIPT "${Dawn_SOURCE_DIR}/generator/opengl_loader_generator.py"
+        PRINT_NAME "OpenGL function loader"
+        ARGS "--gl-xml"
+             "${Dawn_SOURCE_DIR}/third_party/khronos/gl.xml"
+             "--supported-extensions"
+             "${Dawn_SOURCE_DIR}/src/dawn_native/opengl/supported_extensions.json"
+        RESULT_VARIABLE "DAWN_NATIVE_OPENGL_AUTOGEN_SOURCES"
+    )
+
+    # TODO
+endif()
+
+if (DAWN_ENABLE_VULKAN)
+    # TODO
+endif()
+
+# TODO how to do the component build in CMake?
+target_sources(dawn_native PRIVATE "DawnNative.cpp")
+if (DAWN_ENABLE_D3D12)
+    target_sources(dawn_native PRIVATE "d3d12/D3D12Backend.cpp")
+endif()
+if (DAWN_ENABLE_METAL)
+    target_sources(dawn_native PRIVATE "metal/MetalBackend.mm")
+endif()
+if (DAWN_ENABLE_NULL)
+    target_sources(dawn_native PRIVATE "null/NullBackend.cpp")
+endif()
+if (DAWN_ENABLE_OPENGL)
+    target_sources(dawn_native PRIVATE "opengl/OpenGLBackend.cpp")
+endif()
+if (DAWN_ENABLE_VULKAN)
+    target_sources(dawn_native PRIVATE "vulkan/VulkanBackend.cpp")
+endif()
diff --git a/src/dawn_platform/CMakeLists.txt b/src/dawn_platform/CMakeLists.txt
new file mode 100644
index 0000000..d94b552
--- /dev/null
+++ b/src/dawn_platform/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+add_library(dawn_platform STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_platform PRIVATE
+    "${DAWN_INCLUDE_DIR}/dawn_platform/DawnPlatform.h"
+    "tracing/EventTracer.cpp"
+    "tracing/EventTracer.h"
+    "tracing/TraceEvent.h"
+)
+target_link_libraries(dawn_platform PRIVATE dawn_internal_config dawn_common)
diff --git a/src/dawn_wire/CMakeLists.txt b/src/dawn_wire/CMakeLists.txt
new file mode 100644
index 0000000..8ec7bff
--- /dev/null
+++ b/src/dawn_wire/CMakeLists.txt
@@ -0,0 +1,57 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+DawnJSONGenerator(
+    TARGET "dawn_wire"
+    PRINT_NAME "Dawn wire"
+    RESULT_VARIABLE "DAWN_WIRE_GEN_SOURCES"
+)
+
+add_library(dawn_wire STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_wire PRIVATE
+    "${DAWN_INCLUDE_DIR}/dawn_wire/Wire.h"
+    "${DAWN_INCLUDE_DIR}/dawn_wire/WireClient.h"
+    "${DAWN_INCLUDE_DIR}/dawn_wire/WireServer.h"
+    "${DAWN_INCLUDE_DIR}/dawn_wire/dawn_wire_export.h"
+    ${DAWN_WIRE_GEN_SOURCES}
+    "WireClient.cpp"
+    "WireDeserializeAllocator.cpp"
+    "WireDeserializeAllocator.h"
+    "WireServer.cpp"
+    "client/ApiObjects.h"
+    "client/ApiProcs.cpp"
+    "client/Buffer.cpp"
+    "client/Buffer.h"
+    "client/Client.cpp"
+    "client/Client.h"
+    "client/ClientDoers.cpp"
+    "client/ClientInlineMemoryTransferService.cpp"
+    "client/Device.cpp"
+    "client/Device.h"
+    "client/Fence.cpp"
+    "client/Fence.h"
+    "client/ObjectAllocator.h"
+    "server/ObjectStorage.h"
+    "server/Server.cpp"
+    "server/Server.h"
+    "server/ServerBuffer.cpp"
+    "server/ServerDevice.cpp"
+    "server/ServerFence.cpp"
+    "server/ServerInlineMemoryTransferService.cpp"
+    "server/ServerQueue.cpp"
+)
+target_link_libraries(dawn_wire
+    PUBLIC dawn_headers
+    PRIVATE dawn_common dawn_internal_config
+)
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
new file mode 100644
index 0000000..06ec98c
--- /dev/null
+++ b/src/utils/CMakeLists.txt
@@ -0,0 +1,78 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+add_library(dawn_utils STATIC ${DAWN_DUMMY_FILE})
+target_sources(dawn_utils PRIVATE
+    "BackendBinding.cpp"
+    "BackendBinding.h"
+    "ComboRenderBundleEncoderDescriptor.cpp"
+    "ComboRenderBundleEncoderDescriptor.h"
+    "ComboRenderPipelineDescriptor.cpp"
+    "ComboRenderPipelineDescriptor.h"
+    "GLFWUtils.cpp"
+    "GLFWUtils.h"
+    "SystemUtils.cpp"
+    "SystemUtils.h"
+    "TerribleCommandBuffer.cpp"
+    "TerribleCommandBuffer.h"
+    "Timer.h"
+    "WGPUHelpers.cpp"
+    "WGPUHelpers.h"
+)
+target_link_libraries(dawn_utils
+    PUBLIC dawncpp_headers
+    PRIVATE dawn_internal_config
+            dawn_common
+            dawn_native
+            dawn_wire
+            shaderc
+            glfw
+)
+
+if(WIN32)
+    target_sources(dawn_utils PRIVATE "WindowsTimer.cpp")
+elseif(APPLE)
+    target_sources(dawn_utils PRIVATE
+        "OSXTimer.cpp"
+        "ObjCUtils.h"
+        "ObjCUtils.mm"
+    )
+    target_link_libraries(dawn_utils PRIVATE "-framework QuartzCore")
+elseif(UNIX)
+    target_sources(dawn_utils PRIVATE "PosixTimer.cpp")
+endif()
+
+if (DAWN_ENABLE_D3D12)
+    target_sources(dawn_utils PRIVATE "D3D12Binding.cpp")
+endif()
+
+if (DAWN_ENABLE_METAL)
+    target_sources(dawn_utils PRIVATE
+        "GLFWUtils_metal.mm"
+        "MetalBinding.mm"
+    )
+    target_link_libraries(dawn_utils PRIVATE "-framework Metal")
+endif()
+
+if (DAWN_ENABLE_NULL)
+    target_sources(dawn_utils PRIVATE "NullBinding.cpp")
+endif()
+
+if (DAWN_ENABLE_OPENGL)
+    target_sources(dawn_utils PRIVATE "OpenGLBinding.cpp")
+endif()
+
+if (DAWN_ENABLE_VULKAN)
+    target_sources(dawn_utils PRIVATE "VulkanBinding.cpp")
+endif()
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
new file mode 100644
index 0000000..54484fa
--- /dev/null
+++ b/third_party/CMakeLists.txt
@@ -0,0 +1,74 @@
+# Copyright 2020 The Dawn Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if (NOT TARGET SPIRV-Headers)
+    set(SPIRV_HEADERS_SKIP_EXAMPLES ON)
+    set(SPIRV_HEADERS_SKIP_INSTALL ON)
+
+    message(STATUS "Dawn: using SPIRV-Headers at ${DAWN_SPIRV_HEADERS_DIR}")
+    add_subdirectory(${DAWN_SPIRV_HEADERS_DIR})
+endif()
+
+if (NOT TARGET SPIRV-Tools)
+    set(SPIRV_SKIP_TESTS ON)
+    set(SPIRV_SKIP_EXECUTABLES ON)
+    set(SKIP_SPIRV_TOOLS_INSTALL ON)
+
+    message(STATUS "Dawn: using SPIRV-Tools at ${DAWN_SPIRV_TOOLS_DIR}")
+    add_subdirectory(${DAWN_SPIRV_TOOLS_DIR})
+endif()
+
+if (NOT TARGET glslang)
+    set(SKIP_GLSLANG_INSTALL ON)
+    set(ENABLE_SPVREMAPPER OFF)
+    set(ENABLE_GLSLANG_BINARIES OFF)
+    set(ENABLE_CTEST OFF)
+
+    message(STATUS "Dawn: using GLSLang at ${DAWN_GLSLANG_DIR}")
+    add_subdirectory(${DAWN_GLSLANG_DIR})
+endif()
+
+if (TARGET shaderc)
+    if (NOT TARGET shaderc_spvc)
+        message(FATAL_ERROR "Dawn: If shaderc is configured before Dawn, it must include SPVC")
+    endif()
+else()
+    set(SHADERC_SKIP_TESTS ON)
+    set(SHADERC_SKIP_INSTALL ON)
+    set(SHADERC_ENABLE_SPVC ON)
+
+    # Let SPVC's CMakeLists.txt deal with configuring SPIRV-Cross
+    set(SPIRV_CROSS_ENABLE_TESTS OFF)
+    set(SHADERC_SPIRV_CROSS_DIR "${DAWN_SPIRV_CROSS_DIR}")
+
+    message(STATUS "Dawn: using shaderc[_spvc] at ${DAWN_SHADERC_DIR}")
+    message(STATUS "Dawn:  - with SPIRV-Cross at ${DAWN_SPIRV_CROSS_DIR}")
+    add_subdirectory(${DAWN_SHADERC_DIR})
+endif()
+
+if (DAWN_BUILD_EXAMPLES)
+    if (NOT TARGET glfw)
+        set(GLFW_BUILD_DOCS OFF)
+        set(GLFW_BUILD_TESTS OFF)
+        set(GLFW_BUILD_EXAMPLES OFF)
+
+        message(STATUS "Dawn: using GLFW at ${DAWN_GLFW_DIR}")
+        add_subdirectory(${DAWN_GLFW_DIR})
+    endif()
+
+    if (NOT TARGET glm)
+        message(STATUS "Dawn: using GLM at ${DAWN_GLM_DIR}")
+        add_subdirectory(${DAWN_GLM_DIR})
+    endif()
+endif()