|
|
@@ -2,21 +2,14 @@ |
|
|
|
|
|
|
|
#include <stdexcept> |
|
|
|
#include <stdio.h> |
|
|
|
#include <sys/types.h> |
|
|
|
#include <sys/wait.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <string.h> |
|
|
|
#include <errno.h> |
|
|
|
|
|
|
|
#include "globals.h" |
|
|
|
#include "sys.h" |
|
|
|
|
|
|
|
namespace toolchain { |
|
|
|
|
|
|
|
// TODO: Decide whether it would be better to use $SHELL |
|
|
|
static const char *getShell() { |
|
|
|
return "/bin/sh"; |
|
|
|
} |
|
|
|
|
|
|
|
static const char *getPkgConfig() { |
|
|
|
static const char *pkgConfig = nullptr; |
|
|
|
if (pkgConfig != nullptr) { |
|
|
@@ -74,93 +67,6 @@ static const char *getCompilerFor(SourceFile::FileType type) { |
|
|
|
abort(); |
|
|
|
} |
|
|
|
|
|
|
|
static void execute(std::vector<const char *> &args, std::string *output) { |
|
|
|
if (global::verbose) { |
|
|
|
for (size_t i = 0; i < args.size(); ++i) { |
|
|
|
if (i == 0) { |
|
|
|
fprintf(stderr, "%s", args[i]); |
|
|
|
} else { |
|
|
|
fprintf(stderr, " %s", args[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
} |
|
|
|
|
|
|
|
// argv[0] should be interpreted as a shell command, because being able to run |
|
|
|
// CC='gcc --sysroot=/blah' is used by some systems. |
|
|
|
std::string command = std::string(args[0]) + " \"$@\""; |
|
|
|
std::vector<const char *> argv; |
|
|
|
argv.push_back(getShell()); |
|
|
|
argv.push_back("-c"); |
|
|
|
argv.push_back(command.c_str()); |
|
|
|
argv.push_back("--"); |
|
|
|
for (size_t i = 1; i < args.size(); ++i) { |
|
|
|
argv.push_back(args[i]); |
|
|
|
} |
|
|
|
|
|
|
|
argv.push_back(nullptr); |
|
|
|
|
|
|
|
int fds[2]; |
|
|
|
if (pipe(fds) < 0) { |
|
|
|
throw std::runtime_error(std::string("fork: ") + strerror(errno)); |
|
|
|
} |
|
|
|
|
|
|
|
pid_t child = fork(); |
|
|
|
if (child == 0) { |
|
|
|
close(fds[0]); |
|
|
|
dup2(fds[1], 1); |
|
|
|
|
|
|
|
// So, from what I've read, execvp should never modify its argv; so this should be fine? |
|
|
|
if (execvp(argv[0], (char *const *)argv.data()) < 0) { |
|
|
|
perror(argv[0]); |
|
|
|
abort(); |
|
|
|
} |
|
|
|
} else if (child < 0) { |
|
|
|
throw std::runtime_error(std::string("fork: ") + strerror(errno)); |
|
|
|
} |
|
|
|
|
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
if (output == nullptr) { |
|
|
|
close(fds[0]); |
|
|
|
} else { |
|
|
|
char buf[1025]; |
|
|
|
while (true) { |
|
|
|
ssize_t num = read(fds[0], buf, sizeof(buf) - 1); |
|
|
|
if (num < 0 && errno != EAGAIN) { |
|
|
|
close(fds[0]); |
|
|
|
throw std::runtime_error(std::string("read: ") + strerror(errno)); |
|
|
|
} else if (num < 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (num == 0) { |
|
|
|
close(fds[1]); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
buf[num] = '\0'; |
|
|
|
*output += buf; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int wstatus; |
|
|
|
waitpid(child, &wstatus, 0); |
|
|
|
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) { |
|
|
|
throw std::runtime_error(std::string(args[0]) + |
|
|
|
" exited with code " + std::to_string(WEXITSTATUS(wstatus))); |
|
|
|
} |
|
|
|
|
|
|
|
if (WTERMSIG(wstatus)) { |
|
|
|
throw std::runtime_error(std::string(args[0]) + |
|
|
|
" terminated due to " + strsignal(WTERMSIG(wstatus))); |
|
|
|
} |
|
|
|
|
|
|
|
if (output != nullptr && output->back() == '\n') { |
|
|
|
output->pop_back(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static bool isWhitespace(char ch) { |
|
|
|
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; |
|
|
|
} |
|
|
@@ -206,7 +112,7 @@ void pkgFlags(const std::vector<std::string> &pkgs, std::vector<std::string> &fl |
|
|
|
} |
|
|
|
|
|
|
|
std::string output; |
|
|
|
execute(argv, &output); |
|
|
|
sys::execute(argv, &output); |
|
|
|
parseWhitespaceSeparated(output, flags); |
|
|
|
} |
|
|
|
|
|
|
@@ -219,7 +125,7 @@ void pkgLDLibs(const std::vector<std::string> &pkgs, std::vector<std::string> &f |
|
|
|
} |
|
|
|
|
|
|
|
std::string output; |
|
|
|
execute(argv, &output); |
|
|
|
sys::execute(argv, &output); |
|
|
|
parseWhitespaceSeparated(output, flags); |
|
|
|
} |
|
|
|
|
|
|
@@ -241,7 +147,7 @@ void getDependencies( |
|
|
|
argv.push_back("-c"); |
|
|
|
argv.push_back(sourcePath.c_str()); |
|
|
|
std::string output; |
|
|
|
execute(argv, &output); |
|
|
|
sys::execute(argv, &output); |
|
|
|
|
|
|
|
size_t idx = output.find(':'); |
|
|
|
if (idx != std::string::npos) { |
|
|
@@ -259,14 +165,9 @@ void compile( |
|
|
|
std::string destDir = outDir + "/" + srcDir; |
|
|
|
std::string destPath = destDir + "/" + name + ".o"; |
|
|
|
|
|
|
|
// TODO: Change this to a C++ mkdirp function |
|
|
|
std::vector<const char *> argv; |
|
|
|
argv.push_back("mkdir"); |
|
|
|
argv.push_back("-p"); |
|
|
|
argv.push_back(destDir.c_str()); |
|
|
|
execute(argv, nullptr); |
|
|
|
sys::mkdirp(outDir); |
|
|
|
|
|
|
|
argv.clear(); |
|
|
|
std::vector<const char *> argv; |
|
|
|
argv.push_back(getCompilerFor(type)); |
|
|
|
for (auto &flag: flags) { |
|
|
|
argv.push_back(flag.c_str()); |
|
|
@@ -276,7 +177,7 @@ void compile( |
|
|
|
argv.push_back(destPath.c_str()); |
|
|
|
argv.push_back("-c"); |
|
|
|
argv.push_back(sourcePath.c_str()); |
|
|
|
execute(argv, nullptr); |
|
|
|
sys::execute(argv, nullptr); |
|
|
|
} |
|
|
|
|
|
|
|
} |