extension work + static library linking

This commit is contained in:
Hunter 2024-09-28 10:16:00 -04:00
parent ffa0f40652
commit b6ee9d0dc3
20 changed files with 568 additions and 131 deletions

View file

@ -20,7 +20,7 @@ int main() {
// PackageConfig
lua.new_usertype<PackageConfig>(
"PackageConfig", "name", &PackageConfig::name, "libraries",
"PackageConfig", sol::constructors<PackageConfig(sol::table)>(), "name", &PackageConfig::name, "libraries",
&PackageConfig::libraries, "include_dirs", &PackageConfig::include_dirs,
"compile_flags", &PackageConfig::compile_flags, "linker_flags",
&PackageConfig::linker_flags);
@ -28,36 +28,51 @@ int main() {
// GlobalConfig
lua.new_usertype<GlobalConfig>(
"GlobalConfig", "engine_version", &GlobalConfig::engine_version,
"architecture", &GlobalConfig::architecture, "target",
&GlobalConfig::target, "target_config", &GlobalConfig::target_config);
"architecture", &GlobalConfig::architecture, "target_config", &GlobalConfig::platform_config);
// Platform
lua.new_usertype<Platform>("Platform", "name", &Platform::name,
"cxx_compiler", &Platform::cxx_compiler,
"cc_compiler", &Platform::cc_compiler,
"platform_type", &Platform::platform_type, "is_64bit", &Platform::is_64bit);
"platform_type", &Platform::platform_type,
"is_64bit", &Platform::is_64bit);
// PlatformType
lua.new_enum<PlatformType>("PlatformType", {{"Win32", PlatformType_Win32},
{"Linux", PlatformType_Linux}});
// LanguageType
lua.new_enum<LanguageType>("LanguageType", {
{ "Cpp", LanguageType_CPP },
{ "C", LanguageType_C }
});
lua.new_enum<LanguageType>(
"LanguageType", {{"Cpp", LanguageType_CPP}, {"C", LanguageType_C}});
// LibraryType
lua.new_enum<LibraryType>("LibraryType", {{"Static", LibraryType_Static},
{"Shared", LibraryType_Shared}});
// ExecutableConfig
lua.new_usertype<ExecutableConfig>(
"ExecutableConfig", sol::constructors<ExecutableConfig(sol::table)>(),
"name", &ExecutableConfig::name, "files", &ExecutableConfig::files,
"requirments", &ExecutableConfig::requirements, "compile_flags",
"requirements", &ExecutableConfig::requirements, "compile_flags",
&ExecutableConfig::compile_flags, "linker_flags",
&ExecutableConfig::linker_flags, "include_dirs",
&ExecutableConfig::include_dirs, "language_type", &ExecutableConfig::language_type);
&ExecutableConfig::include_dirs, "language_type",
&ExecutableConfig::language_type);
// LibraryConfig
lua.new_usertype<LibraryConfig>(
"LibraryConfig", sol::constructors<LibraryConfig(sol::table)>(), "name",
&LibraryConfig::name, "files", &LibraryConfig::files, "requirements",
&LibraryConfig::requirements, "compile_flags",
&LibraryConfig::compile_flags, "linker_flags",
&LibraryConfig::linker_flags, "include_dirs",
&LibraryConfig::include_dirs, "language_type",
&LibraryConfig::language_type, "lib_type", &LibraryConfig::lib_type,
"package_config", &LibraryConfig::package_config);
// Package
lua.new_usertype<Package>("Package", sol::constructors<Package(sol::table)>(), "name", &Package::name, "compiler_flags",
lua.new_usertype<Package>("Package", sol::constructors<Package(sol::table)>(),
"name", &Package::name, "compiler_flags",
&Package::compiler_flags, "linker_flags",
&Package::linker_flags);
@ -66,6 +81,7 @@ int main() {
lua.set("grbc_get_config", grbc_get_config);
lua.set("grbc_file", grbc_file);
lua.set("grbc_executable", grbc_executable);
lua.set("grbc_library", grbc_library);
lua.set("grbc_load_platform", grbc_load_platform);
lua.set("grbc_set_platform", grbc_set_platform);
lua.set("grbc_find_compiler", grbc_find_compiler);
@ -79,13 +95,15 @@ int main() {
lua.set("grbc_is_linux", grbc_is_linux);
lua.set("grbc_is_win32", grbc_is_win32);
lua.set("grbc_get_platform", grbc_get_platform);
lua.set("grbc_compiler_define", grbc_compiler_define);
lua.set("grbc_get_lib_extension", grbc_get_lib_extension);
lua.set("grbc_bake_package_config", grbc_bake_package_config);
lua.set("grbc_pkg", grbc_pkg);
// Load generators
GState::get().generators.push_back({
.name = "ninja",
.func = ninja_generator
});
GState::get().generators.push_back(
{.name = "ninja", .func = ninja_generator});
log_msg("loading HConfig...");

View file

@ -40,7 +40,7 @@ std::string ninja_build_rule_link_cxx() {
std::string result = "## build_rule_link_cxx ##\n\n";
result += "rule link_cxx\n";
result += " command = $cxx_path $p_cflags -o $out $in $p_linker_flags\n";
result += " description = Linking C++ executables $out\n\n";
result += " description = Linking C++ target $out\n\n";
return result;
}
@ -49,7 +49,16 @@ std::string ninja_build_rule_link_cc() {
std::string result = "## build_rule_link_cc ##\n\n";
result += "rule link_cc\n";
result += " command = $cc_path $p_cflags -o $out $in $p_linker_flags\n";
result += " description = Linking C executables $out\n\n";
result += " description = Linking C target $out\n\n";
return result;
}
std::string ninja_build_rule_archive_library() {
std::string result = "## build_rule_archive_library ##\n\n";
result += "rule archive\n";
result += " command = rm -f $out; ar crs $out $in\n";
result += " description = Creating static library $out\n\n";
return result;
}
@ -79,9 +88,9 @@ std::string ninja_build_default_variables() {
return result;
}
std::string ninja_build_rule_link_exe_target(
const GeneratorLinkExecutableCommand &link_cmd) {
std::string result = "## Link: " + link_cmd.output_exe + " ##\n\n";
std::string
ninja_build_rule_link_lib_target(const GeneratorLinkTargetCommand &link_cmd) {
std::string result = "## Link: " + link_cmd.output_name + " ##\n\n";
std::string file_list;
@ -91,7 +100,34 @@ std::string ninja_build_rule_link_exe_target(
file_list.pop_back();
result += "build " + link_cmd.output_exe + ": link_cxx " + file_list + "\n";
if (link_cmd.target_type == GeneratorTargetType_SharedLibrary) {
result += "build $builddir/" + link_cmd.output_name + ": link_cxx " +
file_list + "\n";
result += " p_linker_flags = " + link_cmd.linker_flags + " -shared\n";
result += " p_cflags = \n\n";
} else {
result += "build $builddir/" + link_cmd.output_name + ": archive " +
file_list + "\n\n";
}
return result;
}
std::string
ninja_build_rule_link_exe_target(const GeneratorLinkTargetCommand &link_cmd) {
std::string result = "## Link: " + link_cmd.output_name + " ##\n\n";
std::string file_list;
for (auto &file : link_cmd.object_files) {
file_list += "$builddir/" + file + " ";
}
file_list.pop_back();
result += "build $builddir/" + link_cmd.output_name + ": link_cxx " +
file_list + "\n";
result += " p_linker_flags = " + link_cmd.linker_flags + "\n";
result += " p_cflags = \n\n";
@ -113,14 +149,19 @@ GeneratorResult ninja_generator() {
result.content += ninja_build_rule_compile_cxx();
result.content += ninja_build_rule_link_cc();
result.content += ninja_build_rule_link_cxx();
result.content += ninja_build_rule_archive_library();
for (auto &target : GState::get().targets) {
for (auto &compile_cmd : target.compile_commands) {
result.content += ninja_build_rule_compile_file(compile_cmd);
}
for (auto &link_cmd : target.link_executable_commands) {
result.content += ninja_build_rule_link_exe_target(link_cmd);
for (auto &link_cmd : target.link_target_commands) {
if (link_cmd.target_type == GeneratorTargetType_Executable) {
result.content += ninja_build_rule_link_exe_target(link_cmd);
} else {
result.content += ninja_build_rule_link_lib_target(link_cmd);
}
}
}

42
src/package.cc Normal file
View file

@ -0,0 +1,42 @@
#include "grbc/spec.h"
#include "grbc/state.h"
Package grbc_pkg(const std::string &package_name) {
for (auto &pkg : GState::get().packages) {
if (pkg.first == package_name) return pkg.second;
}
grbc_exception("Could not find package with name '" + package_name + "'");
return Package{};
}
Package grbc_bake_package_config(const PackageConfig &config) {
Package pkg{};
pkg.name = config.name;
// Generate list of compiler + linker arguments
for (auto &subpkg : config.libraries) {
pkg.compiler_flags += subpkg.compiler_flags + " ";
pkg.linker_flags += subpkg.linker_flags + " ";
}
for (auto &linker_flag : config.linker_flags) {
pkg.linker_flags += linker_flag + " ";
}
for (auto &compiler_flag : config.compile_flags) {
pkg.compiler_flags += compiler_flag + " ";
}
// Remove trailing whitespace
if (pkg.compiler_flags.back() == ' ')
pkg.compiler_flags.pop_back();
if (pkg.linker_flags.back() == ' ')
pkg.linker_flags.pop_back();
return pkg;
}

View file

@ -21,12 +21,16 @@ void grbc_set_platform(const Platform &platform) {
log_msg(("C++ compiler = " + platform.cxx_compiler).c_str());
log_msg(("C compiler = " + platform.cc_compiler).c_str());
grbc_get_config().platform_config = "in_memory";
}
void grbc_load_platform(const std::string &file_path) {
Platform platform = GState::get().lua.script_file(file_path);
grbc_set_platform(platform);
grbc_get_config().platform_config = file_path;
}
std::string grbc_find_compiler(const std::string &compiler_name) {

View file

@ -3,55 +3,60 @@
#include "grbc/state.h"
TargetInfo grbc_executable(const ExecutableConfig &executable_config) {
TargetInfo target_config{};
TargetInfo target_config{};
std::string exe_name = executable_config.name;
std::string compiler_args;
std::string linker_args;
std::string exe_name = executable_config.name;
for (auto &package : executable_config.requirements) {
compiler_args += package.compiler_flags + " ";
linker_args += package.linker_flags + " ";
}
if (grbc_is_win32())
exe_name += ".exe";
for (auto &linker_arg : executable_config.linker_flags) {
linker_args += linker_arg + " ";
}
std::string compiler_args;
std::string linker_args;
for (auto &compiler_arg : executable_config.compile_flags) {
compiler_args += compiler_arg + " ";
}
for (auto &package : executable_config.requirements) {
compiler_args += package.compiler_flags + " ";
linker_args += package.linker_flags + " ";
}
// Include directories
for (auto &linker_arg : executable_config.linker_flags) {
linker_args += linker_arg + " ";
}
compiler_args += grbc_include_dirs_to_cflags(executable_config.include_dirs);
for (auto &compiler_arg : executable_config.compile_flags) {
compiler_args += compiler_arg + " ";
}
GeneratorTarget target{};
// Include directories
std::vector<std::string> object_files;
compiler_args += grbc_include_dirs_to_cflags(executable_config.include_dirs);
for (auto &src_file : executable_config.files) {
GeneratorCompileCommand compile_cmd{};
compile_cmd.source_file = src_file;
compile_cmd.object_file = grbc_object_file(src_file);
compile_cmd.compiler_flags = compiler_args;
compile_cmd.language_type = executable_config.language_type;
GeneratorTarget target{};
object_files.push_back(compile_cmd.object_file);
std::vector<std::string> object_files;
target.compile_commands.push_back(compile_cmd);
}
for (auto &src_file : executable_config.files) {
GeneratorCompileCommand compile_cmd{};
compile_cmd.source_file = src_file;
compile_cmd.object_file = grbc_object_file(src_file);
compile_cmd.compiler_flags = compiler_args;
compile_cmd.language_type = executable_config.language_type;
// Final executable link
object_files.push_back(compile_cmd.object_file);
GeneratorLinkExecutableCommand executable_link_cmd{};
executable_link_cmd.linker_flags = linker_args;
executable_link_cmd.object_files = object_files;
executable_link_cmd.output_exe = exe_name;
target.compile_commands.push_back(compile_cmd);
}
target.link_executable_commands.push_back(executable_link_cmd);
// Final executable link
GState::get().targets.push_back(target);
GeneratorLinkTargetCommand executable_link_cmd{};
executable_link_cmd.linker_flags = linker_args;
executable_link_cmd.object_files = object_files;
executable_link_cmd.output_name = exe_name;
executable_link_cmd.target_type = GeneratorTargetType_Executable;
return target_config;
target.link_target_commands.push_back(executable_link_cmd);
GState::get().targets.push_back(target);
return target_config;
}

81
src/target_lib.cc Normal file
View file

@ -0,0 +1,81 @@
#include "grbc/generator.h"
#include "grbc/spec.h"
#include "grbc/state.h"
TargetInfo grbc_library(const LibraryConfig &library_config) {
TargetInfo target_config{};
std::string lib_name = library_config.name;
lib_name += grbc_get_lib_extension(library_config.lib_type);
std::string compiler_args;
std::string linker_args;
for (auto &package : library_config.requirements) {
compiler_args += package.compiler_flags + " ";
linker_args += package.linker_flags + " ";
}
for (auto &linker_arg : library_config.linker_flags) {
linker_args += linker_arg + " ";
}
for (auto &compiler_arg : library_config.compile_flags) {
compiler_args += compiler_arg + " ";
}
// Include directories
compiler_args += grbc_include_dirs_to_cflags(library_config.include_dirs);
GeneratorTarget target{};
std::vector<std::string> object_files;
for (auto &src_file : library_config.files) {
GeneratorCompileCommand compile_cmd{};
compile_cmd.source_file = src_file;
compile_cmd.object_file = grbc_object_file(src_file);
compile_cmd.compiler_flags = compiler_args;
compile_cmd.language_type = library_config.language_type;
object_files.push_back(compile_cmd.object_file);
target.compile_commands.push_back(compile_cmd);
}
// Generate package config
PackageConfig pkg_cfg{};
pkg_cfg.name = library_config.name;
pkg_cfg.libraries = library_config.package_config.libraries;
pkg_cfg.include_dirs = library_config.include_dirs;
if (library_config.lib_type == LibraryType_Static) {
pkg_cfg.linker_flags.push_back(grbc_get_config().build_dir + "/" + lib_name);
}
// FIXME: Shared library linker flags
if (!pkg_cfg.name.empty()) {
GState::get().packages.insert(
{pkg_cfg.name, grbc_bake_package_config(pkg_cfg)});
}
GeneratorLinkTargetCommand link_target{};
if (library_config.lib_type == LibraryType_Shared) {
link_target.target_type = GeneratorTargetType_SharedLibrary;
} else {
link_target.target_type = GeneratorTargetType_StaticLibrary;
}
link_target.object_files = object_files;
link_target.linker_flags = linker_args;
link_target.output_name = lib_name;
target.link_target_commands.push_back(link_target);
GState::get().targets.push_back(target);
return target_config;
}

View file

@ -1,5 +1,6 @@
#include "grbc/helpers.h"
#include "grbc/spec.h"
#include "grbc/state.h"
#include <cstdlib>
#include <ctime>
#include <filesystem>
@ -20,15 +21,15 @@ void grbc_want_version(const std::string &version) {
}
std::string grbc_object_file(const std::string &file_path) {
std::filesystem::path path(file_path);
path.replace_extension(".o");
std::filesystem::path path(file_path);
path.replace_extension(".o");
std::string path_str = path.generic_string();
std::string path_str = path.generic_string();
// Strip out stuff
std::string no_spaces = grbc_replace_string(path_str, ' ', '_');
// Strip out stuff
std::string no_spaces = grbc_replace_string(path_str, ' ', '_');
return no_spaces;
return no_spaces;
}
std::string grbc_replace_string(const std::string &string, char substring,
@ -47,15 +48,19 @@ std::string grbc_replace_string(const std::string &string, char substring,
return res;
}
GlobalConfig grbc_get_config() {
GlobalConfig& grbc_get_config() {
static GlobalConfig cfg{};
return cfg;
}
std::string grbc_include_dirs_to_cflags(const std::vector<std::string> &include_dirs) {
std::string
grbc_include_dirs_to_cflags(const std::vector<std::string> &include_dirs) {
if (include_dirs.empty())
return "";
std::string result;
for (auto &include_dir : include_dirs) {
result += "-I" + include_dir + " ";
}
@ -65,6 +70,31 @@ std::string grbc_include_dirs_to_cflags(const std::vector<std::string> &include_
return result;
}
void grbc_log(const std::string &message) {
log_msg(message.c_str());
void grbc_log(const std::string &message) { log_msg(message.c_str()); }
std::string grbc_compiler_define(const std::string &define,
const std::string &value) {
return "-D" + define + "=" + value;
}
std::string grbc_get_lib_extension(LibraryType lib_type) {
PlatformType platform_type = GState::get().current_platform.platform_type;
if (platform_type == PlatformType_Linux && lib_type == LibraryType_Shared) {
return ".so";
} else if (platform_type == PlatformType_Linux &&
lib_type == LibraryType_Static) {
return ".a";
} else if (platform_type == PlatformType_Win32 &&
lib_type == LibraryType_Shared) {
return ".dll";
} else if (platform_type == PlatformType_Win32 &&
lib_type == LibraryType_Static) {
return ".lib";
}
grbc_exception("Could not determine library extension for current platform + "
"library combo");
return "";
}