Merge pull request #369 from adierking/crtassert

Report crash messages on Windows to the CRT
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 021f036..3aafa87 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,7 +34,6 @@
 
 set(SWIFT_LIBDIR "lib" CACHE PATH "Library folder name, defined by swift main buildscript")
 set(INSTALL_LIBDIR "${SWIFT_LIBDIR}" CACHE PATH "Path where the libraries should be installed")
-set(WITH_BLOCKS_RUNTIME "" CACHE PATH "Path to blocks runtime")
 
 include(DispatchAppleOptions)
 include(DispatchSanitization)
@@ -133,14 +132,14 @@
 
 option(INSTALL_PRIVATE_HEADERS "installs private headers in the same location as the public ones" OFF)
 
-if(CMAKE_SYSTEM_NAME STREQUAL Linux OR
-   CMAKE_SYSTEM_NAME STREQUAL Android OR
-   CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR
-   CMAKE_SYSTEM_NAME STREQUAL Windows)
+find_package(BlocksRuntime QUIET)
+if(NOT BlocksRuntime_FOUND)
+  set(BlocksRuntime_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/BlocksRuntime)
+
   add_library(BlocksRuntime
               STATIC
                 ${CMAKE_SOURCE_DIR}/src/BlocksRuntime/data.c
-                ${CMAKE_SOURCE_DIR}/src/BlocksRuntime/runtime.c)            
+                ${CMAKE_SOURCE_DIR}/src/BlocksRuntime/runtime.c)
   set_target_properties(BlocksRuntime
                         PROPERTIES
                           POSITION_INDEPENDENT_CODE TRUE)
@@ -149,8 +148,9 @@
                           PROPERTIES
                             INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
   endif()
-  set(WITH_BLOCKS_RUNTIME "${CMAKE_SOURCE_DIR}/src/BlocksRuntime" CACHE PATH "Path to blocks runtime" FORCE)
-  
+
+  add_library(BlocksRuntime::BlocksRuntime ALIAS BlocksRuntime)
+
   install(FILES
             ${CMAKE_SOURCE_DIR}/src/BlocksRuntime/Block.h
           DESTINATION
@@ -161,9 +161,6 @@
             DESTINATION
               "${INSTALL_BLOCK_HEADERS_DIR}")
   endif()
-else()
-  # TODO(compnerd) support system installed BlocksRuntime
-  # find_package(BlocksRuntime REQUIRED)
 endif()
 
 check_symbol_exists(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
@@ -309,6 +306,14 @@
                        ${CMAKE_COMMAND} -E create_symlink "${CMAKE_SOURCE_DIR}/dispatch/darwin/module.modulemap" "${CMAKE_SOURCE_DIR}/dispatch/module.modulemap"
                      COMMAND
                        ${CMAKE_COMMAND} -E create_symlink "${CMAKE_SOURCE_DIR}/private/darwin/module.modulemap" "${CMAKE_SOURCE_DIR}/private/module.modulemap")
+elseif(CMAKE_SYSTEM_NAME STREQUAL Windows)
+  add_custom_command(OUTPUT
+                       "${CMAKE_SOURCE_DIR}/dispatch/module.modulemap"
+                       "${CMAKE_SOURCE_DIR}/private/module.modulemap"
+                     COMMAND
+                       ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dispatch/generic/module.modulemap" "${CMAKE_SOURCE_DIR}/dispatch/module.modulemap"
+                     COMMAND
+                       ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/private/generic/module.modulemap" "${CMAKE_SOURCE_DIR}/private/module.modulemap")
 else()
   add_custom_command(OUTPUT
                        "${CMAKE_SOURCE_DIR}/dispatch/module.modulemap"
diff --git a/INSTALL.md b/INSTALL.md
index a426bcf..0f4fcf3 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -130,7 +130,7 @@
 clang and blocks support:
 
     ```
-    cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DWITH_BLOCKS_RUNTIME=/usr/local/lib <path-to-source>
+    cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DBlocksRuntime_INCLUDE_DIR=/usr/local/include -DBlocksRuntime_LIBRARIES=/usr/local/lib/libBlocksRuntime.so <path-to-source>
     ninja
     ninja test
     ```
diff --git a/cmake/modules/ClangClCompileRules.cmake b/cmake/modules/ClangClCompileRules.cmake
index 9c2a4cd..0265d5e 100644
--- a/cmake/modules/ClangClCompileRules.cmake
+++ b/cmake/modules/ClangClCompileRules.cmake
@@ -3,6 +3,3 @@
 # put a -- before the input file path to force it to be treated as a path.
 string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
 string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT}")
-
-set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
-
diff --git a/cmake/modules/DispatchWindowsSupport.cmake b/cmake/modules/DispatchWindowsSupport.cmake
index eed28a2..67a1069 100644
--- a/cmake/modules/DispatchWindowsSupport.cmake
+++ b/cmake/modules/DispatchWindowsSupport.cmake
@@ -2,7 +2,7 @@
 function(dispatch_windows_arch_spelling arch var)
   if(${arch} STREQUAL i686)
     set(${var} x86 PARENT_SCOPE)
-  elseif(${arch} STREQUAL x86_64)
+  elseif(${arch} STREQUAL x86_64 OR ${arch} STREQUAL AMD64)
     set(${var} x64 PARENT_SCOPE)
   elseif(${arch} STREQUAL armv7)
     set(${var} arm PARENT_SCOPE)
diff --git a/cmake/modules/FindBlocksRuntime.cmake b/cmake/modules/FindBlocksRuntime.cmake
new file mode 100644
index 0000000..111a5d6
--- /dev/null
+++ b/cmake/modules/FindBlocksRuntime.cmake
@@ -0,0 +1,48 @@
+#.rst:
+# FindBlocksRuntime
+# -----------------
+#
+# Find libBlocksRuntime library and headers.
+#
+# The module defines the following variables:
+#
+# ##
+#
+# BlocksRuntime_FOUND        - true if libBlocksRuntime was found
+# BlocksRuntime_INCLUDE_DIR  - include search path
+# BlocksRuntime_LIBRARIES    - libraries to link
+
+if(BlocksRuntime_INCLUDE_DIR AND BlocksRuntime_LIBRARIES)
+  set(BlocksRuntime_FOUND TRUE)
+else()
+  find_path(BlocksRuntime_INCLUDE_DIR
+            NAMES
+              Blocks.h
+            HINTS
+              ${CMAKE_INSTALL_FULL_INCLUDEDIR})
+  find_library(BlocksRuntime_LIBRARIES
+               NAMES
+                 BlocksRuntime libBlocksRuntime
+               HINTS
+                 ${CMAKE_INSTALL_FULL_LIBDIR})
+
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(BlocksRuntime
+                                    REQUIRED_VARS
+                                      BlocksRuntime_LIBRARIES
+                                      BlocksRuntime_INCLUDE_DIR)
+
+  mark_as_advanced(BlocksRuntime_LIBRARIES BlocksRuntime_INCLUDE_DIR)
+endif()
+
+if(BlocksRuntime_FOUND)
+  if(NOT TARGET BlocksRuntime::BlocksRuntime)
+    add_library(BlocksRuntime::BlocksRuntime UNKNOWN IMPORTED)
+    set_target_properties(BlocksRuntime::BlocksRuntime
+                          PROPERTIES
+                            IMPORTED_LOCATION
+                              ${BlocksRuntime_LIBRARIES}
+                            INTERFACE_INCLUDE_DIRECTORIES
+                              ${BlocksRuntime_INCLUDE_DIR})
+  endif()
+endif()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b855657..f01993b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -61,6 +61,7 @@
 elseif(WIN32)
   target_sources(dispatch
                  PRIVATE
+                   shims/generic_sys_queue.h
                    shims/generic_win_stubs.c
                    shims/generic_win_stubs.h)
 endif()
@@ -134,11 +135,9 @@
                              ${CMAKE_CURRENT_SOURCE_DIR}
                              ${CMAKE_CURRENT_BINARY_DIR}
                              ${CMAKE_SOURCE_DIR}/private)
-if(WITH_BLOCKS_RUNTIME)
-  target_include_directories(dispatch
-                             SYSTEM BEFORE PRIVATE
-                               "${WITH_BLOCKS_RUNTIME}")
-endif()
+target_include_directories(dispatch
+                           SYSTEM BEFORE PRIVATE
+                             "${BlocksRuntime_INCLUDE_DIR}")
 if(WIN32)
   target_compile_definitions(dispatch
                              PRIVATE
@@ -190,10 +189,10 @@
 if(BSD_OVERLAY_FOUND)
   target_link_libraries(dispatch PRIVATE ${BSD_OVERLAY_LDFLAGS})
 endif()
-target_link_libraries(dispatch PRIVATE Threads::Threads)
-if(WITH_BLOCKS_RUNTIME)
-  target_link_libraries(dispatch PRIVATE BlocksRuntime)
-endif()
+target_link_libraries(dispatch
+                      PRIVATE
+                        Threads::Threads
+                        BlocksRuntime::BlocksRuntime)
 if(CMAKE_SYSTEM_NAME STREQUAL Windows)
   target_link_libraries(dispatch
                         PRIVATE
@@ -221,6 +220,8 @@
                    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:dispatch> .libs
                    COMMENT "Copying libdispatch to .libs")
 
+get_swift_host_arch(SWIFT_HOST_ARCH)
+
 install(TARGETS
           dispatch
         DESTINATION
@@ -230,6 +231,6 @@
             ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule
             ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftdoc
           DESTINATION
-            "${INSTALL_TARGET_DIR}/${CMAKE_SYSTEM_PROCESSOR}")
+            "${INSTALL_TARGET_DIR}/${SWIFT_HOST_ARCH}")
 endif()
 
diff --git a/src/internal.h b/src/internal.h
index effddae..1eb069c 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -242,11 +242,11 @@
 #endif
 
 #include <sys/stat.h>
-#include <sys/queue.h>
 
 #if defined(_WIN32)
 #include <time.h>
 #else
+#include <sys/queue.h>
 #include <sys/mount.h>
 #ifdef __ANDROID__
 #include <linux/sysctl.h>
diff --git a/src/shims.h b/src/shims.h
index 278b6ce..32d2c85 100644
--- a/src/shims.h
+++ b/src/shims.h
@@ -32,6 +32,7 @@
 #endif
 #if defined(_WIN32)
 #include "shims/generic_win_stubs.h"
+#include "shims/generic_sys_queue.h"
 #elif defined(__unix__)
 #include "shims/generic_unix_stubs.h"
 #endif
diff --git a/src/shims/generic_sys_queue.h b/src/shims/generic_sys_queue.h
new file mode 100644
index 0000000..250abbf
--- /dev/null
+++ b/src/shims/generic_sys_queue.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * 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.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * NOTE: This header files defines a trimmed down version of the BSD sys/queue.h
+ * macros for use on platforms which do not come with a sys/queue.h file.
+ */
+
+#ifndef __DISPATCH_SHIMS_SYS_QUEUE__
+#define __DISPATCH_SHIMS_SYS_QUEUE__
+
+#ifndef TRASHIT
+#define TRASHIT(elem) (elem) = NULL;
+#endif
+
+#define TAILQ_HEAD(list_name, elem_type) \
+	struct list_name { \
+		struct elem_type *tq_first; \
+		struct elem_type *tq_last; \
+	}
+
+#define TAILQ_ENTRY(elem_type) \
+	struct { \
+		struct elem_type *te_next; \
+		struct elem_type *te_prev; \
+	}
+
+#define TAILQ_INIT(list) do { \
+		(list)->tq_first = NULL; \
+		(list)->tq_last = NULL; \
+	} while (0)
+
+#define TAILQ_EMPTY(list) ((list)->tq_first == NULL)
+
+#define TAILQ_FIRST(list) ((list)->tq_first)
+
+#define TAILQ_LAST(list) ((list)->tq_last)
+
+#define TAILQ_NEXT(elem, field) ((elem)->field.te_next)
+
+#define TAILQ_PREV(elem, list, field) ((elem)->field.te_prev)
+
+#define TAILQ_FOREACH(var, list, field) \
+	for ((var) = TAILQ_FIRST(list); \
+	(var) != NULL; \
+	(var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_SAFE(var, list, field, temp) \
+	for ((var) = TAILQ_FIRST(list); \
+	((var) != NULL) && (temp = TAILQ_NEXT(var, field), 1); \
+	(var) = (temp))
+
+#define TAILQ_REMOVE(list, elem, field) do { \
+		if (TAILQ_NEXT(elem, field) != NULL) { \
+			TAILQ_NEXT(elem, field)->field.te_prev = (elem)->field.te_prev; \
+		} else { \
+			(list)->tq_last = (elem)->field.te_prev; \
+		} \
+		if (TAILQ_PREV(elem, list, field) != NULL) { \
+			TAILQ_PREV(elem, list, field)->field.te_next = (elem)->field.te_next; \
+		} else { \
+			(list)->tq_first = (elem)->field.te_next; \
+		} \
+		TRASHIT((elem)->field.te_next); \
+		TRASHIT((elem)->field.te_prev); \
+	} while(0)
+
+#define TAILQ_INSERT_TAIL(list, elem, field) do { \
+		if (TAILQ_EMPTY(list)) { \
+			(list)->tq_first = (list)->tq_last = (elem); \
+			(elem)->field.te_prev = (elem)->field.te_next = NULL; \
+		} else { \
+			(elem)->field.te_next = NULL; \
+			(elem)->field.te_prev = (list)->tq_last; \
+			TAILQ_LAST(list)->field.te_next = (elem); \
+			(list)->tq_last = (elem); \
+		} \
+	} while(0)
+
+#endif // __DISPATCH_SHIMS_SYS_QUEUE__
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 4ad1e0e..508d977 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -72,24 +72,27 @@
     target_compile_options(${name} PRIVATE -DLENIENT_DEADLINES=1)
     target_link_libraries(${name} PRIVATE swiftCore swiftSwiftOnoneSupport)
   endif()
-  if(WITH_BLOCKS_RUNTIME)
-    target_include_directories(${name}
-                               SYSTEM BEFORE PRIVATE
-                                 "${WITH_BLOCKS_RUNTIME}")
-  endif()
+  target_include_directories(${name}
+                             SYSTEM BEFORE PRIVATE
+                               "${BlocksRuntime_INCLUDE_DIR}")
   if(BSD_OVERLAY_FOUND AND NOT AUT_NO_BSD_OVERLAY)
     target_compile_options(${name}
                            PRIVATE
                              ${BSD_OVERLAY_CFLAGS})
   endif()
-  target_compile_options(${name} PRIVATE -fblocks)
+  if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
+    target_compile_options(${name} PRIVATE -Xclang -fblocks)
+  else()
+    target_compile_options(${name} PRIVATE -fblocks)
+  endif()
   # TODO(compnerd) make this portable
   target_compile_options(${name} PRIVATE -Wall -Wno-deprecated-declarations)
   dispatch_set_linker(${name})
-  target_link_libraries(${name} PRIVATE dispatch Threads::Threads)
-  if(WITH_BLOCKS_RUNTIME)
-    target_link_libraries(${name} PRIVATE BlocksRuntime)
-  endif()
+  target_link_libraries(${name}
+                        PRIVATE
+                          dispatch
+                          Threads::Threads
+                          BlocksRuntime::BlocksRuntime)
   if(BSD_OVERLAY_FOUND AND NOT AUT_NO_BSD_OVERLAY)
     target_link_libraries(${name}
                           PRIVATE