Mac build fixes.

This gets us pretty close. There are a few problems with libraries we depend
on (system/core/liblog and external/icu4c) that I have workarounds for, and
a problem with gtest that I haven't yet worked around that prevents us from
linking any of the tests. But this at least gives us a Mac dex2oat binary.

Change-Id: Iac39a6c2963c3d37ab2165d7d1a70e303ba22c45
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 9e05a1c..671ed59 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -68,7 +68,13 @@
 ART_TARGET_NON_DEBUG_CFLAGS := $(art_non_debug_cflags)
 
 # TODO: move -fkeep-inline-functions to art_debug_cflags when target gcc > 4.4
-ART_HOST_DEBUG_CFLAGS := $(art_debug_cflags) -fkeep-inline-functions
+ART_HOST_DEBUG_CFLAGS := $(art_debug_cflags)
+
+ifneq ($(HOST_OS),linux)
+  # Some Mac OS pthread header files are broken with -fkeep-inline-functions.
+  ART_HOST_DEBUG_CFLAGS := $(filter-out -fkeep-inline-functions,)
+endif
+
 ART_TARGET_DEBUG_CFLAGS := $(art_debug_cflags)
 
 DEX2OAT_SRC_FILES := \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 6b4377b..bdd5514 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -74,7 +74,10 @@
   else # host
     LOCAL_STATIC_LIBRARIES += libcutils
     LOCAL_SHARED_LIBRARIES += libz-host
-    LOCAL_LDLIBS := -ldl -lpthread -lrt
+    LOCAL_LDLIBS := -ldl -lpthread
+    ifeq ($(HOST_OS),linux)
+      LOCAL_LDLIBS += -lrt
+    endif
   endif
   LOCAL_STATIC_LIBRARIES += libdex
   ifeq ($$(art_target_or_host),target)
diff --git a/build/Android.libarttest.mk b/build/Android.libarttest.mk
index 86927c3..16bbcad 100644
--- a/build/Android.libarttest.mk
+++ b/build/Android.libarttest.mk
@@ -42,7 +42,10 @@
     include $(BUILD_SHARED_LIBRARY)
   else # host
     LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
-    LOCAL_LDLIBS := -ldl -lrt -lpthread
+    LOCAL_LDLIBS := -ldl -lpthread
+    ifeq ($(HOST_OS),linux)
+      LOCAL_LDLIBS += -lrt
+    endif
     include $(BUILD_HOST_SHARED_LIBRARY)
   endif
 endef
diff --git a/src/mem_map.cc b/src/mem_map.cc
index 09391df..673098d 100644
--- a/src/mem_map.cc
+++ b/src/mem_map.cc
@@ -40,7 +40,10 @@
 }
 
 void CheckMapRequest(byte* addr, size_t length) {
-#ifndef NDEBUG
+#if !defined(NDEBUG)
+#if defined(__APPLE__)
+  UNIMPLEMENTED(WARNING);
+#else
   if (addr == NULL) {
     return;
   }
@@ -101,6 +104,7 @@
     CHECK(i != std::string::npos) << "Failed to find newline from pos " << i << "\n" << maps;
   }
 #endif
+#endif
 }
 
 MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t length, int prot) {
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 1e0d6e7..9935d9d 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -124,7 +124,7 @@
       const char* descriptor = dex_file->GetClassDescriptor(class_def);
       UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index));
       CHECK(oat_class.get() != NULL);
-      os << StringPrintf("%d: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
+      os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
          << oat_class->GetStatus() << ")\n";
       DumpOatClass(os, oat_file, *oat_class.get(), *dex_file, class_def);
     }
@@ -180,7 +180,7 @@
                        method_index, name, signature.c_str(), method_idx);
     os << StringPrintf("\t\tcode: %p (offset=%08x)\n",
                        oat_method.GetCode(), oat_method.GetCodeOffset());
-    os << StringPrintf("\t\tframe_size_in_bytes: %d\n",
+    os << StringPrintf("\t\tframe_size_in_bytes: %zd\n",
                        oat_method.GetFrameSizeInBytes());
     os << StringPrintf("\t\tcore_spill_mask: %08x\n",
                        oat_method.GetCoreSpillMask());
@@ -363,17 +363,17 @@
 
         size_t register_map_bytes = method->GetGcMapLength();
         state->stats_.register_map_bytes += register_map_bytes;
-        StringAppendF(&summary, "GC=%d ", register_map_bytes);
+        StringAppendF(&summary, "GC=%zd ", register_map_bytes);
 
         size_t pc_mapping_table_bytes = method->GetMappingTableLength();
         state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
-        StringAppendF(&summary, "Mapping=%d ", pc_mapping_table_bytes);
+        StringAppendF(&summary, "Mapping=%zd ", pc_mapping_table_bytes);
 
         const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
         size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
         state->stats_.dex_instruction_bytes += dex_instruction_bytes;
 
-        StringAppendF(&summary, "\tSIZE Code=%d GC=%d Mapping=%d",
+        StringAppendF(&summary, "\tSIZE Code=%zd GC=%zd Mapping=%zd",
                       dex_instruction_bytes, register_map_bytes, pc_mapping_table_bytes);
       }
     }
@@ -429,15 +429,15 @@
     }
 
     void Dump(std::ostream& os) {
-      os << StringPrintf("\tfile_bytes = %d\n", file_bytes);
+      os << StringPrintf("\tfile_bytes = %zd\n", file_bytes);
       os << "\n";
 
       os << "\tfile_bytes = header_bytes + object_bytes + alignment_bytes\n";
-      os << StringPrintf("\theader_bytes    = %10d (%2.0f%% of file_bytes)\n",
+      os << StringPrintf("\theader_bytes    = %10zd (%2.0f%% of file_bytes)\n",
                          header_bytes, PercentOfFileBytes(header_bytes));
-      os << StringPrintf("\tobject_bytes    = %10d (%2.0f%% of file_bytes)\n",
+      os << StringPrintf("\tobject_bytes    = %10zd (%2.0f%% of file_bytes)\n",
                          object_bytes, PercentOfFileBytes(object_bytes));
-      os << StringPrintf("\talignment_bytes = %10d (%2.0f%% of file_bytes)\n",
+      os << StringPrintf("\talignment_bytes = %10zd (%2.0f%% of file_bytes)\n",
                          alignment_bytes, PercentOfFileBytes(alignment_bytes));
       os << "\n";
       os << std::flush;
@@ -452,7 +452,7 @@
         size_t count = descriptor_to_count[descriptor];
         double average = static_cast<double>(bytes) / static_cast<double>(count);
         double percent = PercentOfObjectBytes(bytes);
-        os << StringPrintf("\t%32s %8d bytes %6d instances "
+        os << StringPrintf("\t%32s %8zd bytes %6zd instances "
                            "(%3.0f bytes/instance) %2.0f%% of object_bytes\n",
                            descriptor.c_str(), bytes, count,
                            average, percent);
@@ -463,25 +463,25 @@
       os << std::flush;
       CHECK_EQ(object_bytes, object_bytes_total);
 
-      os << StringPrintf("\tmanaged_code_bytes           = %8d (%2.0f%% of object_bytes)\n",
+      os << StringPrintf("\tmanaged_code_bytes           = %8zd (%2.0f%% of object_bytes)\n",
                          managed_code_bytes, PercentOfObjectBytes(managed_code_bytes));
-      os << StringPrintf("\tmanaged_to_native_code_bytes = %8d (%2.0f%% of object_bytes)\n",
+      os << StringPrintf("\tmanaged_to_native_code_bytes = %8zd (%2.0f%% of object_bytes)\n",
                          managed_to_native_code_bytes,
                          PercentOfObjectBytes(managed_to_native_code_bytes));
-      os << StringPrintf("\tnative_to_managed_code_bytes = %8d (%2.0f%% of object_bytes)\n",
+      os << StringPrintf("\tnative_to_managed_code_bytes = %8zd (%2.0f%% of object_bytes)\n",
                          native_to_managed_code_bytes,
                          PercentOfObjectBytes(native_to_managed_code_bytes));
       os << "\n";
       os << std::flush;
 
-      os << StringPrintf("\tregister_map_bytes     = %7d (%2.0f%% of object_bytes)\n",
+      os << StringPrintf("\tregister_map_bytes     = %7zd (%2.0f%% of object_bytes)\n",
                          register_map_bytes, PercentOfObjectBytes(register_map_bytes));
-      os << StringPrintf("\tpc_mapping_table_bytes = %7d (%2.0f%% of object_bytes)\n",
+      os << StringPrintf("\tpc_mapping_table_bytes = %7zd (%2.0f%% of object_bytes)\n",
                          pc_mapping_table_bytes, PercentOfObjectBytes(pc_mapping_table_bytes));
       os << "\n";
       os << std::flush;
 
-      os << StringPrintf("\tdex_instruction_bytes = %d\n", dex_instruction_bytes);
+      os << StringPrintf("\tdex_instruction_bytes = %zd\n", dex_instruction_bytes);
       os << StringPrintf("\tmanaged_code_bytes expansion = %.2f\n",
                          static_cast<double>(managed_code_bytes)
                          / static_cast<double>(dex_instruction_bytes));
diff --git a/src/runtime_linux.cc b/src/runtime_linux.cc
index 89fb627..b614a63 100644
--- a/src/runtime_linux.cc
+++ b/src/runtime_linux.cc
@@ -65,7 +65,7 @@
       index = text.find(')');
       text.erase(index, 1);
     }
-    std::string log_line(StringPrintf("\t#%02d ", i) + function_name + text);
+    std::string log_line(StringPrintf("\t#%02zd ", i) + function_name + text);
     LogMessage(filename.c_str(), -1, ERROR, -1).stream() << log_line;
   }
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index a6f6b0d..160ca49 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1215,11 +1215,11 @@
   return lr;
 }
 
-uintptr_t artTraceMethodUnwindFromCode(Thread* self) {
+uint32_t artTraceMethodUnwindFromCode(Thread* self) {
   Trace* tracer = Runtime::Current()->GetTracer();
   TraceStackFrame trace_frame = self->PopTraceStackFrame();
   Method* method = trace_frame.method_;
-  uintptr_t lr = trace_frame.return_pc_;
+  uint32_t lr = trace_frame.return_pc_;
 
   tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
 
diff --git a/src/thread_x86.cc b/src/thread_x86.cc
index 378889b..cdba138 100644
--- a/src/thread_x86.cc
+++ b/src/thread_x86.cc
@@ -2,16 +2,25 @@
 
 #include "thread.h"
 
-#include <asm/ldt.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 
 #include "asm_support.h"
 #include "macros.h"
 
+#if defined(__APPLE__)
+#include <architecture/i386/table.h>
+#include <i386/user_ldt.h>
+#else
+#include <asm/ldt.h>
+#endif
+
 namespace art {
 
 void Thread::InitCpu() {
+#if defined(__APPLE__)
+  UNIMPLEMENTED(WARNING);
+#else
   // Read LDT
   CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
   std::vector<uint64_t> ldt(LDT_ENTRIES);
@@ -61,6 +70,7 @@
       : "r"(THREAD_SELF_OFFSET)  // input
       :);  // clobber
   CHECK_EQ(self_check, this);
+#endif
 }
 
 }  // namespace art
diff --git a/src/trace.cc b/src/trace.cc
index ff828a3..c149634 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -309,7 +309,7 @@
     os << StringPrintf("clock=wall\n");
   }
   os << StringPrintf("elapsed-time-usec=%llu\n", elapsed);
-  os << StringPrintf("num-method-calls=%d\n", (final_offset - kTraceHeaderLength) / record_size_);
+  os << StringPrintf("num-method-calls=%zd\n", (final_offset - kTraceHeaderLength) / record_size_);
   os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead);
   os << StringPrintf("vm=art\n");
   os << StringPrintf("%cthreads\n", kTraceTokenChar);
diff --git a/src/utils.cc b/src/utils.cc
index bf15bd7..cc0a702 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -16,6 +16,10 @@
 #include "object_utils.h"
 #include "os.h"
 
+#if !defined(HAVE_POSIX_CLOCKS)
+#include <sys/time.h>
+#endif
+
 #if defined(HAVE_PRCTL)
 #include <sys/prctl.h>
 #endif
@@ -66,27 +70,50 @@
 }
 
 uint64_t MilliTime() {
+#if defined(HAVE_POSIX_CLOCKS)
   struct timespec now;
   clock_gettime(CLOCK_MONOTONIC, &now);
   return static_cast<uint64_t>(now.tv_sec) * 1000LL + now.tv_nsec / 1000000LL;
+#else
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<uint64_t>(now.tv_sec) * 1000LL + now.tv_usec / 1000LL;
+#endif
 }
 
 uint64_t MicroTime() {
+#if defined(HAVE_POSIX_CLOCKS)
   struct timespec now;
   clock_gettime(CLOCK_MONOTONIC, &now);
   return static_cast<uint64_t>(now.tv_sec) * 1000000LL + now.tv_nsec / 1000LL;
+#else
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<uint64_t>(now.tv_sec) * 1000000LL + now.tv_usec * 1000LL;
+#endif
 }
 
 uint64_t NanoTime() {
+#if defined(HAVE_POSIX_CLOCKS)
   struct timespec now;
   clock_gettime(CLOCK_MONOTONIC, &now);
   return static_cast<uint64_t>(now.tv_sec) * 1000000000LL + now.tv_nsec;
+#else
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<uint64_t>(now.tv_sec) * 1000000000LL + now.tv_usec * 1000LL;
+#endif
 }
 
 uint64_t ThreadCpuMicroTime() {
+#if defined(HAVE_POSIX_CLOCKS)
   struct timespec now;
   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
   return static_cast<uint64_t>(now.tv_sec) * 1000000LL + now.tv_nsec / 1000LL;
+#else
+  UNIMPLEMENTED(WARNING);
+  return -1;
+#endif
 }
 
 std::string PrettyDescriptor(const String* java_descriptor) {
@@ -563,7 +590,7 @@
 #elif defined(HAVE_PRCTL)
   prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
 #else
-#error no implementation for SetThreadName
+  UNIMPLEMENTED(WARNING) << threadName;
 #endif
 }
 
diff --git a/src/zip_archive.cc b/src/zip_archive.cc
index 6105c21..73728a2 100644
--- a/src/zip_archive.cc
+++ b/src/zip_archive.cc
@@ -280,13 +280,28 @@
   }
 }
 
+static void SetCloseOnExec(int fd) {
+  // This dance is more portable than Linux's O_CLOEXEC open(2) flag.
+  int flags = fcntl(fd, F_GETFD);
+  if (flags == -1) {
+    PLOG(WARNING) << "fcntl(" << fd << ", F_GETFD) failed";
+    return;
+  }
+  int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+  if (rc == -1) {
+    PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed";
+    return;
+  }
+}
+
 ZipArchive* ZipArchive::Open(const std::string& filename) {
   DCHECK(!filename.empty());
-  int fd = open(filename.c_str(), O_RDONLY | O_CLOEXEC, 0);
-  if (fd < 0) {
+  int fd = open(filename.c_str(), O_RDONLY, 0);
+  if (fd == -1) {
     PLOG(WARNING) << "Unable to open '" << filename << "'";
     return NULL;
   }
+  SetCloseOnExec(fd);
   return OpenFromFd(fd);
 }