port gn to aix

Change-Id: I3077efcd131c0f69377bb6dfa85f9a36852df3f1
Reviewed-on: https://gn-review.googlesource.com/2260
Reviewed-by: Brett Wilson <brettw@google.com>
Commit-Queue: Brett Wilson <brettw@google.com>
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 977eb1b..4faf77b 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -100,6 +100,13 @@
   int64_t last_accessed_nsec = stat_info.st_atimespec.tv_nsec;
   time_t creation_time_sec = stat_info.st_ctimespec.tv_sec;
   int64_t creation_time_nsec = stat_info.st_ctimespec.tv_nsec;
+#elif defined(OS_AIX)
+  time_t last_modified_sec = stat_info.st_mtime;
+  int64_t last_modified_nsec = 0;
+  time_t last_accessed_sec = stat_info.st_atime;
+  int64_t last_accessed_nsec = 0;
+  time_t creation_time_sec = stat_info.st_ctime;
+  int64_t creation_time_nsec = 0;
 #else
 #error
 #endif
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 9415735..23c7cb4 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -47,6 +47,12 @@
 #include <grp.h>
 #endif
 
+// We need to do this on AIX due to some inconsistencies in how AIX
+// handles XOPEN_SOURCE and ALL_SOURCE.
+#if defined(OS_AIX)
+extern "C" char* mkdtemp(char* path);
+#endif
+
 namespace base {
 
 namespace {
diff --git a/build/build_aix.ninja.template b/build/build_aix.ninja.template
new file mode 100644
index 0000000..f393e18
--- /dev/null
+++ b/build/build_aix.ninja.template
@@ -0,0 +1,16 @@
+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 $in $libs $solibs
+  description = LINK $out
diff --git a/build/gen.py b/build/gen.py
index 9007277..454d49d 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -24,7 +24,8 @@
 is_win = sys.platform.startswith('win')
 is_linux = sys.platform.startswith('linux')
 is_mac = sys.platform.startswith('darwin')
-is_posix = is_linux or is_mac
+is_aix = sys.platform.startswith('aix')
+is_posix = is_linux or is_mac or is_aix
 
 
 def main(argv):
@@ -159,7 +160,8 @@
   template_filename = os.path.join(SCRIPT_DIR, {
       'win32': 'build_win.ninja.template',
       'darwin': 'build_mac.ninja.template',
-      'linux2': 'build_linux.ninja.template'
+      'linux2': 'build_linux.ninja.template',
+      'aix6': 'build_aix.ninja.template'
   }[sys.platform])
 
   with open(template_filename) as f:
@@ -243,6 +245,11 @@
     cxx = os.environ.get('CXX', 'cl.exe')
     ld = os.environ.get('LD', 'link.exe')
     ar = os.environ.get('AR', 'lib.exe')
+  elif is_aix:
+    cc = os.environ.get('CC', 'gcc')
+    cxx = os.environ.get('CXX', 'g++')
+    ld = os.environ.get('LD', 'g++')
+    ar = os.environ.get('AR', 'ar -X64')
   else:
     cc = os.environ.get('CC', 'clang')
     cxx = os.environ.get('CXX', 'clang++')
@@ -268,9 +275,20 @@
       # unused functions and data items.
       cflags.extend(['-fdata-sections', '-ffunction-sections'])
       ldflags.extend(['-fdata-sections', '-ffunction-sections'])
-      ldflags.append('-Wl,-dead_strip' if is_mac else '-Wl,--gc-sections')
+      if is_mac:
+        ldflags.append('-Wl,-dead_strip')
+      elif not is_aix:
+        # Garbage collection is done by default on aix.
+        ldflags.append('-Wl,--gc-sections')
+
       # Omit all symbol information from the output file.
-      ldflags.append('-Wl,-S' if is_mac else '-Wl,-strip-all')
+      if is_mac:
+        ldflags.append('-Wl,-S')
+      elif is_aix:
+        ldflags.append('-Wl,-s')
+      else:
+        ldflags.append('-Wl,-strip-all')
+
       # Enable identical code-folding.
       if options.use_icf:
         ldflags.append('-Wl,--icf=all')
@@ -306,6 +324,9 @@
       min_mac_version_flag = '-mmacosx-version-min=10.9'
       cflags.append(min_mac_version_flag)
       ldflags.append(min_mac_version_flag)
+    elif is_aix:
+      cflags_cc.append('-maix64')
+      ldflags.extend(['-maix64', '-pthread'])
 
     if options.use_lto:
       cflags.extend(['-flto', '-fwhole-program-vtables'])
@@ -594,7 +615,7 @@
         'base/strings/string16.cc',
     ])
 
-  if is_linux:
+  if is_linux or is_aix:
     static_libraries['base']['sources'].extend([
         'base/strings/sys_string_conversions_posix.cc',
     ])
diff --git a/tools/gn/args.cc b/tools/gn/args.cc
index 3003d9f..aa42ff3 100644
--- a/tools/gn/args.cc
+++ b/tools/gn/args.cc
@@ -294,6 +294,8 @@
   os = "mac";
 #elif defined(OS_LINUX)
   os = "linux";
+#elif defined(OS_AIX)
+  os = "aix";
 #else
 #error Unknown OS type.
 #endif
diff --git a/tools/gn/function_write_file_unittest.cc b/tools/gn/function_write_file_unittest.cc
index 8b64a29..035faba 100644
--- a/tools/gn/function_write_file_unittest.cc
+++ b/tools/gn/function_write_file_unittest.cc
@@ -85,6 +85,9 @@
   FILETIME last_modified_filetime = {};
   ASSERT_TRUE(::SetFileTime(foo_file.GetPlatformFile(), nullptr,
                             &last_access_filetime, &last_modified_filetime));
+#elif defined(OS_AIX)
+  struct timeval times[2] = {};
+  ASSERT_EQ(utimes(foo_name.AsUTF8Unsafe().c_str(), times), 0);
 #else
   struct timeval times[2] = {};
   ASSERT_EQ(futimes(foo_file.GetPlatformFile(), times), 0);
diff --git a/util/semaphore.cc b/util/semaphore.cc
index a1fa779..2ae7b7b 100644
--- a/util/semaphore.cc
+++ b/util/semaphore.cc
@@ -36,7 +36,7 @@
   }
 }
 
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
 
 Semaphore::Semaphore(int count) {
   DCHECK_GE(count, 0);
diff --git a/util/semaphore.h b/util/semaphore.h
index 84d8b60..2de2759 100644
--- a/util/semaphore.h
+++ b/util/semaphore.h
@@ -15,7 +15,7 @@
 #include <windows.h>
 #elif defined(OS_MACOSX)
 #include <mach/mach.h>
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
 #include <semaphore.h>
 #else
 #error Port.
@@ -35,7 +35,7 @@
 
 #if defined(OS_MACOSX)
   typedef semaphore_t NativeHandle;
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
   typedef sem_t NativeHandle;
 #elif defined(OS_WIN)
   typedef HANDLE NativeHandle;
diff --git a/util/ticks.cc b/util/ticks.cc
index df35375..2a90c90 100644
--- a/util/ticks.cc
+++ b/util/ticks.cc
@@ -11,7 +11,7 @@
 #include <windows.h>
 #elif defined(OS_MACOSX)
 #include <mach/mach_time.h>
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
 #include <time.h>
 #else
 #error Port.
@@ -27,7 +27,7 @@
 #elif defined(OS_MACOSX)
 mach_timebase_info_data_t g_timebase;
 uint64_t g_start;
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
 uint64_t g_start;
 #else
 #error Port.
@@ -44,7 +44,7 @@
 #elif defined(OS_MACOSX)
   mach_timebase_info(&g_timebase);
   g_start = (mach_absolute_time() * g_timebase.numer) / g_timebase.denom;
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
   struct timespec ts;
   clock_gettime(CLOCK_MONOTONIC, &ts);
   g_start = static_cast<uint64_t>(ts.tv_sec) * kNano +
@@ -74,7 +74,7 @@
 #elif defined(OS_MACOSX)
   now =
       ((mach_absolute_time() * g_timebase.numer) / g_timebase.denom) - g_start;
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_AIX)
   struct timespec ts;
   clock_gettime(CLOCK_MONOTONIC, &ts);
   now = (static_cast<uint64_t>(ts.tv_sec) * kNano +