mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add support from compiling c from c3c.
This commit is contained in:
4
resources/testproject/csource/test.c
Normal file
4
resources/testproject/csource/test.c
Normal file
@@ -0,0 +1,4 @@
|
||||
int test_doubler(int d)
|
||||
{
|
||||
return d * d;
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
module hello_world;
|
||||
import bar;
|
||||
|
||||
extern fn void printf(char *hello);
|
||||
extern fn int test_doubler(int);
|
||||
extern fn void printf(char *, ...);
|
||||
|
||||
fn int main(int x)
|
||||
{
|
||||
printf("Hello World!\n");
|
||||
bar::test();
|
||||
printf("Hello double: %d\n", test_doubler(11));
|
||||
return 1;
|
||||
}
|
||||
@@ -8,3 +8,7 @@ warnings = ["no-unused"]
|
||||
sources = ["./**"]
|
||||
# libraries to use
|
||||
libs = []
|
||||
# c compiler
|
||||
cc = "cc"
|
||||
# c sources
|
||||
csources = ["./csource/**"]
|
||||
|
||||
@@ -242,6 +242,9 @@ typedef struct
|
||||
CompilerBackend backend;
|
||||
uint32_t symtab_size;
|
||||
uint32_t switchrange_max_size;
|
||||
const char *cc;
|
||||
const char **csource_dirs;
|
||||
const char **csources;
|
||||
struct
|
||||
{
|
||||
SoftFloat soft_float : 3;
|
||||
|
||||
@@ -134,10 +134,8 @@ void project_add_target(Project *project, TomlValue *wrapped_table, const char *
|
||||
target->arch_os_target = ARCH_OS_TARGET_DEFAULT;
|
||||
target->debug_info = DEBUG_INFO_NONE;
|
||||
target->symtab_size = DEFAULT_SYMTAB_SIZE;
|
||||
|
||||
vec_add(project->targets, target);
|
||||
TomlTable *table = wrapped_table->value.table;
|
||||
|
||||
target->name = get_valid_string(table, "name", type, true);
|
||||
VECEACH(project->targets, i)
|
||||
{
|
||||
@@ -148,6 +146,10 @@ void project_add_target(Project *project, TomlValue *wrapped_table, const char *
|
||||
error_exit("More %s contained more than one target with the name %s. Please make all target names unique.", PROJECT_TOML, target->name);
|
||||
}
|
||||
}
|
||||
target->cc = get_valid_string(table, "cc", type, false);
|
||||
if (!target->cc) target->cc = "cc";
|
||||
target->csource_dirs = get_valid_array(table, "csources", type, false);
|
||||
|
||||
type = strformat("%s %s", type, target->name);
|
||||
target->version = get_valid_string(table, "version", type, false);
|
||||
if (!target->version) target->version = "1.0.0";
|
||||
|
||||
@@ -303,7 +303,7 @@ void compiler_compile(void)
|
||||
|
||||
if (global_context.lib_dir)
|
||||
{
|
||||
file_add_wildcard_files(&global_context.sources, global_context.lib_dir, true);
|
||||
file_add_wildcard_files(&global_context.sources, global_context.lib_dir, true, ".c3", ".c3i");
|
||||
}
|
||||
bool has_error = false;
|
||||
VECEACH(global_context.sources, i)
|
||||
@@ -417,8 +417,28 @@ void compiler_compile(void)
|
||||
error_exit("No output files found.");
|
||||
}
|
||||
|
||||
unsigned cfiles = vec_size(active_target.csources);
|
||||
CompileData *compile_data = malloc(sizeof(CompileData) * output_file_count);
|
||||
const char **obj_files = malloc(sizeof(char*) * output_file_count);
|
||||
const char **obj_files = malloc(sizeof(char*) * (output_file_count + cfiles));
|
||||
|
||||
if (cfiles)
|
||||
{
|
||||
platform_compiler(active_target.csources, cfiles);
|
||||
for (int i = 0; i < cfiles; i++)
|
||||
{
|
||||
char *filename = NULL;
|
||||
char *dir = NULL;
|
||||
bool split_worked = filenamesplit(active_target.csources[i], &filename, &dir);
|
||||
assert(split_worked);
|
||||
free(dir);
|
||||
size_t len = strlen(filename);
|
||||
// .c -> .o (quick hack to fix the name on linux)
|
||||
filename[len - 1] = 'o';
|
||||
obj_files[output_file_count + i] = filename;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
TaskQueueRef queue = taskqueue_create(16);
|
||||
|
||||
@@ -439,6 +459,7 @@ void compiler_compile(void)
|
||||
assert(obj_files[i] || !create_exe);
|
||||
}
|
||||
|
||||
output_file_count += cfiles;
|
||||
free(compile_data);
|
||||
|
||||
if (create_exe)
|
||||
@@ -466,12 +487,14 @@ void compiler_compile(void)
|
||||
exit_compiler(COMPILER_SUCCESS_EXIT);
|
||||
}
|
||||
|
||||
static void target_expand_source_names(BuildTarget *target)
|
||||
static const char **target_expand_source_names(const char** dirs, const char *suffix1, const char *suffix2, bool error_on_mismatch)
|
||||
{
|
||||
const char **files = NULL;
|
||||
VECEACH(target->source_dirs, i)
|
||||
size_t len1 = strlen(suffix1);
|
||||
size_t len2 = strlen(suffix2);
|
||||
VECEACH(dirs, i)
|
||||
{
|
||||
const char *name = target->source_dirs[i];
|
||||
const char *name = dirs[i];
|
||||
size_t name_len = strlen(name);
|
||||
if (name_len < 1) goto INVALID_NAME;
|
||||
if (name[name_len - 1] == '*')
|
||||
@@ -480,7 +503,7 @@ static void target_expand_source_names(BuildTarget *target)
|
||||
{
|
||||
char *path = strdup(name);
|
||||
path[name_len - 1] = '\0';
|
||||
file_add_wildcard_files(&files, path, false);
|
||||
file_add_wildcard_files(&files, path, false, suffix1, suffix2);
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
@@ -489,21 +512,22 @@ static void target_expand_source_names(BuildTarget *target)
|
||||
{
|
||||
char *path = strdup(name);
|
||||
path[name_len - 2] = '\0';
|
||||
file_add_wildcard_files(&files, path, true);
|
||||
file_add_wildcard_files(&files, path, true, suffix1, suffix2);
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
goto INVALID_NAME;
|
||||
}
|
||||
if (name_len < 4) goto INVALID_NAME;
|
||||
if (strcmp(&name[name_len - 3], ".c3") != 0 &&
|
||||
(name_len < 5 || strcmp(&name[name_len - 4], ".c3t") != 0)) goto INVALID_NAME;
|
||||
if (strcmp(&name[name_len - len1], suffix1) != 0 &&
|
||||
(name_len < 5 || strcmp(&name[name_len - len2], suffix2) != 0)) goto INVALID_NAME;
|
||||
vec_add(files, name);
|
||||
continue;
|
||||
INVALID_NAME:
|
||||
error_exit("File names must end with .c3 or they cannot be compiled: '%s' is invalid.", name);
|
||||
if (!error_on_mismatch) continue;
|
||||
error_exit("File names must end with %s or they cannot be compiled: '%s' is invalid.", name, suffix1);
|
||||
}
|
||||
target->sources = files;
|
||||
return files;
|
||||
}
|
||||
|
||||
void compile_target(BuildOptions *options)
|
||||
@@ -520,7 +544,11 @@ void compile_file_list(BuildOptions *options)
|
||||
|
||||
void compile()
|
||||
{
|
||||
target_expand_source_names(&active_target);
|
||||
active_target.sources = target_expand_source_names(active_target.source_dirs, ".c3", ".c3t", true);
|
||||
if (active_target.csource_dirs)
|
||||
{
|
||||
active_target.csources = target_expand_source_names(active_target.csource_dirs, ".c", ".c", false);
|
||||
}
|
||||
global_context.sources = active_target.sources;
|
||||
symtab_init(active_target.symtab_size ? active_target.symtab_size : 64 * 1024);
|
||||
target_setup(&active_target);
|
||||
|
||||
@@ -2462,6 +2462,7 @@ static inline AlignSize type_min_alignment(AlignSize a, AlignSize b)
|
||||
bool obj_format_linking_supported(ObjectFormatType format_type);
|
||||
bool linker(const char *output_file, const char **files, unsigned file_count);
|
||||
void platform_linker(const char *output_file, const char **files, unsigned file_count);
|
||||
void platform_compiler(const char **files, unsigned file_count);
|
||||
|
||||
#define CAT(a,b) CAT2(a,b) // force expand
|
||||
#define CAT2(a,b) a##b // actually concatenate
|
||||
|
||||
@@ -285,7 +285,7 @@ const char *concat_string_parts(const char **args)
|
||||
void platform_linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
const char **parts = NULL;
|
||||
vec_add(parts, "cc");
|
||||
vec_add(parts, active_target.cc);
|
||||
VECEACH(active_target.link_args, i)
|
||||
{
|
||||
vec_add(parts, active_target.link_args[i]);
|
||||
@@ -319,6 +319,38 @@ void platform_linker(const char *output_file, const char **files, unsigned file_
|
||||
}
|
||||
printf("Program linked to executable '%s'.\n", output_file);
|
||||
}
|
||||
|
||||
void platform_compiler(const char **files, unsigned file_count)
|
||||
{
|
||||
const char **parts = NULL;
|
||||
vec_add(parts, active_target.cc);
|
||||
switch (platform_target.pie)
|
||||
{
|
||||
case PIE_DEFAULT:
|
||||
UNREACHABLE
|
||||
case PIE_NONE:
|
||||
vec_add(parts, "-fno-PIE");
|
||||
vec_add(parts, "-fno-pie");
|
||||
break;
|
||||
case PIE_SMALL:
|
||||
vec_add(parts, "-fpie");
|
||||
break;
|
||||
case PIE_BIG:
|
||||
vec_add(parts, "-fPIE");
|
||||
break;
|
||||
}
|
||||
vec_add(parts, "-c");
|
||||
for (unsigned i = 0; i < file_count; i++)
|
||||
{
|
||||
vec_add(parts, files[i]);
|
||||
}
|
||||
const char *output = concat_string_parts(parts);
|
||||
if (system(output) != 0)
|
||||
{
|
||||
error_exit("Failed to compile c sources using command '%s'.\n", output);
|
||||
}
|
||||
}
|
||||
|
||||
bool linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
return link_exe(output_file, files, file_count);
|
||||
|
||||
@@ -278,7 +278,7 @@ void file_find_top_dir()
|
||||
}
|
||||
}
|
||||
|
||||
void file_add_wildcard_files(const char ***files, const char *path, bool recursive)
|
||||
void file_add_wildcard_files(const char ***files, const char *path, bool recursive, const char *suffix1, const char *suffix2)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
DIR *dir = opendir(strip_drive_prefix(path));
|
||||
@@ -291,13 +291,15 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi
|
||||
error_exit("Can't open the directory '%s'. Please check the paths. %s", path, strerror(errno));
|
||||
}
|
||||
struct dirent *ent;
|
||||
size_t len1 = strlen(suffix1);
|
||||
size_t len2 = strlen(suffix2);
|
||||
while ((ent = readdir(dir)))
|
||||
{
|
||||
size_t namelen = strlen(ent->d_name);
|
||||
if (namelen < 3) continue;
|
||||
|
||||
// Doesn't end with .c3
|
||||
if (strncmp(&ent->d_name[namelen - 3], ".c3", 3) != 0)
|
||||
if (strncmp(&ent->d_name[namelen - len1], suffix1, len1) != 0 && strncmp(&ent->d_name[namelen - len2], suffix2, len2) != 0)
|
||||
{
|
||||
char *new_path = NULL;
|
||||
char *format = path_ends_with_slash ? "%s%s" : "%s/%s";
|
||||
@@ -315,7 +317,7 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi
|
||||
is_directory = S_ISDIR(st.st_mode);
|
||||
if (is_directory && ent->d_name[0] != '.' && recursive)
|
||||
{
|
||||
file_add_wildcard_files(files, new_path, recursive);
|
||||
file_add_wildcard_files(files, new_path, recursive, suffix1, suffix2);
|
||||
}
|
||||
free(new_path);
|
||||
continue;
|
||||
|
||||
@@ -33,7 +33,7 @@ const char* find_lib_dir(void);
|
||||
char *read_file(const char *path, size_t *return_size);
|
||||
void path_get_dir_and_filename_from_full(const char *full_path, char **filename, char **dir_path);
|
||||
void file_find_top_dir();
|
||||
void file_add_wildcard_files(const char ***files, const char *path, bool recursive);
|
||||
void file_add_wildcard_files(const char ***files, const char *path, bool recursive, const char *suffix1, const char *suffix2);
|
||||
void *cmalloc(size_t size);
|
||||
void memory_init(void);
|
||||
void memory_release();
|
||||
|
||||
Reference in New Issue
Block a user