From 5dc2981cf8ff580fda060c93e663730b17e9be95 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Fri, 5 Dec 2014 01:16:31 +0000 Subject: [PATCH] Added support to Platform to indicate (1) whether the current platform supports Clang modules, and (2) what options to pass to Clang so it can load those Clang modules. llvm-svn: 223431 --- lldb/include/lldb/Target/Platform.h | 11 +- .../Plugins/Platform/MacOSX/PlatformDarwin.cpp | 291 ++++++++++++++++++++- .../Plugins/Platform/MacOSX/PlatformDarwin.h | 37 +++ .../Plugins/Platform/MacOSX/PlatformDarwinKernel.h | 3 + .../Plugins/Platform/MacOSX/PlatformMacOSX.h | 6 + .../Plugins/Platform/MacOSX/PlatformRemoteiOS.h | 6 + .../Plugins/Platform/MacOSX/PlatformiOSSimulator.h | 6 + lldb/source/Target/Platform.cpp | 14 + 8 files changed, 372 insertions(+), 2 deletions(-) diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index ca4e57c..6b6bd54 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -560,7 +560,16 @@ namespace lldb_private { SetSDKBuild (const ConstString &sdk_build) { m_sdk_build = sdk_build; - } + } + + // Override this to return true if your platform supports Clang modules. + // You may also need to override AddClangModuleCompilationOptions to pass the right Clang flags for your platform. + virtual bool + SupportsModules () { return false; } + + // Appends the platform-specific options required to find the modules for the current platform. + virtual void + AddClangModuleCompilationOptions (std::vector &options); ConstString GetWorkingDirectory (); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index fb48c01..acf99be 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1181,4 +1181,293 @@ void PlatformDarwin::CalculateTrapHandlerSymbolNames () { m_trap_handlers.push_back (ConstString ("_sigtramp")); -} +} + + +static const char *const sdk_strings[] = { + "MacOSX", + "iPhoneSimulator", + "iPhoneOS", +}; + +static FileSpec +GetXcodeContentsPath () +{ + const char substr[] = ".app/Contents/"; + + // First, try based on the current shlib's location + + { + FileSpec fspec; + + if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBShlibDir, fspec)) + { + std::string path_to_shlib = fspec.GetPath(); + size_t pos = path_to_shlib.rfind(substr); + if (pos != std::string::npos) + { + path_to_shlib.erase(pos + strlen(substr)); + return FileSpec(path_to_shlib.c_str(), false); + } + } + } + + // Fall back to using xcrun + + { + int status = 0; + int signo = 0; + std::string output; + const char *command = "xcrun -sdk macosx --show-sdk-path"; + lldb_private::Error error = Host::RunShellCommand (command, // shell command to run + NULL, // current working directory + &status, // Put the exit status of the process in here + &signo, // Put the signal that caused the process to exit in here + &output, // Get the output from the command and place it in this string + 3); // Timeout in seconds to wait for shell program to finish + if (status == 0 && !output.empty()) + { + size_t first_non_newline = output.find_last_not_of("\r\n"); + if (first_non_newline != std::string::npos) + { + output.erase(first_non_newline+1); + } + + size_t pos = output.rfind(substr); + if (pos != std::string::npos) + { + output.erase(pos + strlen(substr)); + return FileSpec(output.c_str(), false); + } + } + } + + return FileSpec(); +} + +bool +PlatformDarwin::SDKSupportsModules (SDKType sdk_type, uint32_t major, uint32_t minor, uint32_t micro) +{ + switch (sdk_type) + { + default: + return false; + case SDKType::MacOSX: + if (major > 10 || (major == 10 && minor >= 10)) + return true; + break; + case SDKType::iPhoneOS: + case SDKType::iPhoneSimulator: + if (major >= 8) + return true; + break; + } + + return false; +} + +bool +PlatformDarwin::SDKSupportsModules (SDKType desired_type, const FileSpec &sdk_path) +{ + ConstString last_path_component = sdk_path.GetLastPathComponent(); + + if (last_path_component) + { + const llvm::StringRef sdk_name = last_path_component.GetStringRef(); + + llvm::StringRef version_part; + + if (sdk_name.startswith(sdk_strings[(int)desired_type])) + { + version_part = sdk_name.drop_front(strlen(sdk_strings[(int)desired_type])); + } + else + { + return false; + } + + const size_t major_dot_offset = version_part.find('.'); + if (major_dot_offset == llvm::StringRef::npos) + return false; + + const llvm::StringRef major_version = version_part.slice(0, major_dot_offset); + const llvm::StringRef minor_part = version_part.drop_front(major_dot_offset + 1); + + const size_t minor_dot_offset = minor_part.find('.'); + if (minor_dot_offset == llvm::StringRef::npos) + return false; + + const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset); + + unsigned int major = 0; + unsigned int minor = 0; + unsigned int micro = 0; + + if (major_version.getAsInteger(10, major)) + return false; + + if (minor_version.getAsInteger(10, minor)) + return false; + + return SDKSupportsModules(desired_type, major, minor, micro); + } + + return false; +} + +FileSpec::EnumerateDirectoryResult +PlatformDarwin::DirectoryEnumerator(void *baton, + FileSpec::FileType file_type, + const FileSpec &spec) +{ + SDKEnumeratorInfo *enumerator_info = static_cast(baton); + + if (SDKSupportsModules(enumerator_info->sdk_type, spec)) + { + enumerator_info->found_path = spec; + return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; + } + + return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; +}; + +FileSpec +PlatformDarwin::FindSDKInXcodeForModules (SDKType sdk_type, + const FileSpec &sdks_spec) +{ + // Look inside Xcode for the required installed iOS SDK version + + if (!sdks_spec.IsDirectory()) + return FileSpec(); + + const bool find_directories = true; + const bool find_files = false; + const bool find_other = true; // include symlinks + + SDKEnumeratorInfo enumerator_info; + + enumerator_info.sdk_type = sdk_type; + + FileSpec::EnumerateDirectory(sdks_spec.GetPath().c_str(), + find_directories, + find_files, + find_other, + DirectoryEnumerator, + &enumerator_info); + + if (enumerator_info.found_path.IsDirectory()) + return enumerator_info.found_path; + else + return FileSpec(); +} + +FileSpec +PlatformDarwin::GetSDKDirectoryForModules (SDKType sdk_type) +{ + switch (sdk_type) + { + default: + return FileSpec(); + case SDKType::MacOSX: + case SDKType::iPhoneSimulator: + case SDKType::iPhoneOS: + break; + } + + FileSpec sdks_spec = GetXcodeContentsPath(); + sdks_spec.AppendPathComponent("Developer"); + sdks_spec.AppendPathComponent("Platforms"); + + switch (sdk_type) + { + default: + return FileSpec(); + case SDKType::MacOSX: + sdks_spec.AppendPathComponent("MacOSX.platform"); + break; + case SDKType::iPhoneSimulator: + sdks_spec.AppendPathComponent("iPhoneSimulator.platform"); + break; + case SDKType::iPhoneOS: + sdks_spec.AppendPathComponent("iPhoneOS.platform"); + break; + } + + sdks_spec.AppendPathComponent("Developer"); + sdks_spec.AppendPathComponent("SDKs"); + + if (sdk_type == SDKType::MacOSX) + { + uint32_t major = 0; + uint32_t minor = 0; + uint32_t micro = 0; + + if (HostInfo::GetOSVersion(major, minor, micro)) + { + if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro)) + { + // We slightly prefer the exact SDK for this machine. See if it is there. + + FileSpec native_sdk_spec = sdks_spec; + StreamString native_sdk_name; + native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor); + native_sdk_spec.AppendPathComponent(native_sdk_name.GetString().c_str()); + + if (native_sdk_spec.Exists()) + { + return native_sdk_spec; + } + } + } + } + + return FindSDKInXcodeForModules(sdk_type, sdks_spec); +} + +void +PlatformDarwin::AddClangModuleCompilationOptionsForSDKType (std::vector &options, SDKType sdk_type) +{ + const std::vector apple_arguments = + { + "-x", "objective-c++", + "-fobjc-arc", + "-fblocks", + "-D_ISO646_H", + "-D__ISO646_H" + }; + + options.insert(options.end(), + apple_arguments.begin(), + apple_arguments.end()); + + StreamString minimum_version_option; + unsigned int major = 0, minor = 0, micro = 0; + GetOSVersion(major, minor, micro); + if (micro == UINT32_MAX) + micro = 0; // FIXME who actually likes this behavior? + + switch (sdk_type) + { + case SDKType::iPhoneOS: + minimum_version_option.PutCString("-mios-version-min="); + minimum_version_option.PutCString(clang::VersionTuple(major, minor, micro).getAsString().c_str()); + break; + case SDKType::iPhoneSimulator: + minimum_version_option.PutCString("-mios-simulator-version-min="); + minimum_version_option.PutCString(clang::VersionTuple(major, minor, micro).getAsString().c_str()); + break; + case SDKType::MacOSX: + minimum_version_option.PutCString("-mmacosx-version-min="); + minimum_version_option.PutCString(clang::VersionTuple(major, minor, micro).getAsString().c_str()); + } + + options.push_back(minimum_version_option.GetString()); + + FileSpec sysroot_spec = GetSDKDirectoryForModules(sdk_type); + + if (sysroot_spec.IsDirectory()) + { + options.push_back("-isysroot"); + options.push_back(sysroot_spec.GetPath()); + } +} diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h index dbde3c5..ca19d26 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -14,6 +14,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Host/FileSpec.h" #include "Plugins/Platform/POSIX/PlatformPOSIX.h" class PlatformDarwin : public PlatformPOSIX @@ -79,6 +80,9 @@ public: void CalculateTrapHandlerSymbolNames () override; + + bool + SupportsModules () override { return true; } protected: @@ -94,6 +98,39 @@ protected: const lldb_private::FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); + + + enum class SDKType { + MacOSX = 0, + iPhoneSimulator, + iPhoneOS, + }; + + static bool + SDKSupportsModules (SDKType sdk_type, uint32_t major, uint32_t minor, uint32_t micro); + + static bool + SDKSupportsModules (SDKType desired_type, const lldb_private::FileSpec &sdk_path); + + struct SDKEnumeratorInfo { + lldb_private::FileSpec found_path; + SDKType sdk_type; + }; + + static lldb_private::FileSpec::EnumerateDirectoryResult + DirectoryEnumerator(void *baton, + lldb_private::FileSpec::FileType file_type, + const lldb_private::FileSpec &spec); + + static lldb_private::FileSpec + FindSDKInXcodeForModules (SDKType sdk_type, + const lldb_private::FileSpec &sdks_spec); + + static lldb_private::FileSpec + GetSDKDirectoryForModules (PlatformDarwin::SDKType sdk_type); + + void + AddClangModuleCompilationOptionsForSDKType (std::vector &options, SDKType sdk_type); std::string m_developer_directory; diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h index 3a901d6..2baccdc 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h @@ -93,6 +93,9 @@ public: virtual bool GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch); + + bool + SupportsModules() override { return false; } protected: diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h index 3f5cef9..a5a9051 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h @@ -97,6 +97,12 @@ public: virtual lldb_private::ConstString GetSDKDirectory (lldb_private::Target &target); + + void + AddClangModuleCompilationOptions (std::vector &options) override + { + return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(options, PlatformDarwin::SDKType::MacOSX); + } private: DISALLOW_COPY_AND_ASSIGN (PlatformMacOSX); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h index 9df723c..bc1b425 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h @@ -95,6 +95,12 @@ public: virtual bool GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch); + + void + AddClangModuleCompilationOptions (std::vector &options) override + { + return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(options, PlatformDarwin::SDKType::iPhoneOS); + } protected: struct SDKDirectoryInfo diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h b/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h index efbf0d1..6617989 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h @@ -97,6 +97,12 @@ public: virtual bool GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch); + + void + AddClangModuleCompilationOptions (std::vector &options) override + { + return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(options, PlatformDarwin::SDKType::iPhoneSimulator); + } protected: std::string m_sdk_directory; diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 6ea6c4e..4ebd18b 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -462,6 +462,20 @@ Platform::GetOSKernelDescription (std::string &s) return GetRemoteOSKernelDescription (s); } +void +Platform::AddClangModuleCompilationOptions (std::vector &options) +{ + std::vector default_compilation_options = + { + "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc" + }; + + options.insert(options.end(), + default_compilation_options.begin(), + default_compilation_options.end()); +} + + ConstString Platform::GetWorkingDirectory () { -- 2.7.4