npi-build/source/helper.cpp
2024-03-12 09:20:44 +01:00

755 lines
25 KiB
C++

#include <math.h>
#include <condition_variable>
#include <fileHash.hpp>
#include <filesystem>
#include <fstream>
#include <future>
#include <helper.hpp>
#include <iomanip>
#include <iostream>
#include <json.hpp>
#include <mutex>
#include <random>
#include <sstream>
#include <stack>
#include <string>
#include <thread>
#define CCRED "\033[31m"
#define CCGREEN "\033[32m"
#define CCYELLOW "\033[33m"
#define CCBLUE "\033[34m"
#define CCMAGENTA "\033[35m"
#define CCCYAN "\033[36m"
#define CCRESET "\033[0m"
#define veccmp(vec1, vec2) (vec1.size() == vec2.size())
void updateProgressBar(float progress, std::string f) {
const int w = 50;
int pos = static_cast<int>(progress * w);
std::cout << CCYELLOW << "[";
for (int i = 0; i < w; ++i) {
if (i < pos)
std::cout << "=";
else if (i == pos)
std::cout << ">";
else
std::cout << " ";
}
std::cout << "] " << std::setw(3) << static_cast<int>(progress * 100.0)
<< "% " << CCRESET << '\r';
std::cout.flush();
}
template <typename T>
std::pair<T, bool> js_catch(const nlohmann::json &js, const std::string &at) {
bool exists = true;
if (!js.contains(at) || js[at].is_null()) exists = false;
return std::make_pair(js[at].get<T>(), exists);
}
void recursive_repl(std::string &i, char v1, char v2) {
std::replace(i.begin(), i.end(), v1, v2);
}
std::vector<std::filesystem::path> get_files_in_dir(
const std::vector<std::string> &dir_paths, const std::string &extension) {
std::vector<std::filesystem::path> files;
for (const auto &dir_path : dir_paths) {
if (!std::filesystem::exists(dir_path)) continue;
for (const auto &entry : std::filesystem::directory_iterator(dir_path)) {
if (std::filesystem::is_regular_file(entry.path())) {
std::string fn = entry.path().string();
if (fn.length() > extension.length()) {
if (fn.ends_with(extension)) {
files.push_back(fix_path(entry.path().string()));
}
}
}
}
}
return files;
}
void Js2Vec(std::vector<std::string> &vec, nlohmann::json js) {
vec.clear();
for (auto const &it : js) {
vec.push_back(it.get<std::string>());
}
}
void Vec2Json(std::vector<std::string> vec, nlohmann::json &js,
NpiProject ref) {
int indx = 0;
for (auto const &it : vec) {
js[indx] = it;
indx++;
}
}
std::string Flags2Str(std::vector<std::string> flags) {
std::string res = "";
for (auto const &it : flags) res += "-" + it + " ";
return res;
}
std::string IncludeDirs(std::vector<std::string> dirs) {
std::string res = "";
for (auto const &it : dirs) res += "-I " + it + " ";
return res;
}
std::string LibIncludes(std::vector<std::string> dirs) {
std::string res = "";
for (auto const &it : dirs) res += "-I " + it + "include/ ";
return res;
}
void VecGetExtra(std::vector<std::string> &result,
std::vector<std::string> input, NpiProject ref) {
result.clear();
for (auto const &it : input) {
if (it == "[arch_flags]") {
for (auto const &af : ref.arch_flags) {
result.push_back(af);
}
} else if (it == "[c_flags]") {
for (auto const &cf : ref.c_flags) {
result.push_back(cf);
}
} else {
result.push_back(it);
}
}
}
void ReplVariables(std::string &str, const std::string &from,
const std::string &to) {
if (from.empty()) return;
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing
// 'x' with 'yx'
}
}
void AutoRepl(std::string &str) {
std::string dkp_env = getenv("DEVKITPRO");
std::string cwd = std::filesystem::current_path().string();
ReplVariables(str, "{DEVKITPRO}", dkp_env);
ReplVariables(str, "{cwd}", cwd);
}
void ReplVector(std::vector<std::string> &vec, const std::string &from,
const std::string &to) {
for (size_t i = 0; i < vec.size(); i++) ReplVariables(vec[i], from, to);
}
void AutoVecRepl(std::vector<std::string> &strs) {
for (size_t i = 0; i < strs.size(); i++) AutoRepl(strs[i]);
}
void ProcessPrj2Cmp(NpiProject *prj, NpiProject src) {
VecGetExtra(prj->arch_flags, src.arch_flags, src);
VecGetExtra(prj->c_flags, src.c_flags, src);
VecGetExtra(prj->cxx_flags, src.cxx_flags,
prj[0]); // Use Prj as ref cause arch_flags already written
VecGetExtra(prj->as_flags, src.as_flags, src);
VecGetExtra(prj->linker_flags, src.linker_flags, src);
}
std::string LinkerInput(std::vector<std::filesystem::path> o_files,
std::vector<std::filesystem::path> d_files) {
std::string res = "";
/*if (o_files.size() != d_files.size()) {
std::cerr << "The Number of .d and .o files is wrong";
return "";
}*/
for (size_t i = 0; i < o_files.size(); i++)
res += o_files[i].string() + " "; // + d_files[i].string() + " ";
return res;
}
std::string Libs(std::vector<std::string> libs) {
std::string res = "";
for (auto const &it : libs) res += "-l" + it + " ";
return res;
}
std::string LibPaths(std::vector<std::string> libs) {
std::string res = "";
for (auto const &it : libs) res += "-L" + it + "lib/ ";
return res;
}
void DeleteFiles(std::string path, std::vector<std::string> extensions) {
for (const auto &entry : std::filesystem::directory_iterator(path)) {
if (std::filesystem::is_directory(entry)) {
DeleteFiles(fix_path(entry.path().string()), extensions);
} else {
for (const auto &ext : extensions) {
if (entry.path().extension() == ext) {
std::filesystem::remove(entry);
std::cout << CCRED
<< "[*] Deleted file: " << fix_path(entry.path().string())
<< CCRESET << std::endl;
break;
}
}
}
}
}
void DeleteDirectory(std::string path) {
for (const auto &entry : std::filesystem::directory_iterator(path)) {
if (std::filesystem::is_directory(entry)) {
DeleteDirectory(fix_path(entry.path().string()));
} else {
std::filesystem::remove(entry);
std::cout << CCRED
<< "[*] Deleted file: " << fix_path(entry.path().string())
<< CCRESET << std::endl;
}
}
std::filesystem::remove(path);
std::cout << CCRED << "[*] Deleted directory: " << path << CCRESET
<< std::endl;
}
void GenerateHashes(NpiProject prj, std::string dir_) {
auto cpp_hashes = createHashes(prj.source_dirs, ".cpp");
auto c_hashes = createHashes(prj.source_dirs, ".c");
auto hpp_hashes = createHashes(prj.include_dirs, ".hpp");
auto h_hashes = createHashes(prj.include_dirs, ".h");
auto v_pica_hashes = createHashes(prj.source_dirs, ".v.pica");
auto shlist_hashes = createHashes(prj.source_dirs, ".shlist");
auto s_hashes = createHashes(prj.source_dirs, ".s");
auto t3s_hashes = createHashes({std::string(dir_ + "/gfx")}, ".t3s");
nlohmann::json jscpp_hashes;
for (auto const &it : cpp_hashes) jscpp_hashes[it.first] = it.second;
nlohmann::json jsc_hashes;
for (auto const &it : c_hashes) jsc_hashes[it.first] = it.second;
nlohmann::json jshpp_hashes;
for (auto const &it : hpp_hashes) jshpp_hashes[it.first] = it.second;
nlohmann::json jsh_hashes;
for (auto const &it : h_hashes) jsh_hashes[it.first] = it.second;
nlohmann::json jsv_pica_hashes;
for (auto const &it : v_pica_hashes) jsv_pica_hashes[it.first] = it.second;
nlohmann::json jsshlist_hashes;
for (auto const &it : shlist_hashes) jsshlist_hashes[it.first] = it.second;
nlohmann::json jss_hashes;
for (auto const &it : s_hashes) jss_hashes[it.first] = it.second;
nlohmann::json jst3s_hashes;
for (auto const &it : t3s_hashes) jst3s_hashes[it.first] = it.second;
nlohmann::json hashes;
hashes["cpp"] = jscpp_hashes;
hashes["c"] = jsc_hashes;
hashes["hpp"] = jshpp_hashes;
hashes["h"] = jsh_hashes;
hashes["v_pica"] = jsv_pica_hashes;
hashes["shlist"] = jsshlist_hashes;
hashes["s"] = jss_hashes;
hashes["t3s"] = jst3s_hashes;
std::ofstream hashes_file(dir_ + "/" + "build/hashes.json");
hashes_file << hashes.dump(4);
hashes_file.close();
}
std::map<std::string, std::string> GetHashMap(std::string dir_,
std::string extension) {
nlohmann::json js;
std::ifstream is(dir_ + "/build/hashes.json");
if (!is) {
std::cerr << "[-]hashes.json not in " << dir_ + "/build/"
<< "!\n";
exit(-1);
}
is >> js;
is.close();
std::string mod_ext = extension.substr(1);
std::replace(mod_ext.begin(), mod_ext.end(), '.', '_');
std::map<std::string, std::string> res;
for (auto &[filename, hash] : js[mod_ext].items()) {
res[filename] = hash;
}
return res;
}
bool C_CXX_Compile(bool cxx, std::string dir_, std::filesystem::path it,
NpiProject prj) {
std::string command =
(cxx ? prj.cxx_compiler : prj.c_compiler) + " -MMD -MP -MF " + dir_ +
"/build/" + fix_path(it.stem().string()) + ".d " + "-c " +
fix_path(it.string()) + " -o " + dir_ + "/build/" +
fix_path(it.stem().string()) + ".o " +
Flags2Str((cxx ? prj.cxx_flags : prj.c_flags)) + " " +
IncludeDirs(prj.include_dirs) + " " + LibIncludes(prj.lib_dirs);
std::cout << CCMAGENTA << "Compiling: " << CCCYAN
<< fix_path(it.filename().string()) << std::endl;
int reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ")
<< fix_path(it.filename().string()) << std::endl;
return reqres != 0;
}
bool Picasso_Compile(std::string dir_, std::string dkp_env,
std::filesystem::path it, NpiProject prj) {
std::string res_f =
dir_ + "/build/" + fix_path(it.stem().stem().string()) + ".shbin ";
std::string command =
dkp_env + "/tools/bin/picasso -o " + res_f + fix_path(it.string());
std::cout << CCMAGENTA << "Generating: " << CCCYAN << res_f << std::endl;
int reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ") << res_f << std::endl;
if (reqres != 0) return true;
// Bin2o action
// Mod res_f
std::string erf = res_f;
recursive_repl(erf, '.', '_');
erf = erf.substr(0, erf.length() - 1);
std::string tmp = "t.s";
std::string obj = erf + ".o";
std::string hdr = erf + ".h";
// Convert bin2asm
std::string cmd = "bin2s -a 4 -H " + hdr + ' ' + res_f + " > " + tmp;
reqres = system(cmd.c_str());
if (reqres != 0) return true;
cmd = prj.cxx_compiler + " -x assembler-with-cpp " + tmp + " -c -o " + obj;
reqres = system(cmd.c_str());
// remove asm file
remove(tmp.c_str());
if (reqres != 0) return true;
return false;
}
bool Tex3ds_Compile(std::string dir_, std::string dkp_env,
std::filesystem::path it, NpiProject prj) {
std::string command =
dkp_env + "/tools/bin/tex3ds -i " + fix_path(it.string()) + " -H " +
dir_ + "/build/" + fix_path(it.stem().string()) + ".h" + " -d " + dir_ +
"/build/" + fix_path(it.stem().string()) + ".d" + " -o " + dir_ +
"/romfs/gfx//" + fix_path(it.stem().string()) + ".t3x";
std::cout << CCMAGENTA << "Generating: " << CCCYAN
<< fix_path(it.filename().string()) << std::endl;
int reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ")
<< fix_path(it.filename().string()) << std::endl;
return reqres != 0;
}
void CompileProject(NpiProject &prj, std::string dir_, bool async = true) {
#ifdef _WIN32
std::string dkp_env = "C:/devkitPro/";
std::cout << CCYELLOW
<< "[+] Warning: Windows Usage Detected!\n[+] Make sure you have "
"devkitpro installed at <C:/devkitPro>!"
<< CCRESET << std::endl;
#else
std::string dkp_env = getenv("DEVKITPRO");
#endif
bool any_errors = false;
AutoVecRepl(prj.source_dirs);
AutoVecRepl(prj.include_dirs);
// Inject build dir as include dir
prj.include_dirs.push_back(dir_ + "/build");
std::vector<std::filesystem::path> cpp_files =
get_files_in_dir(prj.source_dirs, ".cpp");
std::vector<std::filesystem::path> c_files =
get_files_in_dir(prj.source_dirs, ".c");
std::vector<std::filesystem::path> hpp_files =
get_files_in_dir(prj.include_dirs, ".hpp");
std::vector<std::filesystem::path> h_files =
get_files_in_dir(prj.include_dirs, ".h");
std::vector<std::filesystem::path> v_pica_files =
get_files_in_dir(prj.source_dirs, ".v.pica");
std::vector<std::filesystem::path> shlist_files =
get_files_in_dir(prj.source_dirs, ".shlist");
std::vector<std::filesystem::path> t3s_files =
get_files_in_dir({std::string(dir_ + "/gfx")}, ".t3s");
std::vector<std::filesystem::path> s_files =
get_files_in_dir(prj.source_dirs, ".s");
std::filesystem::create_directories(dir_ + "/build");
std::vector<std::filesystem::path> cpp_files_;
std::vector<std::filesystem::path> c_files_;
std::vector<std::filesystem::path> v_pica_files_;
std::vector<std::filesystem::path> shlist_files_;
std::vector<std::filesystem::path> s_files_;
std::vector<std::filesystem::path> t3s_files_;
if (!std::filesystem::exists(
std::filesystem::path(dir_ + "/build/hashes.json"))) {
GenerateHashes(prj, dir_);
cpp_files_ = get_files_in_dir(prj.source_dirs, ".cpp");
c_files_ = get_files_in_dir(prj.source_dirs, ".c");
v_pica_files_ = get_files_in_dir(prj.source_dirs, ".v.pica");
shlist_files_ = get_files_in_dir(prj.source_dirs, ".shlist");
s_files_ = get_files_in_dir(prj.source_dirs, ".s");
t3s_files_ = get_files_in_dir({std::string(dir_ + "/gfx")}, ".t3s");
} else {
cpp_files_ = getChangedFiles(GetHashMap(dir_, ".cpp"));
c_files_ = getChangedFiles(GetHashMap(dir_, ".c"));
v_pica_files_ = getChangedFiles(GetHashMap(dir_, ".v.pica"));
shlist_files_ = getChangedFiles(GetHashMap(dir_, ".shlist"));
s_files_ = getChangedFiles(GetHashMap(dir_, ".s"));
t3s_files_ = getChangedFiles(GetHashMap(dir_, ".t3s"));
if ((getChangedFiles(GetHashMap(dir_, ".hpp")).size() != 0) ||
(getChangedFiles(GetHashMap(dir_, ".hpp")).size() != 0)) {
cpp_files_ = get_files_in_dir(prj.source_dirs, ".cpp");
c_files_ = get_files_in_dir(prj.source_dirs, ".c");
}
}
if (GetHashMap(dir_, ".cpp").size() != cpp_files.size() ||
GetHashMap(dir_, ".c").size() != c_files.size()) {
cpp_files_ = get_files_in_dir(prj.source_dirs, ".cpp");
c_files_ = get_files_in_dir(prj.source_dirs, ".c");
}
if (GetHashMap(dir_, ".hpp").size() != hpp_files.size() ||
GetHashMap(dir_, ".h").size() != h_files.size()) {
cpp_files_ = get_files_in_dir(prj.source_dirs, ".cpp");
c_files_ = get_files_in_dir(prj.source_dirs, ".c");
}
ReplVector(prj.lib_dirs, "{DEVKITPRO}", dkp_env);
ReplVariables(prj.cxx_compiler, "{DEVKITPRO}", dkp_env);
ReplVariables(prj.c_compiler, "{DEVKITPRO}", dkp_env);
ReplVariables(prj.asm_compiler, "{DEVKITPRO}", dkp_env);
ReplVariables(prj.linker, "{DEVKITPRO}", dkp_env);
int prgc = 0;
int wa = cpp_files_.size() + c_files_.size() + t3s_files_.size() +
v_pica_files_.size();
int prga = cpp_files_.size() + c_files_.size();
if (prga <= 0) {
prgc = 1;
prga = 1;
std::cout << CCGREEN << "[+] Everything is Up to date..." << CCRESET
<< std::endl;
return;
}
for (auto const &it : t3s_files_) {
prgc++;
Tex3ds_Compile(dir_, dkp_env, it, prj);
}
for (auto const &it : v_pica_files_) {
prgc++;
Picasso_Compile(dir_, dkp_env, it, prj);
}
/*if (async)
{
}
else
{*/
for (auto const &it : cpp_files_) {
prgc++;
C_CXX_Compile(true, dir_, it, prj);
}
for (auto const &it : c_files_) {
prgc++;
C_CXX_Compile(false, dir_, it, prj);
}
//}
// updateProgressBar(1.f);
std::cout << std::endl;
std::vector<std::filesystem::path> o_files =
get_files_in_dir({dir_ + "/build/"}, ".o");
std::vector<std::filesystem::path> d_files =
get_files_in_dir({dir_ + "/build/"}, ".d");
if (!any_errors) {
std::string command = prj.linker + " -o " + dir_ + "/" + prj.name +
".elf " + LinkerInput(o_files, d_files) + " " +
Libs(prj.libraries) + " " + LibPaths(prj.lib_dirs) +
" " + Flags2Str(prj.linker_flags);
std::cout << CCBLUE << "[+] Linking..." << CCRESET << std::endl;
int reqres = system(command.c_str());
if (reqres != 0) any_errors = true;
if (prj.ctr_type) {
command =
"bannertool makebanner -i \"app/banner.png\" -a "
"\"app/BannerAudio.wav\" -o \"build/banner.bin\"";
std::cout << CCBLUE << "[+] Creating Banner..." << CCRESET << std::endl;
reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ") << "Banner" << std::endl;
}
command = "bannertool makesmdh -i \"app/icon.png\" -s \"" + prj.name +
"\" -l \"Description\" -p \"" + prj.author +
"\" -o \"build/icon.bin\"";
std::cout << CCBLUE << "[+] Creating smdh..." << CCRESET << std::endl;
reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ") << "Icon" << std::endl;
command = dkp_env += "/tools/bin/3dsxtool " + dir_ + "/" + prj.name +
".elf " + dir_ + "/" + prj.name + ".3dsx " +
"--smdh=" + dir_ + "/build/icon.bin" +
" --romfs=" + dir_ + "/romfs";
std::cout << CCBLUE << "[+] Creating 3dsx..." << CCRESET << std::endl;
reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ") << prj.name + ".3dsx "
<< std::endl;
if (prj.ctr_type) {
command =
"makerom -f cia -target t -exefslogo -o " + dir_ + "/" + prj.name +
".cia -elf " + dir_ + "/" + prj.name + ".elf " + " -rsf " + dir_ +
"/" + prj.rsf_path + " -banner " + dir_ + "/build/banner.bin" +
" -icon " + dir_ + "/build/icon.bin" + " -logo " + dir_ + "/" +
prj.logo_lz11_path + " -DAPP_ROMFS=" + dir_ + "/" + prj.dir_romfs +
" -major " + std::to_string(prj.vmajor) + " -minor " +
std::to_string(prj.vminor) + " -micro " + std::to_string(prj.vbuild) +
" -DAPP_VERSION_MAJOR=" + std::to_string(prj.vmajor);
std::cout << CCBLUE << "[+] Creating Cia..." << CCRESET << std::endl;
reqres = system(command.c_str());
std::cout << (reqres == 0 ? CCGREEN : CCRED)
<< (reqres == 0 ? "[+] " : "[-] ") << prj.name + ".cia "
<< std::endl;
}
}
if (any_errors) {
std::cout
<< CCRED
<< "\nErrors Happened!\nTake a look at the Top of this Message...\n"
<< CCRESET;
}
GenerateHashes(prj, dir_);
std::cout << CCRESET << std::endl;
}
namespace helper {
std::string GenerateUniqueId() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 15);
std::stringstream ss;
ss << "0x";
for (int i = 0; i < 5; ++i) {
ss << std::hex << dis(gen);
}
std::string hex_str = ss.str();
return hex_str;
}
void ArrayToFile(unsigned char *array_, size_t size_, std::string filename) {
std::ofstream file(filename, std::ios::binary);
if (!file.is_open()) {
std::cerr << CCRED << "[-]: Could not open file" << CCRESET << std::endl;
return;
}
file.write(reinterpret_cast<char *>(array_), size_);
file.close();
}
void GenerateTemplateFile(std::string path, NpiProject prj) {
nlohmann::ordered_json js;
js["project_name"] = prj.name;
js["author"] = prj.author;
js["description"] = prj.description;
js["vmajor"] = prj.vmajor;
js["vminor"] = prj.vminor;
js["vbuild"] = prj.vbuild;
if (prj.ctr_type) {
js["unique_id"] = prj.unique_id;
js["prod_code"] = prj.prod;
}
js["platform"] = prj.platform;
if (prj.platform == "3ds") {
js["cia"] = prj.ctr_type;
}
nlohmann::json source_dirs;
Vec2Json(prj.source_dirs, source_dirs, prj);
js["source_dirs"] = source_dirs;
nlohmann::json include_dirs;
Vec2Json(prj.include_dirs, include_dirs, prj);
js["include_dirs"] = include_dirs;
nlohmann::json libraries;
Vec2Json(prj.libraries, libraries, prj);
js["libraries"] = libraries;
nlohmann::json lib_dirs;
Vec2Json(prj.lib_dirs, lib_dirs, prj);
js["lib_dirs"] = lib_dirs;
js["icon_path"] = prj.icon_path;
if (prj.ctr_type) {
js["banner_path"] = prj.banner_path;
js["banner_a_path"] = prj.banner_a_path;
js["rsf_path"] = prj.rsf_path;
js["logo_lz11_path"] = prj.logo_lz11_path;
}
js["dir_gfx"] = prj.dir_gfx;
js["dir_gfxbuild"] = prj.dir_gfxbuild;
js["dir_romfs"] = prj.dir_romfs;
nlohmann::json arch_flags;
Vec2Json(prj.arch_flags, arch_flags, prj);
js["arch_flags"] = arch_flags;
nlohmann::json c_flags;
Vec2Json(prj.c_flags, c_flags, prj);
js["c_flags"] = c_flags;
nlohmann::json cxx_flags;
Vec2Json(prj.cxx_flags, cxx_flags, prj);
js["cxx_flags"] = cxx_flags;
nlohmann::json as_flags;
Vec2Json(prj.as_flags, as_flags, prj);
js["as_flags"] = as_flags;
nlohmann::json linker_flags;
Vec2Json(prj.linker_flags, linker_flags, prj);
js["linker_flags"] = linker_flags;
js["cxx_compiler"] = prj.cxx_compiler;
js["c_compiler"] = prj.c_compiler;
js["asm_compiler"] = prj.asm_compiler;
js["linker"] = prj.linker;
std::ofstream fout(path);
fout << js.dump(4);
fout.close();
}
void CompileProject(std::string path, bool async) {
std::string dkp_env = getenv("DEVKITPRO");
if (dkp_env.c_str() == NULL) {
std::cerr << CCRED << "[-] Please set DEVKITPRO ENV Variable!\n" << CCRESET;
return;
}
nlohmann::json js;
std::ifstream is(path + "/build.json");
if (!is) {
std::cerr << CCRED << "[-] build.json not in " << path << "!\n" << CCRESET;
return;
}
is >> js;
is.close();
std::cout << CCBLUE << "[+] Compiling at " << path << " ...\n" << CCRESET;
NpiProject prj;
auto __name = js_catch<std::string>(js, "project_name");
auto __author = js_catch<std::string>(js, "author");
auto __vmajor = js_catch<int>(js, "vmajor");
auto __vminor = js_catch<int>(js, "vminor");
auto __vbuild = js_catch<int>(js, "vbuild");
auto __platform = js_catch<std::string>(js, "platform");
auto __ctr_type = js_catch<bool>(js, "cia");
auto __description = js_catch<std::string>(js, "description");
std::pair<std::string, bool> __unique_id;
std::pair<std::string, bool> __prod;
if (__ctr_type.first) {
__unique_id = js_catch<std::string>(js, "unique_id");
__prod = js_catch<std::string>(js, "prod_code");
}
std::pair<std::string, bool> __banner_path;
std::pair<std::string, bool> __banner_a_path;
std::pair<std::string, bool> __rsf_path;
std::pair<std::string, bool> __logo_lz11_path;
auto __icon_path = js_catch<std::string>(js, "icon_path");
if (__ctr_type.first) {
__banner_path = js_catch<std::string>(js, "banner_path");
__banner_a_path = js_catch<std::string>(js, "banner_a_path");
__rsf_path = js_catch<std::string>(js, "rsf_path");
__logo_lz11_path = js_catch<std::string>(js, "logo_lz11_path");
}
auto __dir_gfx = js_catch<std::string>(js, "dir_gfx");
auto __dir_gfxbuild = js_catch<std::string>(js, "dir_gfxbuild");
auto __dir_romfs = js_catch<std::string>(js, "dir_romfs");
auto __cxx_compiler = js_catch<std::string>(js, "cxx_compiler");
auto __c_compiler = js_catch<std::string>(js, "c_compiler");
auto __asm_compiler = js_catch<std::string>(js, "asm_compiler");
auto __linker = js_catch<std::string>(js, "linker");
prj.name = __name.first;
prj.author = __author.first;
prj.vmajor = __vmajor.first;
prj.vminor = __vminor.first;
prj.vbuild = __vbuild.first;
prj.description = __description.first;
prj.unique_id = __unique_id.first;
prj.prod = __prod.first;
prj.platform = __platform.first;
prj.ctr_type = __ctr_type.first;
prj.icon_path = __icon_path.first;
prj.banner_path = __banner_path.first;
prj.banner_a_path = __banner_a_path.first;
prj.rsf_path = __rsf_path.first;
prj.logo_lz11_path = __logo_lz11_path.first;
prj.dir_gfx = __dir_gfx.first;
prj.dir_gfxbuild = __dir_gfxbuild.first;
prj.dir_romfs = __dir_romfs.first;
Js2Vec(prj.arch_flags, js["arch_flags"]);
Js2Vec(prj.linker_flags, js["linker_flags"]);
Js2Vec(prj.c_flags, js["c_flags"]);
Js2Vec(prj.cxx_flags, js["cxx_flags"]);
Js2Vec(prj.as_flags, js["as_flags"]);
Js2Vec(prj.source_dirs, js["source_dirs"]);
Js2Vec(prj.include_dirs, js["include_dirs"]);
Js2Vec(prj.lib_dirs, js["lib_dirs"]);
Js2Vec(prj.libraries, js["libraries"]);
prj.cxx_compiler = __cxx_compiler.first;
prj.c_compiler = __c_compiler.first;
prj.asm_compiler = __asm_compiler.first;
prj.linker = __linker.first;
NpiProject _2build = prj;
ProcessPrj2Cmp(&_2build, prj);
CompileProject(_2build, path, async);
}
void CleanProject(std::string path) {
DeleteFiles(path, {".3dsx", ".cia", ".elf"});
DeleteFiles(path + "/" + "romfs", {".t3x"});
DeleteDirectory(path + "/build");
}
} // namespace helper