diff --git a/resources/testproject/csource/test.c b/resources/testproject/csource/test.c new file mode 100644 index 000000000..43083708f --- /dev/null +++ b/resources/testproject/csource/test.c @@ -0,0 +1,4 @@ +int test_doubler(int d) +{ + return d * d; +} \ No newline at end of file diff --git a/resources/testproject/hello_world.c3 b/resources/testproject/hello_world.c3 index 6ad121883..8877a4a25 100644 --- a/resources/testproject/hello_world.c3 +++ b/resources/testproject/hello_world.c3 @@ -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; } \ No newline at end of file diff --git a/resources/testproject/project.toml b/resources/testproject/project.toml index f557f4ebb..a06374c3e 100644 --- a/resources/testproject/project.toml +++ b/resources/testproject/project.toml @@ -8,3 +8,7 @@ warnings = ["no-unused"] sources = ["./**"] # libraries to use libs = [] +# c compiler +cc = "cc" +# c sources +csources = ["./csource/**"] diff --git a/src/build/build_options.h b/src/build/build_options.h index 36ce4986e..5b8253f25 100644 --- a/src/build/build_options.h +++ b/src/build/build_options.h @@ -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; diff --git a/src/build/project.c b/src/build/project.c index 5eff9509d..6a7b75df5 100644 --- a/src/build/project.c +++ b/src/build/project.c @@ -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"; diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 3e8053807..a2f76103b 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -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); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 8d3396c95..3befbbfb7 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -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 diff --git a/src/compiler/linker.c b/src/compiler/linker.c index 93f7f1610..824be63d2 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -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); diff --git a/src/utils/file_utils.c b/src/utils/file_utils.c index 2c0eade45..9e664a5f0 100644 --- a/src/utils/file_utils.c +++ b/src/utils/file_utils.c @@ -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; diff --git a/src/utils/lib.h b/src/utils/lib.h index e5d7c3c9b..8e7498af5 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -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();