Add support for building on Haiku.

This commit adds support for building GN on Haiku.
All tests pass on 32 bit and 64 bit Haiku.

Change-Id: I010dc8aafe44c29b3e7e90cb3bf5d69e822825ea
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/5000
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/base/files/file.h b/base/files/file.h
index 3355030..838d0b8 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -22,8 +22,8 @@
 
 namespace base {
 
-#if defined(OS_BSD) || defined(OS_MACOSX) || \
-    defined(OS_ANDROID) && __ANDROID_API__ < 21
+#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) || \
+    defined(OS_HAIKU) || defined(OS_ANDROID) && __ANDROID_API__ < 21
 typedef struct stat stat_wrapper_t;
 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
 typedef struct stat64 stat_wrapper_t;
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 90b80d0..2a73f7e 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -24,8 +24,8 @@
 
 namespace {
 
-#if defined(OS_BSD) || defined(OS_MACOSX) || \
-    defined(OS_ANDROID) && __ANDROID_API__ < 21
+#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) || \
+    defined(OS_HAIKU) || defined(OS_ANDROID) && __ANDROID_API__ < 21
 int CallFstat(int fd, stat_wrapper_t* sb) {
   return fstat(fd, sb);
 }
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 3306004..87a38dd 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -57,8 +57,8 @@
 
 namespace {
 
-#if defined(OS_BSD) || defined(OS_MACOSX) || \
-    defined(OS_ANDROID) && __ANDROID_API__ < 21
+#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) || \
+    defined(OS_HAIKU) || defined(OS_ANDROID) && __ANDROID_API__ < 21
 int CallStat(const char* path, stat_wrapper_t* sb) {
   return stat(path, sb);
 }
diff --git a/build/build_haiku.ninja.template b/build/build_haiku.ninja.template
new file mode 100644
index 0000000..e59854b
--- /dev/null
+++ b/build/build_haiku.ninja.template
@@ -0,0 +1,19 @@
+rule cc
+  command = $cc -MMD -MF $out.d $defines $includes $cflags $cflags_c -c $in -o $out
+  description = CC $out
+  depfile = $out.d
+  deps = gcc
+
+rule cxx
+  command = $cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc -c $in -o $out
+  description = CXX $out
+  depfile = $out.d
+  deps = gcc
+
+rule alink_thin
+  command = rm -f $out && $ar rcsT $out $in
+  description = AR $out
+
+rule link
+  command = $ld $ldflags -o $out -Wl,--start-group $in $libs -Wl,--end-group $solibs
+  description = LINK $out
diff --git a/build/gen.py b/build/gen.py
index 64e3f55..126b7d4 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -43,10 +43,12 @@
       self._platform = 'freebsd'
     elif self._platform.startswith('openbsd'):
       self._platform = 'openbsd'
+    elif self._platform.startswith('haiku'):
+      self._platform = 'haiku'
 
   @staticmethod
   def known_platforms():
-    return ['linux', 'darwin', 'msvc', 'aix', 'fuchsia', 'freebsd', 'openbsd']
+    return ['linux', 'darwin', 'msvc', 'aix', 'fuchsia', 'freebsd', 'openbsd', 'haiku']
 
   def platform(self):
     return self._platform
@@ -69,8 +71,11 @@
   def is_aix(self):
     return self._platform == 'aix'
 
+  def is_haiku(self):
+    return self._platform == 'haiku'
+
   def is_posix(self):
-    return self._platform in ['linux', 'freebsd', 'darwin', 'aix', 'openbsd']
+    return self._platform in ['linux', 'freebsd', 'darwin', 'aix', 'openbsd', 'haiku']
 
 
 def main(argv):
@@ -179,6 +184,7 @@
       'freebsd': 'build_linux.ninja.template',
       'aix': 'build_aix.ninja.template',
       'openbsd': 'build_openbsd.ninja.template',
+      'haiku': 'build_haiku.ninja.template',
   }[platform.platform()])
 
   with open(template_filename) as f:
@@ -341,8 +347,11 @@
     elif platform.is_aix():
       cflags_cc.append('-maix64')
       ldflags.append('-maix64')
+    elif platform.is_haiku():
+      cflags_cc.append('-fPIC')
+      cflags_cc.extend(['-D_BSD_SOURCE'])
 
-    if platform.is_posix():
+    if platform.is_posix() and not platform.is_haiku():
       ldflags.append('-pthread')
 
     if options.use_lto:
diff --git a/tools/gn/args.cc b/tools/gn/args.cc
index e14adf6..4741ca4 100644
--- a/tools/gn/args.cc
+++ b/tools/gn/args.cc
@@ -314,6 +314,8 @@
   os = "aix";
 #elif defined(OS_OPENBSD)
   os = "openbsd";
+#elif defined(OS_HAIKU)
+  os = "haiku";
 #else
 #error Unknown OS type.
 #endif
@@ -334,7 +336,7 @@
   // Set the host CPU architecture based on the underlying OS, not
   // whatever the current bit-tedness of the GN binary is.
   std::string os_arch = OperatingSystemArchitecture();
-  if (os_arch == "x86")
+  if (os_arch == "x86" || os_arch == "BePC")
     arch = kX86;
   else if (os_arch == "x86_64")
     arch = kX64;
diff --git a/tools/gn/exec_process.cc b/tools/gn/exec_process.cc
index e266d90..de7c945 100644
--- a/tools/gn/exec_process.cc
+++ b/tools/gn/exec_process.cc
@@ -22,7 +22,7 @@
 #else
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/signal.h>
+#include <signal.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
diff --git a/tools/gn/function_write_file_unittest.cc b/tools/gn/function_write_file_unittest.cc
index 4e317e1..a7fcd9b 100644
--- a/tools/gn/function_write_file_unittest.cc
+++ b/tools/gn/function_write_file_unittest.cc
@@ -13,7 +13,7 @@
 #include "tools/gn/test_with_scope.h"
 #include "util/test/test.h"
 
-#if defined(OS_LINUX) || defined(OS_MACOSX)
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_HAIKU)
 #include <sys/time.h>
 #endif
 
@@ -85,7 +85,7 @@
   FILETIME last_modified_filetime = {};
   ASSERT_TRUE(::SetFileTime(foo_file.GetPlatformFile(), nullptr,
                             &last_access_filetime, &last_modified_filetime));
-#elif defined(OS_AIX)
+#elif defined(OS_AIX) || defined(OS_HAIKU)
   struct timeval times[2] = {};
   ASSERT_EQ(utimes(foo_name.value().c_str(), times), 0);
 #else
diff --git a/util/build_config.h b/util/build_config.h
index f98f044..f7cc991 100644
--- a/util/build_config.h
+++ b/util/build_config.h
@@ -51,7 +51,9 @@
 #elif defined(_AIX)
 #define OS_AIX 1
 #elif defined(__asmjs__)
-#define OS_ASMJS
+#define OS_ASMJS 1
+#elif defined(__HAIKU__)
+#define OS_HAIKU 1
 #else
 #error Please add support for your platform in build_config.h
 #endif
@@ -68,8 +70,8 @@
 // more specific macro.
 #if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) ||    \
     defined(OS_FREEBSD) || defined(OS_LINUX) || defined(OS_MACOSX) || \
-    defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) ||   \
-    defined(OS_SOLARIS)
+    defined(OS_NACL) || defined(OS_NETBSD) || defined(OS_OPENBSD) ||  \
+    defined(OS_QNX) || defined(OS_SOLARIS) || defined(OS_HAIKU)
 #define OS_POSIX 1
 #endif
 
diff --git a/util/exe_path.cc b/util/exe_path.cc
index 4d487fa..3b66a7b 100644
--- a/util/exe_path.cc
+++ b/util/exe_path.cc
@@ -19,6 +19,9 @@
 #include <limits.h>
 #include <sys/sysctl.h>
 #include <sys/types.h>
+#elif defined(OS_HAIKU)
+#include <OS.h>
+#include <image.h>
 #endif
 
 #if defined(OS_MACOSX)
@@ -64,6 +67,19 @@
   return base::FilePath(buf);
 }
 
+#elif defined(OS_HAIKU)
+
+base::FilePath GetExePath() {
+  image_info i_info;
+  int32 image_cookie = 0;
+  while (get_next_image_info(B_CURRENT_TEAM, &image_cookie, &i_info) == B_OK) {
+    if (i_info.type == B_APP_IMAGE) {
+      break;
+    }
+  }
+  return base::FilePath(std::string(i_info.name));
+}
+
 #else
 
 base::FilePath GetExePath() {