Skip to content

Commit

Permalink
On OpenBSD, search the PATH to find the Bazel executable.
Browse files Browse the repository at this point in the history
Searching the `PATH` is the only feasible way to find the executable on OpenBSD when `argv[0]` is not an absolute path or a relative path. This change resolves a TODO.

This change moves a preexisting `Which` function for searching the `PATH` out of `blaze_util_linux.cc` and into `blaze_util_posix.cc`, so that the Linux code and the BSD code can share this function.

In my testing on OpenBSD 6.6-current, a bootstrap build of Bazel succeeds and the resulting `bazel` binary can find itself on the `PATH`. (One caveat: For the bootstrap build to succeed, I had to manually apply the unrelated change in #10639, since it's not merged yet.)

This change is part of the OpenBSD port in #10250.

@jmmv FYI.

Closes #10691.

PiperOrigin-RevId: 293183553
  • Loading branch information
aldersondrive authored and copybara-github committed Feb 4, 2020
1 parent 43337bb commit dd41ff0
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 27 deletions.
10 changes: 6 additions & 4 deletions src/main/cpp/blaze_util_bsd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,15 @@ string GetSelfPath(const char* argv0) {
return blaze_util::GetCwd() + "/" + argv0str;
}

// TODO(aldersondrive): Try to find the executable by inspecting the PATH.
// Otherwise, try to find the executable by searching the PATH.
const std::string from_search_path = Which(argv0);
if (!from_search_path.empty()) {
return from_search_path;
}

// None of the above worked. Give up.
BAZEL_DIE(blaze_exit_code::BAD_ARGV)
<< "Unable to determine the location of this Bazel executable. "
"Currently, argv[0] must be an absolute or relative path to the "
"executable.";
<< "Unable to determine the location of this Bazel executable.";
return ""; // Never executed. Needed so compiler does not complain.
#else
# error This BSD is not supported
Expand Down
23 changes: 0 additions & 23 deletions src/main/cpp/blaze_util_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,29 +132,6 @@ bool IsSharedLibrary(const string &filename) {
return blaze_util::ends_with(filename, ".so");
}

static string Which(const string &executable) {
string path(GetPathEnv("PATH"));
if (path.empty()) {
return "";
}

vector<string> pieces = blaze_util::Split(path, ':');
for (auto piece : pieces) {
if (piece.empty()) {
piece = ".";
}

struct stat file_stat;
string candidate = blaze_util::JoinPath(piece, executable);
if (access(candidate.c_str(), X_OK) == 0 &&
stat(candidate.c_str(), &file_stat) == 0 &&
S_ISREG(file_stat.st_mode)) {
return candidate;
}
}
return "";
}

string GetSystemJavabase() {
// if JAVA_HOME is defined, then use it as default.
string javahome = GetPathEnv("JAVA_HOME");
Expand Down
4 changes: 4 additions & 0 deletions src/main/cpp/blaze_util_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ 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);
Expand Down
24 changes: 24 additions & 0 deletions src/main/cpp/blaze_util_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "src/main/cpp/util/numbers.h"
#include "src/main/cpp/util/path.h"
#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/util/strings.h"

namespace blaze {

Expand Down Expand Up @@ -217,6 +218,29 @@ string GetHomeDir() { return GetPathEnv("HOME"); }

string GetJavaBinaryUnderJavabase() { return "bin/java"; }

string Which(const string& executable) {
const string path = GetPathEnv("PATH");
if (path.empty()) {
return "";
}

const vector<string> pieces = blaze_util::Split(path, ':');
for (string piece : pieces) {
if (piece.empty()) {
piece = ".";
}

struct stat file_stat;
const string candidate = blaze_util::JoinPath(piece, executable);
if (access(candidate.c_str(), X_OK) == 0 &&
stat(candidate.c_str(), &file_stat) == 0 &&
S_ISREG(file_stat.st_mode)) {
return candidate;
}
}
return "";
}

// Converter of C++ data structures to a C-style array of strings.
//
// The primary consumer of this class is the execv family of functions
Expand Down

0 comments on commit dd41ff0

Please sign in to comment.