Index: llvm/trunk/lib/Support/Host.cpp =================================================================== --- llvm/trunk/lib/Support/Host.cpp +++ llvm/trunk/lib/Support/Host.cpp @@ -1494,7 +1494,8 @@ #endif std::string sys::getProcessTriple() { - Triple PT(Triple::normalize(LLVM_HOST_TRIPLE)); + std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE); + Triple PT(Triple::normalize(TargetTripleString)); if (sizeof(void *) == 8 && PT.isArch32Bit()) PT = PT.get64BitArchVariant(); Index: llvm/trunk/lib/Support/Unix/Host.inc =================================================================== --- llvm/trunk/lib/Support/Unix/Host.inc +++ llvm/trunk/lib/Support/Unix/Host.inc @@ -34,18 +34,31 @@ return info.release; } -std::string sys::getDefaultTargetTriple() { - std::string TargetTripleString(LLVM_DEFAULT_TARGET_TRIPLE); - - // On darwin, we want to update the version to match that of the - // target. +static std::string updateTripleOSVersion(std::string TargetTripleString) { + // On darwin, we want to update the version to match that of the target. std::string::size_type DarwinDashIdx = TargetTripleString.find("-darwin"); if (DarwinDashIdx != std::string::npos) { TargetTripleString.resize(DarwinDashIdx + strlen("-darwin")); TargetTripleString += getOSVersion(); + return TargetTripleString; + } + std::string::size_type MacOSDashIdx = TargetTripleString.find("-macos"); + if (MacOSDashIdx != std::string::npos) { + TargetTripleString.resize(MacOSDashIdx); + // Reset the OS to darwin as the OS version from `uname` doesn't use the + // macOS version scheme. + TargetTripleString += "-darwin"; + TargetTripleString += getOSVersion(); } + return TargetTripleString; +} + +std::string sys::getDefaultTargetTriple() { + std::string TargetTripleString = + updateTripleOSVersion(LLVM_DEFAULT_TARGET_TRIPLE); - // Override the default target with an environment variable named by LLVM_TARGET_TRIPLE_ENV. + // Override the default target with an environment variable named by + // LLVM_TARGET_TRIPLE_ENV. #if defined(LLVM_TARGET_TRIPLE_ENV) if (const char *EnvTriple = std::getenv(LLVM_TARGET_TRIPLE_ENV)) TargetTripleString = EnvTriple; Index: llvm/trunk/lib/Support/Windows/Host.inc =================================================================== --- llvm/trunk/lib/Support/Windows/Host.inc +++ llvm/trunk/lib/Support/Windows/Host.inc @@ -17,6 +17,10 @@ using namespace llvm; +static void updateTripleOSVersion(std::string &) { + // Do nothing. +} + std::string sys::getDefaultTargetTriple() { const char *Triple = LLVM_DEFAULT_TARGET_TRIPLE; Index: llvm/trunk/unittests/Support/Host.cpp =================================================================== --- llvm/trunk/unittests/Support/Host.cpp +++ llvm/trunk/unittests/Support/Host.cpp @@ -10,9 +10,23 @@ #include "llvm/Support/Host.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #include "gtest/gtest.h" +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + SmallString<128> MessageStorage; \ + raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } + using namespace llvm; class HostTest : public testing::Test { @@ -114,3 +128,50 @@ EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo), "cortex-a53"); } + +#if defined(__APPLE__) +TEST_F(HostTest, getMacOSHostVersion) { + using namespace llvm::sys; + llvm::Triple HostTriple(getProcessTriple()); + if (!HostTriple.isMacOSX()) + return; + + SmallString<128> TestDirectory; + ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory)); + SmallString<128> OutputFile(TestDirectory); + path::append(OutputFile, "out"); + + const char *SwVersPath = "/usr/bin/sw_vers"; + const char *argv[] = {SwVersPath, "-productVersion", nullptr}; + StringRef OutputPath = OutputFile.str(); + const StringRef *Redirects[] = {/*STDIN=*/nullptr, /*STDOUT=*/&OutputPath, + /*STDERR=*/nullptr}; + int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/nullptr, Redirects); + ASSERT_EQ(0, RetCode); + + int FD = 0; + ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD)); + off_t Size = ::lseek(FD, 0, SEEK_END); + ASSERT_NE(-1, Size); + ::lseek(FD, 0, SEEK_SET); + std::unique_ptr Buffer = llvm::make_unique(Size); + ASSERT_EQ(::read(FD, Buffer.get(), Size), Size); + ::close(FD); + + // Ensure that the two versions match. + StringRef SystemVersion(Buffer.get(), Size); + unsigned SystemMajor, SystemMinor, SystemMicro; + ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersion)) + .getMacOSXVersion(SystemMajor, SystemMinor, SystemMicro), + true); + unsigned HostMajor, HostMinor, HostMicro; + ASSERT_EQ(HostTriple.getMacOSXVersion(HostMajor, HostMinor, HostMicro), true); + + // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin' + // triples. + ASSERT_EQ(std::tie(SystemMajor, SystemMinor), std::tie(HostMajor, HostMinor)); + + ASSERT_NO_ERROR(fs::remove(OutputPath)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} +#endif