Allow building on wider range of dependencies on Linux

This patch allows building libdispatch with a wider range of dependencies on Linux systems. This also removes references to ‘swift’ in paths if Swift is not enabled.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cd874b2..43bc70d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,19 +62,21 @@
                         PROPERTIES
                           IMPORTED_LOCATION
                            ${SWIFT_RUNTIME_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}swiftSwiftOnoneSupport${CMAKE_SHARED_LIBRARY_SUFFIX})
+
+  set(INSTALL_TARGET_DIR "${INSTALL_LIBDIR}/swift/${SWIFT_OS}" CACHE PATH "Path where the libraries will be installed")
+  set(INSTALL_DISPATCH_HEADERS_DIR "${INSTALL_LIBDIR}/swift/dispatch" CACHE PATH "Path where the headers will be installed for libdispatch")
+  set(INSTALL_BLOCK_HEADERS_DIR "${INSTALL_LIBDIR}/swift/Block" CACHE PATH "Path where the headers will be installed for the blocks runtime")
+  set(INSTALL_OS_HEADERS_DIR "${INSTALL_LIBDIR}/swift/os" CACHE PATH "Path where the os/ headers will be installed")
 endif()
 
-if(CMAKE_SYSTEM_NAME STREQUAL Android)
-  set(ENABLE_DTRACE_DEFAULT OFF)
-else()
-  find_program(DTRACEPROG dtrace)
-  if(DTRACEPROG)
-    set(ENABLE_DTRACE_DEFAULT ON)
-  else()
-    set(ENABLE_DTRACE_DEFAULT OFF)
-  endif()
+if(NOT ENABLE_SWIFT)
+  set(INSTALL_TARGET_DIR "${INSTALL_LIBDIR}" CACHE PATH "Path where the libraries will be installed")
+  set(INSTALL_DISPATCH_HEADERS_DIR "include/dispatch" CACHE PATH "Path where the headers will be installed")
+  set(INSTALL_BLOCK_HEADERS_DIR "include" CACHE PATH "Path where the headers will be installed for the blocks runtime")
+  set(INSTALL_OS_HEADERS_DIR "include/os" CACHE PATH "Path where the headers will be installed")
 endif()
-option(ENABLE_DTRACE "enable dtrace support" ${ENABLE_DTRACE_DEFAULT})
+
+option(ENABLE_DTRACE "enable dtrace support" "")
 
 option(BUILD_SHARED_LIBS "build shared libraries" ON)
 
@@ -114,13 +116,15 @@
   endif()
 endif()
 
+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 Windows)
   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)
@@ -130,6 +134,17 @@
                             INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
   endif()
   set(WITH_BLOCKS_RUNTIME "${CMAKE_SOURCE_DIR}/src/BlocksRuntime" CACHE PATH "Path to blocks runtime" FORCE)
+  
+  install(FILES
+            ${CMAKE_SOURCE_DIR}/src/BlocksRuntime/Block.h
+          DESTINATION
+            "${INSTALL_BLOCK_HEADERS_DIR}")
+  if(INSTALL_PRIVATE_HEADERS)
+    install(FILES
+              ${CMAKE_SOURCE_DIR}/src/BlocksRuntime/Block_private.h
+            DESTINATION
+              "${INSTALL_BLOCK_HEADERS_DIR}")
+  endif()
 else()
   # TODO(compnerd) support system installed BlocksRuntime
   # find_package(BlocksRuntime REQUIRED)
@@ -159,6 +174,7 @@
 check_function_exists(pthread_workqueue_setdispatch_np HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP)
 check_function_exists(strlcpy HAVE_STRLCPY)
 check_function_exists(sysconf HAVE_SYSCONF)
+check_function_exists(arc4random HAVE_ARC4RANDOM)
 
 if(NOT HAVE_STRLCPY AND NOT HAVE_GETPROGNAME)
   include(FindPkgConfig)
@@ -233,14 +249,29 @@
 check_symbol_exists(VQ_QUOTA "sys/mount.h" HAVE_DECL_VQ_QUOTA)
 check_symbol_exists(VQ_UPDATE "sys/mount.h" HAVE_DECL_VQ_UPDATE)
 check_symbol_exists(VQ_VERYLOWDISK "sys/mount.h" HAVE_DECL_VQ_VERYLOWDISK)
-
+check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
 check_symbol_exists(program_invocation_name "errno.h" HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
+if (HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
+  add_definitions(-D_GNU_SOURCE=1)
+endif()
+check_symbol_exists(__printflike "bsd/sys/cdefs.h" HAVE_PRINTFLIKE)
 
 if(CMAKE_SYSTEM_NAME STREQUAL Windows)
   add_definitions(-DTARGET_OS_WIN32)
 endif()
 
-if(ENABLE_DTRACE)
+if(CMAKE_SYSTEM_NAME STREQUAL Android)
+  set(ENABLE_DTRACE_DEFAULT OFF)
+endif()
+
+if(ENABLE_DTRACE STREQUAL "")
+  find_program(dtrace_EXECUTABLE dtrace)
+  if(dtrace_EXECUTABLE)
+    add_definitions(-DDISPATCH_USE_DTRACE=1)
+  else()
+    add_definitions(-DDISPATCH_USE_DTRACE=0)
+  endif()
+elseif(ENABLE_DTRACE)
   find_program(dtrace_EXECUTABLE dtrace)
   if(NOT dtrace_EXECUTABLE)
     message(FATAL_ERROR "dtrace not found but explicitly requested")
diff --git a/dispatch/CMakeLists.txt b/dispatch/CMakeLists.txt
index 971c068..8b8be8c 100644
--- a/dispatch/CMakeLists.txt
+++ b/dispatch/CMakeLists.txt
@@ -14,12 +14,12 @@
           source.h
           time.h
         DESTINATION
-          "${INSTALL_LIBDIR}/swift/dispatch")
+          "${INSTALL_DISPATCH_HEADERS_DIR}")
 if(ENABLE_SWIFT)
   get_filename_component(MODULE_MAP module.modulemap REALPATH)
   install(FILES
             ${MODULE_MAP}
           DESTINATION
-            "${INSTALL_LIBDIR}/swift/dispatch")
+            "${INSTALL_DISPATCH_HEADERS_DIR}")
 endif()
 
diff --git a/os/CMakeLists.txt b/os/CMakeLists.txt
index 1c29616..e1e93a4 100644
--- a/os/CMakeLists.txt
+++ b/os/CMakeLists.txt
@@ -6,5 +6,5 @@
           object.h
           linux_base.h
         DESTINATION
-          "${INSTALL_LIBDIR}/swift/os")
+          "${INSTALL_OS_HEADERS_DIR}")
 
diff --git a/private/CMakeLists.txt b/private/CMakeLists.txt
index 18788d7..a2ee9bd 100644
--- a/private/CMakeLists.txt
+++ b/private/CMakeLists.txt
@@ -3,3 +3,17 @@
 # io_private.h layout_private.h mach_private.h private.h queue_private.h
 # source_private.h are included in the source tarball
 
+if (INSTALL_PRIVATE_HEADERS)
+  install(FILES
+            benchmark.h
+            data_private.h
+            introspection_private.h
+            io_private.h
+            layout_private.h
+            mach_private.h
+            private.h
+            queue_private.h
+            source_private.h
+          DESTINATION
+            "${INSTALL_DISPATCH_HEADERS_DIR}")
+endif()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2336908..0dd6a3c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,6 +19,7 @@
               time.c
               transform.c
               voucher.c
+              shims.c
               protocol.defs
               provider.d
               allocator_internal.h
@@ -208,12 +209,12 @@
 install(TARGETS
           dispatch
         DESTINATION
-          "${INSTALL_LIBDIR}/swift/${SWIFT_OS}")
+          "${INSTALL_TARGET_DIR}")
 if(ENABLE_SWIFT)
   install(FILES
             ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule
             ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftdoc
           DESTINATION
-            "${INSTALL_LIBDIR}/swift/${SWIFT_OS}/${CMAKE_SYSTEM_PROCESSOR}")
+            "${INSTALL_TARGET_DIR}/${CMAKE_SYSTEM_PROCESSOR}")
 endif()
 
diff --git a/src/internal.h b/src/internal.h
index 84e33e3..ef116a8 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -373,15 +373,11 @@
 #define _TAILQ_MARK_NOT_ENQUEUED(elm, field) \
 		do { (elm)->field.tqe_prev = NULL; } while (0)
 
-#if DISPATCH_DEBUG
 // sys/queue.h debugging
-#if defined(__linux__)
-#define QUEUE_MACRO_DEBUG 1
-#else
-#undef TRASHIT
+#ifndef TRASHIT
 #define TRASHIT(x) do {(x) = (void *)-1;} while (0)
 #endif
-#endif // DISPATCH_DEBUG
+
 #define _TAILQ_TRASH_ENTRY(elm, field) do { \
 			TRASHIT((elm)->field.tqe_next); \
 			TRASHIT((elm)->field.tqe_prev); \
diff --git a/src/shims.c b/src/shims.c
new file mode 100644
index 0000000..6ac1b57
--- /dev/null
+++ b/src/shims.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013-2016 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@
+ */
+
+#include "internal.h"
+#include "shims.h"
+
+#if !HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t size) {
+	size_t res = strlen(dst) + strlen(src) + 1;
+	if (size > 0) {
+		size_t n = size - 1;
+		strncpy(dst, src, n);
+		dst[n] = 0;
+	}
+	return res;
+}
+#endif
diff --git a/src/shims.h b/src/shims.h
index 28e1c53..fad36bc 100644
--- a/src/shims.h
+++ b/src/shims.h
@@ -66,19 +66,18 @@
 #define FD_COPY(f, t) (void)(*(t) = *(f))
 #endif
 
+#if HAVE_STRLCPY
+#include <string.h>
+#else // that is, if !HAVE_STRLCPY
+
+size_t strlcpy(char *dst, const char *src, size_t size);
+
+#endif // HAVE_STRLCPY
+
+
 #if TARGET_OS_WIN32
 #define bzero(ptr,len) memset((ptr), 0, (len))
 #define snprintf _snprintf
-
-inline size_t strlcpy(char *dst, const char *src, size_t size) {
-	int res = strlen(dst) + strlen(src) + 1;
-	if (size > 0) {
-		size_t n = size - 1;
-		strncpy(dst, src, n);
-		dst[n] = 0;
-	}
-	return res;
-}
 #endif // TARGET_OS_WIN32
 
 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20140716
diff --git a/src/shims/getprogname.h b/src/shims/getprogname.h
index 7eb1978..49c7187 100644
--- a/src/shims/getprogname.h
+++ b/src/shims/getprogname.h
@@ -19,6 +19,8 @@
  * @APPLE_APACHE_LICENSE_HEADER_END@
  */
 
+#include <errno.h>
+
 #ifndef __DISPATCH_SHIMS_GETPROGNAME__
 #define __DISPATCH_SHIMS_GETPROGNAME__
 
diff --git a/src/shims/linux_stubs.h b/src/shims/linux_stubs.h
index ec68417..14251b9 100644
--- a/src/shims/linux_stubs.h
+++ b/src/shims/linux_stubs.h
@@ -22,12 +22,6 @@
 		(var) && ((temp) = TAILQ_NEXT((var), field), 1); (var) = (temp))
 #endif
 
-#if DISPATCH_DEBUG
-#ifndef TRASHIT
-#define TRASHIT(x) do { (x) = (void *)-1; } while (0)
-#endif
-#endif
-
 /*
  * Stub out defines for some mach types and related macros
  */
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index eee686f..adfc188 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -2,6 +2,10 @@
 execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_SOURCE_DIR}/private" "${CMAKE_CURRENT_BINARY_DIR}/dispatch")
 execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/leaks-wrapper.sh" "${CMAKE_CURRENT_BINARY_DIR}/leaks-wrapper")
 
+if(CMAKE_SYSTEM_NAME STREQUAL Linux)
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt")
+endif()
+
 add_library(bsdtests
             STATIC
               bsdtests.c
diff --git a/tests/bsdtests.h b/tests/bsdtests.h
index cfebb4f..8bf733f 100644
--- a/tests/bsdtests.h
+++ b/tests/bsdtests.h
@@ -21,6 +21,18 @@
 #ifndef __BSD_TEST_H__
 #define __BSD_TEST_H__
 
+
+#if !HAVE_PRINTFLIKE
+#ifndef __printflike
+#if __has_attribute(format)
+#define __printflike(a,b) __attribute__((format(printf, a, b)))
+#else
+#define __printflike(a,b)
+#endif // __has_attribute(format)
+#endif // !defined(__printflike)
+#endif // !HAVE_PRINTFLIKE
+
+
 #include <errno.h>
 #ifdef __APPLE__
 #include <mach/error.h>
@@ -30,6 +42,7 @@
 #endif
 
 #include <string.h>
+#include <stdint.h>
 
 static inline const char*
 __BASENAME__(const char *_str_)
diff --git a/tests/dispatch_group.c b/tests/dispatch_group.c
index 708cf0d..a9a8e8b 100644
--- a/tests/dispatch_group.c
+++ b/tests/dispatch_group.c
@@ -126,7 +126,11 @@
 
 	// n=4 works great for a 4CPU Mac Pro, this might work for a wider range of
 	// systems.
+#if HAVE_ARC4RANDOM
 	const int n = 1 + arc4random() % 8;
+#else
+    const int n = 1 + random() % 8;
+#endif
 	dispatch_group_t group = dispatch_group_create();
 	dispatch_queue_t qa[n];
 
diff --git a/tests/dispatch_queue_finalizer.c b/tests/dispatch_queue_finalizer.c
index 1b190a2..e70df43 100644
--- a/tests/dispatch_queue_finalizer.c
+++ b/tests/dispatch_queue_finalizer.c
@@ -50,11 +50,15 @@
 {
 	dispatch_test_start("Dispatch Queue Finalizer");
 
+#if HAS_ARC4RANDOM
 #if defined(__LP64__) || defined(_WIN64)
 	ctxt_magic = (void*)((uintptr_t)arc4random() << 32 | arc4random());
 #else
 	ctxt_magic = (void*)arc4random();
 #endif
+#else // that is, if !HAS_ARC4RANDOM
+    ctxt_magic = (void *)random();
+#endif
 
 	// we need a non-NULL value for the tests to work properly
 	if (ctxt_magic == NULL) {