void AbstractInterpreter::anchor() {}
-#if defined(LLVM_ON_UNIX)
-const char EXESuffix[] = "";
-#elif defined(_WIN32)
-const char EXESuffix[] = "exe";
-#endif
-
-/// Prepend the path to the program being executed
-/// to \p ExeName, given the value of argv[0] and the address of main()
-/// itself. This allows us to find another LLVM tool if it is built in the same
-/// directory. An empty string is returned on error; note that this function
-/// just mainpulates the path and doesn't check for executability.
-/// Find a named executable.
-static std::string PrependMainExecutablePath(const std::string &ExeName,
+ErrorOr<std::string> llvm::FindProgramByName(const std::string &ExeName,
const char *Argv0,
void *MainAddr) {
// Check the directory that the calling program is in. We can do
// is a relative path to the executable itself.
std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
StringRef Result = sys::path::parent_path(Main);
+ if (ErrorOr<std::string> Path = sys::findProgramByName(ExeName, Result))
+ return *Path;
- if (!Result.empty()) {
- SmallString<128> Storage = Result;
- sys::path::append(Storage, ExeName);
- sys::path::replace_extension(Storage, EXESuffix);
- return Storage.str();
- }
-
- return Result.str();
+ // Check the user PATH.
+ return sys::findProgramByName(ExeName);
}
// LLI create method - Try to find the LLI executable
AbstractInterpreter *
AbstractInterpreter::createLLI(const char *Argv0, std::string &Message,
const std::vector<std::string> *ToolArgs) {
- std::string LLIPath =
- PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI);
- if (!LLIPath.empty()) {
- Message = "Found lli: " + LLIPath + "\n";
- return new LLI(LLIPath, ToolArgs);
+ if (ErrorOr<std::string> LLIPath =
+ FindProgramByName("lli", Argv0, (void *)(intptr_t)&createLLI)) {
+ Message = "Found lli: " + *LLIPath + "\n";
+ return new LLI(*LLIPath, ToolArgs);
+ } else {
+ Message = LLIPath.getError().message() + "\n";
+ return nullptr;
}
-
- Message = "Cannot find `lli' in executable directory!\n";
- return nullptr;
}
//===---------------------------------------------------------------------===//
// '\ ' -> ' '
// 'exa\mple' -> 'example'
//
-static void lexCommand(std::string &Message, const std::string &CommandLine,
- std::string &CmdPath, std::vector<std::string> &Args) {
+static void lexCommand(const char *Argv0, std::string &Message,
+ const std::string &CommandLine, std::string &CmdPath,
+ std::vector<std::string> &Args) {
std::string Token;
std::string Command;
Token.push_back(CommandLine[Pos]);
}
- auto Path = sys::findProgramByName(Command);
+ auto Path = FindProgramByName(Command, Argv0, (void *)(intptr_t)&lexCommand);
if (!Path) {
Message = std::string("Cannot find '") + Command +
"' in PATH: " + Path.getError().message() + "\n";
// Custom execution environment create method, takes the execution command
// as arguments
AbstractInterpreter *AbstractInterpreter::createCustomCompiler(
- std::string &Message, const std::string &CompileCommandLine) {
+ const char *Argv0, std::string &Message,
+ const std::string &CompileCommandLine) {
std::string CmdPath;
std::vector<std::string> Args;
- lexCommand(Message, CompileCommandLine, CmdPath, Args);
+ lexCommand(Argv0, Message, CompileCommandLine, CmdPath, Args);
if (CmdPath.empty())
return nullptr;
// Custom execution environment create method, takes the execution command
// as arguments
AbstractInterpreter *
-AbstractInterpreter::createCustomExecutor(std::string &Message,
+AbstractInterpreter::createCustomExecutor(const char *Argv0,
+ std::string &Message,
const std::string &ExecCommandLine) {
std::string CmdPath;
std::vector<std::string> Args;
- lexCommand(Message, ExecCommandLine, CmdPath, Args);
+ lexCommand(Argv0, Message, ExecCommandLine, CmdPath, Args);
if (CmdPath.empty())
return nullptr;
const std::vector<std::string> *Args,
const std::vector<std::string> *CCArgs,
bool UseIntegratedAssembler) {
- std::string LLCPath =
- PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC);
- if (LLCPath.empty()) {
- Message = "Cannot find `llc' in executable directory!\n";
+ ErrorOr<std::string> LLCPath =
+ FindProgramByName("llc", Argv0, (void *)(intptr_t)&createLLC);
+ if (!LLCPath) {
+ Message = LLCPath.getError().message() + "\n";
return nullptr;
}
- CC *cc = CC::create(Message, CCBinary, CCArgs);
+ CC *cc = CC::create(Argv0, Message, CCBinary, CCArgs);
if (!cc) {
errs() << Message << "\n";
exit(1);
}
- Message = "Found llc: " + LLCPath + "\n";
- return new LLC(LLCPath, cc, Args, UseIntegratedAssembler);
+ Message = "Found llc: " + *LLCPath + "\n";
+ return new LLC(*LLCPath, cc, Args, UseIntegratedAssembler);
}
//===---------------------------------------------------------------------===//
AbstractInterpreter *
AbstractInterpreter::createJIT(const char *Argv0, std::string &Message,
const std::vector<std::string> *Args) {
- std::string LLIPath =
- PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT);
- if (!LLIPath.empty()) {
- Message = "Found lli: " + LLIPath + "\n";
- return new JIT(LLIPath, Args);
+ if (ErrorOr<std::string> LLIPath =
+ FindProgramByName("lli", Argv0, (void *)(intptr_t)&createJIT)) {
+ Message = "Found lli: " + *LLIPath + "\n";
+ return new JIT(*LLIPath, Args);
+ } else {
+ Message = LLIPath.getError().message() + "\n";
+ return nullptr;
}
-
- Message = "Cannot find `lli' in executable directory!\n";
- return nullptr;
}
//===---------------------------------------------------------------------===//
/// create - Try to find the CC executable
///
-CC *CC::create(std::string &Message, const std::string &CCBinary,
+CC *CC::create(const char *Argv0, std::string &Message,
+ const std::string &CCBinary,
const std::vector<std::string> *Args) {
- auto CCPath = sys::findProgramByName(CCBinary);
+ auto CCPath = FindProgramByName(CCBinary, Argv0, (void *)(intptr_t)&create);
if (!CCPath) {
Message = "Cannot find `" + CCBinary + "' in PATH: " +
CCPath.getError().message() + "\n";
public:
enum FileType { AsmFile, ObjectFile, CFile };
- static CC *create(std::string &Message, const std::string &CCBinary,
+ static CC *create(const char *Argv0, std::string &Message,
+ const std::string &CCBinary,
const std::vector<std::string> *Args);
/// ExecuteProgram - Execute the program specified by "ProgramFile" (which is
const std::vector<std::string> *Args = nullptr);
static AbstractInterpreter *
- createCustomCompiler(std::string &Message,
+ createCustomCompiler(const char *Argv0, std::string &Message,
const std::string &CompileCommandLine);
static AbstractInterpreter *
- createCustomExecutor(std::string &Message,
+ createCustomExecutor(const char *Argv0, std::string &Message,
const std::string &ExecCommandLine);
virtual ~AbstractInterpreter() {}
unsigned MemoryLimit = 0) override;
};
+/// Find the first executable file \ExeName, either in the user's PATH or,
+/// failing that, in the same directory as argv[0]. This allows us to find
+/// another LLVM tool if it is built in the same directory. If no executable is
+/// found, an error is returned.
+ErrorOr<std::string> FindProgramByName(const std::string &ExeName,
+ const char *Argv0, void *MainAddr);
+
} // End llvm namespace
#endif