Browse Source

compile_commands

feature/dependency-graph
Martin Dørum 3 years ago
parent
commit
33bef52e6d
7 changed files with 132 additions and 44 deletions
  1. 11
    0
      src/SourceFile.cc
  2. 1
    0
      src/SourceFile.h
  3. 58
    18
      src/main.cc
  4. 23
    4
      src/sys.cc
  5. 2
    1
      src/sys.h
  6. 30
    21
      src/toolchain.cc
  7. 7
    0
      src/toolchain.h

+ 11
- 0
src/SourceFile.cc View File

@@ -177,3 +177,14 @@ void SourceFile::compile(const std::string &outDir) const {
compileFlags_.clear();
hasCompileFlags_ = false;
}

std::vector<std::string> SourceFile::compileCommand(const std::string &outDir) const {
auto res = toolchain::getCompileCommand(compileFlags(), type_, dir_, name_, outDir);

// Nothing will need compile flags after this, so no reason to
// keep it around in memory
compileFlags_.clear();
hasCompileFlags_ = false;

return res;
}

+ 1
- 0
src/SourceFile.h View File

@@ -35,6 +35,7 @@ public:
std::vector<std::string> dependencies() const;
bool needsRecompile(const std::string &outDir) const;
void compile(const std::string &outDir) const;
std::vector<std::string> compileCommand(const std::string &outDir) const;

private:
std::string dir_;

+ 58
- 18
src/main.cc View File

@@ -159,6 +159,37 @@ static bool compileAndLink(
return false;
}

static void printCompileCommands(
const std::vector<SourceFile> &sources, const std::string &outDir,
std::ostream &os) {
std::string cwd = sys::cwd();

os << "[\n\t";

bool first = true;
for (auto &source: sources) {
std::string command;
for (auto arg: source.compileCommand(outDir)) {
command += arg + ' ';
}
command.pop_back();

if (!first) {
os << ", ";
}

os << "{\n"
<< "\t\t\"directory\":\"" << cwd << "\"\n"
<< "\t\t\"command\":\"" << command << "\"\n"
<< "\t\t\"file\":\"" << source.path() << "\"\n"
<< "\t}";

first = false;
}

os << "\n]\n";
}

static std::string findTargetName(
const BBParser::Variables &vars,
const std::vector<SourceFile> &sources) {
@@ -186,39 +217,40 @@ int main(int argc, char **argv) {
std::string target = "";

enum class Action {
BUILD, PRINT_STATE,
BUILD, PRINT_COMPILE_COMMANDS, PRINT_STATE,
};
Action action = Action::BUILD;

const char *shortopts = "hvo:j:C:t:p";
const char *shortopts = "hvo:j:C:cp";
const struct option opts[] = {
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "output", required_argument, NULL, 'o' },
{ "jobs", required_argument, NULL, 'j' },
{ "directory", required_argument, NULL, 'C' },
{ "target", required_argument, NULL, 't' },
{ "print-state", no_argument, NULL, 'p' },
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "output", required_argument, NULL, 'o' },
{ "jobs", required_argument, NULL, 'j' },
{ "directory", required_argument, NULL, 'C' },
{ "target", required_argument, NULL, 't' },
{ "compile-commands", no_argument, NULL, 'c' },
{ "print-state", no_argument, NULL, 'p' },
{},
};

const char usage[] =
"Usage: bbbuild [options...] [sources]\n"
"\n"
" -h, --help "
" -h, --help "
"Show this help text.\n"
" -v, --verbose "
"Show every command as it's executing."
" -o, --output <dir> "
" -v, --verbose "
"Show every command as it's executing.\n"
" -o, --output <dir> "
"Set output directory. Default: bbbuild\n"
" -j, --jobs <count> "
" -j, --jobs <count> "
"Set the number of jobs run simultaneously. "
"Default: the number of cores in the machine.\n"
" -C, --directory <dir> "
" -C, --directory <dir> "
"Change directory before doing anything else.\n"
" -t, --target <name> "
"Set the name of the executable.\n"
" -p, --print-state "
" -c, --compile-commands "
"Write compile commands to stdout.\n"
" -p, --print-state "
"Print the state instead of building.\n";

// Parse options from argv
@@ -255,6 +287,10 @@ int main(int argc, char **argv) {
workDir = optarg;
break;

case 'c':
action = Action::PRINT_COMPILE_COMMANDS;
break;

case 'p':
action = Action::PRINT_STATE;
break;
@@ -316,6 +352,10 @@ int main(int argc, char **argv) {
}
break;

case Action::PRINT_COMPILE_COMMANDS:
printCompileCommands(sources, outDir, std::cout);
break;

case Action::PRINT_STATE:
printState(sources);
break;

+ 23
- 4
src/sys.cc View File

@@ -9,6 +9,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <stdexcept>
#include <system_error>

#include "logger.h"
#include "globals.h"
@@ -44,14 +45,14 @@ bool fileExists(const std::string &path) {

void mkdirp(const std::string &path) {
// TODO: Implement this in C++ instead
std::vector<const char *> argv;
std::vector<std::string> argv;
argv.push_back("mkdir");
argv.push_back("-p");
argv.push_back(path.c_str());
argv.push_back(path);
execute(argv, nullptr, global::verbose >= 2);
}

void execute(std::vector<const char *> &args, std::string *output, bool print) {
void execute(const std::vector<std::string> &args, std::string *output, bool print) {
if (print) {
std::string str;
for (size_t i = 0; i < args.size(); ++i) {
@@ -72,7 +73,7 @@ void execute(std::vector<const char *> &args, std::string *output, bool print) {
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(args[i].c_str());
}

argv.push_back(nullptr);
@@ -165,4 +166,22 @@ void chdir(const std::string &path) {
}
}

std::string cwd() {
std::vector<char> buf;
buf.reserve(128);
while (1) {
char *res = getcwd(buf.data(), buf.capacity());
if (res == NULL) {
if (errno == ERANGE) {
buf.reserve(buf.capacity() * 2);
} else {
throw std::system_error(EFAULT, std::generic_category());
}
} else {
std::string str(buf.data());
return str;
}
}
}

}

+ 2
- 1
src/sys.h View File

@@ -14,8 +14,9 @@ struct FileInfo {
FileInfo fileInfo(const std::string &path);
bool fileExists(const std::string &path);
void mkdirp(const std::string &path);
void execute(std::vector<const char *> &args, std::string *output, bool print);
void execute(const std::vector<std::string> &args, std::string *output, bool print);
void readDir(const std::string &path, std::vector<std::string> &files);
void chdir(const std::string &path);
std::string cwd();

}

+ 30
- 21
src/toolchain.cc View File

@@ -129,11 +129,11 @@ std::string targetFilePath(
}

void getPkgConfigFlags(const std::vector<std::string> &pkgs, std::vector<std::string> &flags) {
std::vector<const char *> argv;
std::vector<std::string> argv;
argv.push_back(getPkgConfig());
argv.push_back("--cflags");
for (auto &pkg: pkgs) {
argv.push_back(pkg.c_str());
argv.push_back(pkg);
}

// Execute $(PKG_CONFIG) --cflags $(PKGS)
@@ -143,11 +143,11 @@ void getPkgConfigFlags(const std::vector<std::string> &pkgs, std::vector<std::st
}

void getPkgConfigLDLibs(const std::vector<std::string> &pkgs, std::vector<std::string> &flags) {
std::vector<const char *> argv;
std::vector<std::string> argv;
argv.push_back(getPkgConfig());
argv.push_back("--libs");
for (auto &pkg: pkgs) {
argv.push_back(pkg.c_str());
argv.push_back(pkg);
}

// Execute $(PKG_CONFIG) --libs $(PKGS)
@@ -164,19 +164,19 @@ void getDependencies(
std::vector<std::string> &deps) {
std::string sourcePath = srcDir + "/" + name;

std::vector<const char *> argv;
std::vector<std::string> argv;

// $(compiler)
argv.push_back(getCompilerFor(type));

// $(flags)
for (auto &flag: flags) {
argv.push_back(flag.c_str());
argv.push_back(flag);
}

// -MM $<
argv.push_back("-MM");
argv.push_back(sourcePath.c_str());
argv.push_back(sourcePath);

// Execute $(compiler) $(flags) -MM $<
std::string output;
@@ -188,20 +188,16 @@ void getDependencies(
}
}

void compile(
std::vector<std::string> getCompileCommand(
const std::vector<std::string> &flags,
SourceFile::FileType type,
const std::string &srcDir,
const std::string &name,
const std::string &outDir) {
std::string sourcePath = srcDir + "/" + name;
std::string destDir = outDir + "/" + srcDir;
std::string objectPath = objectFilePath(srcDir, name, outDir);

// Ensure the output directory actually exists
sys::mkdirp(destDir);

std::vector<const char *> argv;
std::vector<std::string> argv;

// $(compiler)
argv.push_back(getCompilerFor(type));
@@ -213,11 +209,24 @@ void compile(

// -o $@ -c $<
argv.push_back("-o");
argv.push_back(objectPath.c_str());
argv.push_back(std::move(objectPath));
argv.push_back("-c");
argv.push_back(sourcePath.c_str());
argv.push_back(std::move(sourcePath));

return argv;
}

void compile(
const std::vector<std::string> &flags,
SourceFile::FileType type,
const std::string &srcDir,
const std::string &name,
const std::string &outDir) {
// Ensure the output directory actually exists
std::string destDir = outDir + "/" + srcDir;
sys::mkdirp(destDir);

// Execute $(compiler) $(flags) -o $@ -c $<
std::vector<std::string> argv = getCompileCommand(flags, type, srcDir, name, outDir);
sys::execute(argv, nullptr, global::verbose >= 1);
}

@@ -234,28 +243,28 @@ void link(
// TODO: Use ar to create STATIC_LIBRARY,
// use GCC with -shared to make SHARED_LIBRARY

std::vector<const char *> argv;
std::vector<std::string> argv;

// $(compiler)
argv.push_back(getCompilerFor(type));

// $(ldflags)
for (auto &flag: ldFlags) {
argv.push_back(flag.c_str());
argv.push_back(flag);
}

// -o $@
argv.push_back("-o");
argv.push_back(outPath.c_str());
argv.push_back(outPath);

// $(objs)
for (auto &obj: objs) {
argv.push_back(obj.c_str());
argv.push_back(obj);
}

// $(ldlibs)
for (auto &flag: ldLibs) {
argv.push_back(flag.c_str());
argv.push_back(flag);
}

// Execute $(compiler) $(ldflags) -o $@ $(objs) $(ldlibs)

+ 7
- 0
src/toolchain.h View File

@@ -32,6 +32,13 @@ void getDependencies(
const std::string &name,
std::vector<std::string> &deps);

std::vector<std::string> getCompileCommand(
const std::vector<std::string> &flags,
SourceFile::FileType type,
const std::string &srcDir,
const std::string &name,
const std::string &outDir);

void compile(
const std::vector<std::string> &flags,
SourceFile::FileType type,

Loading…
Cancel
Save