Implement the compiler and linker section operations.
Rename and move the fake_build_execute() to fake_execute() to be shared among both the build and the make operations.
}
#endif // _di_fake_build_copy_
-#ifndef _di_fake_build_execute_
- void fake_build_execute(const fake_data data, const fake_build_data data_build, const f_string_static program, const f_string_statics arguments, f_status *status) {
- if (F_status_is_error(*status)) return;
-
- if (data.verbosity == fake_verbosity_verbose) {
- printf("%s", program.string);
-
- for (f_array_length i = 0; i < arguments.used; i++) {
- if (arguments.array[i].used == 0) continue;
-
- printf(" %s", arguments.array[i].string);
- } // for
-
- printf("%c", f_string_eol[0]);
-
- // flush to stdout before executing command.
- fflush(f_type_output);
- }
-
- {
- int result = 0;
-
- *status = fll_execute_program_environment(program.string, arguments, data_build.environment.names, data_build.environment.values, &result);
-
- if (result != 0) {
- *status = F_status_set_error(F_failure);
- }
- else if (F_status_is_error(*status)) {
- if (F_status_set_fine(*status) == F_file_found_not) {
- if (data.verbosity != fake_verbosity_quiet) {
- fprintf(f_type_error, "%c", f_string_eol[0]);
- fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find program '");
- fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", program.string);
- fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' for executing.");
- }
- }
- else {
- fake_print_error(data, F_status_set_fine(*status), "fll_execute_program_environment", F_true);
- }
- }
- }
- }
-#endif // _di_fake_build_execute_
-
#ifndef _di_fake_build_skeleton_
void fake_build_skeleton(const fake_data data, const fake_build_data data_build, const mode_t mode, const f_string_static file_stage, f_status *status) {
if (F_status_is_error(*status) || f_file_exists(file_stage.string) == F_true) return;
}
}
- fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status);
f_macro_string_dynamics_delete_simple(arguments);
}
}
- fake_build_execute(data, data_build, data_build.setting.build_linker, arguments, status);
+ fake_execute(data, data_build.environment, data_build.setting.build_linker, arguments, status);
f_macro_string_dynamic_delete_simple(file_name);
f_macro_string_dynamic_delete_simple(source_path);
break;
}
- fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status);
if (F_status_is_error(*status)) break;
f_macro_string_dynamics_delete_simple(arguments);
return;
}
- fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status);
f_macro_string_dynamics_delete_simple(arguments);
return;
}
- fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ fake_execute(data, data_build.environment, data_build.setting.build_compiler, arguments, status);
f_macro_string_dynamics_delete_simple(arguments);
#endif // _di_fake_build_copy_
/**
- * Execute the given command and arguments.
- *
- * Will print the command if in verbose mode.
- *
- * @param data
- * The program data.
- * @param data_build
- * The build data.
- * @param program
- * The program to be executed.
- * @param arguments
- * The arguments to be passed to the program.
- * @param status
- * The return status.
- */
-#ifndef _di_fake_build_execute_
- extern void fake_build_execute(const fake_data data, const fake_build_data data_build, const f_string_static program, const f_string_statics arguments, f_status *status) f_gcc_attribute_visibility_internal;
-#endif // _di_fake_build_execute_
-
-/**
* Create all of the base directories inside the build directory.
*
* @param data
extern "C" {
#endif
+#ifndef _di_fake_execute_
+ void fake_execute(const fake_data data, const fake_environment environment, const f_string_static program, const f_string_statics arguments, f_status *status) {
+ if (F_status_is_error(*status)) return;
+
+ if (data.verbosity == fake_verbosity_verbose) {
+ printf("%s", program.string);
+
+ for (f_array_length i = 0; i < arguments.used; i++) {
+ if (arguments.array[i].used == 0) continue;
+
+ printf(" %s", arguments.array[i].string);
+ } // for
+
+ printf("%c", f_string_eol[0]);
+
+ // flush to stdout before executing command.
+ fflush(f_type_output);
+ }
+
+ {
+ int result = 0;
+
+ *status = fll_execute_program_environment(program.string, arguments, environment.names, environment.values, &result);
+
+ if (result != 0) {
+ *status = F_status_set_error(F_failure);
+ }
+ else if (F_status_is_error(*status)) {
+ if (F_status_set_fine(*status) == F_file_found_not) {
+ if (data.verbosity != fake_verbosity_quiet) {
+ fprintf(f_type_error, "%c", f_string_eol[0]);
+ fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find program '");
+ fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", program.string);
+ fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' for executing.");
+ }
+ }
+ else {
+ fake_print_error(data, F_status_set_fine(*status), "fll_execute_program_environment", F_true);
+ }
+ }
+ }
+ }
+#endif // _di_fake_execute_
+
#ifndef _di_fake_file_buffer_
f_return_status fake_file_buffer(const fake_data data, const f_string path_file, f_string_dynamic *buffer) {
f_file file = f_file_initialize;
#endif // _di_fake_environment_
/**
+ * Execute the given command and arguments.
+ *
+ * Will print the command if in verbose mode.
+ *
+ * @param data
+ * The program data.
+ * @param environment
+ * The environment variable data.
+ * @param program
+ * The program to be executed.
+ * @param arguments
+ * The arguments to be passed to the program.
+ * @param status
+ * The return status.
+ */
+#ifndef _di_fake_execute_
+ extern void fake_execute(const fake_data data, const fake_environment environment, const f_string_static program, const f_string_statics arguments, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_execute_
+
+/**
* Load the contents of a file into the given buffer, handling all potential errors.
*
* @param data
}
}
+ f_string_range *range_compiler = 0;
+ f_string_range *range_linker = 0;
+
data_make->setting_make.parameter.array[0].value.used = 1;
data_make->setting_make.load_build = F_true;
data_make->setting_make.fail = fake_make_operation_fail_type_exit;
if (settings.objects.used) {
- bool unmatched_load = F_true;
bool unmatched_fail = F_true;
+ bool unmatched_load = F_true;
for (f_array_length i = 0; i < settings.objects.used; i++) {
- if (fl_string_dynamic_partial_compare_string(fake_make_setting_load_build, data_make->buffer, fake_make_setting_load_build_length, settings.objects.array[i]) == F_equal_to) {
- if (unmatched_load) {
+ if (fl_string_dynamic_partial_compare_string(fake_make_setting_compiler, data_make->buffer, fake_make_setting_compiler_length, settings.objects.array[i]) == F_equal_to) {
+ if (range_compiler) {
+ fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_compiler);
+ }
+ else {
if (settings.contents.array[i].used) {
- if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_yes, data_make->buffer, fake_common_setting_bool_yes_length, settings.contents.array[i].array[0]) == F_equal_to) {
- data_make->setting_make.load_build = F_true;
- }
- else if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_no, data_make->buffer, fake_common_setting_bool_no_length, settings.contents.array[i].array[0]) == F_equal_to) {
- data_make->setting_make.load_build = F_false;
- }
- else {
- fake_print_error_fakefile_settings_content_invalid(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings);
- }
-
- unmatched_load = F_false;
+ range_compiler = &settings.contents.array[i].array[0];
if (settings.contents.array[i].used > 1) {
- fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build);
+ fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_compiler);
}
}
else {
fake_print_error_fakefile_settings_content_empty(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings);
}
}
- else {
- fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build);
- }
}
else if (fl_string_dynamic_partial_compare_string(fake_make_setting_fail, data_make->buffer, fake_make_setting_fail_length, settings.objects.array[i]) == F_equal_to) {
if (unmatched_fail) {
fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_fail);
}
}
+ else if (fl_string_dynamic_partial_compare_string(fake_make_setting_linker, data_make->buffer, fake_make_setting_linker_length, settings.objects.array[i]) == F_equal_to) {
+ if (range_linker) {
+ fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_linker);
+ }
+ else {
+ if (settings.contents.array[i].used) {
+ range_linker = &settings.contents.array[i].array[0];
+
+ if (settings.contents.array[i].used > 1) {
+ fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_linker);
+ }
+ }
+ else {
+ fake_print_error_fakefile_settings_content_empty(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings);
+ }
+ }
+ }
+ else if (fl_string_dynamic_partial_compare_string(fake_make_setting_load_build, data_make->buffer, fake_make_setting_load_build_length, settings.objects.array[i]) == F_equal_to) {
+ if (unmatched_load) {
+ if (settings.contents.array[i].used) {
+ if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_yes, data_make->buffer, fake_common_setting_bool_yes_length, settings.contents.array[i].array[0]) == F_equal_to) {
+ data_make->setting_make.load_build = F_true;
+ }
+ else if (fl_string_dynamic_partial_compare_string(fake_common_setting_bool_no, data_make->buffer, fake_common_setting_bool_no_length, settings.contents.array[i].array[0]) == F_equal_to) {
+ data_make->setting_make.load_build = F_false;
+ }
+ else {
+ fake_print_error_fakefile_settings_content_invalid(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings);
+ }
+
+ unmatched_load = F_false;
+
+ if (settings.contents.array[i].used > 1) {
+ fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build);
+ }
+ }
+ else {
+ fake_print_error_fakefile_settings_content_empty(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], fake_make_section_settings);
+ }
+ }
+ else {
+ fake_print_warning_settings_content_multiple(data, data.file_data_build_fakefile.string, fake_make_setting_load_build);
+ }
+ }
else if (fl_string_dynamic_partial_compare_string(fake_make_setting_parameter, data_make->buffer, fake_make_setting_parameter_length, settings.objects.array[i]) == F_equal_to) {
if (settings.contents.array[i].used) {
if (fl_string_dynamic_partial_compare_string(fake_make_setting_return, data_make->buffer, fake_make_setting_return_length, settings.contents.array[i].array[0]) == F_equal_to) {
if (data_make->setting_make.load_build) {
fake_build_load_setting(data, &data_make->setting_build, status);
+
+ if (F_status_is_error(*status)) {
+ fake_print_error(data, *status, "fake_build_load_setting", F_true);
+
+ f_macro_fss_set_delete_simple(settings);
+ return;
+ }
+ }
+
+ // if either compiler or linker is specified, each will replace any existing build_compiler or build_linker, respectively.
+ if (range_compiler) {
+ data_make->setting_build.build_compiler.used = 0;
+ *status = fl_string_dynamic_partial_append(data_make->buffer, *range_compiler, &data_make->setting_build.build_compiler);
+ }
+
+ if (F_status_is_fine(*status) && range_linker) {
+ data_make->setting_build.build_linker.used = 0;
+ *status = fl_string_dynamic_partial_append(data_make->buffer, *range_linker, &data_make->setting_build.build_linker);
+ }
+
+ if (F_status_is_error(*status)) {
+ fake_print_error(data, *status, "fl_string_dynamic_partial_append", F_true);
+
+ f_macro_fss_set_delete_simple(settings);
+ return;
}
f_string_map_multis define = f_string_map_multis_initialize;
if (F_status_is_error(*status)) return;
if (operation == fake_make_operation_type_archive) {
- // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
- //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
- //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ if (data_make->setting_build.build_linker.used) {
+ fake_execute(data, data_make->environment, data_make->setting_build.build_linker, arguments, status);
+
+ if (F_status_is_error(*status)) {
+ fake_print_error(data, F_status_set_fine(*status), "fake_execute", F_true);
+ return;
+ }
+ }
+ else {
+ if (data.verbosity != fake_verbosity_quiet) {
+ fprintf(f_type_error, "%c", f_string_eol[0]);
+ fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: No linker has been specified, cannot perform '");
+ fl_color_print(f_type_error, data.context.notable, data.context.reset, fake_make_operation_archive);
+ fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' section operation.");
+ }
+
+ *status = F_status_set_error(F_failure);
+ }
return;
}
}
if (operation == fake_make_operation_type_compile) {
- // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
- //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
- //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ if (data_make->setting_build.build_compiler.used) {
+ fake_execute(data, data_make->environment, data_make->setting_build.build_compiler, arguments, status);
+
+ if (F_status_is_error(*status)) {
+ fake_print_error(data, F_status_set_fine(*status), "fake_execute", F_true);
+ return;
+ }
+ }
+ else {
+ if (data.verbosity != fake_verbosity_quiet) {
+ fprintf(f_type_error, "%c", f_string_eol[0]);
+ fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: No compiler has been specified, cannot perform '");
+ fl_color_print(f_type_error, data.context.notable, data.context.reset, fake_make_operation_compile);
+ fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' section operation.");
+ }
+
+ *status = F_status_set_error(F_failure);
+ }
+
return;
}
// fake_make_assure_inside_project
// *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
//fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
- //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ //fake_execute(data, data_make->environment, data_build.setting.build_compiler, arguments, status);
return;
}
// fake_make_assure_inside_project
// *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
//fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
- //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ //fake_execute(data, data_make->environment, data_build.setting.build_compiler, arguments, status);
return;
}
if (operation == fake_make_operation_type_link) {
// fake_make_assure_inside_project
- // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
- //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
- //fake_build_execute(data, data_build, data_build.setting.build_compiler, arguments, status);
+ // @todo: create symlink.
return;
}
#define fake_macro_make_setting_delete_simple(setting) \
f_macro_string_map_multis_delete_simple(setting.parameter)
+ #define fake_make_setting_compiler "compiler"
#define fake_make_setting_define "define"
#define fake_make_setting_fail "fail"
+ #define fake_make_setting_linker "linker"
#define fake_make_setting_load_build "load_build"
#define fake_make_setting_parameter "parameter"
#define fake_make_setting_return "return"
+ #define fake_make_setting_compiler_length 8
#define fake_make_setting_define_length 6
#define fake_make_setting_fail_length 4
+ #define fake_make_setting_linker_length 6
#define fake_make_setting_load_build_length 10
#define fake_make_setting_parameter_length 9
#define fake_make_setting_return_length 6
load_build yes
fail exit
+ compiler gcc
+ linker ar
+
parameter verbose +v
parameter verbose_fll +V
The build settings may also be specified in the Settings Section.
The following settings are available (in addition to the build settings)\:
+ - compiler\:
+ This represents the name of the compiler program to use, such as "gcc".
+
- define\:
This represents an environment variable to define on run.
The environment variable name is case-sensitive.
The return code for programs can still be retrieved through using the reserved iki vaiable "return".
+ - linker\:
+ This represents the name of the linker program to use, such as "ar".
+
- load_build\:
This represents whether or not to load the load the build settings file.
The first Content value may be "true" to load the build settings and "false" to not load the build settings file.
The first Content must be either "file" or "directory".
Use "file" to designate that this is a regular file being created.
- The "directory" to designate that this is a directory file being created.
+ Use "directory" to designate that this is a directory file being created.
- The second Content must be the file to be created.
+ The second Content must be the file to be created (be it a regular "file" or a "directory" file).
- An optional third Content may be specified for "directory".
- This third Content, if specified, may only be "recursive".
- When specified, this will create all directories specified in the given directory file path.
+ - creates\:
+ Identical to "create", except that this will create all directories specified in the given directory file path.
- define\:
This represents an environment variable to define on run.
Use "file" to designate that this is a regular file being deleted.
The "directory" to designate that this is a directory file being deleted.
- The second Content must be the file to be created.
+ The second Content must be the file to be deleted.
+
+ When the first content is "directory" and that directory is not empty, then this will not delete the directory.
- An optional third Content may be specified for "directory".
- This third Content, if specified, may only be "recursive".
- When specified, this will create all directories specified in the given directory file path.
- If the directory is not empty, then "recursive" must be specified to delete the directory.
+ - deletes\:
+ Identical to "delete", except that when the first content is "directory" and that directory is not empty, then this will delete the directory.
- else\:
Performs a programmatic "else" condition.
- main: contains a list of Operation Objects and Content in FSS-0001 (Extended) format.
The Settings Objects are\:
+ - archiver: Only one Content, which must only be a valid filename.
+ - compiler: Only one Content, which must only be a valid filename.
- define: First Content represents variable name (case-sensitive), remaining Content represents varaiable value for IKI substitution.
- fail: Only one Content, which must be either "exit", "warn" or "ignore" (quotes not required) (case-sensitive).
- load_build: Only one Content, which must be either "yes" or "no" (quotes not required) (case-sensitive).
- build: Zero or One Content. First Content represents path to the settings file, relative to the project root.
- clean: Zero Content.
- compile: One or more Content as parameters to compiler.
- - create: Two or three Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file, and third Content is "recursive" (case-sensitive) or is not provided.
+ - create: Two Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file.
+ - creates: Two Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file.
- define: Two or more Content.
- - delete: Two or three Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file, and third Content is "recursive" (case-sensitive) or is not provided.
+ - delete: One or more Content representing paths to files.
+ - deletes: One or more Content representing paths to files.
- else: Zero Content.
- fail: One Content. First Content must be one of "exit", "warn", or "ignore" (case-sensitive).
- group: Two or more Content. First Content is group name or number, remaining Content are paths to files.