#include #include "../include/FileUtil.hpp" #include "../include/Conf.hpp" #include "../include/Dependency.hpp" #include "../backend/ninja/Ninja.hpp" #include #include using namespace std; using namespace sibs; void usage() { printf("Simple build system for native languages\n"); printf("usage:\n"); printf(" sibs \n"); printf("option:\n"); printf(" project path: Path containing project.conf\n"); printf("examples:\n"); printf(" sibs myProject"); exit(1); } void validateDirectoryPath(const char *projectPath) { FileType projectPathFileType = getFileType(projectPath); if(projectPathFileType == FileType::FILE_NOT_FOUND) { perror(projectPath); exit(2); } else if(projectPathFileType == FileType::REGULAR) { printf("Expected project path (%s) to be a directory, was a file", projectPath); exit(3); } } void validateFilePath(const char *projectConfPath) { FileType projectConfFileType = getFileType(projectConfPath); if(projectConfFileType == FileType::FILE_NOT_FOUND) { perror(projectConfPath); exit(4); } else if(projectConfFileType == FileType::DIRECTORY) { printf("Expected project path (%s) to be a file, was a directory", projectConfPath); exit(5); } } class SibsConfig : public ConfigCallback { public: SibsConfig() : finishedProcessing(false) {} const string& getPackageName() const { assert(finishedProcessing); return packageName; } const std::vector& getDependencies() const { return dependencies; } protected: void processObject(StringView name) override { currentObject = name; printf("Process object: %.*s\n", name.size, name.data); } void processField(StringView name, const ConfigValue &value) override { printf("Process field: %.*s, value: ", name.size, name.data); if(value.isSingle()) { printf("\"%.*s\"", value.asSingle().size, value.asSingle().data); } else { printf("["); int i = 0; for(auto listElement : value.asList()) { if(i > 0) printf(", "); printf("\"%.*s\"", listElement.size, listElement.data); ++i; } printf("]"); } printf("\n"); if(currentObject.equals("package") && name.equals("name")) { if(value.isSingle()) packageName = string(value.asSingle().data, value.asSingle().size); else throw ParserException("Expected package.name to be a single value, was a list"); } else if(currentObject.equals("dependencies")) { if(value.isSingle()) { // TODO: Validate version is number in correct format Dependency dependency; dependency.name = string(name.data, name.size); dependency.version = string(value.asSingle().data, value.asSingle().size); dependencies.emplace_back(dependency); } else throw ParserException("Expected field under dependencies to be a single value, was a list"); } } void finished() override { finishedProcessing = true; } private: StringView currentObject; string packageName; std::vector dependencies; bool finishedProcessing; }; const char *sourceFileExtensions[] = { "cc", "cpp", "cxx" }; bool isSourceFile(tinydir_file *file) { if(!file->is_reg) return false; for(const char *sourceFileExtension : sourceFileExtensions) { if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0) return true; } return false; } int main(int argc, const char **argv) { if(argc != 2) usage(); string projectPath = argv[1]; validateDirectoryPath(projectPath.c_str()); string projectConfFilePath = projectPath; projectConfFilePath += "/project.conf"; validateFilePath(projectConfFilePath.c_str()); SibsConfig sibsConfig; Result result = Config::readFromFile(projectConfFilePath.c_str(), sibsConfig); if(result.isErr()) { printf("Failed to read config: %s\n", result.getErrMsg().c_str()); exit(6); } //string projectSrcPath = projectPath + "/src"; //validateDirectoryPath(projectSrcPath.c_str()); backend::Ninja ninja; walkDirFiles(projectPath.c_str(), [&ninja, &projectPath](tinydir_file *file) { if (isSourceFile(file)) { printf("Adding source file: %s\n", file->path + projectPath.size() + 1); ninja.addSourceFile(file->path + projectPath.size() + 1); } else { printf("Ignoring non-source file: %s\n", file->path + projectPath.size() + 1); } }); // TODO: Create build path if it doesn't exist string debugBuildPath = projectPath + "/build/debug"; string buildFilePath = debugBuildPath + "/build.ninja"; Result buildFileResult = ninja.createBuildFile(sibsConfig.getPackageName(), sibsConfig.getDependencies(), buildFilePath.c_str()); if(buildFileResult.isErr()) { printf("Failed to build ninja file: %s\n", buildFileResult.getErrMsg().c_str()); exit(7); } Result buildResult = ninja.build(debugBuildPath.c_str()); if(buildResult.isErr()) { exit(8); } return 0; }