|  | // Copyright 2014 The Bazel Authors. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #ifndef BAZEL_SRC_MAIN_CPP_BLAZE_UTIL_PLATFORM_H_ | 
|  | #define BAZEL_SRC_MAIN_CPP_BLAZE_UTIL_PLATFORM_H_ | 
|  |  | 
|  | #include <cinttypes> | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "src/main/cpp/blaze_util.h" | 
|  | #include "src/main/cpp/server_process_info.h" | 
|  | #include "src/main/cpp/util/path.h" | 
|  | #include "src/main/cpp/util/port.h" | 
|  |  | 
|  | namespace blaze { | 
|  |  | 
|  | namespace embedded_binaries { | 
|  |  | 
|  | // Dumps embedded binaries that were extracted from the Bazel zip to disk. | 
|  | // The platform-specific implementations may use multi-threaded I/O. | 
|  | class Dumper { | 
|  | public: | 
|  | // Requests to write the `data` of `size` bytes to disk under `path`. | 
|  | // The actual writing may happen asynchronously. | 
|  | // `path` must be an absolute path. All of its parent directories will be | 
|  | // created. | 
|  | // The caller retains ownership of `data` and may release it immediately after | 
|  | // this method returns. | 
|  | // Callers may call this method repeatedly, but only from the same thread | 
|  | // (this method is not thread-safe). | 
|  | // If writing fails, this method sets a flag in the `Dumper`, and `Finish` | 
|  | // will return false. Subsequent `Dump` calls will have no effect. | 
|  | virtual void Dump(const void* data, const size_t size, | 
|  | const std::string& path) = 0; | 
|  |  | 
|  | // Finishes dumping data. | 
|  | // | 
|  | // This method may block in case the Dumper is asynchronous and some async | 
|  | // writes are still in progress. | 
|  | // Subsequent `Dump` calls after this method have no effect. | 
|  | // | 
|  | // Returns true if there were no errors in any of the `Dump` calls. | 
|  | // Returns false if any of the `Dump` calls failed, and if `error` is not | 
|  | // null then puts an error message in `error`. | 
|  | virtual bool Finish(std::string* error) = 0; | 
|  |  | 
|  | // Destructor. Subclasses should make sure it calls `Finish(nullptr)`. | 
|  | virtual ~Dumper() {} | 
|  |  | 
|  | protected: | 
|  | Dumper() {} | 
|  | }; | 
|  |  | 
|  | // Creates a new Dumper. The caller takes ownership of the returned object. | 
|  | // Returns nullptr upon failure and puts an error message in `error` (if `error` | 
|  | // is not nullptr). | 
|  | Dumper* Create(std::string* error = nullptr); | 
|  |  | 
|  | }  // namespace embedded_binaries | 
|  |  | 
|  | class StartupOptions; | 
|  |  | 
|  | class SignalHandler { | 
|  | public: | 
|  | typedef void (* Callback)(); | 
|  |  | 
|  | static SignalHandler& Get() { return INSTANCE; } | 
|  | const ServerProcessInfo* GetServerProcessInfo() const { | 
|  | return server_process_info_; | 
|  | } | 
|  | const std::string& GetProductName() const { return product_name_; } | 
|  | const blaze_util::Path& GetOutputBase() const { return output_base_; } | 
|  | void CancelServer() { cancel_server_(); } | 
|  | void Install(const std::string& product_name, | 
|  | const blaze_util::Path& output_base, | 
|  | const ServerProcessInfo* server_process_info, | 
|  | Callback cancel_server); | 
|  | ATTRIBUTE_NORETURN void PropagateSignalOrExit(int exit_code); | 
|  |  | 
|  | private: | 
|  | static SignalHandler INSTANCE; | 
|  |  | 
|  | std::string product_name_; | 
|  | blaze_util::Path output_base_; | 
|  | const ServerProcessInfo* server_process_info_; | 
|  | Callback cancel_server_; | 
|  |  | 
|  | SignalHandler() : server_process_info_(nullptr), cancel_server_(nullptr) {} | 
|  | }; | 
|  |  | 
|  | // A signal-safe version of fprintf(stderr, ...). | 
|  | void SigPrintf(const char *format, ...); | 
|  |  | 
|  | std::string GetProcessIdAsString(); | 
|  |  | 
|  | // Locates a file named `executable` in the PATH. Returns a path to the first | 
|  | // matching file, or an empty string if `executable` is not found on the PATH. | 
|  | std::string Which(const std::string& executable); | 
|  |  | 
|  | // Gets an absolute path to the binary being executed that is guaranteed to be | 
|  | // readable. | 
|  | std::string GetSelfPath(const char* argv0); | 
|  |  | 
|  | // Returns the directory Bazel can use to store output. | 
|  | std::string GetOutputRoot(); | 
|  |  | 
|  | // Returns the current user's home directory, or the empty string if unknown. | 
|  | // On Linux/macOS, this is $HOME. On Windows this is %USERPROFILE%. | 
|  | std::string GetHomeDir(); | 
|  |  | 
|  | // Warn about dubious filesystem types, such as NFS, case-insensitive (?). | 
|  | void WarnFilesystemType(const blaze_util::Path& output_base); | 
|  |  | 
|  | // Returns elapsed milliseconds since some unspecified start of time. | 
|  | // The results are monotonic, i.e. subsequent calls to this method never return | 
|  | // a value less than a previous result. | 
|  | uint64_t GetMillisecondsMonotonic(); | 
|  |  | 
|  | // Set cpu and IO scheduling properties. Note that this can take ~50ms | 
|  | // on Linux, so it should only be called when necessary. | 
|  | void SetScheduling(bool batch_cpu_scheduling, int io_nice_level); | 
|  |  | 
|  | // Returns the current working directory of the specified process, or nullptr | 
|  | // if the directory is unknown. | 
|  | std::unique_ptr<blaze_util::Path> GetProcessCWD(int pid); | 
|  |  | 
|  | bool IsSharedLibrary(const std::string& filename); | 
|  |  | 
|  | // Returns the absolute path to the user's local JDK install, to be used as | 
|  | // the default target javabase and as a fall-back host_javabase. This is not | 
|  | // the embedded JDK. | 
|  | std::string GetSystemJavabase(); | 
|  |  | 
|  | // Return the path to the JVM binary relative to a javabase, e.g. "bin/java". | 
|  | std::string GetJavaBinaryUnderJavabase(); | 
|  |  | 
|  | // Start the Bazel server's JVM in the current directory. | 
|  | // | 
|  | // Note on Windows: 'server_jvm_args' is NOT expected to be escaped for | 
|  | // CreateProcessW. | 
|  | // | 
|  | // This function does not return on success. | 
|  | ATTRIBUTE_NORETURN void ExecuteServerJvm( | 
|  | const blaze_util::Path& exe, | 
|  | const std::vector<std::string>& server_jvm_args); | 
|  |  | 
|  | // Execute the "bazel run" request in the current directory. | 
|  | // | 
|  | // Note on Windows: 'run_request_args' IS expected to be escaped for | 
|  | // CreateProcessW. | 
|  | // | 
|  | // This function does not return on success. | 
|  | ATTRIBUTE_NORETURN void ExecuteRunRequest( | 
|  | const blaze_util::Path& exe, | 
|  | const std::vector<std::string>& run_request_args); | 
|  |  | 
|  | class BlazeServerStartup { | 
|  | public: | 
|  | virtual ~BlazeServerStartup() {} | 
|  | virtual bool IsStillAlive() = 0; | 
|  | }; | 
|  |  | 
|  |  | 
|  | // Starts a daemon process with its standard output and standard error | 
|  | // redirected (and conditionally appended) to the file "daemon_output". Sets | 
|  | // server_startup to an object that can be used to query if the server is | 
|  | // still alive. The PID of the daemon started is written into server_dir, | 
|  | // both as a symlink (for legacy reasons) and as a file, and returned to the | 
|  | // caller. | 
|  | int ExecuteDaemon( | 
|  | const blaze_util::Path& exe, const std::vector<std::string>& args_vector, | 
|  | const std::map<std::string, EnvVarValue>& env, | 
|  | const blaze_util::Path& daemon_output, const bool daemon_output_append, | 
|  | const std::string& binaries_dir, const blaze_util::Path& server_dir, | 
|  | const StartupOptions& options, BlazeServerStartup** server_startup); | 
|  |  | 
|  | // A character used to separate paths in a list. | 
|  | extern const char kListSeparator; | 
|  |  | 
|  | // Create a symlink to directory ``target`` at location ``link``. | 
|  | // Returns true on success, false on failure. The target must be absolute. | 
|  | // Implemented via junctions on Windows. | 
|  | bool SymlinkDirectories(const std::string& target, | 
|  | const blaze_util::Path& link); | 
|  |  | 
|  | struct BlazeLock { | 
|  | #if defined(_WIN32) || defined(__CYGWIN__) | 
|  | /* HANDLE */ void* handle; | 
|  | #else | 
|  | int lockfd; | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | // Acquires a lock on the output base. Exits if the lock cannot be acquired. | 
|  | // Sets ``lock`` to a value that can subsequently be passed to ReleaseLock(). | 
|  | // Returns the number of milliseconds spent with waiting for the lock. | 
|  | uint64_t AcquireLock(const blaze_util::Path& output_base, bool batch_mode, | 
|  | bool block, BlazeLock* blaze_lock); | 
|  |  | 
|  | // Releases the lock on the output base. In case of an error, continues as | 
|  | // usual. | 
|  | void ReleaseLock(BlazeLock* blaze_lock); | 
|  |  | 
|  | // Verifies whether the server process still exists. Returns true if it does. | 
|  | bool VerifyServerProcess(int pid, const blaze_util::Path& output_base); | 
|  |  | 
|  | // Kills a server process based on its PID. | 
|  | // Returns true if the server process was found and killed. | 
|  | // WARNING! This function can be called from a signal handler! | 
|  | bool KillServerProcess(int pid, const blaze_util::Path& output_base); | 
|  |  | 
|  | // Wait for approximately the specified number of milliseconds. The actual | 
|  | // amount of time waited may be more or less because of interrupts or system | 
|  | // clock resolution. | 
|  | void TrySleep(unsigned int milliseconds); | 
|  |  | 
|  | // Mark path as being excluded from backups (if supported by operating system). | 
|  | void ExcludePathFromBackup(const blaze_util::Path& path); | 
|  |  | 
|  | // Returns the canonical form of the base dir given a root and a hashable | 
|  | // string. The resulting dir is composed of the root + md5(hashable) | 
|  | std::string GetHashedBaseDir(const std::string& root, | 
|  | const std::string& hashable); | 
|  |  | 
|  | // Create a safe installation directory where we keep state, installations etc. | 
|  | // This method ensures that the directory is created, is owned by the current | 
|  | // user, and not accessible to anyone else. | 
|  | void CreateSecureOutputRoot(const blaze_util::Path& path); | 
|  |  | 
|  | std::string GetEnv(const std::string& name); | 
|  |  | 
|  | std::string GetPathEnv(const std::string& name); | 
|  |  | 
|  | bool ExistsEnv(const std::string& name); | 
|  |  | 
|  | void SetEnv(const std::string& name, const std::string& value); | 
|  |  | 
|  | void UnsetEnv(const std::string& name); | 
|  |  | 
|  | // Returns true and prints a warning if Bazel was started by clicking its icon. | 
|  | // This is typical on Windows. Other platforms should return false, unless they | 
|  | // wish to handle this case too. | 
|  | bool WarnIfStartedFromDesktop(); | 
|  |  | 
|  | // Ensure we have open file descriptors for stdin/stdout/stderr. | 
|  | void SetupStdStreams(); | 
|  |  | 
|  | std::string GetUserName(); | 
|  |  | 
|  | // Returns true iff the current terminal is running inside an Emacs. | 
|  | bool IsEmacsTerminal(); | 
|  |  | 
|  | // Returns true iff both stdout and stderr support color and cursor movement. | 
|  | // This is used to determine whether or not to use stylized output, which relies | 
|  | // on both stdout and stderr being standard terminals to avoid confusing UI | 
|  | // issues (ie one stream deleting a line the other intended to be displayed). | 
|  | bool IsStandardTerminal(); | 
|  |  | 
|  | // Returns the number of columns of the terminal to which stdout is connected, | 
|  | // or 80 if there is no such terminal. | 
|  | int GetTerminalColumns(); | 
|  |  | 
|  | // Gets the system-wide explicit limit for the given resource. | 
|  | // | 
|  | // The resource is one of the RLIMIT_* constants defined in sys/resource.h. | 
|  | // Returns 0 if the limit could not be fetched and returns -1 if the function | 
|  | // is not implemented for this platform. | 
|  | // | 
|  | // It is OK to call this function with a parameter of -1 to check if the | 
|  | // function is implemented for the platform. | 
|  | int32_t GetExplicitSystemLimit(const int resource); | 
|  |  | 
|  | // Raises soft system resource limits to hard limits in an attempt to let | 
|  | // large builds work. This is a best-effort operation and may or may not be | 
|  | // implemented for a given platform. Returns true if all limits were properly | 
|  | // raised; false otherwise. | 
|  | bool UnlimitResources(); | 
|  |  | 
|  | // Raises the soft coredump limit to the hard limit in an attempt to let | 
|  | // coredumps work. This is a best-effort operation and may or may not be | 
|  | // implemented for a given platform. Returns true if all limits were properly | 
|  | // raised; false otherwise. | 
|  | bool UnlimitCoredumps(); | 
|  |  | 
|  | #if defined(_WIN32) || defined(__CYGWIN__) | 
|  | std::string DetectBashAndExportBazelSh(); | 
|  | #endif  // if defined(_WIN32) || defined(__CYGWIN__) | 
|  |  | 
|  | // This function has no effect on Unix platforms. | 
|  | // On Windows, this function looks into PATH to find python.exe, if python | 
|  | // binary is found then add | 
|  | // --default_override=0:build=--python_path=<python/path> into options. | 
|  | void EnsurePythonPathOption(std::vector<std::string>* options); | 
|  |  | 
|  | }  // namespace blaze | 
|  |  | 
|  | #endif  // BAZEL_SRC_MAIN_CPP_BLAZE_UTIL_PLATFORM_H_ |