Support c-file compilation in libraries.

This commit is contained in:
Christoffer Lerno
2024-07-06 23:49:10 +02:00
parent c3ecad96b7
commit 3f62775f4b
19 changed files with 421 additions and 347 deletions

View File

@@ -45,6 +45,7 @@ jobs:
- name: Build testproject
run: |
set PATH=%PATH%;"C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/14.40.33807/bin/Hostx64/x64"
cd resources/testproject
..\..\build\${{ matrix.build_type }}\c3c.exe --debug-log --emit-llvm run hello_world_win32
dir build\llvm_ir

View File

@@ -244,6 +244,7 @@ add_executable(c3c
src/build/builder.c
src/build/build_options.c
src/build/project_creation.c
src/build/libraries.c
src/compiler/ast.c
src/compiler/bigint.c
src/compiler/codegen_general.c
@@ -256,7 +257,6 @@ add_executable(c3c
src/compiler/headers.c
src/compiler/json_output.c
src/compiler/lexer.c
src/compiler/libraries.c
src/compiler/linker.c
src/compiler/llvm_codegen.c
src/compiler/abi/c_abi_aarch64.c
@@ -325,7 +325,8 @@ add_executable(c3c
src/compiler/expr.c
src/utils/time.c
src/utils/http.c
src/compiler/sema_liveness.c)
src/compiler/sema_liveness.c
src/build/common_build.c)
if (C3_USE_TB)

View File

@@ -13,6 +13,7 @@
- Updated mangling.
- Added `$$unaligned_load` and `$$unaligned_store`.
- `--no-headers` option to suppress creating headers when generating a library.
- Support c-file compilation in libraries.
### Fixes
- Error with unsigned compare in `@ensure` when early returning 0 #1207.

View File

@@ -1,6 +1,7 @@
module hello_world;
import std;
import bar;
import clib;
fn int test_doubler(int x) @if(env::WIN32) => x * x;
extern fn int test_doubler(int) @if(!env::WIN32);
@@ -12,6 +13,6 @@ fn int main()
bar::test();
printf("Hello double: %d\n", test_doubler(11));
if ($feature(ABCD)) io::printn("ABCD");
clib::hello_from_c();
return 0;
}

View File

@@ -0,0 +1,3 @@
module clib;
extern fn void hello_from_c();

View File

@@ -0,0 +1,5 @@
#include <stdio.h>
void hello_from_c(void)
{
puts("Hello from C!");
}

View File

@@ -0,0 +1,13 @@
{
"provides" : "clib",
"c-sources" : ["hello.c"],
"targets" : {
"macos-x64" : {
},
"macos-aarch64" : {},
"linux-x64" : {
"c-flags-override": "-fPIE"
},
"windows-x64" : { }
}
}

View File

@@ -11,23 +11,23 @@
"sources": [
"./**"
],
// libraries to use
"dependencies": [],
"dependency-search-paths": [ "./lib" ],
"dependencies": ["clib"],
"features": ["ABCD"],
// c compiler
"cc": "cc",
// c sources
"targets": {
"hello_world": {
"type": "executable",
"c-sources-override": [
"./csource/**"
]
],
"reloc": "PIE",
},
"hello_world_win32": {
"type": "executable",
"cc" : "cl.exe",
"c-sources-override": [
]
},

View File

@@ -419,19 +419,27 @@ typedef enum
typedef struct
{
struct Library__ *parent;
ArchOsTarget arch_os;
const char *cc;
const char *cflags;
const char **csource_dirs;
const char **csources;
const char **execs;
const char **link_flags;
const char **linked_libs;
const char **depends;
} LibraryTarget;
typedef struct
typedef struct Library__
{
const char *dir;
const char *provides;
const char **depends;
const char **execs;
const char *cc;
const char *cflags;
const char **csource_dirs;
LibraryTarget *target_used;
LibraryTarget **targets;
} Library;
@@ -441,6 +449,7 @@ typedef struct
{
TargetType type;
Library **library_list;
LibraryTarget **ccompling_libraries;
const char *name;
const char *version;
const char *langrev;
@@ -501,9 +510,9 @@ typedef struct
const char *testfn;
const char *cc;
const char *cflags;
const char **exec;
const char **csource_dirs;
const char **csources;
const char **exec;
const char **feature_list;
const char *custom_linker_path;
struct
@@ -566,7 +575,7 @@ static BuildTarget default_build_target = {
.strip_unused = STRIP_UNUSED_NOT_SET,
.symtab_size = DEFAULT_SYMTAB_SIZE,
.reloc_model = RELOC_DEFAULT,
.cc = "cc",
.cc = NULL,
.version = "1.0.0",
.langrev = "1",
.cpu = "generic",
@@ -591,3 +600,4 @@ bool command_accepts_files(CompilerCommand command);
void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting level);
void create_project(BuildOptions *build_options);
void create_library(BuildOptions *build_options);
void resolve_libraries(BuildTarget *build_target);

View File

@@ -12,6 +12,8 @@ typedef struct
BuildTarget **targets;
} Project;
extern const char *trust_level[3];
static const char *memory_environment[6] = {
[MEMORY_ENV_NORMAL] = "normal",
[MEMORY_ENV_SMALL] = "small",
@@ -85,3 +87,15 @@ static const char *reloc_models[5] = {
Project *project_load(void);
BuildTarget *project_select_target(Project *project, const char *optional_target);
void update_feature_flags(const char ***flags, const char ***removed_flag, const char *arg, bool add);
const char *get_string(const char *file, const char *category, JSONObject *table, const char *key,
const char *default_value);
int get_valid_bool(const char *file, const char *target, JSONObject *json, const char *key, int default_val);
const char *get_optional_string(const char *file, const char *category, JSONObject *table, const char *key);
const char *get_mandatory_string(const char *file, const char *category, JSONObject *object, const char *key);
const char **get_string_array(const char *file, const char *category, JSONObject *table, const char *key, bool mandatory);
const char **get_optional_string_array(const char *file, const char *target, JSONObject *table, const char *key);
const char *get_cflags(const char *file, const char *target, JSONObject *json, const char *original_flags);
void get_list_append_strings(const char *file, const char *target, JSONObject *json, const char ***list_ptr,
const char *base, const char *override, const char *add);
int get_valid_string_setting(const char *file, const char *target, JSONObject *json, const char *key, const char** values, int first_result, int count, const char *expected);

135
src/build/common_build.c Normal file
View File

@@ -0,0 +1,135 @@
#include "build_internal.h"
#include "utils/common.h"
const char *get_optional_string(const char *file, const char *category, JSONObject *table, const char *key)
{
JSONObject *value = json_obj_get(table, key);
if (!value) return NULL;
if (value->type != J_STRING)
{
if (category) error_exit("In file '%s': '%s' had an invalid '%s' field that was not a string, please correct it.", file, category, key);
error_exit("File '%s' had an invalid '%s' field that was not a string, please correct it.", file, category, key);
}
return value->str;
}
const char *get_mandatory_string(const char *file, const char *category, JSONObject *object, const char *key)
{
const char *value = get_optional_string(file, category, object, key);
if (!value)
{
if (category) error_exit("In file '%s': The mandatory field '%s' was missing in '%s'.", file, key, category);
error_exit("In file '%s': The mandatory field '%s' was missing.", file);
}
return value;
}
const char *get_string(const char *file, const char *category, JSONObject *table, const char *key,
const char *default_value)
{
const char *value = get_optional_string(file, category, table, key);
return value ? value : default_value;
}
int get_valid_bool(const char *file, const char *target, JSONObject *json, const char *key, int default_val)
{
JSONObject *value = json_obj_get(json, key);
if (!value) return default_val;
if (value->type != J_BOOL)
{
if (target) error_exit("In file '%s': '%s' had an invalid '%s' field that was not a boolean, please correct it.", file, target, key);
error_exit("In file '%s': An invalid '%s' field that was not a boolean, please correct it.", file, target, key);
}
return value->b;
}
const char **get_string_array(const char *file, const char *category, JSONObject *table, const char *key, bool mandatory)
{
JSONObject *value = json_obj_get(table, key);
if (!value)
{
if (mandatory)
{
if (category) error_exit("In file '%s': '%s' was missing a mandatory '%s' field, please add it.", file, category, key);
error_exit("In file '%s': mandatory '%s' field is missing, please add it.", file, key);
}
return NULL;
}
if (value->type != J_ARRAY) goto NOT_ARRAY;
const char **values = NULL;
for (unsigned i = 0; i < value->array_len; i++)
{
JSONObject *val = value->elements[i];
if (val->type != J_STRING) goto NOT_ARRAY;
vec_add(values, val->str);
}
return values;
NOT_ARRAY:
if (category) error_exit("In file '%s': '%s' had an invalid mandatory '%s' field that was not a string array, please correct it", file, category, key);
error_exit("In file '%s': mandatory '%s' field that was not a string array, please correct it.", file, key);
}
const char **get_optional_string_array(const char *file, const char *target, JSONObject *table, const char *key)
{
return get_string_array(file, target, table, key, false);
}
const char *get_cflags(const char *file, const char *target, JSONObject *json, const char *original_flags)
{
// CFlags
const char *cflags = get_optional_string(file, target, json, target ? "cflags-override" : "cflags");
const char *cflags_add = target ? get_optional_string(file, target, json, "cflags-add") : NULL;
if (cflags && cflags_add)
{
error_exit("In file '%s': '%s' is combining both 'cflags-add' and 'cflags-override', only one may be used.", file, target);
}
if (cflags) original_flags = cflags;
if (!cflags_add) return original_flags;
if (original_flags)
{
return str_printf("%s %s", original_flags, cflags_add);
}
return cflags_add;
}
INLINE void append_strings_to_strings(const char*** list_of_strings_ptr, const char **strings_to_append)
{
FOREACH(const char *, string, strings_to_append) vec_add(*list_of_strings_ptr, string);
}
void get_list_append_strings(const char *file, const char *target, JSONObject *json, const char ***list_ptr,
const char *base, const char *override, const char *add)
{
const char **value = get_optional_string_array(file, target, json, target ? override : base);
const char **add_value = target ? get_optional_string_array(file, target, json, add) : NULL;
if (value && add_value)
{
error_exit("In file '%s': '%s' is combining both '%s' and '%s', only one may be used.", file, target, override, add);
}
if (value) *list_ptr = value;
if (add_value)
{
append_strings_to_strings(&add_value, *list_ptr);
*list_ptr = add_value;
}
}
int get_valid_string_setting(const char *file, const char *target, JSONObject *json, const char *key, const char** values, int first_result, int count, const char *expected)
{
JSONObject *value = json_obj_get(json, key);
if (!value)
{
return -1;
}
if (value->type == J_STRING)
{
int res = str_findlist(value->str, count, values);
if (res >= 0) return res + first_result;
}
if (target)
{
error_exit("In file '%s': '%s' had an invalid value for '%s', expected %s", file, target, key, expected);
}
error_exit("In file '%s': Invalid value for '%s', expected %s", file, key, expected);
}

View File

@@ -1,49 +1,10 @@
#include "compiler_internal.h"
#include "../utils/json.h"
#include "build_internal.h"
#include "compiler/compiler.h"
#define MANIFEST_FILE "manifest.json"
static inline void parse_library_target(Library *library, LibraryTarget *target, JSONObject *object);
static inline JSONObject *get_mandatory(Library *library, JSONObject *object, const char *key)
{
JSONObject *value = json_obj_get(object, key);
if (!value) error_exit("The mandatory '%s' field was missing in '%s'.", library->dir);
return value;
}
static inline const char *get_mandatory_string(Library *library, JSONObject *object, const char *key)
{
JSONObject *value = get_mandatory(library, object, key);
if (value->type != J_STRING) error_exit("Expected string value for '%s' in '%s'.", library->dir);
return value->str;
}
static inline JSONObject *get_optional_string_array(Library *library, JSONObject *object, const char *key)
{
JSONObject *value = json_obj_get(object, key);
if (!value) return NULL;
if (value->type != J_ARRAY) error_exit("Expected an array value for '%s' in '%s'.", library->dir);
for (int i = 0; i < value->array_len; i++)
{
JSONObject *val = value->elements[i];
if (val->type != J_STRING) error_exit("Expected only strings in array '%s' in '%s'.", library->dir);
}
return value;
}
static inline const char **get_optional_string_array_as_array(Library *library, JSONObject *object, const char *key)
{
JSONObject *array = get_optional_string_array(library, object, key);
if (!array || !array->array_len) return NULL;
const char **array_result = VECNEW(const char*, array->array_len);
for (size_t i = 0; i < array->array_len; i++)
{
vec_add(array_result, array->elements[i]->str);
}
return array_result;
}
static inline void parse_library_target(Library *library, LibraryTarget *target, const char *target_name,
JSONObject *object);
static inline void parse_library_type(Library *library, LibraryTarget ***target_group, JSONObject *object)
{
@@ -55,6 +16,7 @@ static inline void parse_library_type(Library *library, LibraryTarget ***target_
const char *key = object->keys[i];
if (member->type != J_OBJECT) error_exit("Expected a list of properties for a target in %s.", library->dir);
LibraryTarget *library_target = CALLOCS(LibraryTarget);
library_target->parent = library;
ArchOsTarget target = arch_os_target_from_string(key);
if (target == ARCH_OS_TARGET_DEFAULT)
{
@@ -62,39 +24,45 @@ static inline void parse_library_type(Library *library, LibraryTarget ***target_
}
library_target->arch_os = target;
vec_add(*target_group, library_target);
parse_library_target(library, library_target, member);
parse_library_target(library, library_target, key, member);
}
}
static inline void parse_library_target(Library *library, LibraryTarget *target, JSONObject *object)
static inline void parse_library_target(Library *library, LibraryTarget *target, const char *target_name,
JSONObject *object)
{
target->link_flags = get_optional_string_array_as_array(library, object, "linkflags");
target->linked_libs = get_optional_string_array_as_array(library, object, "linked-libs");
target->depends = get_optional_string_array_as_array(library, object, "depends");
target->execs = get_optional_string_array_as_array(library, object, "execs");
target->link_flags = get_string_array(library->dir, target_name, object, "linkflags", false);
target->linked_libs = get_string_array(library->dir, target_name, object, "linked-libs", false);
target->depends = get_string_array(library->dir, target_name, object, "depends", false);
target->execs = get_string_array(library->dir, target_name, object, "execs", false);
target->cc = get_string(library->dir, target_name, object, "cc", library->cc);
target->cflags = get_cflags(library->dir, target_name, object, library->cflags);
target->csource_dirs = library->csource_dirs;
get_list_append_strings(library->dir, target_name, object, &target->csource_dirs, "c-sources", "c-sources-override", "c-sources-add");
}
static Library *add_library(JSONObject *object, const char *dir)
{
Library *library = CALLOCS(Library);
library->dir = dir;
const char *provides = get_mandatory_string(library, object, "provides");
const char *provides = get_mandatory_string(dir, NULL, object, "provides");
DEBUG_LOG("Added library %s", provides);
if (!str_is_valid_lowercase_name(provides))
{
char *res = strdup(provides);
str_ellide_in_place(res, 32);
error_exit("Invalid 'provides' module name in %s, was '%s'.", library->dir,
json_obj_get(object, "provides")->str);
error_exit("Invalid 'provides' module name in %s, was '%s'.", library->dir, res);
}
library->provides = provides;
library->execs = get_optional_string_array_as_array(library, object, "execs");
library->depends = get_optional_string_array_as_array(library, object, "depends");
library->execs = get_optional_string_array(library->dir, NULL, object, "execs");
library->depends = get_optional_string_array(library->dir, NULL, object, "depends");
library->cc = get_optional_string(dir, NULL, object, "cc");
library->cflags = get_cflags(library->dir, NULL, object, NULL);
get_list_append_strings(library->dir, NULL, object, &library->csource_dirs, "c-sources", "c-sources-override", "c-sources-add");
parse_library_type(library, &library->targets, json_obj_get(object, "targets"));
return library;
}
static Library *find_library(Library **libs, size_t lib_count, const char *name)
{
for (size_t i = 0; i < lib_count; i++)
@@ -104,13 +72,13 @@ static Library *find_library(Library **libs, size_t lib_count, const char *name)
error_exit("Required library '%s' could not be found. You can add additional library search paths using '--libdir' in case you forgot one.", name);
}
static void add_library_dependency(Library *library, Library **library_list, size_t lib_count)
static void add_library_dependency(BuildTarget *build_target, Library *library, Library **library_list, size_t lib_count)
{
if (library->target_used) return;
LibraryTarget *target_found = NULL;
FOREACH(LibraryTarget *, target, library->targets)
{
if (target->arch_os == active_target.arch_os_target)
if (target->arch_os == build_target->arch_os_target)
{
target_found = target;
break;
@@ -118,16 +86,17 @@ static void add_library_dependency(Library *library, Library **library_list, siz
}
if (!target_found)
{
error_exit("Library '%s' cannot be used with arch/os '%s'.", library->provides, arch_os_target[active_target.arch_os_target]);
error_exit("Library '%s' cannot be used with arch/os '%s'.", library->provides, arch_os_target[build_target->arch_os_target]);
}
library->target_used = target_found;
FOREACH(const char *, dependency, library->depends)
{
add_library_dependency(find_library(library_list, lib_count, dependency), library_list, lib_count);
add_library_dependency(build_target, find_library(library_list, lib_count, dependency), library_list, lib_count);
}
FOREACH(const char *, dependency, target_found->depends)
{
add_library_dependency(find_library(library_list, lib_count, dependency),
add_library_dependency(build_target,
find_library(library_list, lib_count, dependency),
library_list,
lib_count);
}
@@ -150,7 +119,7 @@ INLINE JSONObject* read_manifest(const char *lib, const char *manifest_data)
return json;
}
static inline JSONObject *resolve_zip_library(const char *lib, const char **resulting_library)
static inline JSONObject *resolve_zip_library(BuildTarget *build_target, const char *lib, const char **resulting_library)
{
FILE *f = fopen(lib, "rb");
if (!f) error_exit("Failed to open library '%s' for reading.", lib);
@@ -176,7 +145,7 @@ static inline JSONObject *resolve_zip_library(const char *lib, const char **resu
// Create the directory for the temporary files.
const char *lib_name = filename(lib);
scratch_buffer_clear();
scratch_buffer_append(active_target.build_dir ? active_target.build_dir : "_temp_build");
scratch_buffer_append(build_target->build_dir ? build_target->build_dir : "_temp_build");
scratch_buffer_printf("/_c3l/%s_%x/", lib_name, file.file_crc32);
const char *lib_dir = scratch_buffer_copy();
dir_make_recursive(scratch_buffer_to_string());
@@ -197,21 +166,24 @@ static inline JSONObject *resolve_zip_library(const char *lib, const char **resu
return json;
}
void resolve_libraries(void)
void resolve_libraries(BuildTarget *build_target)
{
DEBUG_LOG("Resolve libraries");
static const char *c3lib_suffix = ".c3l";
const char **c3_libs = NULL;
unsigned libdir_count = vec_size(active_target.libdirs);
unsigned libdir_count = vec_size(build_target->libdirs);
if (libdir_count)
{
FOREACH(const char *, dir, active_target.libdirs)
FOREACH(const char *, dir, build_target->libdirs)
{
DEBUG_LOG("Search %s", dir);
file_add_wildcard_files(&c3_libs, dir, false, &c3lib_suffix, 1);
}
}
else
{
// Default to '.'
DEBUG_LOG("Search '.'");
file_add_wildcard_files(&c3_libs, ".", false, &c3lib_suffix, 1);
}
Library *libraries[MAX_LIB_DIRS * 2];
@@ -221,7 +193,7 @@ void resolve_libraries(void)
JSONObject *json;
if (!file_is_dir(lib))
{
json = resolve_zip_library(lib, &lib);
json = resolve_zip_library(build_target, lib, &lib);
}
else
{
@@ -232,24 +204,28 @@ void resolve_libraries(void)
if (lib_count == MAX_LIB_DIRS * 2) error_exit("Too many libraries added, exceeded %d.", MAX_LIB_DIRS * 2);
libraries[lib_count++] = add_library(json, lib);
}
FOREACH(const char *, lib_name, active_target.libs)
FOREACH(const char *, lib_name, build_target->libs)
{
add_library_dependency(find_library(libraries, lib_count, lib_name), libraries, lib_count);
add_library_dependency(build_target, find_library(libraries, lib_count, lib_name), libraries, lib_count);
}
for (size_t i = 0; i < lib_count; i++)
{
Library *library = libraries[i];
LibraryTarget *target = library->target_used;
if (!target) continue;
file_add_wildcard_files(&active_target.sources, library->dir, false, c3_suffix_list, 3);
vec_add(active_target.library_list, library);
const char *libdir = file_append_path(library->dir, arch_os_target[active_target.arch_os_target]);
if (file_is_dir(libdir)) vec_add(active_target.linker_libdirs, libdir);
if ((vec_size(library->execs) || vec_size(target->execs)) && active_target.trust_level < TRUST_FULL)
if (vec_size(target->csource_dirs))
{
vec_add(build_target->ccompling_libraries, target);
}
file_add_wildcard_files(&build_target->sources, library->dir, false, c3_suffix_list, 3);
vec_add(build_target->library_list, library);
const char *libdir = file_append_path(library->dir, arch_os_target[build_target->arch_os_target]);
if (file_is_dir(libdir)) vec_add(build_target->linker_libdirs, libdir);
if ((vec_size(library->execs) || vec_size(target->execs)) && build_target->trust_level < TRUST_FULL)
{
error_exit("Could not use library '%s' as it requires 'exec' trust level to execute (it "
"is currently '%s'). Use the '--trust=full' option to enable it.",
library->provides, trust_level[active_target.trust_level]);
library->provides, trust_level[build_target->trust_level]);
}
FOREACH(const char *, exec, library->execs)
{

View File

@@ -4,8 +4,13 @@
#include <math.h>
#include "build_internal.h"
#include "utils/json.h"
#define MAX_SYMTAB_SIZE (1024 * 1024)
#define GET_SETTING(type__, key__, strings__, comment__) \
(type__)get_valid_string_setting(PROJECT_JSON, target_name, json, key__, strings__, 0, ELEMENTLEN(strings__), comment__)
const char *project_default_keys[][2] = {
{"authors", "Authors, optionally with email."},
{"benchfn", "Override the benchmark function."},
@@ -120,54 +125,6 @@ const char* project_target_keys[][2] = {
const int project_target_keys_count = ELEMENTLEN(project_target_keys);
static const char *get_string(JSONObject *table, const char *key, const char *category, const char *default_value)
{
JSONObject *value = json_obj_get(table, key);
if (!value) return default_value;
if (value->type != J_STRING)
{
error_exit("%s had an invalid '%s' field that was not a string, please correct it.", category, key);
}
return value->str;
}
static const char *get_valid_string(JSONObject *table, const char *key, const char *category)
{
JSONObject *value = json_obj_get(table, key);
if (!value) return NULL;
if (value->type != J_STRING)
{
error_exit("%s had an invalid '%s' field that was not a string, please correct it.", category, key);
}
return value->str;
}
int get_valid_bool(JSONObject *json, const char *key, const char *category, int default_val)
{
JSONObject *value = json_obj_get(json, key);
if (!value) return default_val;
if (value->type != J_BOOL)
{
error_exit("%s had an invalid mandatory '%s' field that was not a boolean, please correct it.", category, key);
}
return value->b;
}
static int get_valid_string_setting(JSONObject *json, const char *key, const char *category, const char** values, int first_result, int count, const char *expected)
{
JSONObject *value = json_obj_get(json, key);
if (!value)
{
return -1;
}
if (value->type == J_STRING)
{
int res = str_findlist(value->str, count, values);
if (res >= 0) return res + first_result;
}
error_exit("%s had an invalid value for '%s', expected %s", category, key, expected);
}
long get_valid_integer(JSONObject *table, const char *key, const char *category, bool mandatory)
{
@@ -187,36 +144,7 @@ long get_valid_integer(JSONObject *table, const char *key, const char *category,
return (long)trunc(value->f);
}
static const char **get_valid_array(JSONObject *table, const char *key, const char *category, bool mandatory)
{
JSONObject *value = json_obj_get(table, key);
if (!value)
{
if (mandatory)
{
error_exit("Error reading %s: %s was missing a mandatory '%s' field, please add it.", PROJECT_JSON, category, key);
}
return NULL;
}
if (value->type != J_ARRAY)
{
error_exit("Error reading %s: %s had an invalid mandatory '%s' field that was not an array, please correct it.", PROJECT_JSON, category, key);
}
const char **values = NULL;
for (unsigned i = 0; i < value->array_len; i++)
{
JSONObject *val = value->elements[i];
if (val->type != J_STRING)
{
error_exit("Error reading %s: %s had an invalid mandatory '%s' array that did not only hold strings, please correct it.", PROJECT_JSON, category, key);
}
vec_add(values, val->str);
}
return values;
}
static void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONObject *json, const char *type)
static void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONObject *json, const char *target_name)
{
static bool failed_shown = false;
bool failed = false;
@@ -227,7 +155,7 @@ static void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONO
{
if (strcmp(key, valid_keys[j][0]) == 0) goto OK;
}
eprintf("WARNING: Unknown parameter '%s' in '%s'.\n", key, type);
eprintf("WARNING: Unknown parameter '%s' in '%s'.\n", key, target_name ? target_name : "default_target");
failed = true;
OK:;
}
@@ -238,103 +166,48 @@ static void check_json_keys(const char* valid_keys[][2], size_t key_count, JSONO
}
}
INLINE void append_strings_to_strings(const char*** list_of_strings_ptr, const char **strings_to_append)
static void load_into_build_target(JSONObject *json, const char *target_name, BuildTarget *target)
{
FOREACH(const char *, string, strings_to_append)
if (target_name)
{
vec_add(*list_of_strings_ptr, string);
}
}
static void target_append_strings(JSONObject *json, const char *type, const char ***list_ptr, const char *base, const char *override, const char *add, bool is_default)
{
const char **value = get_valid_array(json, is_default ? base : override, type, false);
const char **add_value = is_default ? NULL : get_valid_array(json, add, type, false);
if (value && add_value)
{
error_exit("'%s' is combining both '%s' and '%s', only one may be used.", type, override, add);
}
if (value) *list_ptr = value;
if (add_value)
{
append_strings_to_strings(&add_value, *list_ptr);
*list_ptr = add_value;
}
}
static void load_into_build_target(JSONObject *json, const char *type, BuildTarget *target, bool is_default)
{
if (is_default)
{
check_json_keys(project_default_keys, project_default_keys_count, json, type);
check_json_keys(project_target_keys, project_target_keys_count, json, target_name);
}
else
{
check_json_keys(project_target_keys, project_target_keys_count, json, type);
check_json_keys(project_default_keys, project_default_keys_count, json, NULL);
}
target->cc = get_string(json, "cc", type, target->cc);
target->cc = get_string(PROJECT_JSON, target_name, json, "cc", target->cc);
target->script_dir = get_string(json, "script-dir", type, target->script_dir);
target->script_dir = get_string(PROJECT_JSON, target_name, json, "script-dir", target->script_dir);
// Exec
const char **exec = get_valid_array(json, is_default ? "exec" : "exec-override" , type, false);
const char **exec_add = is_default ? NULL : get_valid_array(json, "exec-add" , type, false);
if (exec && exec_add)
{
error_exit("'%s' is combining both 'exec-add' and 'exec-override', only one may be used.", type);
}
if (exec_add && !target->exec)
{
target->exec = exec_add;
exec_add = NULL;
}
if (exec) target->exec = exec;
if (exec_add)
{
assert(target->exec);
FOREACH(const char *, exec_command, exec_add) vec_add(target->exec, exec_command);
}
target->output_dir = get_string(json, "output", type, target->output_dir);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->exec, "exec", "exec-override", "exec-add");
target->output_dir = get_string(PROJECT_JSON, target_name, json,"output", target->output_dir);
// CFlags
const char *cflags = get_valid_string(json, is_default ? "cflags" : "cflags-override" , type);
const char *cflags_add = is_default ? NULL : get_valid_string(json, "cflags-add" , type);
if (cflags && cflags_add)
{
error_exit("'%s' is combining both 'cflags-add' and 'cflags-override', only one may be used.", type);
}
if (cflags) target->cflags = cflags;
if (cflags_add)
{
if (target->cflags)
{
target->cflags = str_printf("%s %s", target->cflags, cflags_add);
}
else
{
target->cflags = cflags_add;
}
}
target->cflags = get_cflags(PROJECT_JSON, target_name, json, target->cflags);
// C source dirs.
target_append_strings(json, type, &target->csource_dirs, "c-sources", "c-sources-override", "c-sources-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->csource_dirs, "c-sources", "c-sources-override", "c-sources-add");
// Sources
target_append_strings(json, type, &target->source_dirs, "sources", "sources-override", "sources-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->source_dirs, "sources", "sources-override", "sources-add");
// Linked-libraries - libraries to add at link time
target_append_strings(json, type, &target->linker_libs, "linked-libraries", "linked-libraries-override", "linked-libraries-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->linker_libs, "linked-libraries", "linked-libraries-override", "linked-libraries-add");
// linker-search-paths libs dir - libraries to add at link time
target_append_strings(json, type, &target->linker_libdirs, "linker-search-paths", "linker-search-paths-override", "linker-search-paths-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->linker_libdirs, "linker-search-paths", "linker-search-paths-override", "linker-search-paths-add");
// link-args - link args to add at link time
target_append_strings(json, type, &target->link_args, "link-args", "link-args-override", "link-args-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->link_args, "link-args", "link-args-override", "link-args-add");
// dependency-search-paths - path to search for libraries
target_append_strings(json, type, &target->libdirs, "dependency-search-paths", "dependency-search-paths-override", "dependency-search-paths-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->libdirs, "dependency-search-paths", "dependency-search-paths-override", "dependency-search-paths-add");
// Dependencies
target_append_strings(json, type, &target->libs, "dependencies", "dependencies-override", "dependencies-add", is_default);
get_list_append_strings(PROJECT_JSON, target_name, json, &target->libs, "dependencies", "dependencies-override", "dependencies-add");
FOREACH(const char *, name, target->libs)
{
if (!str_is_valid_lowercase_name(name))
@@ -351,16 +224,14 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
[DEBUG_INFO_NONE] = "none",
[DEBUG_INFO_LINE_TABLES] = "line-tables"
};
DebugInfo info = get_valid_string_setting(json, "debug-info", type, debug_infos, 0, ELEMENTLEN(debug_infos), "one of 'full' 'line-table' or 'none'.");
DebugInfo info = GET_SETTING(DebugInfo, "debug-info", debug_infos, "one of 'full' 'line-table' or 'none'.");
if (info > -1) target->debug_info = info;
// Optimization Level
OptimizationLevel optlevel = (OptimizationLevel)get_valid_string_setting(json, "optlevel", type, optlevels, 0, ELEMENTLEN(optlevels), "`none`, `less`, `more`, `max`.");
target->optlevel = optlevel;
target->optlevel = GET_SETTING(OptimizationLevel, "optlevel", optlevels, "`none`, `less`, `more`, `max`.");
// Size optimization
SizeOptimizationLevel optsize = (SizeOptimizationLevel)get_valid_string_setting(json, "optsize", type, optsizes, 0, ELEMENTLEN(optlevels), "`none`, `small`, `tiny`.");
target->optsize = optsize;
target->optsize = GET_SETTING(SizeOptimizationLevel, "optsize", optlevels, "`none`, `small`, `tiny`.");
static const char *opt_settings[8] = {
[OPT_SETTING_O0] = "O0",
@@ -372,62 +243,63 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
[OPT_SETTING_OSMALL] = "Os",
[OPT_SETTING_OTINY] = "Oz"
};
OptimizationSetting opt = (OptimizationSetting)get_valid_string_setting(json, "opt", type, opt_settings, 0, ELEMENTLEN(opt_settings), "'O0', 'O1' etc.");
OptimizationSetting opt = GET_SETTING(OptimizationSetting, "opt", opt_settings, "'O0', 'O1' etc.");
if (opt != OPT_SETTING_NOT_SET) target->optsetting = opt;
// Safety level
target->feature.safe_mode = (SafetyLevel)get_valid_bool(json, "safe", type, target->feature.safe_mode);
target->feature.safe_mode = (SafetyLevel)get_valid_bool(PROJECT_JSON, target_name, json, "safe", target->feature.safe_mode);
// Panic level
target->feature.panic_level = (PanicLevel)get_valid_bool(json, "panic-msg", type, target->feature.panic_level);
target->feature.panic_level = (PanicLevel)get_valid_bool(PROJECT_JSON, target_name, json, "panic-msg",
target->feature.panic_level);
// Single module
target->single_module = (SingleModule)get_valid_bool(json, "single-module", type, target->single_module);
target->single_module = (SingleModule) get_valid_bool(PROJECT_JSON, target_name, json, "single-module", target->single_module);
// Memory environment for memory constrained environments.
MemoryEnvironment env = get_valid_string_setting(json, "memory-env", type, memory_environment, 0, ELEMENTLEN(memory_environment), "one of 'normal', 'small', 'tiny' or 'none'.");
if (env > -1) target->memory_environment = env;
MemoryEnvironment env = GET_SETTING(MemoryEnvironment, "memory-env", memory_environment, "one of 'normal', 'small', 'tiny' or 'none'.");
if (env != MEMORY_ENV_NOT_SET) target->memory_environment = env;
// Symtab
long symtab_size = get_valid_integer(json, "symtab", type, false);
long symtab_size = get_valid_integer(json, "symtab", target_name, false);
if (symtab_size > 0)
{
if (symtab_size < 1024)
{
error_exit("Error reading %s: %s symtab was less than 1024.", PROJECT_JSON, type);
error_exit("Error reading %s: %s symtab was less than 1024.", PROJECT_JSON, target_name);
}
if (symtab_size > MAX_SYMTAB_SIZE)
{
error_exit("Error reading %s: %s symtab may not exceed %d.", PROJECT_JSON, type, MAX_SYMTAB_SIZE);
error_exit("Error reading %s: %s symtab may not exceed %d.", PROJECT_JSON, target_name, MAX_SYMTAB_SIZE);
}
target->symtab_size = (uint32_t)symtab_size;
}
// Target
const char *arch_os_string = get_valid_string(json, "target", type);
const char *arch_os_string = get_optional_string(PROJECT_JSON, target_name, json, "target");
if (arch_os_string)
{
ArchOsTarget arch_os = arch_os_target_from_string(arch_os_string);
if (arch_os == ARCH_OS_TARGET_DEFAULT) error_exit("Error reading %s: %s target was not valid.", PROJECT_JSON, type);
if (arch_os == ARCH_OS_TARGET_DEFAULT) error_exit("Error reading %s: %s target was not valid.", PROJECT_JSON, target_name);
target->arch_os_target = arch_os;
}
// Reloc
int reloc = get_valid_string_setting(json, "reloc", type, reloc_models, 0, ELEMENTLEN(reloc_models), "'none', 'pic', 'PIC', 'pie' or 'PIE'.");
if (reloc > -1) target->reloc_model = (RelocModel)reloc;
RelocModel reloc = GET_SETTING(RelocModel, "reloc", reloc_models, "'none', 'pic', 'PIC', 'pie' or 'PIE'.");
if (reloc != RELOC_DEFAULT) target->reloc_model = reloc;
// Cpu
target->cpu = get_string(json, "cpu", type, target->cpu);
target->cpu = get_string(PROJECT_JSON, target_name, json, "cpu", target->cpu);
// WinCRT
int wincrt = get_valid_string_setting(json, "wincrt", type, wincrt_linking, 0, ELEMENTLEN(wincrt_linking), "'none', 'static' or 'dynamic'.");
if (wincrt > -1) target->win.crt_linking = (WinCrtLinking)wincrt;
WinCrtLinking wincrt = GET_SETTING(WinCrtLinking, "wincrt", wincrt_linking, "'none', 'static' or 'dynamic'.");
if (wincrt != WIN_CRT_DEFAULT) target->win.crt_linking = wincrt;
// fp-math
int fpmath = get_valid_string_setting(json, "fp-math", type, fp_math, 0, ELEMENTLEN(fp_math), "`strict`, `relaxed` or `fast`.");
FpOpt fpmath = GET_SETTING(FpOpt, "fp-math", fp_math, "`strict`, `relaxed` or `fast`.");
if (fpmath > -1) target->feature.fp_math = fpmath;
const char **features = get_valid_array(json, "features", type, false);
const char **features = get_optional_string_array(PROJECT_JSON, target_name, json, "features");
if (features)
{
FOREACH(const char *, feature, features)
@@ -441,61 +313,61 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
}
// x86vec
int x86vec = get_valid_string_setting(json, "x86vec", type, x86_vector_capability, 0, ELEMENTLEN(x86_vector_capability), "`none`, `native`, `mmx`, `sse`, `avx` or `avx512`.");
X86VectorCapability x86vec = GET_SETTING(X86VectorCapability, "x86vec", x86_vector_capability, "`none`, `native`, `mmx`, `sse`, `avx` or `avx512`.");
if (x86vec > -1) target->feature.x86_vector_capability = x86vec;
// x86vec
int x86cpu = get_valid_string_setting(json, "x86cpu", type, x86_cpu_set, 0, ELEMENTLEN(x86_cpu_set), "`baseline`, `ssse3`, `sse4`, `avx1`, `avx2-v1`, `avx2-v2`, `avx512` or `native`.");
if (x86cpu > -1) target->feature.x86_cpu_set = x86cpu;
X86CpuSet x86cpu = GET_SETTING(X86CpuSet, "x86cpu", x86_cpu_set, "`baseline`, `ssse3`, `sse4`, `avx1`, `avx2-v1`, `avx2-v2`, `avx512` or `native`.");
if (x86cpu > X86CPU_DEFAULT) target->feature.x86_cpu_set = x86cpu;
// riscvfloat
int riscv_float = get_valid_string_setting(json, "riscvfloat", type, riscv_capability, 0, ELEMENTLEN(riscv_capability), "`none`, `float` or `double`.");
if (riscv_float > -1) target->feature.riscv_float_capability = riscv_float;
RiscvFloatCapability riscv_float = GET_SETTING(RiscvFloatCapability, "riscvfloat", riscv_capability, "`none`, `float` or `double`.");
if (riscv_float != RISCVFLOAT_DEFAULT) target->feature.riscv_float_capability = riscv_float;
// winsdk
target->win.sdk = get_string(json, "winsdk", type, target->win.sdk);
target->win.sdk = get_string(PROJECT_JSON, target_name, json, "winsdk", target->win.sdk);
// windef
target->win.def = get_string(json, "windef", type, target->win.def);
target->win.def = get_string(PROJECT_JSON, target_name, json, "windef", target->win.def);
// macossdk
target->macos.sysroot = get_string(json, "macossdk", type, target->macos.sysroot);
target->macos.sysroot = get_string(PROJECT_JSON, target_name, json, "macossdk", target->macos.sysroot);
// macos-min-version
target->macos.min_version = get_string(json, "macos-min-version", type, target->macos.min_version);
target->macos.min_version = get_string(PROJECT_JSON, target_name, json, "macos-min-version", target->macos.min_version);
// macos-sdk-version
target->macos.sdk_version = get_string(json, "macos-sdk-version", type, target->macos.sdk_version);
target->macos.sdk_version = get_string(PROJECT_JSON, target_name, json, "macos-sdk-version", target->macos.sdk_version);
// Linux crt
target->linuxpaths.crt = get_string(json, "linux-crt", type, target->linuxpaths.crt);
target->linuxpaths.crt = get_string(PROJECT_JSON, target_name, json, "linux-crt", target->linuxpaths.crt);
// Linux crtbegin
target->linuxpaths.crtbegin = get_string(json, "linux-crtbegin", type, target->linuxpaths.crtbegin);
target->linuxpaths.crtbegin = get_string(PROJECT_JSON, target_name, json, "linux-crtbegin", target->linuxpaths.crtbegin);
// version
target->version = get_string(json, "version", type, target->version);
target->version = get_string(PROJECT_JSON, target_name, json, "version", target->version);
// langrev
target->langrev = get_string(json, "langrev", type, target->langrev);
target->langrev = get_string(PROJECT_JSON, target_name, json, "langrev", target->langrev);
// panicfn
target->panicfn = get_string(json, "panicfn", type, target->panicfn);
target->panicfn = get_string(PROJECT_JSON, target_name, json, "panicfn", target->panicfn);
// testfn
target->testfn = get_string(json, "testfn", type, target->testfn);
target->testfn = get_string(PROJECT_JSON, target_name, json, "testfn", target->testfn);
// testfn
target->benchfn = get_string(json, "benchfn", type, target->benchfn);
target->benchfn = get_string(PROJECT_JSON, target_name, json, "benchfn", target->benchfn);
// link-libc
target->link_libc = (LinkLibc)get_valid_bool(json, "link-libc", type, target->link_libc);
target->link_libc = (LinkLibc) get_valid_bool(PROJECT_JSON, target_name, json, "link-libc", target->link_libc);
// strip-unused
target->strip_unused = (StripUnused)get_valid_bool(json, "strip-unused", type, target->strip_unused);
target->strip_unused = (StripUnused) get_valid_bool(PROJECT_JSON, target_name, json, "strip-unused", target->strip_unused);
// linker
const char *linker_selection = get_string(json, "linker", type, NULL);
const char *linker_selection = get_optional_string(PROJECT_JSON, target_name, json, "linker");
if (linker_selection)
{
if (str_eq("cc", linker_selection))
@@ -516,24 +388,26 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
}
// no-entry
target->no_entry = get_valid_bool(json, "no-entry", type, target->no_entry);
target->no_entry = get_valid_bool(PROJECT_JSON, target_name, json, "no-entry", target->no_entry);
// use-stdlib
target->use_stdlib = (UseStdlib)get_valid_bool(json, "use-stdlib", type, target->use_stdlib);
target->use_stdlib = (UseStdlib) get_valid_bool(PROJECT_JSON, target_name, json, "use-stdlib", target->use_stdlib);
// emit-stdlib
target->emit_stdlib = (EmitStdlib)get_valid_bool(json, "emit-stdlib", type, target->emit_stdlib);
target->emit_stdlib = (EmitStdlib) get_valid_bool(PROJECT_JSON, target_name, json, "emit-stdlib", target->emit_stdlib);
// single-module
target->single_module = (SingleModule)get_valid_bool(json, "single-module", type, target->single_module);
target->single_module = (SingleModule) get_valid_bool(PROJECT_JSON, target_name, json, "single-module", target->single_module);
// Trap on wrap
target->feature.trap_on_wrap = get_valid_bool(json, "trap-on-wrap", type, target->feature.trap_on_wrap);
target->feature.trap_on_wrap = get_valid_bool(PROJECT_JSON, target_name, json, "trap-on-wrap", target->feature.trap_on_wrap);
// Use the fact that they correspond to 0, 1, -1
target->feature.x86_struct_return = get_valid_bool(json, "x86-stack-struct-return", type, target->feature.x86_struct_return);
target->feature.soft_float = get_valid_bool(json, "soft-float", type, target->feature.soft_float);
target->feature.pass_win64_simd_as_arrays = get_valid_bool(json, "win64-simd-array", type, target->feature.pass_win64_simd_as_arrays);
target->feature.x86_struct_return = get_valid_bool(PROJECT_JSON, target_name, json, "x86-stack-struct-return",
target->feature.x86_struct_return);
target->feature.soft_float = get_valid_bool(PROJECT_JSON, target_name, json, "soft-float", target->feature.soft_float);
target->feature.pass_win64_simd_as_arrays = get_valid_bool(PROJECT_JSON, target_name, json, "win64-simd-array",
target->feature.pass_win64_simd_as_arrays);
}
static void project_add_target(Project *project, BuildTarget *default_target, JSONObject *json, const char *name, const char *type, TargetType target_type)
@@ -553,7 +427,7 @@ static void project_add_target(Project *project, BuildTarget *default_target, J
}
}
type = str_printf("%s %s", type, target->name);
load_into_build_target(json, type, target, false);
load_into_build_target(json, type, target);
update_build_target_with_opt_level(target, target->optsetting);
}
@@ -578,7 +452,7 @@ static void project_add_targets(Project *project, JSONObject *project_data)
};
BuildTarget default_target = default_build_target;
load_into_build_target(project_data, "default target", &default_target, true);
load_into_build_target(project_data, NULL, &default_target);
JSONObject *targets_json = json_obj_get(project_data, "targets");
if (!targets_json)
{
@@ -596,7 +470,7 @@ static void project_add_targets(Project *project, JSONObject *project_data)
{
error_exit("Invalid data in target '%s'", key);
}
int type = get_valid_string_setting(object, "type", "Target type", targets, 0, ELEMENTLEN(targets), "a target type like 'executable' or 'static-lib'");
int type = get_valid_string_setting(PROJECT_JSON, NULL, object, "type", targets, 0, ELEMENTLEN(targets), "a target type like 'executable' or 'static-lib'");
if (type < 0) error_exit("Target %s did not contain 'type' key.", key);
project_add_target(project, &default_target, object, key, target_desc[type], type);
}

View File

@@ -253,6 +253,16 @@ static void free_arenas(void)
if (debug_stats) print_arena_status();
}
static int compile_cfiles(const char *compiler, const char **files, const char *flags, const char **out_files)
{
int total = 0;
FOREACH(const char *, file, files)
{
out_files[total++] = cc_compiler(compiler, file, flags);
}
return total;
}
static void compiler_print_bench(void)
{
if (debug_stats)
@@ -439,8 +449,12 @@ void compiler_compile(void)
uint32_t output_file_count = vec_size(gen_contexts);
unsigned cfiles = vec_size(active_target.csources);
if (output_file_count + cfiles > MAX_OUTPUT_FILES)
unsigned cfiles_library = 0;
FOREACH(LibraryTarget *, lib, active_target.ccompling_libraries)
{
cfiles_library += vec_size(lib->csources);
}
if (output_file_count + cfiles + cfiles_library > MAX_OUTPUT_FILES)
{
error_exit("Too many output files.");
}
@@ -450,16 +464,18 @@ void compiler_compile(void)
}
CompileData *compile_data = ccalloc(sizeof(CompileData), output_file_count);
const char **obj_files = cmalloc(sizeof(char*) * (output_file_count + cfiles));
const char **obj_files = cmalloc(sizeof(char*) * (output_file_count + cfiles + cfiles_library));
if (cfiles)
{
for (int i = 0; i < cfiles; i++)
{
const char *file = active_target.csources[i];
const char *obj = platform_compiler(file, active_target.cflags);
obj_files[output_file_count + i] = obj;
}
int compiled = compile_cfiles(active_target.cc, active_target.csources, active_target.cflags, &obj_files[output_file_count]);
assert(cfiles == compiled);
(void)compiled;
}
const char **obj_file_next = &obj_files[output_file_count + cfiles];
FOREACH(LibraryTarget *, lib, active_target.ccompling_libraries)
{
obj_file_next += compile_cfiles(lib->cc ? lib->cc : active_target.cc, lib->csources, lib->cflags, obj_file_next);
}
Task **tasks = NULL;
@@ -501,7 +517,7 @@ void compiler_compile(void)
puts("# output-files-end");
}
output_file_count += cfiles;
output_file_count += cfiles + cfiles_library;
free(compile_data);
compiler_codegen_time = bench_mark();
@@ -663,11 +679,12 @@ void compiler_compile(void)
free(obj_files);
}
static const char **target_expand_source_names(const char** dirs, const char **suffix_list, int suffix_count, bool error_on_mismatch)
static const char **target_expand_source_names(const char *base_dir, const char** dirs, const char **suffix_list, int suffix_count, bool error_on_mismatch)
{
const char **files = NULL;
FOREACH(const char *, name, dirs)
{
if (base_dir) name = file_append_path(base_dir, name);
INFO_LOG("Searching for sources in %s", name);
size_t name_len = strlen(name);
if (name_len < 1) goto INVALID_NAME;
@@ -683,7 +700,7 @@ static const char **target_expand_source_names(const char** dirs, const char **s
INFO_LOG("Searching for wildcard sources in %s", name);
if (name_len == 2 || name[name_len - 3] == '/')
{
char *path = str_copy(name, name_len - 2);
const char *path = str_copy(name, name_len - 2);
DEBUG_LOG("Reduced path %s", path);
file_add_wildcard_files(&files, path, true, suffix_list, suffix_count);
continue;
@@ -705,6 +722,15 @@ static const char **target_expand_source_names(const char** dirs, const char **s
return files;
}
INLINE void expand_csources(const char *base_dir, const char **source_dirs, const char ***sources_ref)
{
if (source_dirs)
{
static const char* c_suffix_list[3] = { ".c" };
*sources_ref = target_expand_source_names(base_dir, source_dirs, c_suffix_list, 1, false);
}
}
void compile_target(BuildOptions *options)
{
init_default_build_target(&active_target, options);
@@ -890,8 +916,6 @@ void print_syntax(BuildOptions *options)
}
void resolve_libraries(void);
static int jump_buffer_size()
{
switch (active_target.arch_os_target)
@@ -980,24 +1004,22 @@ static void execute_scripts(void)
dir_change(old_path);
free(old_path);
}
void compile()
{
symtab_init(active_target.symtab_size);
active_target.sources = target_expand_source_names(active_target.source_dirs, c3_suffix_list, 3, true);
if (active_target.csource_dirs)
{
static const char* c_suffix_list[3] = { ".c" };
active_target.csources = target_expand_source_names(active_target.csource_dirs, c_suffix_list, 1, false);
}
active_target.sources = target_expand_source_names(NULL, active_target.source_dirs, c3_suffix_list, 3, true);
expand_csources(NULL, active_target.csource_dirs, &active_target.csources);
execute_scripts();
global_context.main = NULL;
global_context.string_type = NULL;
asm_target.initialized = false;
target_setup(&active_target);
resolve_libraries();
resolve_libraries(&active_target);
global_context.sources = active_target.sources;
FOREACH(LibraryTarget *, lib, active_target.ccompling_libraries)
{
expand_csources(lib->parent->dir, lib->csource_dirs, &lib->csources);
}
TokenType type = TOKEN_CONST_IDENT;
FOREACH(const char *, feature_flag, active_target.feature_list)
{
@@ -1034,10 +1056,6 @@ void compile()
if (!vec_size(active_target.sources) && !active_target.read_stdin) error_exit("No files to compile.");
if (active_target.exec)
{
}
if (active_target.lex_only)
{
compiler_lex();

View File

@@ -49,7 +49,6 @@ extern const char *project_default_keys[][2];
extern const int project_default_keys_count;
extern const char* project_target_keys[][2];
extern const int project_target_keys_count;
extern const char *trust_level[3];
typedef struct Ast_ Ast;
typedef struct Decl_ Decl;
@@ -3505,7 +3504,7 @@ bool static_lib_linker(const char *output_file, const char **files, unsigned fil
bool dynamic_lib_linker(const char *output_file, const char **files, unsigned file_count);
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);
const char *platform_compiler(const char *file, const char* flags);
const char *cc_compiler(const char *cc, const char *file, const char *flags);
const char *arch_to_linker_arch(ArchType arch);
#define CAT(a,b) CAT2(a,b) // force expand

View File

@@ -761,11 +761,12 @@ void platform_linker(const char *output_file, const char **files, unsigned file_
printf("Program linked to executable '%s'.\n", output_file);
}
const char *platform_compiler(const char *file, const char *flags)
const char *cc_compiler(const char *cc, const char *file, const char *flags)
{
const char *dir = active_target.object_file_dir;
if (!dir) dir = active_target.build_dir;
bool is_cl_exe = str_eq(cc, "cl.exe");
char *filename = NULL;
bool split_worked = file_namesplit(file, &filename, NULL);
if (!split_worked) error_exit("Cannot compile '%s'", file);
@@ -781,12 +782,21 @@ const char *platform_compiler(const char *file, const char *flags)
len -= 2;
filename[len] = 0;
}
const char *out_name = dir
? str_printf("%s/%s%s", dir, filename, get_object_extension())
: str_printf("%s%s", filename, get_object_extension());
const char *out_name;
if (is_cl_exe)
{
out_name = dir
? str_printf("/Fo:\"%s\\%s%s\"", dir, filename, get_object_extension())
: str_printf("/Fo:\"%s%s\"", filename, get_object_extension());
}
else
{
out_name = dir
? str_printf("%s/%s%s", dir, filename, get_object_extension())
: str_printf("%s%s", filename, get_object_extension());
}
const char **parts = NULL;
vec_add(parts, active_target.cc);
vec_add(parts, cc);
const bool pie_set =
flags != NULL &&
@@ -794,18 +804,19 @@ const char *platform_compiler(const char *file, const char *flags)
strstr(flags, "-fno-pie") || // it is being set in user defined cflags.
strstr(flags, "-fpie") ||
strstr(flags, "-fPIE")); // strcasestr is apparently nonstandard >:(
if (!pie_set)
if (!pie_set && !is_cl_exe)
{
append_fpie_pic_options(platform_target.reloc_model, &parts);
}
vec_add(parts, "-c");
vec_add(parts, is_cl_exe ? "/c" : "-c");
if (flags) vec_add(parts, flags);
vec_add(parts, file);
vec_add(parts, "-o");
if (!is_cl_exe) vec_add(parts, "-o");
vec_add(parts, out_name);
const char *output = concat_string_parts(parts);
DEBUG_LOG("Compiling c sources using '%s'", output);
if (system(output) != 0)
{
error_exit("Failed to compile c sources using command '%s'.\n", output);

View File

@@ -302,6 +302,8 @@ static char *x86_feature_name[] = {
[X86_FEAT_SSE4_2] = "sse4.2",
[X86_FEAT_AVX] = "avx",
[X86_FEAT_AVX2] = "avx2",
[X86_FEAT_AVX10_1_512] = "avx10.1-512",
[X86_FEAT_AVX10_1_256] = "avx10.1-256",
[X86_FEAT_SSE4_A] = "sse4a",
[X86_FEAT_FMA4] = "fma4",
[X86_FEAT_XOP] = "xop",
@@ -375,6 +377,7 @@ static char *x86_feature_name[] = {
[X86_FEAT_TBM] = "tbm",
[X86_FEAT_TSXLDTRK] = "tsxldtrk",
[X86_FEAT_UINTR] = "uintr",
[X86_FEAT_USERMSR] = "usermsr",
[X86_FEAT_VAES] = "vaes",
[X86_FEAT_VZEROUPPER] = "vzeroupper",
[X86_FEAT_WAITPKG] = "waitpkg",
@@ -664,6 +667,11 @@ static void x86_features_add_feature(X86Features *cpu_features, X86Feature featu
case X86_FEAT_X87:
case X86_FEAT_XSAVE:
return;
case X86_FEAT_AVX10_1_256:
case X86_FEAT_AVX10_1_512:
case X86_FEAT_USERMSR:
// TODO
return;
}
UNREACHABLE
}
@@ -1864,7 +1872,10 @@ void target_setup(BuildTarget *target)
default:
break;
}
if (!target->cc)
{
target->cc = platform_target.os == OS_TYPE_WIN32 ? "cl.exe" : "cc";
}
platform_target.int128 = os_target_supports_int128(platform_target.os, platform_target.arch);
platform_target.vec128f = os_target_supports_vec(platform_target.os, platform_target.arch, 128, false);

View File

@@ -392,6 +392,8 @@ typedef enum X64Feature
X86_FEAT_AMX_INT8,
X86_FEAT_AMX_TILE,
X86_FEAT_AVX,
X86_FEAT_AVX10_1_512,
X86_FEAT_AVX10_1_256,
X86_FEAT_AVX2,
X86_FEAT_AVX5124FMAPS,
X86_FEAT_AVX5124VNNIW,
@@ -476,6 +478,7 @@ typedef enum X64Feature
X86_FEAT_TBM,
X86_FEAT_TSXLDTRK,
X86_FEAT_UINTR,
X86_FEAT_USERMSR,
X86_FEAT_VAES,
X86_FEAT_VPCLMULQDQ,
X86_FEAT_VZEROUPPER,

View File

@@ -507,28 +507,26 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi
bool path_ends_with_slash = is_path_separator(path[strlen(path) - 1]);
struct _wfinddata_t file_data;
intptr_t file_handle;
const char *search = str_printf(path_ends_with_slash ? "%s*.*" : "%s/*.*", path);
const char *search = str_printf(path_ends_with_slash ? "%s*.*" : "%s\\*.*", path);
DEBUG_LOG("Search %s", search);
if ((file_handle = _wfindfirst(win_utf8to16(search), &file_data)) == -1L) return;
do
{
if ((file_data.attrib & _A_SUBDIR))
char *name = win_utf16to8(file_data.name);
if (file_has_suffix_in_list(name, strlen(name), suffix_list, suffix_count))
{
if (recursive)
{
if (file_data.name[0] == L'.')
{
continue;
}
char *format = path_ends_with_slash ? "%s%ls" : "%s/%ls";
char *new_path = str_printf(format, path, file_data.name);
file_add_wildcard_files(files, new_path, true, suffix_list, suffix_count);
}
char *format = path_ends_with_slash ? "%s%s" : "%s\\%s";
vec_add(*files, str_printf(format, path, name));
continue;
}
char *name = win_utf16to8(file_data.name);
if (!file_has_suffix_in_list(name, strlen(name), suffix_list, suffix_count)) continue;
char *format = path_ends_with_slash ? "%s%s" : "%s/%s";
vec_add(*files, str_printf(format, path, name));
if (!(file_data.attrib & _A_SUBDIR)) continue;
if (recursive)
{
if (file_data.name[0] == L'.') continue;
char *format = path_ends_with_slash ? "%s%s" : "%s\\%s";
char *new_path = str_printf(format, path, name);
file_add_wildcard_files(files, new_path, true, suffix_list, suffix_count);
}
} while (_wfindnext(file_handle, &file_data) == 0);
_findclose(file_handle);
}