projgen: Initial commit
This commit adds `projgen`, a very simplistic project generator. Some knobs to the build system were added to ensure that only the needed parts will build with each end (building the GMod module won't build projgen since that isn't needed on the host) The fun part will be figuring out how to jail things properly
This commit is contained in:
parent
5f7f36296f
commit
568064068e
|
@ -1,10 +1,6 @@
|
|||
build/
|
||||
# this one is created by the build script
|
||||
module_build/
|
||||
native/projects/riscv/ref
|
||||
|
||||
# for now
|
||||
native/projects/projgen
|
||||
|
||||
.cache/
|
||||
.vscode/
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
path = native/projects/lcpu/third_party/gmod_headers
|
||||
url = https://github.com/Facepunch/gmod-module-base
|
||||
branch = development
|
||||
[submodule "native/projects/projgen/third_party/daw_json_link"]
|
||||
path = native/projects/projgen/third_party/daw_json_link
|
||||
url = https://github.com/beached/daw_json_link
|
||||
|
|
|
@ -28,8 +28,9 @@ cmake_build() {
|
|||
}
|
||||
|
||||
build_and_place() {
|
||||
cmake_gen linux32 --toolchain $PWD/native/cmake/linux32-toolchain.cmake
|
||||
cmake_gen linux64
|
||||
# don't build utilities; they're only needed by the oci image
|
||||
cmake_gen linux32 --toolchain $PWD/native/cmake/linux32-toolchain.cmake -DLCPU_BUILD_UTILITIES=OFF
|
||||
cmake_gen linux64 -DLCPU_BUILD_UTILITIES=OFF
|
||||
cmake_build linux32
|
||||
cmake_build linux64
|
||||
|
||||
|
|
|
@ -3,12 +3,17 @@ project(lcpu-native
|
|||
DESCRIPTION "Superproject for LCPU GMOD Native Module"
|
||||
)
|
||||
|
||||
option(LCPU_BUILD_UTILITIES "Build LCPU utiltiies" ON)
|
||||
option(LCPU_BUILD_MODULE "Build GMod module" ON)
|
||||
|
||||
# Lucore (lily utilities core)
|
||||
add_subdirectory(projects/lucore)
|
||||
|
||||
# RISC-V emulator library
|
||||
add_subdirectory(projects/riscv)
|
||||
if(LCPU_BUILD_MODULE)
|
||||
add_subdirectory(projects/riscv)
|
||||
add_subdirectory(projects/lcpu)
|
||||
endif()
|
||||
|
||||
# Garry's Mod native bindings to RISC-V emulator
|
||||
# Also lua device stuff
|
||||
add_subdirectory(projects/lcpu)
|
||||
if(LCPU_BUILD_UTILITIES)
|
||||
add_subdirectory(projects/projgen)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
project(lcpu-projgen
|
||||
DESCRIPTION "LCPU Project Generator - generates a Makefile from project.json"
|
||||
)
|
||||
|
||||
set(DAW_USE_CPP17_NAMES OFF)
|
||||
add_subdirectory(third_party/daw_json_link)
|
||||
|
||||
add_executable(lcpu_projgen
|
||||
# driver
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(lcpu_projgen
|
||||
lucore::lucore
|
||||
daw::json_link
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/// These are the hardcoded defaults
|
||||
#define PROJGEN_CC "riscv32-unknown-elf-gcc"
|
||||
#define PROJGEN_CXX "riscv32-unknown-elf-g++"
|
||||
#define PROJGEN_BASE_C_FLAGS "-ffreestanding -fno-stack-protector -fdata-sections -ffunction-sections -march=rv32ima -mabi=ilp32"
|
||||
#define PROJGEN_BASE_CC_FLAGS "-ffreestanding -fno-stack-protector -fdata-sections -ffunction-sections -march=rv32ima -mabi=ilp32"
|
||||
#define PROJGEN_BASE_LD_FLAGS "-nostdlib"
|
|
@ -0,0 +1,30 @@
|
|||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace projgen::util {
|
||||
|
||||
using unique_file_ptr = std::unique_ptr<std::FILE, decltype(&std::fclose)>;
|
||||
|
||||
unique_file_ptr UniqueFopen(std::string_view path, std::string_view mode) {
|
||||
return unique_file_ptr(std::fopen(path.data(), mode.data()), &std::fclose);
|
||||
}
|
||||
|
||||
std::string ReadFileAsString(const fs::path& path) {
|
||||
auto file = UniqueFopen(path.string(), "r");
|
||||
std::string data;
|
||||
if(file) {
|
||||
std::fseek(file.get(), 0, SEEK_END);
|
||||
auto len = std::ftell(file.get());
|
||||
std::fseek(file.get(), 0, SEEK_SET);
|
||||
|
||||
data.resize(len);
|
||||
std::fread(data.data(), 1, len, file.get());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace projgen::util
|
|
@ -0,0 +1,49 @@
|
|||
#include <daw/json/daw_json_link.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace projgen {
|
||||
struct Project {
|
||||
struct Configuration {
|
||||
/// The C/C++/linker flags for this configuration.
|
||||
/// These append to the defaults.
|
||||
std::string cCompileFlags;
|
||||
std::string cppCompileFlags;
|
||||
std::optional<std::string> linkerFlags;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::unordered_map<std::string, Project::Configuration> configurations;
|
||||
std::vector<std::string> sourceFileNames;
|
||||
};
|
||||
|
||||
} // namespace projgen
|
||||
|
||||
/// DAW JSON Link bindings
|
||||
namespace daw::json {
|
||||
|
||||
template <>
|
||||
struct json_data_contract<projgen::Project::Configuration> {
|
||||
using type = json_member_list<json_string<"CCompileFlags">, json_string<"CppCompileFlags">, json_string_null<"LinkerFlags"> >;
|
||||
|
||||
static inline auto to_json_data(const projgen::Project::Configuration& value) {
|
||||
return std::forward_as_tuple(value.cCompileFlags, value.cppCompileFlags, value.linkerFlags);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct json_data_contract<projgen::Project> {
|
||||
using type =
|
||||
json_member_list<json_string<"Name">,
|
||||
json_key_value<"Configurations", std::unordered_map<std::string, projgen::Project::Configuration>, projgen::Project::Configuration>,
|
||||
json_array<"Sources", std::string> >;
|
||||
|
||||
static inline auto to_json_data(const projgen::Project& value) {
|
||||
return std::forward_as_tuple(value.name, value.configurations, value.sourceFileNames);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace daw::json
|
|
@ -0,0 +1,94 @@
|
|||
//! Main for the LCPU project generator
|
||||
|
||||
#include <lucore/Logger.hpp>
|
||||
#include <lucore/StdoutSink.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "BaseConfig.hpp"
|
||||
#include "FsUtils.hpp"
|
||||
#include "Project.hpp"
|
||||
|
||||
template <class T>
|
||||
T ParseJsonFromFile(const fs::path& path) {
|
||||
auto data = projgen::util::ReadFileAsString(path);
|
||||
return daw::json::from_json<T>(data);
|
||||
}
|
||||
|
||||
// this describes a source file
|
||||
struct SourceFile {
|
||||
enum class Type {
|
||||
Invalid, // invalid file
|
||||
AsmSourceFile, // Assembly source file
|
||||
CSourceFile, // C source code
|
||||
CppSourceFile, // C++ source code
|
||||
LinkerScript, // prepended to linker flags with a -T (only one can exist in a project)
|
||||
};
|
||||
|
||||
static constexpr Type TypeFromExtension(std::string_view extension) {
|
||||
if(extension == "s" || extension == "S")
|
||||
return Type::AsmSourceFile;
|
||||
|
||||
if(extension == "c")
|
||||
return Type::CSourceFile;
|
||||
if(extension == "cpp" || extension == "cc")
|
||||
return Type::CppSourceFile;
|
||||
if(extension == "ld")
|
||||
return Type::LinkerScript;
|
||||
|
||||
return Type::Invalid;
|
||||
}
|
||||
|
||||
explicit SourceFile(const std::string& filename) : filename(filename) {
|
||||
if(auto pos = filename.rfind('.'); pos != std::string::npos) {
|
||||
type = TypeFromExtension(filename.substr(pos + 1));
|
||||
} else {
|
||||
type = Type::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<SourceFile> MakeArray(const std::vector<std::string>& filenames) {
|
||||
auto vec = std::vector<SourceFile>();
|
||||
vec.reserve(filenames.size());
|
||||
|
||||
for(auto& filename : filenames)
|
||||
vec.emplace_back(filename);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
Type type;
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
lucore::LoggerAttachStdout();
|
||||
|
||||
lucore::LogInfo("LCPU project generator!");
|
||||
|
||||
auto project_json_path = (fs::current_path() / "project.json");
|
||||
|
||||
if(!fs::exists(project_json_path)) {
|
||||
lucore::LogFatal("The directory \"{}\" does not seem like it's a project to me", fs::current_path().string());
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
auto project = ParseJsonFromFile<projgen::Project>(project_json_path);
|
||||
|
||||
for(auto& pair : project.configurations) {
|
||||
std::printf("%s: %s %s %s\n", pair.first.c_str(), pair.second.cCompileFlags.c_str(), pair.second.cppCompileFlags.c_str(),
|
||||
pair.second.linkerFlags.value_or(PROJGEN_BASE_LD_FLAGS).c_str());
|
||||
}
|
||||
|
||||
auto sourceFiles = SourceFile::MakeArray(project.sourceFileNames);
|
||||
|
||||
for(auto& source : sourceFiles) {
|
||||
std::printf("%s -> %d\n", source.filename.c_str(), source.type);
|
||||
}
|
||||
|
||||
} catch(daw::json::json_exception& ex) {
|
||||
lucore::LogFatal("Exception while trying to parse JSON data: {} {}", ex.what(), ex.reason());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 730a54f2780c771df6263a43087fa8621e871052
|
|
@ -1,23 +1,22 @@
|
|||
{
|
||||
"Project": {
|
||||
"Name": "test",
|
||||
"Name": "test",
|
||||
|
||||
"Configurations": {
|
||||
"Debug": {
|
||||
"CCompileFlags": "-O0 ${BaseCCompileFlags}",
|
||||
"CppCompileFlags": "-O0 ${BaseCppCompileFlags}"
|
||||
},
|
||||
"Release": {
|
||||
"CCompileFlags": "-O2 ${BaseCCompileFlags}",
|
||||
"CppCompileFlags": "-O2 ${BaseCppCompileFlags}",
|
||||
"LinkerFlags": "-Wl,--gc-sections ${BaseLinkerFlags}"
|
||||
}
|
||||
"Configurations": {
|
||||
"Debug": {
|
||||
"CCompileFlags": "-O0",
|
||||
"CppCompileFlags": "-O0",
|
||||
"LinkerFlags": ""
|
||||
},
|
||||
"Release": {
|
||||
"CCompileFlags": "-O2",
|
||||
"CppCompileFlags": "-O2",
|
||||
"LinkerFlags": "-Wl,--gc-sections"
|
||||
}
|
||||
},
|
||||
|
||||
"Sources": [
|
||||
"binary.ld",
|
||||
"start.S",
|
||||
"main.c"
|
||||
]
|
||||
}
|
||||
"Sources": [
|
||||
"binary.ld",
|
||||
"start.S",
|
||||
"main.c"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue