Enable warnings on non-MSVC
diff --git a/.travis.yml b/.travis.yml
index a804445..fa448d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -47,7 +47,7 @@
  - mkdir -p build
  - cd build
  - cmake --version
- - cmake -G "Ninja" -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
+ - cmake -G "Ninja" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DNXT_USE_WERROR=1 ..
  - cmake --build .
 
  # Test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4793325..5997f05 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,31 +15,62 @@
 cmake_minimum_required(VERSION 2.8)
 project(nxt C CXX)
 
-function(SetCXX14 Target)
-    if(MSVC)
-        set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS "/std:c++14")
-    else()
-        set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS "-std=c++14")
-    endif()
-endfunction()
-function(SetPIC Target)
-    if(MSVC)
-    else()
-        set_property(TARGET ${Target} APPEND PROPERTY COMPILE_OPTIONS "-fPIC")
-    endif()
-endfunction()
+################################################################################
+# Configuration options
+################################################################################
+
+option(NXT_USE_WERROR "Treat warnings as error (useful for CI)" 0)
+
+################################################################################
+# Precompute compile flags and defines, functions to set them
+################################################################################
+
+set(NXT_FLAGS "")
+set(NXT_DEFS "")
+set(NXT_INTERNAL_FLAGS "")
+set(NXT_INTERNAL_DEFS "")
 
 if (WIN32)
-    # Define NOMINMAX to prevent conflics between std::min/max and the min/max macros in WinDef.h
-    add_definitions(-DNOMINMAX)
+    # Define NOMINMAX to prevent conflicts between std::min/max and the min/max macros in WinDef.h
+    list(APPEND NXT_DEFS "NOMINMAX")
     # Remove compile error where the mock NXT creates too many sections for the old obj format.
-    add_compile_options("/bigobj")
+    list(APPEND NXT_FLAGS "/bigobj")
 endif()
 
-add_subdirectory(third_party)
-add_subdirectory(generator)
+if (MSVC)
+    list(APPEND NXT_FLAGS "/std:c++14")
+else()
+    # Activate C++14 only on C++ files, not C files.
+    list(APPEND NXT_FLAGS "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:-std=c++14>")
+    list(APPEND NXT_FLAGS "-fPIC")
+
+    list(APPEND NXT_INTERNAL_FLAGS "-Wall" "-Wextra")
+    list(APPEND NXT_GENERATED_FLAGS "-Wno-unused-variable")
+    if(NXT_USE_WERROR)
+        list(APPEND NXT_INTERNAL_FLAGS "-Werror")
+    endif()
+endif()
+
+function(NXTExternalTarget folder target)
+    set_property(TARGET ${target} APPEND PROPERTY COMPILE_OPTIONS ${NXT_FLAGS})
+    set_property(TARGET ${target} APPEND PROPERTY COMPILE_DEFINITIONS ${NXT_DEFS})
+    set_property(TARGET ${target} PROPERTY FOLDER ${folder})
+endfunction()
+
+function(NXTInternalTarget folder target)
+    NXTExternalTarget("${folder}" ${target})
+    set_property(TARGET ${target} APPEND PROPERTY COMPILE_OPTIONS ${NXT_INTERNAL_FLAGS})
+    set_property(TARGET ${target} APPEND PROPERTY COMPILE_DEFINITIONS ${NXT_INTERNAL_DEFS})
+endfunction()
+
+################################################################################
+# Generate the C and C++ NXT APIs
+################################################################################
 
 set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/include)
+set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
+add_subdirectory(generator)
 
 Generate(
     LIB_NAME nxt
@@ -61,21 +92,12 @@
 )
 target_include_directories(nxtcpp PUBLIC ${GENERATED_DIR} PUBLIC ${INCLUDE_DIR})
 target_link_libraries(nxtcpp nxt)
-SetCXX14(nxtcpp)
 
-Generate(
-    LIB_NAME mock_nxt
-    LIB_TYPE STATIC
-    PRINT_NAME libMockNXT
-    COMMAND_LINE_ARGS
-        ${GENERATOR_COMMON_ARGS}
-        -T mock_nxt
-)
-target_include_directories(mock_nxt PUBLIC ${GENERATED_DIR})
-target_link_libraries(mock_nxt nxt gtest)
-SetCXX14(mock_nxt)
+################################################################################
+# Call to other CMakeLists.txt
+################################################################################
 
-set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
+add_subdirectory(third_party)
 
 add_subdirectory(src/common)
 add_subdirectory(src/backend)
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index e741738..e2ad4b2 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -17,51 +17,25 @@
     SampleUtils.h
 )
 target_link_libraries(sample_utils utils nxt_wire)
-SetCXX14(sample_utils)
+NXTInternalTarget("examples" sample_utils)
 
-add_executable(CHelloTriangle CHelloTriangle.cpp)
-target_link_libraries(CHelloTriangle sample_utils)
-SetCXX14(CHelloTriangle)
+function(add_nxt_sample target sources)
+    add_executable(${target} ${sources})
+    target_link_libraries(${target} sample_utils)
+    target_include_directories(${target} PRIVATE ${GLM_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+    NXTInternaltarget("examples" ${target})
+endfunction()
 
-add_executable(CppHelloTriangle HelloTriangle.cpp)
-target_link_libraries(CppHelloTriangle sample_utils)
-SetCXX14(CppHelloTriangle)
+add_nxt_sample(CHelloTriangle CHelloTriangle.cpp)
+add_nxt_sample(CppHelloTriangle HelloTriangle.cpp)
+add_nxt_sample(ComputeBoids ComputeBoids.cpp)
+add_nxt_sample(HelloVertices HelloVertices.cpp)
+add_nxt_sample(HelloInstancing HelloInstancing.cpp)
+add_nxt_sample(HelloIndices HelloIndices.cpp)
+add_nxt_sample(HelloUBO HelloUBO.cpp)
+add_nxt_sample(HelloCompute HelloCompute.cpp)
+add_nxt_sample(RenderToTexture RenderToTexture.cpp)
+add_nxt_sample(Animometer Animometer.cpp)
+add_nxt_sample(CppHelloDepthStencil HelloDepthStencil.cpp)
 
-add_executable(ComputeBoids ComputeBoids.cpp)
-target_link_libraries(ComputeBoids sample_utils)
-target_include_directories(ComputeBoids PUBLIC ../ ${GLM_INCLUDE_DIR})
-SetCXX14(ComputeBoids)
-
-add_executable(HelloVertices HelloVertices.cpp)
-target_link_libraries(HelloVertices sample_utils)
-SetCXX14(HelloVertices)
-
-add_executable(HelloInstancing HelloInstancing.cpp)
-target_link_libraries(HelloInstancing sample_utils)
-SetCXX14(HelloInstancing)
-
-add_executable(HelloIndices HelloIndices.cpp)
-target_link_libraries(HelloIndices sample_utils)
-SetCXX14(HelloIndices)
-
-add_executable(HelloUBO HelloUBO.cpp)
-target_link_libraries(HelloUBO sample_utils)
-SetCXX14(HelloUBO)
-
-add_executable(HelloCompute HelloCompute.cpp)
-target_link_libraries(HelloCompute sample_utils)
-SetCXX14(HelloCompute)
-
-add_executable(RenderToTexture RenderToTexture.cpp)
-target_link_libraries(RenderToTexture sample_utils)
-SetCXX14(RenderToTexture)
-
-add_executable(Animometer Animometer.cpp)
-target_link_libraries(Animometer sample_utils)
-SetCXX14(Animometer)
-
-add_executable(CppHelloDepthStencil HelloDepthStencil.cpp)
-target_link_libraries(CppHelloDepthStencil sample_utils)
-SetCXX14(CppHelloDepthStencil)
-
-add_subdirectory(glTFViewer)
+add_nxt_sample(glTFViewer glTFViewer/glTFViewer.cpp)
diff --git a/examples/glTFViewer/CMakeLists.txt b/examples/glTFViewer/CMakeLists.txt
deleted file mode 100644
index 7fd29e9..0000000
--- a/examples/glTFViewer/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2017 The NXT 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_executable(glTFViewer glTFViewer.cpp)
-target_link_libraries(glTFViewer sample_utils)
-target_include_directories(glTFViewer PUBLIC ../ ${GLM_INCLUDE_DIR})
-SetCXX14(glTFViewer)
diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt
index d3521b1..998a124 100644
--- a/generator/CMakeLists.txt
+++ b/generator/CMakeLists.txt
@@ -26,7 +26,7 @@
 endif()
 
 function(Generate)
-    set(oneValueArgs LIB_NAME LIB_TYPE PRINT_NAME EXECUTABLE)
+    set(oneValueArgs LIB_NAME LIB_TYPE PRINT_NAME EXECUTABLE FOLDER)
     set(multiValueArgs COMMAND_LINE_ARGS EXTRA_DEPS EXTRA_SOURCES)
     cmake_parse_arguments(G "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
@@ -60,6 +60,12 @@
         ${G_EXTRA_SOURCES}
         ${OUTPUTS}
     )
+
+    NXTInternalTarget("${G_FOLDER}" ${G_LIB_NAME})
+    if (NOT MSVC)
+        target_compile_options(${G_LIB_NAME} PRIVATE "-Wno-unused-variable")
+        target_compile_options(${G_LIB_NAME} PRIVATE "-Wno-unused-function")
+    endif()
 endfunction()
 
 set(GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt
index 6da612b..04e35fa 100644
--- a/src/backend/CMakeLists.txt
+++ b/src/backend/CMakeLists.txt
@@ -69,6 +69,7 @@
 Generate(
     LIB_NAME opengl_autogen
     LIB_TYPE STATIC
+    FOLDER "backend"
     PRINT_NAME "OpenGL backend autogenerated files"
     COMMAND_LINE_ARGS
         ${GENERATOR_COMMON_ARGS}
@@ -77,8 +78,6 @@
 target_link_libraries(opengl_autogen glfw glad nxtcpp)
 target_include_directories(opengl_autogen PRIVATE ${SRC_DIR})
 target_include_directories(opengl_autogen PUBLIC ${GENERATED_DIR})
-SetCXX14(opengl_autogen)
-SetPIC(opengl_autogen)
 
 list(APPEND BACKEND_SOURCES
     ${OPENGL_DIR}/CommandBufferGL.cpp
@@ -105,6 +104,7 @@
 Generate(
     LIB_NAME null_autogen
     LIB_TYPE STATIC
+    FOLDER "backend"
     PRINT_NAME "Null backend autogenerated files"
     COMMAND_LINE_ARGS
         ${GENERATOR_COMMON_ARGS}
@@ -113,8 +113,6 @@
 target_link_libraries(null_autogen nxtcpp)
 target_include_directories(null_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
 target_include_directories(null_autogen PUBLIC ${SRC_DIR})
-SetCXX14(null_autogen)
-SetPIC(null_autogen)
 
 list(APPEND BACKEND_SOURCES
     ${NULL_DIR}/NullBackend.cpp
@@ -127,6 +125,7 @@
     Generate(
         LIB_NAME metal_autogen
         LIB_TYPE STATIC
+        FOLDER "backend"
         PRINT_NAME "Metal backend autogenerated files"
         COMMAND_LINE_ARGS
             ${GENERATOR_COMMON_ARGS}
@@ -135,8 +134,6 @@
     target_link_libraries(metal_autogen glfw glad nxtcpp "-framework QuartzCore" "-framework Metal")
     target_include_directories(metal_autogen PRIVATE ${SRC_DIR})
     target_include_directories(metal_autogen PUBLIC ${GENERATED_DIR})
-    SetCXX14(metal_autogen)
-    SetPIC(metal_autogen)
 
     list(APPEND BACKEND_SOURCES
         ${METAL_DIR}/BufferMTL.mm
@@ -170,6 +167,7 @@
     Generate(
         LIB_NAME d3d12_autogen
         LIB_TYPE STATIC
+        FOLDER "backend"
         PRINT_NAME "D3D12 backend autogenerated files"
         COMMAND_LINE_ARGS
             ${GENERATOR_COMMON_ARGS}
@@ -229,8 +227,6 @@
     target_include_directories(d3d12_autogen SYSTEM PRIVATE ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR})
     target_include_directories(d3d12_autogen PRIVATE ${SRC_DIR})
     target_include_directories(d3d12_autogen PUBLIC ${GENERATED_DIR})
-    SetCXX14(d3d12_autogen)
-    SetPIC(d3d12_autogen)
 
     list(APPEND BACKEND_SOURCES
         ${D3D12_DIR}/BindGroupD3D12.cpp
@@ -269,12 +265,12 @@
 endif()
 
 add_library(nxt_backend STATIC ${BACKEND_SOURCES})
+NXTInternalTarget("backend" nxt_backend)
 
-target_link_libraries(nxt_backend nxt_common opengl_autogen null_autogen glfw glad spirv-cross)
+target_link_libraries(nxt_backend nxt_common opengl_autogen null_autogen glfw glad spirv_cross)
 if (APPLE)
     target_link_libraries(nxt_backend metal_autogen)
 endif()
 if (WIN32)
     target_link_libraries(nxt_backend d3d12_autogen)
 endif()
-SetCXX14(nxt_backend)
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 7eabb07..afee023 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -24,4 +24,4 @@
 
 add_library(nxt_common STATIC ${COMMON_SOURCES})
 target_include_directories(nxt_common PUBLIC ${SRC_DIR})
-SetCXX14(nxt_common)
+NXTInternalTarget("src" nxt_common)
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 8d5b0f4..a4af9ae 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -12,6 +12,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+Generate(
+    LIB_NAME mock_nxt
+    LIB_TYPE STATIC
+    FOLDER "tests"
+    PRINT_NAME libMockNXT
+    COMMAND_LINE_ARGS
+        ${GENERATOR_COMMON_ARGS}
+        -T mock_nxt
+)
+target_include_directories(mock_nxt PUBLIC ${GENERATED_DIR})
+target_link_libraries(mock_nxt nxt gtest)
+
 set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 set(UNITTESTS_DIR ${TESTS_DIR}/unittests)
 set(VALIDATION_TESTS_DIR ${UNITTESTS_DIR}/validation)
@@ -42,7 +54,7 @@
     ${TESTS_DIR}/UnittestsMain.cpp
 )
 target_link_libraries(nxt_unittests nxt_common gtest nxt_backend mock_nxt nxt_wire utils)
-SetCXX14(nxt_unittests)
+NXTInternalTarget("tests" nxt_unittests)
 
 add_executable(nxt_end2end_tests
     ${END2END_TESTS_DIR}/BasicTests.cpp
@@ -52,4 +64,4 @@
     ${TESTS_DIR}/NXTTest.h
 )
 target_link_libraries(nxt_end2end_tests nxt_common gtest utils)
-SetCXX14(nxt_end2end_tests)
+NXTInternalTarget("tests" nxt_end2end_tests)
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
index 4832fa3..1202d0e 100644
--- a/src/utils/CMakeLists.txt
+++ b/src/utils/CMakeLists.txt
@@ -38,4 +38,4 @@
 add_library(utils STATIC ${UTILS_SOURCES})
 target_link_libraries(utils nxt_backend shaderc nxtcpp nxt)
 target_include_directories(utils PUBLIC ${SRC_DIR})
-SetCXX14(utils)
+NXTInternalTarget("" utils)
diff --git a/src/wire/CMakeLists.txt b/src/wire/CMakeLists.txt
index 311f455..3d15903 100644
--- a/src/wire/CMakeLists.txt
+++ b/src/wire/CMakeLists.txt
@@ -18,6 +18,7 @@
 Generate(
     LIB_NAME wire_autogen
     LIB_TYPE STATIC
+    FOLDER "wire"
     PRINT_NAME "Wire serialization/deserialization autogenerated files"
     EXTRA_DEPS nxt
     COMMAND_LINE_ARGS
@@ -30,8 +31,6 @@
 target_include_directories(wire_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
 target_include_directories(wire_autogen PUBLIC ${GENERATED_DIR})
 target_link_libraries(wire_autogen nxt nxt_common)
-SetCXX14(wire_autogen)
-SetPic(wire_autogen)
 
 add_library(nxt_wire STATIC
     ${WIRE_DIR}/TerribleCommandBuffer.cpp
@@ -39,4 +38,4 @@
     ${WIRE_DIR}/Wire.h
 )
 target_link_libraries(nxt_wire wire_autogen)
-SetCXX14(nxt_wire)
+NXTInternalTarget("wire" nxt_wire)
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 262f49c..b4a4d4e 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -18,6 +18,7 @@
 set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
 set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
 add_subdirectory(glfw)
+NXTExternalTarget("third_party" glfw)
 
 # GoogleTest
 set(GTEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest)
@@ -27,6 +28,7 @@
 target_include_directories(gtest PRIVATE ${GTEST_DIR} ${GMOCK_DIR})
 find_package(Threads)
 target_link_libraries(gtest ${CMAKE_THREAD_LIBS_INIT})
+NXTExternalTarget("third_party" gtest)
 
 # Glad
 add_library(glad STATIC
@@ -35,6 +37,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/glad/include/KHR/khrplatform.h
 )
 target_include_directories(glad PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/glad/include)
+NXTExternalTarget("third_party" glad)
 
 # ShaderC
 set(SHADERC_SKIP_TESTS ON)
@@ -47,11 +50,11 @@
 # Need to include this for spirv-tools to find it
 add_subdirectory(spirv-headers)
 add_subdirectory(shaderc)
-SetPIC(shaderc)
-SetPIC(shaderc_util)
+NXTExternalTarget("third_party" shaderc)
+NXTExternalTarget("third_party" shaderc_util)
 
 # SPIRV-Cross
-add_library(spirv-cross STATIC
+add_library(spirv_cross STATIC
     ${CMAKE_CURRENT_SOURCE_DIR}/spirv-cross/GLSL.std.450.h
     ${CMAKE_CURRENT_SOURCE_DIR}/spirv-cross/spirv_common.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/spirv-cross/spirv_cfg.cpp
@@ -68,8 +71,8 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/spirv-cross/spirv_hlsl.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/spirv-cross/spirv_hlsl.hpp
 )
-target_include_directories(spirv-cross PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-SetCXX14(spirv-cross)
+target_include_directories(spirv_cross PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+NXTExternalTarget("third_party" spirv_cross)
 
 # STB, used for stb_image
 set(STB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stb PARENT_SCOPE)