Imported Upstream version 3.12.3 upstream/3.12.3
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 8 Oct 2021 00:13:29 +0000 (09:13 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 8 Oct 2021 00:13:29 +0000 (09:13 +0900)
31 files changed:
Help/prop_dir/TESTS.rst
Modules/FindDoxygen.cmake
Modules/FindMPI.cmake
Source/CMakeVersion.cmake
Source/CTest/cmCTestMultiProcessHandler.cxx
Source/CTest/cmCTestMultiProcessHandler.h
Source/cmCTest.cxx
Source/cmGeneratorTarget.cxx
Source/cmGeneratorTarget.h
Source/cmVisualStudio10TargetGenerator.cxx
Tests/CSharpLinkToCxx/CMakeLists.txt
Tests/CSharpLinkToCxx/cpp_static.cpp [new file with mode: 0644]
Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt [deleted file]
Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt [deleted file]
Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt [deleted file]
Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt [new file with mode: 0644]
Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt [new file with mode: 0644]
Tests/RunCMake/ctest_start/RunCMakeTest.cmake
Tests/RunCMake/ctest_start/test.cmake.in
Tests/RunCMake/ctest_test/CTestTestLoadFail-result.txt [deleted file]
Tests/RunCMake/ctest_test/CTestTestLoadFail-stderr.txt [deleted file]
Tests/RunCMake/ctest_test/CTestTestLoadFail-stdout.txt [deleted file]
Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt [new file with mode: 0644]
Tests/RunCMake/ctest_test/RunCMakeTest.cmake
Tests/RunCMake/ctest_test/TestLoadFail-result.txt [deleted file]
Tests/RunCMake/ctest_test/TestLoadFail-stderr.txt [deleted file]
Tests/RunCMake/ctest_test/TestLoadFail-stdout.txt [deleted file]
Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt [new file with mode: 0644]
Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
Utilities/cmlibuv/src/unix/fs.c

index c6e1d88..91acd3e 100644 (file)
@@ -4,4 +4,4 @@ TESTS
 List of tests.
 
 This read-only property holds a :ref:`;-list <CMake Language Lists>` of tests
-defined so far by the :command:`add_test` command.
+defined so far, in the current directory, by the :command:`add_test` command.
index 945ee0e..2ed9449 100644 (file)
@@ -370,6 +370,9 @@ Deprecated Hint Variables
 
 #]=======================================================================]
 
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
 # For backwards compatibility support
 if(Doxygen_FIND_QUIETLY)
     set(DOXYGEN_FIND_QUIETLY TRUE)
@@ -1108,3 +1111,5 @@ doxygen_add_docs() for target ${targetName}")
     )
 
 endfunction()
+
+cmake_policy(POP)
index 75c4441..bfcd876 100644 (file)
@@ -1680,7 +1680,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
     set(MPI_${LANG}_INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}")
     unset(MPI_${LANG}_COMPILE_FLAGS)
     if(MPI_${LANG}_COMPILE_OPTIONS)
-      set(MPI_${LANG}_COMPILE_FLAGS "${MPI_${LANG}_COMPILE_OPTIONS}")
+      list(JOIN MPI_${LANG}_COMPILE_FLAGS " " MPI_${LANG}_COMPILE_OPTIONS)
     endif()
     if(MPI_${LANG}_COMPILE_DEFINITIONS)
       foreach(_MPI_DEF IN LISTS MPI_${LANG}_COMPILE_DEFINITIONS)
index e236d31..4978bd6 100644 (file)
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 12)
-set(CMake_VERSION_PATCH 2)
+set(CMake_VERSION_PATCH 3)
 #set(CMake_VERSION_RC 0)
index dcef8a0..322da23 100644 (file)
@@ -5,7 +5,6 @@
 #include "cmAffinity.h"
 #include "cmCTest.h"
 #include "cmCTestRunTest.h"
-#include "cmCTestScriptHandler.h"
 #include "cmCTestTestHandler.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
@@ -53,6 +52,7 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
 {
   this->ParallelLevel = 1;
   this->TestLoad = 0;
+  this->FakeLoadForTesting = 0;
   this->Completed = 0;
   this->RunningCount = 0;
   this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
@@ -97,6 +97,16 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
 void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load)
 {
   this->TestLoad = load;
+
+  std::string fake_load_value;
+  if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING",
+                            fake_load_value)) {
+    if (!cmSystemTools::StringToULong(fake_load_value.c_str(),
+                                      &this->FakeLoadForTesting)) {
+      cmSystemTools::Error("Failed to parse fake load value: ",
+                           fake_load_value.c_str());
+    }
+  }
 }
 
 void cmCTestMultiProcessHandler::RunTests()
@@ -259,12 +269,19 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
 
 void cmCTestMultiProcessHandler::StartNextTests()
 {
-  size_t numToStart = 0;
+  if (this->TestLoadRetryTimer.get() != nullptr) {
+    // This timer may be waiting to call StartNextTests again.
+    // Since we have been called it is no longer needed.
+    uv_timer_stop(this->TestLoadRetryTimer);
+  }
 
   if (this->Tests.empty()) {
+    this->TestLoadRetryTimer.reset();
     return;
   }
 
+  size_t numToStart = 0;
+
   if (this->RunningCount < this->ParallelLevel) {
     numToStart = this->ParallelLevel - this->RunningCount;
   }
@@ -280,7 +297,6 @@ void cmCTestMultiProcessHandler::StartNextTests()
   }
 
   bool allTestsFailedTestLoadCheck = false;
-  bool usedFakeLoadForTesting = false;
   size_t minProcessorsRequired = this->ParallelLevel;
   std::string testWithMinProcessors;
 
@@ -293,15 +309,11 @@ void cmCTestMultiProcessHandler::StartNextTests()
     allTestsFailedTestLoadCheck = true;
 
     // Check for a fake load average value used in testing.
-    std::string fake_load_value;
-    if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING",
-                              fake_load_value)) {
-      usedFakeLoadForTesting = true;
-      if (!cmSystemTools::StringToULong(fake_load_value.c_str(),
-                                        &systemLoad)) {
-        cmSystemTools::Error("Failed to parse fake load value: ",
-                             fake_load_value.c_str());
-      }
+    if (this->FakeLoadForTesting > 0) {
+      systemLoad = this->FakeLoadForTesting;
+      // Drop the fake load for the next iteration to a value low enough
+      // that the next iteration will start tests.
+      this->FakeLoadForTesting = 1;
     }
     // If it's not set, look up the true load average.
     else {
@@ -385,18 +397,25 @@ void cmCTestMultiProcessHandler::StartNextTests()
     }
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
 
-    if (usedFakeLoadForTesting) {
-      // Break out of the infinite loop of waiting for our fake load
-      // to come down.
-      this->StopTimePassed = true;
-    } else {
-      // Wait between 1 and 5 seconds before trying again.
-      cmCTestScriptHandler::SleepInSeconds(cmSystemTools::RandomSeed() % 5 +
-                                           1);
+    // Wait between 1 and 5 seconds before trying again.
+    unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000;
+    if (this->FakeLoadForTesting) {
+      milliseconds = 10;
+    }
+    if (this->TestLoadRetryTimer.get() == nullptr) {
+      this->TestLoadRetryTimer.init(this->Loop, this);
     }
+    this->TestLoadRetryTimer.start(
+      &cmCTestMultiProcessHandler::OnTestLoadRetryCB, milliseconds, 0);
   }
 }
 
+void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer)
+{
+  auto self = static_cast<cmCTestMultiProcessHandler*>(timer->data);
+  self->StartNextTests();
+}
+
 void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner,
                                                    bool started)
 {
index 203170e..07a5fe7 100644 (file)
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "cmUVHandlePtr.h"
 #include "cm_uv.h"
 
 class cmCTest;
@@ -101,6 +102,8 @@ protected:
   void EraseTest(int index);
   void FinishTestProcess(cmCTestRunTest* runner, bool started);
 
+  static void OnTestLoadRetryCB(uv_timer_t* timer);
+
   void RemoveTest(int index);
   // Check if we need to resume an interrupted test set
   void CheckResume();
@@ -135,7 +138,9 @@ protected:
   std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
   size_t ParallelLevel; // max number of process that can be run at once
   unsigned long TestLoad;
+  unsigned long FakeLoadForTesting;
   uv_loop_t Loop;
+  cm::uv_timer_ptr TestLoadRetryTimer;
   cmCTestTestHandler* TestHandler;
   cmCTest* CTest;
   bool HasCycles;
index d0e668d..bcb754a 100644 (file)
@@ -478,11 +478,13 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
           tag.clear();
         }
         std::string track;
-        if (cmSystemTools::GetLineFromStream(tfin, track)) {
+        if (cmSystemTools::GetLineFromStream(tfin, track) &&
+            !this->Parts[PartStart] && !command) {
           this->SpecificTrack = track;
         }
         std::string model;
-        if (cmSystemTools::GetLineFromStream(tfin, model)) {
+        if (cmSystemTools::GetLineFromStream(tfin, model) &&
+            !this->Parts[PartStart] && !command) {
           this->TestModel = GetTestModelFromString(model.c_str());
         }
         tfin.close();
index b223c5e..8aab1be 100644 (file)
@@ -5227,10 +5227,14 @@ bool cmGeneratorTarget::HasLanguage(std::string const& language,
 {
   std::set<std::string> languages;
   this->GetLanguages(languages, config);
+  // The "exclusive" check applies only to source files and not
+  // the linker language which may be affected by dependencies.
+  if (exclusive && languages.size() > 1) {
+    return false;
+  }
   // add linker language (if it is different from compiler languages)
   languages.insert(this->GetLinkerLanguage(config));
-  return (languages.size() == 1 || !exclusive) &&
-    languages.count(language) > 0;
+  return languages.count(language) > 0;
 }
 
 void cmGeneratorTarget::ComputeLinkImplementationLanguages(
index 2132b15..2810887 100644 (file)
@@ -366,7 +366,7 @@ public:
 
   // Evaluate if the target uses the given language for compilation
   // and/or linking. If 'exclusive' is true, 'language' is expected
-  // to be the only language used for the target.
+  // to be the only language used in source files for the target.
   bool HasLanguage(std::string const& language, std::string const& config,
                    bool exclusive = true) const;
 
index f472d8a..b8b04ae 100644 (file)
@@ -2413,10 +2413,12 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   }
 
   // Choose a language whose flags to use for ClCompile.
-  static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+  static const char* clLangs[] = { "CXX", "C", "Fortran" };
   std::string langForClCompile;
-  if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) !=
-      cm::cend(clLangs)) {
+  if (this->ProjectType == csproj) {
+    langForClCompile = "CSharp";
+  } else if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) !=
+             cm::cend(clLangs)) {
     langForClCompile = linkLanguage;
   } else {
     std::set<std::string> languages;
index 153c57c..a3067af 100644 (file)
@@ -21,3 +21,9 @@ target_link_libraries(CSharpLinkToCxx CLIApp)
 # because it is unmanaged
 add_library(CppNativeApp SHARED cpp_native.hpp cpp_native.cpp)
 target_link_libraries(CSharpLinkToCxx CppNativeApp)
+
+# Link a static C++ library into the CSharp executable.
+# We do not actually use any symbols but this helps cover
+# link language selection.
+add_library(CppStaticLib STATIC cpp_static.cpp)
+target_link_libraries(CSharpLinkToCxx CppStaticLib)
diff --git a/Tests/CSharpLinkToCxx/cpp_static.cpp b/Tests/CSharpLinkToCxx/cpp_static.cpp
new file mode 100644 (file)
index 0000000..9af2b6e
--- /dev/null
@@ -0,0 +1,3 @@
+void cpp_static()
+{
+}
index 3033c9c..9e8d050 100644 (file)
@@ -111,8 +111,8 @@ endfunction()
 set(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING} 5)
 
 # Verify that new tests are not started when the load average exceeds
-# our threshold.
-run_TestLoad(test-load-fail 2)
+# our threshold and that they then run once the load average drops.
+run_TestLoad(test-load-wait 3)
 
 # Verify that warning message is displayed but tests still start when
 # an invalid argument is given.
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt
deleted file mode 100644 (file)
index eafba1c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-No tests were found!!!
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt
deleted file mode 100644 (file)
index 153da09..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
-\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test TestLoad[1-2] requires 1\*\*\*\*\*
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt
deleted file mode 100644 (file)
index 10f3293..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^$
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-wait-stdout.txt
new file mode 100644 (file)
index 0000000..11a768a
--- /dev/null
@@ -0,0 +1,8 @@
+^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
+\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 3, Smallest test TestLoad[1-2] requires 1\*\*\*\*\*
+    Start 1: TestLoad1
+    Start 2: TestLoad2
+1/2 Test #[1-2]: TestLoad[1-2] ........................   Passed +[0-9.]+ sec
+2/2 Test #[1-2]: TestLoad[1-2] ........................   Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt b/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt
new file mode 100644 (file)
index 0000000..4a6f1e9
--- /dev/null
@@ -0,0 +1,8 @@
+Run dashboard with model Experimental
+   Source directory: .*/Tests/RunCMake/ctest_start/NoAppendDifferentTrack
+   Build directory: .*/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-build
+   Track: ExperimentalDifferent
+   Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/NoAppendDifferentTrack/CTestConfig.cmake
+   Site: test-site
+   Build name: test-build-name
+   Use ExperimentalDifferent tag: [0-9-]+
index 2e8aa75..9b57b1b 100644 (file)
@@ -30,6 +30,7 @@ run_ctest_start(AppendSameModel Continuous APPEND)
 run_ctest_start(AppendDifferentModel Experimental APPEND)
 run_ctest_start(AppendNoModel APPEND)
 run_ctest_start(AppendDifferentTrack TRACK ExperimentalDifferent APPEND)
+run_ctest_start(NoAppendDifferentTrack Experimental TRACK ExperimentalDifferent)
 run_ctest_start(AppendNoMatchingTrack Continuous APPEND)
 run_ctest_start(AppendOldContinuous Continuous APPEND)
 run_ctest_start(AppendOldNoModel APPEND)
index 172baf7..8cd3cff 100644 (file)
@@ -14,7 +14,7 @@ function(setup_tests)
   ctest_start(${ctest_start_args})
 endfunction()
 
-if("@CASE_NAME@" MATCHES "^Append")
+if("@CASE_NAME@" MATCHES "^(No)?Append")
   if("@CASE_NAME@" MATCHES "^AppendNoMatchingTrack$")
     file(WRITE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "19551112-2204\nSomeWeirdTrackName\n")
   else()
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadFail-result.txt b/Tests/RunCMake/ctest_test/CTestTestLoadFail-result.txt
deleted file mode 100644 (file)
index b57e2de..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(-1|255)
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadFail-stderr.txt b/Tests/RunCMake/ctest_test/CTestTestLoadFail-stderr.txt
deleted file mode 100644 (file)
index eafba1c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-No tests were found!!!
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadFail-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadFail-stdout.txt
deleted file mode 100644 (file)
index e203c10..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadFail-build
-\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 4, Smallest test RunCMakeVersion requires 1\*\*\*\*\*$
diff --git a/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt b/Tests/RunCMake/ctest_test/CTestTestLoadWait-stdout.txt
new file mode 100644 (file)
index 0000000..2af3838
--- /dev/null
@@ -0,0 +1,8 @@
+Test project .*/Tests/RunCMake/ctest_test/CTestTestLoadWait-build
+\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 4, Smallest test RunCMakeVersion requires 1\*\*\*\*\*
+    Start 1: RunCMakeVersion
+1/1 Test #1: RunCMakeVersion ..................   Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec$
index 1b31726..6877e6a 100644 (file)
@@ -21,8 +21,8 @@ set(ENV{__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING} 5)
 run_ctest_test(TestLoadPass TEST_LOAD 6)
 
 # Verify that new tests are not started when the load average exceeds
-# our threshold.
-run_ctest_test(TestLoadFail TEST_LOAD 2)
+# our threshold and that they then run once the load average drops.
+run_ctest_test(TestLoadWait TEST_LOAD 2)
 
 # Verify that when an invalid "TEST_LOAD" value is given, a warning
 # message is displayed and the value is ignored.
@@ -34,9 +34,9 @@ set(CASE_CTEST_TEST_LOAD 7)
 run_ctest_test(CTestTestLoadPass)
 
 # Verify that new tests are not started when the load average exceeds
-# our threshold.
+# our threshold and that they then run once the load average drops.
 set(CASE_CTEST_TEST_LOAD 4)
-run_ctest_test(CTestTestLoadFail)
+run_ctest_test(CTestTestLoadWait)
 
 # Verify that when an invalid "CTEST_TEST_LOAD" value is given,
 # a warning message is displayed and the value is ignored.
diff --git a/Tests/RunCMake/ctest_test/TestLoadFail-result.txt b/Tests/RunCMake/ctest_test/TestLoadFail-result.txt
deleted file mode 100644 (file)
index b57e2de..0000000
+++ /dev/null
@@ -1 +0,0 @@
-(-1|255)
diff --git a/Tests/RunCMake/ctest_test/TestLoadFail-stderr.txt b/Tests/RunCMake/ctest_test/TestLoadFail-stderr.txt
deleted file mode 100644 (file)
index eafba1c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-No tests were found!!!
diff --git a/Tests/RunCMake/ctest_test/TestLoadFail-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadFail-stdout.txt
deleted file mode 100644 (file)
index 4d7ce48..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Test project .*/Tests/RunCMake/ctest_test/TestLoadFail-build
-\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test RunCMakeVersion requires 1\*\*\*\*\*$
diff --git a/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt b/Tests/RunCMake/ctest_test/TestLoadWait-stdout.txt
new file mode 100644 (file)
index 0000000..07f4ed3
--- /dev/null
@@ -0,0 +1,8 @@
+Test project .*/Tests/RunCMake/ctest_test/TestLoadWait-build
+\*\*\*\*\* WAITING, System Load: 5, Max Allowed Load: 2, Smallest test RunCMakeVersion requires 1\*\*\*\*\*
+    Start 1: RunCMakeVersion
+1/1 Test #1: RunCMakeVersion ..................   Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec$
index 59f95b8..921249b 100644 (file)
@@ -28,7 +28,8 @@
 #include <openssl/hmac.h>
 #include <openssl/opensslv.h>
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+       (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
 #include <stdlib.h> /* malloc, free */
 #include <string.h> /* memset */
 static inline HMAC_CTX *HMAC_CTX_new(void)
index 4545168..a6cc6db 100644 (file)
@@ -425,19 +425,22 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) {
   return n;
 }
 
+#if defined(_POSIX_PATH_MAX)
+# define UV__FS_PATH_MAX _POSIX_PATH_MAX
+#elif defined(PATH_MAX)
+# define UV__FS_PATH_MAX PATH_MAX
+#else
+# define UV__FS_PATH_MAX_FALLBACK 8192
+# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK
+#endif
 
 static ssize_t uv__fs_pathmax_size(const char* path) {
   ssize_t pathmax;
 
   pathmax = pathconf(path, _PC_PATH_MAX);
 
-  if (pathmax == -1) {
-#if defined(PATH_MAX)
-    return PATH_MAX;
-#else
-#error "PATH_MAX undefined in the current platform"
-#endif
-  }
+  if (pathmax == -1)
+    pathmax = UV__FS_PATH_MAX;
 
   return pathmax;
 }
@@ -446,7 +449,28 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
   ssize_t len;
   char* buf;
 
+#if defined(UV__FS_PATH_MAX_FALLBACK)
+  /* We may not have a real PATH_MAX.  Read size of link.  */
+  struct stat st;
+  int ret;
+  ret = lstat(req->path, &st);
+  if (ret != 0)
+    return -1;
+  if (!S_ISLNK(st.st_mode)) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  len = st.st_size;
+
+  /* According to readlink(2) lstat can report st_size == 0
+     for some symlinks, such as those in /proc or /sys.  */
+  if (len == 0)
+    len = uv__fs_pathmax_size(req->path);
+#else
   len = uv__fs_pathmax_size(req->path);
+#endif
+
   buf = uv__malloc(len + 1);
 
   if (buf == NULL) {
@@ -473,9 +497,15 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
 }
 
 static ssize_t uv__fs_realpath(uv_fs_t* req) {
-  ssize_t len;
   char* buf;
 
+#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
+  buf = realpath(req->path, NULL);
+  if (buf == NULL)
+    return -1;
+#else
+  ssize_t len;
+
   len = uv__fs_pathmax_size(req->path);
   buf = uv__malloc(len + 1);
 
@@ -488,6 +518,7 @@ static ssize_t uv__fs_realpath(uv_fs_t* req) {
     uv__free(buf);
     return -1;
   }
+#endif
 
   req->ptr = buf;