Browse Source

rebrand to boxberry

rebrand
Martin Dørum 3 years ago
parent
commit
94438aa1b7
14 changed files with 135 additions and 135 deletions
  1. 3
    3
      Makefile
  2. 11
    11
      README.md
  3. 1
    1
      build.bx
  4. 22
    22
      src/BXParser.cc
  5. 14
    14
      src/BXParser.h
  6. 19
    19
      src/CompileStep.cc
  7. 5
    5
      src/CompileStep.h
  8. 12
    12
      src/LinkStep.cc
  9. 1
    1
      src/LinkStep.h
  10. 15
    15
      src/build.cc
  11. 2
    2
      src/build.h
  12. 23
    23
      src/main.cc
  13. 3
    3
      src/toolchain.cc
  14. 4
    4
      src/toolchain.h

+ 3
- 3
Makefile View File

SRCS = \ SRCS = \
src/BBParser.cc src/build.cc src/compdb.cc src/CompileStep.cc src/DepNode.cc \
src/BXParser.cc src/build.cc src/compdb.cc src/CompileStep.cc src/DepNode.cc \
src/globals.cc src/LinkStep.cc src/logger.cc src/parallel.cc src/sys.cc \ src/globals.cc src/LinkStep.cc src/logger.cc src/parallel.cc src/sys.cc \
src/toolchain.cc src/main.cc src/toolchain.cc src/main.cc
HDRS = \ HDRS = \
src/BBParser.h src/build.h src/compdb.h src/CompileStep.h src/DepNode.h \
src/BXParser.h src/build.h src/compdb.h src/CompileStep.h src/DepNode.h \
src/globals.h src/LinkStep.h src/logger.h src/parallel.h src/sys.h \ src/globals.h src/LinkStep.h src/logger.h src/parallel.h src/sys.h \
src/toolchain.h src/toolchain.h
BUILD = build BUILD = build
@mkdir -p $(@D) @mkdir -p $(@D)
$(CXX) $(CFLAGS) -c $< -o $@ $(CXX) $(CFLAGS) -c $< -o $@


$(BUILD)/bbbuild: $(OBJS)
$(BUILD)/box: $(OBJS)
@mkdir -p $(@D) @mkdir -p $(@D)
$(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)



+ 11
- 11
README.md View File

# BBBuild: A build system which scales down
# Boxberry: A build system which scales down


BBBuild is a build system which aims to be usable for tiny projects,
Boxberry is a build system which aims to be usable for tiny projects,
all the way down to single source files. all the way down to single source files.


Not all projects need a big Makefile or a huge CMakeLists.txt. Not all projects need a big Makefile or a huge CMakeLists.txt.
However, almost all projects grow to the size where they need some library, However, almost all projects grow to the size where they need some library,
or some compiler flag, maybe an optimization option. or some compiler flag, maybe an optimization option.
BBBuild aims to make the path from running `cc file.c` to running
Boxberry aims to make the path from running `cc file.c` to running
`cc -lpthread file.c` to `cc file.c $(pkg-config --libs --cflags libfoo) -lpthread` `cc -lpthread file.c` to `cc file.c $(pkg-config --libs --cflags libfoo) -lpthread`
as easy as possible. as easy as possible.


* Source files are automatically discovered (by default). * Source files are automatically discovered (by default).
* Dependencies can be specified in the source file: `//#bb pkgs := libfoo`
* Dependencies can be specified in the source file: `//#bx pkgs := libfoo`
* Linker and compiler flags can be specified in the source file: * Linker and compiler flags can be specified in the source file:
`//#bb ldlibs := -lpthread ldflags := -fsanitize=address cflags := -fsanitize=address`
`//#bx ldlibs := -lpthread ldflags := -fsanitize=address cflags := -fsanitize=address`
* A source file is automatically recompiled if it has changed, or if any * A source file is automatically recompiled if it has changed, or if any
included header files have changed. included header files have changed.
* If your project grows, you can put global configs in a `build.bb` file.
Each directory can have a build.bb file, and each directory inherits the
* If your project grows, you can put global configs in a `build.bx` file.
Each directory can have a build.bx file, and each directory inherits the
configuration of its parent. configuration of its parent.
* Files can be specified instead of discovered automatically by setting the * Files can be specified instead of discovered automatically by setting the
`files` variable in a `build.bb` file.
`files` variable in a `build.bx` file.


## Building ## Building


This project can be built by running either `make` or `bbbuild`.
This project can be built by running either `make` or `box`.
The only dependency is `pthreads`. The only dependency is `pthreads`.


## TODO ## TODO


* ~~Add `--print-compile-commands`~~ * ~~Add `--print-compile-commands`~~
* ~~Consider changing the config file format name from BBB to BB~~ * ~~Consider changing the config file format name from BBB to BB~~
* Support different build configurations (requires conditionals in the BBB parser)
* Support different build configurations (requires conditionals in the parser)
* Re-work the command-line interface * Re-work the command-line interface
* ~~Save build configuration in the output dir~~ * ~~Save build configuration in the output dir~~
* ~~Support one "main" build.bb file which specifies things like the target name~~
* ~~Support one "main" build.bx file which specifies things like the target name~~
* Support creating shared/static libraries too, not just binaries * Support creating shared/static libraries too, not just binaries
* Implement recursive mkdir in C++ instead of shelling out to mkdir * Implement recursive mkdir in C++ instead of shelling out to mkdir
* Support subprojects * Support subprojects

build.bb → build.bx View File

target := bbbuild
target := box
files := src files := src
warnings := all extra no-unused-parameter warnings := all extra no-unused-parameter
std := c++14 std := c++14

src/BBParser.cc → src/BXParser.cc View File

#include "BBParser.h"
#include "BXParser.h"


#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>


int BBParser::get() {
int BXParser::get() {
int ch = stream_.get(); int ch = stream_.get();
if (ch == '\n') { if (ch == '\n') {
line_ += 1; line_ += 1;
return ch; return ch;
} }


BBParser::Operator BBParser::readOperator() {
BXParser::Operator BXParser::readOperator() {
int ch2 = peek2(); int ch2 = peek2();
if (peek() == ':' && ch2 == '=') { if (peek() == ':' && ch2 == '=') {
skip(); // ':' skip(); // ':'
return Operator::NONE; return Operator::NONE;
} }


void BBParser::skip(char expected) {
void BXParser::skip(char expected) {
int ch = get(); int ch = get();
if (ch == EOF) { if (ch == EOF) {
error(std::string("Expected '") + expected + "', got EOF"); error(std::string("Expected '") + expected + "', got EOF");
} }
} }


[[noreturn]] void BBParser::error(std::string msg) {
throw BBParseError(std::to_string(line_) + ":" + std::to_string(ch_) + ": " + msg);
[[noreturn]] void BXParser::error(std::string msg) {
throw BXParseError(std::to_string(line_) + ":" + std::to_string(ch_) + ": " + msg);
} }


static bool isWhitespace(int ch) { static bool isWhitespace(int ch) {
return false; return false;
} }


void BBParser::skipWhitespace() {
void BXParser::skipWhitespace() {
if (flags_ & FLAG_ONE_LINE) { if (flags_ & FLAG_ONE_LINE) {
int ch; int ch;
while (isWhitespace(ch = peek()) && ch != '\r' && ch != '\n') while (isWhitespace(ch = peek()) && ch != '\r' && ch != '\n')
} }
} }


char BBParser::parseEscape() {
char BXParser::parseEscape() {
skip(); // '\' skip(); // '\'
int ch; int ch;
switch (ch = get()) { switch (ch = get()) {
} }


static void appendVariableToString( static void appendVariableToString(
const BBVariables &vars, std::string &name,
const BXVariables &vars, std::string &name,
std::string &value) { std::string &value) {
if (name.size() == 0) if (name.size() == 0)
return; return;
} }


static void appendVariableToArray( static void appendVariableToArray(
const BBVariables &vars, const std::string &name,
const BXVariables &vars, const std::string &name,
std::vector<std::string> &values) { std::vector<std::string> &values) {
if (name.size() == 0) if (name.size() == 0)
return; return;
} }
} }


void BBParser::parseExpansion(const BBVariables &vars, std::vector<std::string> &values) {
void BXParser::parseExpansion(const BXVariables &vars, std::vector<std::string> &values) {
skip(); // '$' skip(); // '$'


std::string str; std::string str;
} }
} }


void BBParser::parseQuotedExpansion(const BBVariables &vars, std::string &content) {
void BXParser::parseQuotedExpansion(const BXVariables &vars, std::string &content) {
skip(); // '$' skip(); // '$'


std::string str; std::string str;
} }
} }


void BBParser::parseQuotedString(const BBVariables &vars, std::string &content) {
void BXParser::parseQuotedString(const BXVariables &vars, std::string &content) {
skip(); // '"' skip(); // '"'


int ch; int ch;
} }
} }


bool BBParser::parseString(const BBVariables &vars, std::string &content, int sep) {
bool BXParser::parseString(const BXVariables &vars, std::string &content, int sep) {
bool success = false; bool success = false;
int ch; int ch;
while (1) { while (1) {
} }
} }


bool BBParser::parseIdentifier(std::string &content) {
bool BXParser::parseIdentifier(std::string &content) {
int ch = peek(); int ch = peek();
if (!( if (!(
(ch >= 'a' && ch <= 'z') || (ch >= 'a' && ch <= 'z') ||
} }
} }


void BBParser::parse(BBVariables &vars) {
void BXParser::parse(BXVariables &vars) {
std::string key, value; std::string key, value;
std::vector<std::string> values; std::vector<std::string> values;


doAssignment(); doAssignment();
} }


void BBParser::parseList(const BBVariables &vars, std::vector<std::string> &values) {
void BXParser::parseList(const BXVariables &vars, std::vector<std::string> &values) {
while (true) { while (true) {
skipWhitespace(); skipWhitespace();
std::string value; std::string value;
} }
} }


void BBWriter::put(char ch) {
void BXWriter::put(char ch) {
ch_ += 1; ch_ += 1;
stream_ << ch; stream_ << ch;
} }


void BBWriter::put(const std::string &str) {
void BXWriter::put(const std::string &str) {
ch_ += str.size(); ch_ += str.size();
stream_ << str; stream_ << str;
} }


void BBWriter::newline() {
void BXWriter::newline() {
ch_ = 1; ch_ = 1;
line_ += 1; line_ += 1;
stream_ << '\n'; stream_ << '\n';
} }


void BBWriter::escape(const std::string &str) {
void BXWriter::escape(const std::string &str) {
put('"'); put('"');
for (char ch: str) { for (char ch: str) {
if (ch == '$' || ch == '"' || ch == '\\') { if (ch == '$' || ch == '"' || ch == '\\') {
put('"'); put('"');
} }


void BBWriter::write(const BBVariables &vars) {
void BXWriter::write(const BXVariables &vars) {
for (const auto &pair: vars) { for (const auto &pair: vars) {
put(pair.first); put(pair.first);
put(" :="); put(" :=");

src/BBParser.h → src/BXParser.h View File

#include <iostream> #include <iostream>
#include <exception> #include <exception>


struct BBParseError: std::exception {
BBParseError(std::string msg): message(msg) {}
struct BXParseError: std::exception {
BXParseError(std::string msg): message(msg) {}
std::string message; std::string message;


const char *what() const noexcept override { const char *what() const noexcept override {
} }
}; };


using BBVariables = std::unordered_map<std::string, std::vector<std::string>>;
using BXVariables = std::unordered_map<std::string, std::vector<std::string>>;


class BBParser {
class BXParser {
public: public:
static const int FLAG_NONE = 0; static const int FLAG_NONE = 0;
static const int FLAG_ONE_LINE = 1 << 0; static const int FLAG_ONE_LINE = 1 << 0;


BBParser(std::istream &stream, int flags, int line = 1, int ch = 1):
BXParser(std::istream &stream, int flags, int line = 1, int ch = 1):
flags_(flags), line_(line), ch_(ch), stream_(stream) {} flags_(flags), line_(line), ch_(ch), stream_(stream) {}


void parse(BBVariables &vars);
void parseList(const BBVariables &vars, std::vector<std::string> &values);
void parse(BXVariables &vars);
void parseList(const BXVariables &vars, std::vector<std::string> &values);


int peek() { return stream_.peek(); } int peek() { return stream_.peek(); }
int peek2() { stream_.get(); int ch = peek(); stream_.unget(); return ch; } int peek2() { stream_.get(); int ch = peek(); stream_.unget(); return ch; }
void skipWhitespace(); void skipWhitespace();


char parseEscape(); char parseEscape();
void parseExpansion(const BBVariables &vars, std::vector<std::string> &values);
void parseQuotedExpansion(const BBVariables &vars, std::string &content);
void parseQuotedString(const BBVariables &vars, std::string &content);
bool parseString(const BBVariables &vars, std::string &content, int sep = -1);
void parseExpansion(const BXVariables &vars, std::vector<std::string> &values);
void parseQuotedExpansion(const BXVariables &vars, std::string &content);
void parseQuotedString(const BXVariables &vars, std::string &content);
bool parseString(const BXVariables &vars, std::string &content, int sep = -1);
bool parseIdentifier(std::string &content); bool parseIdentifier(std::string &content);


int flags_; int flags_;
std::istream &stream_; std::istream &stream_;
}; };


class BBWriter {
class BXWriter {
public: public:
BBWriter(std::ostream &stream, int line = 1, int ch = 1):
BXWriter(std::ostream &stream, int line = 1, int ch = 1):
line_(line), ch_(ch), stream_(stream) {} line_(line), ch_(ch), stream_(stream) {}


void write(const BBVariables &vars);
void write(const BXVariables &vars);


private: private:
void put(char ch); void put(char ch);

+ 19
- 19
src/CompileStep.cc View File

#include "logger.h" #include "logger.h"
#include "globals.h" #include "globals.h"


static bool startsWith(BBParser &parser, const char *str) {
static bool startsWith(BXParser &parser, const char *str) {
for (size_t i = 0; str[i] != '\0'; ++i) { for (size_t i = 0; str[i] != '\0'; ++i) {
if (parser.peek() != str[i]) if (parser.peek() != str[i])
return false; return false;
return true; return true;
} }


std::string bbPath = this->bbPath(outDir);
if (!sys::fileExists(bbPath)) {
std::string confPath = this->confPath(outDir);
if (!sys::fileExists(confPath)) {
return true; return true;
} }


BBVariables cachedVariables;
BXVariables cachedVariables;
try { try {
std::ifstream f = sys::ifstream(bbPath);
BBParser parser(f, BBParser::FLAG_NONE);
std::ifstream f = sys::ifstream(confPath);
BXParser parser(f, BXParser::FLAG_NONE);
parser.parse(cachedVariables); parser.parse(cachedVariables);
} catch (BBParseError &err) {
logger::log(bbPath + ": " + err.what());
} catch (BXParseError &err) {
logger::log(confPath + ": " + err.what());
return true; return true;
} }


// the object file hasn't actually changed. // the object file hasn't actually changed.
auto depsIt = cachedVariables.find("deps"); auto depsIt = cachedVariables.find("deps");
if (depsIt == cachedVariables.end()) { if (depsIt == cachedVariables.end()) {
logger::log(bbPath + ": Missing 'deps' field");
logger::log(confPath + ": Missing 'deps' field");
return true; return true;
} }


// Maybe the build command has changed? // Maybe the build command has changed?
auto commandIt = cachedVariables.find("command"); auto commandIt = cachedVariables.find("command");
if (commandIt == cachedVariables.end()) { if (commandIt == cachedVariables.end()) {
logger::log(bbPath + ": Missing 'command' field");
logger::log(confPath + ": Missing 'command' field");
return true; return true;
} }


std::string dirPath = sys::dirname(objPath); std::string dirPath = sys::dirname(objPath);
std::vector<std::string> command = compileCommand(outDir); std::vector<std::string> command = compileCommand(outDir);


BBVariables newCachedVars = {
BXVariables newCachedVars = {
{ "deps", toolchain::getDependencies(flags(), type_, path_) }, { "deps", toolchain::getDependencies(flags(), type_, path_) },
{ "command", command}, { "command", command},
}; };


sys::mkdirp(dirPath); sys::mkdirp(dirPath);


std::ofstream f = sys::ofstream(bbPath(outDir));
BBWriter writer(f);
std::ofstream f = sys::ofstream(confPath(outDir));
BXWriter writer(f);
writer.write(newCachedVars); writer.write(newCachedVars);


sys::execute(command, nullptr, verboseCommand); sys::execute(command, nullptr, verboseCommand);
} }


std::vector<std::string> CompileStep::getPublicLDFlags(const std::string &outDir) { std::vector<std::string> CompileStep::getPublicLDFlags(const std::string &outDir) {
BBVariables &vars = variables();
BXVariables &vars = variables();
std::vector<std::string> flags; std::vector<std::string> flags;
toolchain::getLDFlags(vars, flags); toolchain::getLDFlags(vars, flags);
return flags; return flags;
} }


std::vector<std::string> CompileStep::getPublicLDLibs(const std::string &outDir) { std::vector<std::string> CompileStep::getPublicLDLibs(const std::string &outDir) {
BBVariables &vars = variables();
BXVariables &vars = variables();
std::vector<std::string> libs; std::vector<std::string> libs;
toolchain::getLDLibs(vars, libs); toolchain::getLDLibs(vars, libs);
return libs; return libs;
return std::vector<std::string>{ toolchain::objectFilePath(path_, outDir) }; return std::vector<std::string>{ toolchain::objectFilePath(path_, outDir) };
} }


BBVariables &CompileStep::variables() {
BXVariables &CompileStep::variables() {
if (hasVariables_) { if (hasVariables_) {
return variables_; return variables_;
} }


std::ifstream f = sys::ifstream(path_); std::ifstream f = sys::ifstream(path_);
BBParser parser(f, BBParser::FLAG_ONE_LINE);
BXParser parser(f, BXParser::FLAG_ONE_LINE);


while (f.good()) { while (f.good()) {
if (startsWith(parser, "//#bb")) {
if (startsWith(parser, "//#bx")) {
parser.parse(variables_); parser.parse(variables_);
} else { } else {
while (f.good() && parser.get() != '\n'); while (f.good() && parser.get() != '\n');
return flags_; return flags_;
} }


BBVariables &vars = variables();
BXVariables &vars = variables();


toolchain::getFlags(vars, type_, flags_); toolchain::getFlags(vars, type_, flags_);
hasFlags_ = true; hasFlags_ = true;

+ 5
- 5
src/CompileStep.h View File

#pragma once #pragma once


#include "DepNode.h" #include "DepNode.h"
#include "BBParser.h"
#include "BXParser.h"
#include "toolchain.h" #include "toolchain.h"


class CompileStep: public DepNode { class CompileStep: public DepNode {
public: public:
CompileStep(std::string path, toolchain::FileType type, BBVariables vars):
CompileStep(std::string path, toolchain::FileType type, BXVariables vars):
path_(std::move(path)), type_(type), variables_(std::move(vars)) {} path_(std::move(path)), type_(type), variables_(std::move(vars)) {}


private: private:
std::vector<std::string> getPublicObjects(const std::string &outDir) override; std::vector<std::string> getPublicObjects(const std::string &outDir) override;


bool hasVariables_ = false; bool hasVariables_ = false;
BBVariables variables_;
BBVariables &variables();
BXVariables variables_;
BXVariables &variables();


bool hasFlags_ = false; bool hasFlags_ = false;
std::vector<std::string> flags_; std::vector<std::string> flags_;
std::vector<std::string> compileCommand_; std::vector<std::string> compileCommand_;
std::vector<std::string> &compileCommand(const std::string &outDir); std::vector<std::string> &compileCommand(const std::string &outDir);


std::string bbPath(const std::string &outDir) { return outDir + '/' + path_ + ".bb"; }
std::string confPath(const std::string &outDir) { return outDir + '/' + path_ + ".bx"; }
}; };

+ 12
- 12
src/LinkStep.cc View File

#include "sys.h" #include "sys.h"
#include "logger.h" #include "logger.h"
#include "globals.h" #include "globals.h"
#include "BBParser.h"
#include "BXParser.h"


bool LinkStep::checkHasChanged(const std::string &outDir) { bool LinkStep::checkHasChanged(const std::string &outDir) {
std::string targetPath = toolchain::targetFilePath(type_, path_, outDir); std::string targetPath = toolchain::targetFilePath(type_, path_, outDir);
return true; return true;
} }


std::string bbPath = this->bbPath(outDir);
if (!sys::fileExists(bbPath)) {
std::string confPath = this->confPath(outDir);
if (!sys::fileExists(confPath)) {
return true; return true;
} }


BBVariables cachedVariables;
BXVariables cachedVariables;
try { try {
std::ifstream f = sys::ifstream(bbPath);
BBParser parser(f, BBParser::FLAG_NONE);
std::ifstream f = sys::ifstream(confPath);
BXParser parser(f, BXParser::FLAG_NONE);
parser.parse(cachedVariables); parser.parse(cachedVariables);
} catch (BBParseError &err) {
logger::log(bbPath + ": " + err.what());
} catch (BXParseError &err) {
logger::log(confPath + ": " + err.what());
return true; return true;
} }


auto commandIt = cachedVariables.find("command"); auto commandIt = cachedVariables.find("command");
if (commandIt == cachedVariables.end()) { if (commandIt == cachedVariables.end()) {
logger::log(bbPath + ": Missing 'command' field");
logger::log(confPath + ": Missing 'command' field");
return true; return true;
} }


std::vector<std::string> command = linkCommand(outDir); std::vector<std::string> command = linkCommand(outDir);
std::string dirPath = sys::dirname(outDir + '/' + path_); std::string dirPath = sys::dirname(outDir + '/' + path_);


BBVariables newCachedVars = {
BXVariables newCachedVars = {
{ "command", command}, { "command", command},
}; };


std::ofstream f = sys::ofstream(bbPath(outDir));
BBWriter writer(f);
std::ofstream f = sys::ofstream(confPath(outDir));
BXWriter writer(f);
writer.write(newCachedVars); writer.write(newCachedVars);


sys::mkdirp(dirPath); sys::mkdirp(dirPath);

+ 1
- 1
src/LinkStep.h View File

std::vector<std::string> linkCommand_; std::vector<std::string> linkCommand_;
std::vector<std::string> &linkCommand(const std::string &outDir); std::vector<std::string> &linkCommand(const std::string &outDir);


std::string bbPath(const std::string &outDir) { return outDir + '/' + path_ + ".bb"; }
std::string confPath(const std::string &outDir) { return outDir + '/' + path_ + ".bx"; }
}; };

+ 15
- 15
src/build.cc View File

#include <string.h> #include <string.h>


#include "sys.h" #include "sys.h"
#include "BBParser.h"
#include "BXParser.h"
#include "CompileStep.h" #include "CompileStep.h"
#include "LinkStep.h" #include "LinkStep.h"
#include "logger.h" #include "logger.h"
} }


static void addFile( static void addFile(
std::string path, BBVariables variables,
std::string path, BXVariables variables,
std::vector<std::unique_ptr<DepNode>> &deps) { std::vector<std::unique_ptr<DepNode>> &deps) {
toolchain::FileType type; toolchain::FileType type;
std::string ext = extension(path); std::string ext = extension(path);


static void findDeps( static void findDeps(
const std::string &dir, const std::string &name, const std::string &dir, const std::string &name,
const BBVariables &variables, std::vector<std::unique_ptr<DepNode>> &deps) {
const BXVariables &variables, std::vector<std::unique_ptr<DepNode>> &deps) {
std::string path = dir + "/" + name; std::string path = dir + "/" + name;
sys::FileInfo info; sys::FileInfo info;
try { try {


if (info.isDir) { if (info.isDir) {
// May or may not need to copy variables // May or may not need to copy variables
BBVariables subvars;
const BBVariables *varsptr = &variables;
BXVariables subvars;
const BXVariables *varsptr = &variables;
std::vector<std::string> subpaths; std::vector<std::string> subpaths;


// There might be a $path/build.bb. If there is, files in that dir
// needs a new copy of variables, and that $path/build.bb might contain
// There might be a $path/build.bx. If there is, files in that dir
// needs a new copy of variables, and that $path/build.bx might contain
// a files property. // a files property.
if (sys::fileExists(path + "/build.bb")) {
if (sys::fileExists(path + "/build.bx")) {
subvars = variables; subvars = variables;
varsptr = &subvars; varsptr = &subvars;


std::ifstream stream = sys::ifstream("build.bb");
BBParser parser(stream, BBParser::FLAG_NONE);
std::ifstream stream = sys::ifstream("build.bx");
BXParser parser(stream, BXParser::FLAG_NONE);
parser.parse(subvars); parser.parse(subvars);


auto it = subvars.find("files"); auto it = subvars.find("files");
} }
} }


static std::string findTargetName(const BBVariables &variables) {
static std::string findTargetName(const BXVariables &variables) {
auto it = variables.find("target"); auto it = variables.find("target");
if (it != variables.end() && it->second.size() != 0) { if (it != variables.end() && it->second.size() != 0) {
return it->second[0]; return it->second[0];
return "target"; return "target";
} }


std::unique_ptr<DepNode> buildDepTree(const std::string &outDir, BBVariables variables) {
std::unique_ptr<DepNode> buildDepTree(const std::string &outDir, BXVariables variables) {
// Read config from file // Read config from file
if (sys::fileExists("build.bb")) {
std::ifstream stream = sys::ifstream("build.bb");
BBParser parser(stream, BBParser::FLAG_NONE);
if (sys::fileExists("build.bx")) {
std::ifstream stream = sys::ifstream("build.bx");
BXParser parser(stream, BXParser::FLAG_NONE);
parser.parse(variables); parser.parse(variables);
} }



+ 2
- 2
src/build.h View File

#include <memory> #include <memory>


#include "DepNode.h" #include "DepNode.h"
#include "BBParser.h"
#include "BXParser.h"


std::unique_ptr<DepNode> buildDepTree(const std::string &outDir, BBVariables variables);
std::unique_ptr<DepNode> buildDepTree(const std::string &outDir, BXVariables variables);

+ 23
- 23
src/main.cc View File

//#bb ldlibs := pthread
//#bx ldlibs := pthread


#include <getopt.h> #include <getopt.h>
#include <string.h> #include <string.h>
#include <utility> #include <utility>
#include <stdexcept> #include <stdexcept>


#include "BBParser.h"
#include "BXParser.h"
#include "parallel.h" #include "parallel.h"
#include "toolchain.h" #include "toolchain.h"
#include "globals.h" #include "globals.h"


if (args.size() == 0) { if (args.size() == 0) {
op = "build"; op = "build";
path = "./bb-out";
path = "./bx-out";
} else if (args[0][0] == '.' || args[0][0] == '/') { } else if (args[0][0] == '.' || args[0][0] == '/') {
op = "build"; op = "build";
path = args[0]; path = args[0];
} else if (args.size() == 1) { } else if (args.size() == 1) {
op = args[0]; op = args[0];
path = "./bb-out";
path = "./bx-out";
} else if (args.size() == 2) { } else if (args.size() == 2) {
op = args[0]; op = args[0];
path = args[1]; path = args[1];


sys::mkdirp(path); sys::mkdirp(path);


auto buildVariables = [&]() -> BBVariables {
BBVariables variables;
if (sys::fileExists(path + "/.config.bb")) {
std::ifstream f = sys::ifstream(path + "/.config.bb");
BBParser parser(f, BBParser::FLAG_NONE);
auto buildVariables = [&]() -> BXVariables {
BXVariables variables;
if (sys::fileExists(path + "/.config.bx")) {
std::ifstream f = sys::ifstream(path + "/.config.bx");
BXParser parser(f, BXParser::FLAG_NONE);
parser.parse(variables); parser.parse(variables);
} }


for (auto &pair: kwargs) { for (auto &pair: kwargs) {
std::stringstream ss(pair.second); std::stringstream ss(pair.second);
BBParser parser(ss, BBParser::FLAG_NONE);
BXParser parser(ss, BXParser::FLAG_NONE);
auto &list = variables[pair.first]; auto &list = variables[pair.first];
list.clear(); list.clear();
parser.parseList(variables, list); parser.parseList(variables, list);
} }


if (kwargs.size() > 0) { if (kwargs.size() > 0) {
std::ofstream f = sys::ofstream(path + "/.config.bb");
BBWriter w(f);
std::ofstream f = sys::ofstream(path + "/.config.bx");
BXWriter w(f);
w.write(variables); w.write(variables);
} }


return variables; return variables;
}; };


auto buildTree = [&](BBVariables vars) -> std::unique_ptr<DepNode> {
auto buildTree = [&](BXVariables vars) -> std::unique_ptr<DepNode> {
return buildDepTree(path, std::move(vars)); return buildDepTree(path, std::move(vars));
}; };


} }


} else if (op == "config") { } else if (op == "config") {
BBVariables variables = buildVariables();
BXVariables variables = buildVariables();


printf("%s:\n", (path + "/.config.bb").c_str());
printf("%s:\n", (path + "/.config.bx").c_str());
if (variables.size() == 0) { if (variables.size() == 0) {
printf("No config options set.\n"); printf("No config options set.\n");
} }


} else if (op == "clean") { } else if (op == "clean") {
// TODO: Remove what's needed, instead of removing everything and // TODO: Remove what's needed, instead of removing everything and
// re-creating .config.bb
BBVariables variables = buildVariables();
// re-creating .config.bx
BXVariables variables = buildVariables();
sys::rmrf(path); sys::rmrf(path);
sys::rmrf("compile_commands.json"); sys::rmrf("compile_commands.json");
sys::mkdirp(path); sys::mkdirp(path);
std::ofstream f = sys::ofstream(path + "/.config.bb");
BBWriter w(f);
std::ofstream f = sys::ofstream(path + "/.config.bx");
BXWriter w(f);
w.write(variables); w.write(variables);


} else { } else {
} }


int main(int argc, char **argv) { int main(int argc, char **argv) {
std::string outDir = "bbbuild";
int jobs = parallel::coreCount() * 1.2 + 2; int jobs = parallel::coreCount() * 1.2 + 2;
std::string workDir = ""; std::string workDir = "";
std::string target = ""; std::string target = "";
}; };


const char usage[] = const char usage[] =
"Usage: bbbuild [options...] [build | config | compile-commands | clean] [path]\n"
"Usage: %s [options...] [build | config | compile-commands | clean] [path]\n"
"\n" "\n"
" -h, --help " " -h, --help "
"Show this help text.\n" "Show this help text.\n"


switch (c) { switch (c) {
case 'h': case 'h':
puts(usage);
printf(usage, argv[0]);
return 0; return 0;


case 'v': case 'v':
break; break;


default: default:
printf("Unknown option: '%c'.\n%s", (char)c, usage);
printf("Unknown option: '%c'.\n", (char)c);
printf(usage, argv[0]);
return 1; return 1;
} }
} }

+ 3
- 3
src/toolchain.cc View File

abort(); abort();
} }


void getFlags(const BBVariables &vars, FileType type, std::vector<std::string> &flags) {
void getFlags(const BXVariables &vars, FileType type, std::vector<std::string> &flags) {
auto stdver = vars.find("std"); auto stdver = vars.find("std");
if (stdver != vars.end() && stdver->second.size() > 0) { if (stdver != vars.end() && stdver->second.size() > 0) {
flags.push_back("-std=" + stdver->second[0]); flags.push_back("-std=" + stdver->second[0]);
} }
} }


void getLDLibs(const BBVariables &vars, std::vector<std::string> &flags) {
void getLDLibs(const BXVariables &vars, std::vector<std::string> &flags) {
auto pkgs = vars.find("pkgs"); auto pkgs = vars.find("pkgs");
if (pkgs != vars.end()) { if (pkgs != vars.end()) {
std::vector<std::string> argv; std::vector<std::string> argv;
} }
} }


void getLDFlags(const BBVariables &vars, std::vector<std::string> &flags) {
void getLDFlags(const BXVariables &vars, std::vector<std::string> &flags) {
auto sanitize = vars.find("sanitizers"); auto sanitize = vars.find("sanitizers");
if (sanitize != vars.end()) { if (sanitize != vars.end()) {
for (auto &s: sanitize->second) { for (auto &s: sanitize->second) {

+ 4
- 4
src/toolchain.h View File

#include <vector> #include <vector>
#include <string> #include <string>


#include "BBParser.h"
#include "BXParser.h"


namespace toolchain { namespace toolchain {


const std::string &path, const std::string &path,
const std::string &outDir); const std::string &outDir);


void getFlags(const BBVariables &vars, FileType type, std::vector<std::string> &flags);
void getLDLibs(const BBVariables &vars, std::vector<std::string> &flags);
void getLDFlags(const BBVariables &vars, std::vector<std::string> &flags);
void getFlags(const BXVariables &vars, FileType type, std::vector<std::string> &flags);
void getLDLibs(const BXVariables &vars, std::vector<std::string> &flags);
void getLDFlags(const BXVariables &vars, std::vector<std::string> &flags);


std::vector<std::string> getDependencies( std::vector<std::string> getDependencies(
const std::vector<std::string> &flags, const std::vector<std::string> &flags,

Loading…
Cancel
Save