added: linker file discovery

This commit is contained in:
Sven Vogel 2024-06-06 22:47:53 +02:00
parent 110946b1e1
commit bd368f99ef
5 changed files with 106 additions and 34 deletions

View File

@ -107,32 +107,6 @@ TargetConfig* default_target_config() {
return config; return config;
} }
const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) {
for (guint i = 0; i < config->link_search_paths->len; i++) {
const char* link_directory_path = g_array_index(config->link_search_paths, char*, i);
char* path = g_build_filename(link_directory_path, link_target_name, NULL);
char* cwd = g_get_current_dir();
char* canonical = g_canonicalize_filename(path, cwd);
const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS);
const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR);
g_free(path);
g_free(cwd);
if (exists && !is_dir) {
return canonical;
}
g_free(canonical);
}
// file not found
return NULL;
}
TargetConfig* default_target_config_from_args() { TargetConfig* default_target_config_from_args() {
DEBUG("generating default target from command line..."); DEBUG("generating default target from command line...");

View File

@ -48,12 +48,21 @@ LLVMCodeGenOptLevel llvm_opt_from_int(int level) {
PANIC("invalid code generation optimization level: %d", level); PANIC("invalid code generation optimization level: %d", level);
} }
static char* create_target_output_name(const TargetConfig* config) {
char* prefix = "";
if (config->mode == Library) {
prefix = "lib";
}
return g_strjoin("", prefix, config->name, NULL);
}
Target create_target_from_config(const TargetConfig* config) { Target create_target_from_config(const TargetConfig* config) {
DEBUG("Building target from configuration"); DEBUG("Building target from configuration");
Target target = create_native_target(); Target target = create_native_target();
target.name.str = config->name; target.name.str = create_target_output_name(config);
target.name.allocation = NONE; // freed later by compiler target.name.allocation = NONE; // freed later by compiler
target.opt = llvm_opt_from_int(config->optimization_level); target.opt = llvm_opt_from_int(config->optimization_level);

View File

@ -3,4 +3,88 @@
// //
#include <llvm/link/lld.h> #include <llvm/link/lld.h>
#include <sys/log.h>
const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) {
for (guint i = 0; i < config->link_search_paths->len; i++) {
const char* link_directory_path = g_array_index(config->link_search_paths, char*, i);
char* path = g_build_filename(link_directory_path, link_target_name, NULL);
char* cwd = g_get_current_dir();
char* canonical = g_canonicalize_filename(path, cwd);
const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS);
const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR);
g_free(path);
g_free(cwd);
if (exists && !is_dir) {
return canonical;
}
g_free(canonical);
}
// file not found
return NULL;
}
TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfig* target_config, const Module* module) {
DEBUG("generating link configuration");
TargetLinkConfig* config = malloc(sizeof(TargetLinkConfig));
config->object_file_names = g_array_new(FALSE, FALSE, sizeof(char*));
// append build object file
const char* target_object = get_absolute_link_path(target_config, (const char*) target->name.str);
if (target_object == NULL) {
ERROR("failed to resolve path to target object: %s", target->name.str);
lld_delete_link_config(config);
return NULL;
}
g_array_append_val(config->object_file_names, target_object);
INFO("resolved path of target object: %s", target_object);
// resolve absolute paths to dependent library object files
DEBUG("resolving target dependencies...");
for (guint i = 0; i < module->imports->len; i++) {
const char* dependency = g_array_index(module->imports, const char*, i);
const char* dependency_object = get_absolute_link_path(target_config, dependency);
if (dependency_object == NULL) {
ERROR("failed to resolve path to dependency object: %s", dependency);
lld_delete_link_config(config);
return NULL;
}
g_array_append_val(config->object_file_names, dependency_object);
INFO("resolved path of target object: %s", dependency_object);
}
INFO("resolved %d dependencies", config->object_file_names->len);
return config;
}
BackendError lld_link_target(TargetLinkConfig* config) {
BackendError err = SUCCESS;
char*
for (guint i = 0; i < config->object_file_names->len; i++) {
const char* path = g_array_index(config->object_file_names, const char*, i);
}
return err;
}
void lld_delete_link_config(TargetLinkConfig* config) {
for (guint i = 0; i < config->object_file_names->len; i++) {
free((void*) g_array_index(config->object_file_names, const char*, i));
}
g_array_free(config->object_file_names, TRUE);
free(config);
}

View File

@ -8,12 +8,10 @@
#include <codegen/backend.h> #include <codegen/backend.h>
#include <llvm/backend.h> #include <llvm/backend.h>
/** TargetLinkConfig* lld_create_link_config(const Target * target, const TargetConfig* target_config, const Module* module);
* @brief Link the target by its configuration to the final output.
* @param target BackendError lld_link_target(TargetLinkConfig* config);
* @param config
* @return void lld_delete_link_config(TargetLinkConfig* config);
*/
BackendError link_target(const Target* target, const TargetConfig* config);
#endif // LLVM_BACKEND_LLD_H #endif // LLVM_BACKEND_LLD_H

View File

@ -15,6 +15,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/log.h> #include <sys/log.h>
#include <llvm/link/lld.h>
BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target, BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target,
const TargetConfig* config) { const TargetConfig* config) {
@ -242,6 +243,12 @@ BackendError parse_module(const Module* module, const TargetConfig* config) {
export_module(unit, &target, config); export_module(unit, &target, config);
TargetLinkConfig* link_config = lld_create_link_config(&target, target, module);
lld_link_target(link_config);
lld_delete_link_config(link_config);
delete_target(target); delete_target(target);
} }