added: linker file discovery
This commit is contained in:
parent
110946b1e1
commit
bd368f99ef
|
@ -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...");
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue