Change exe name to follow the module of the main. Detect missing / multiple main functions.

This commit is contained in:
Christoffer Lerno
2022-08-10 01:14:07 +02:00
parent ebd7611164
commit 3eee9ddc06
5 changed files with 58 additions and 20 deletions

View File

@@ -234,7 +234,9 @@ Then run
c3c compile main.c3 c3c compile main.c3
``` ```
The generated binary will be called `a.out`. The generated binary will by default be named after the module that contains the main
function. In our case that is `hello_world`, so the resulting binary will be
called `hello_world` or `hello_world.exe`depending on platform.
### Compiling ### Compiling

View File

@@ -123,21 +123,36 @@ void thread_compile_task_tb(void *compile_data)
} }
static const char *active_target_name(void) static const char *exe_name(void)
{ {
assert(global_context.main);
const char *name;
if (active_target.name)
{
name = active_target.name;
}
else
{
Path *path = global_context.main->unit->module->name;
size_t first = 0;
for (size_t i = path->len; i > 0; i--)
{
if (path->module[i - 1] == ':')
{
first = i;
break;
}
}
name = &path->module[first];
}
switch (active_target.arch_os_target) switch (active_target.arch_os_target)
{ {
case WINDOWS_X86: case WINDOWS_X86:
case WINDOWS_X64: case WINDOWS_X64:
case MINGW_X64: case MINGW_X64:
if (active_target.name) return str_cat(name, ".exe");
{
return str_cat(active_target.name, ".exe");
}
return "a.exe";
default: default:
if (active_target.name) return active_target.name; return name;
return "a.out";
} }
} }
@@ -268,12 +283,21 @@ void compiler_compile(void)
} }
compiler_ir_gen_time = bench_mark(); compiler_ir_gen_time = bench_mark();
const char *output_exe = NULL;
if (!active_target.no_link && !active_target.test_output && (active_target.type == TARGET_TYPE_EXECUTABLE || active_target.type == TARGET_TYPE_TEST))
{
if (!global_context.main)
{
puts("No main function was found, compilation only object files are generated.");
}
else
{
output_exe = exe_name();
}
}
free_arenas(); free_arenas();
bool create_exe = !active_target.no_link && !active_target.test_output && (active_target.type == TARGET_TYPE_EXECUTABLE || active_target.type == TARGET_TYPE_TEST);
uint32_t output_file_count = vec_size(gen_contexts); uint32_t output_file_count = vec_size(gen_contexts);
unsigned cfiles = vec_size(active_target.csources); unsigned cfiles = vec_size(active_target.csources);
@@ -322,26 +346,27 @@ void compiler_compile(void)
for (unsigned i = 0; i < output_file_count; i++) for (unsigned i = 0; i < output_file_count; i++)
{ {
obj_files[i] = compile_data[i].object_name; obj_files[i] = compile_data[i].object_name;
assert(obj_files[i] || !create_exe); assert(obj_files[i] || !output_exe);
} }
output_file_count += cfiles; output_file_count += cfiles;
free(compile_data); free(compile_data);
compiler_codegen_time = bench_mark(); compiler_codegen_time = bench_mark();
if (create_exe) if (output_exe)
{ {
const char *output_name = active_target_name();
if (platform_target.os != OS_TYPE_WIN32 && active_target.arch_os_target == default_target && !active_target.force_linker) if (platform_target.os != OS_TYPE_WIN32 && active_target.arch_os_target == default_target && !active_target.force_linker)
{ {
platform_linker(output_name, obj_files, output_file_count); platform_linker(output_exe, obj_files, output_file_count);
compiler_link_time = bench_mark(); compiler_link_time = bench_mark();
compiler_print_bench(); compiler_print_bench();
} }
else else
{ {
compiler_print_bench(); compiler_print_bench();
if (!obj_format_linking_supported(platform_target.object_format) || !linker(output_name, obj_files, if (!obj_format_linking_supported(platform_target.object_format) || !linker(output_exe, obj_files,
output_file_count)) output_file_count))
{ {
printf("No linking is performed due to missing linker support.\n"); printf("No linking is performed due to missing linker support.\n");
@@ -352,8 +377,8 @@ void compiler_compile(void)
if (active_target.run_after_compile) if (active_target.run_after_compile)
{ {
DEBUG_LOG("Will run"); DEBUG_LOG("Will run");
printf("Launching %s...\n", output_name); printf("Launching %s...\n", output_exe);
int ret = system(platform_target.os == OS_TYPE_WIN32 ? output_name : str_printf("./%s", output_name)); int ret = system(platform_target.os == OS_TYPE_WIN32 ? output_exe : str_printf("./%s", output_exe));
printf("Program finished with exit code %d.", ret); printf("Program finished with exit code %d.", ret);
} }
} }
@@ -536,6 +561,7 @@ void compile()
active_target.csources = target_expand_source_names(active_target.csource_dirs, c_suffix_list, 1, false); active_target.csources = target_expand_source_names(active_target.csource_dirs, c_suffix_list, 1, false);
} }
global_context.sources = active_target.sources; global_context.sources = active_target.sources;
global_context.main = NULL;
target_setup(&active_target); target_setup(&active_target);
resolve_libraries(); resolve_libraries();

View File

@@ -1491,6 +1491,7 @@ typedef struct
DeclTable generic_symbols; DeclTable generic_symbols;
Path std_module_path; Path std_module_path;
Decl *panic_fn; Decl *panic_fn;
Decl *main;
} GlobalContext; } GlobalContext;

View File

@@ -1796,6 +1796,15 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl)
assert(body); assert(body);
function->func_decl.body = astid(body); function->func_decl.body = astid(body);
context->unit->main_function = function; context->unit->main_function = function;
if (global_context.main)
{
SEMA_ERROR(function, "Duplicate main functions found.");
SEMA_PREV(global_context.main, "The first one was found here.");
}
else
{
global_context.main = function;
}
return true; return true;
} }

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.5" #define COMPILER_VERSION "0.3.6"