#include "BackendUtils.hpp" #include "../include/FileUtil.hpp" #include "../include/Exec.hpp" #include "ninja/Ninja.hpp" using namespace std; using namespace sibs; static std::vector cCompilerPath; static std::vector cppCompilerPath; static std::vector linkerPath; namespace backend { static bool isPathSubPathOf(const FileString &path, const FileString &subPathOf) { return _tinydir_strncmp(path.c_str(), subPathOf.c_str(), subPathOf.size()) == 0; } const _tinydir_char_t *cFileExtensions[] = { TINYDIR_STRING("c"), TINYDIR_STRING("C"), TINYDIR_STRING("cc") }; const _tinydir_char_t *cppFileExtensions[] = { TINYDIR_STRING("cp"), TINYDIR_STRING("cpp"), TINYDIR_STRING("cxx"), TINYDIR_STRING("c++") }; sibs::FileString BackendUtils::getFileExtension(const sibs::FileString &filepath) { size_t indexOfDot = filepath.find_last_of('.'); if(indexOfDot == sibs::FileString::npos) return TINYDIR_STRING(""); indexOfDot += 1; return filepath.substr(indexOfDot); } sibs::Language BackendUtils::getFileLanguage(const _tinydir_char_t *extension) { for(const _tinydir_char_t *sourceFileExtension : cFileExtensions) { if(_tinydir_strcmp(sourceFileExtension, extension) == 0) return sibs::Language::C; } for(const _tinydir_char_t *sourceFileExtension : cppFileExtensions) { if(_tinydir_strcmp(sourceFileExtension, extension) == 0) return sibs::Language::CPP; } if(_tinydir_strcmp(TINYDIR_STRING("zig"), extension) == 0) return sibs::Language::ZIG; return sibs::Language::NONE; } sibs::Language BackendUtils::getFileLanguage(tinydir_file *file) { if(!file->is_reg) return sibs::Language::NONE; return getFileLanguage(file->extension); } void BackendUtils::collectSourceFiles(const _tinydir_char_t *projectPath, Ninja *ninjaProject, const SibsConfig &sibsConfig, bool recursive) { walkDir(projectPath, [ninjaProject, &sibsConfig, recursive](tinydir_file *file) { FileString pathNative = file->path; #if OS_FAMILY == OS_FAMILY_WINDOWS replaceChar(pathNative, L'/', L'\\'); #endif if(file->is_reg) { sibs::Language fileLanguage = getFileLanguage(file); if (fileLanguage != sibs::Language::NONE) { string filePathUtf8 = toUtf8(pathNative.c_str() + sibsConfig.getProjectPath().size()); ninjaProject->addSourceFile(fileLanguage, filePathUtf8.c_str()); } else { //printf("Ignoring non-source file: %s\n", file->path + projectPath.size()); } } else { if (!sibsConfig.getTestPath().empty() && isPathSubPathOf(pathNative.c_str(), sibsConfig.getTestPath())) { string filePathUtf8 = toUtf8(pathNative.c_str()); ninjaProject->setTestSourceDir(filePathUtf8.c_str()); } else if(recursive && !directoryToIgnore(pathNative, sibsConfig.getIgnoreDirs()) && _tinydir_strcmp(file->name, TINYDIR_STRING("sibs-build")) != 0) { FileString projectConfPath = file->path; #if OS_FAMILY == OS_FAMILY_WINDOWS projectConfPath += L'\\'; #else projectConfPath += '/'; #endif projectConfPath += TINYDIR_STRING("project.conf"); if(!sibsConfig.isTest() && getFileType(projectConfPath.c_str()) == FileType::REGULAR) { backend::Ninja *subProject = new backend::Ninja(); SibsConfig *subProjectConfig = new SibsConfig(sibsConfig.getCompiler(), file->path, sibsConfig.getOptimizationLevel(), false); subProjectConfig->packaging = sibsConfig.packaging; subProjectConfig->platform = sibsConfig.platform; subProjectConfig->bundling = sibsConfig.bundling; FileString subProjectBuildPath; readSibsConfig(file->path, projectConfPath, *subProjectConfig, subProjectBuildPath); collectSourceFiles(file->path, subProject, *subProjectConfig, true); ninjaProject->addSubProject(subProject, subProjectConfig, move(subProjectBuildPath)); } else collectSourceFiles(file->path, ninjaProject, sibsConfig, true); } } return true; }); } std::vector BackendUtils::getCompilerCExecutable(Compiler compiler) { if(!cCompilerPath.empty()) return cCompilerPath; char *cc = std::getenv("CC"); if(cc) { cCompilerPath = { toFileString(cc) }; return cCompilerPath; } switch(compiler) { case Compiler::GCC: cCompilerPath = { TINYDIR_STRING("ccache"), TINYDIR_STRING("cc") }; break; case Compiler::MINGW_W64: cCompilerPath = { TINYDIR_STRING("x86_64-w64-mingw32-cc") }; break; case Compiler::MSVC: cCompilerPath = { TINYDIR_STRING("cl.exe") }; break; } return cCompilerPath; } std::vector BackendUtils::getCompilerCppExecutable(Compiler compiler) { if(!cppCompilerPath.empty()) return cppCompilerPath; char *cxx = std::getenv("CXX"); if(cxx) { cppCompilerPath = { toFileString(cxx) }; return cppCompilerPath; } switch(compiler) { case Compiler::GCC: cppCompilerPath = { TINYDIR_STRING("ccache"), TINYDIR_STRING("c++") }; break; case Compiler::MINGW_W64: cppCompilerPath = { TINYDIR_STRING("x86_64-w64-mingw32-c++") }; break; case Compiler::MSVC: cppCompilerPath = { TINYDIR_STRING("cl.exe") }; break; } return cppCompilerPath; } std::vector BackendUtils::getCompilerLinker(Compiler compiler) { if(!linkerPath.empty()) return linkerPath; char *ar = std::getenv("AR"); if(ar) { linkerPath = { toFileString(ar) }; return linkerPath; } switch(compiler) { case Compiler::GCC: linkerPath = { TINYDIR_STRING("ar") }; break; case Compiler::MINGW_W64: linkerPath = { TINYDIR_STRING("x86_64-w64-mingw32-ar") }; break; case Compiler::MSVC: linkerPath = { TINYDIR_STRING("lib.exe") }; break; } return linkerPath; } RuntimeCompilerType BackendUtils::getCCompilerType(Compiler compiler) { RuntimeCompilerType cCompilerType = RuntimeCompilerType::NONE; std::vector args = getCompilerCExecutable(compiler); args.push_back(TINYDIR_STRING("--version")); Result cCompilerVersion = exec(args); if(cCompilerVersion && cCompilerVersion.unwrap().exitCode == 0) { if(cCompilerVersion.unwrap().execStdout.find("Emscripten") != string::npos) cCompilerType = RuntimeCompilerType::EMSCRIPTEN; else if(cCompilerVersion.unwrap().execStdout.find("clang") != string::npos) cCompilerType = RuntimeCompilerType::CLANG; else cCompilerType = RuntimeCompilerType::OTHER; } return cCompilerType; } RuntimeCompilerType BackendUtils::getCppCompilerType(Compiler compiler) { RuntimeCompilerType cppCompilerType = RuntimeCompilerType::NONE; std::vector args = getCompilerCppExecutable(compiler); args.push_back(TINYDIR_STRING("--version")); Result cppCompilerVersion = exec(args); if(cppCompilerVersion && cppCompilerVersion.unwrap().exitCode == 0) { if(cppCompilerVersion.unwrap().execStdout.find("Emscripten") != string::npos) cppCompilerType = RuntimeCompilerType::EMSCRIPTEN; else if(cppCompilerVersion.unwrap().execStdout.find("clang") != string::npos) cppCompilerType = RuntimeCompilerType::CLANG; else cppCompilerType = RuntimeCompilerType::OTHER; } return cppCompilerType; } }