diff --git a/src/linker/lnk.c b/src/linker/lnk.c
index 8e8160ff..98f1fc9a 100644
--- a/src/linker/lnk.c
+++ b/src/linker/lnk.c
@@ -270,21 +270,27 @@ lnk_make_full_path(Arena *arena, String8 work_dir, PathStyle system_path_style,
////////////////////////////////
-internal String8List
+internal String8
lnk_make_linker_manifest(Arena *arena,
B32 manifest_uac,
String8 manifest_level,
String8 manifest_ui_access,
String8List manifest_dependency_list)
{
+ // TODO: we write a temp file with manifest attributes collected from obj directives and command line switches
+ // so we can pass file to mt.exe or llvm-mt.exe, when we have our own tool for merging manifest we can switch
+ // to writing manifest file in memory to skip roun-trip to disk
+
+ Temp scratch = scratch_begin(&arena, 1);
+
String8List srl = {0};
- str8_serial_begin(arena, &srl);
- str8_serial_push_string(arena, &srl, str8_lit(
+ str8_serial_begin(scratch.arena, &srl);
+ str8_serial_push_string(scratch.arena, &srl, str8_lit(
"\n"
"\n"));
if (manifest_uac) {
- String8 uac = push_str8f(arena,
+ String8 uac = push_str8f(scratch.arena,
" \n"
" \n"
" \n"
@@ -294,64 +300,119 @@ lnk_make_linker_manifest(Arena *arena,
" \n",
manifest_level,
manifest_ui_access);
- str8_serial_push_string(arena, &srl, uac);
+ str8_serial_push_string(scratch.arena, &srl, uac);
}
for (String8Node *node = manifest_dependency_list.first; node != 0; node = node->next) {
- String8 dep = push_str8f(arena,
+ String8 dep = push_str8f(scratch.arena,
" \n"
" \n"
" \n"
" \n"
" \n",
node->string);
- str8_serial_push_string(arena, &srl, dep);
+ str8_serial_push_string(scratch.arena, &srl, dep);
}
- str8_serial_push_string(arena, &srl, str8_lit("\n"));
- return srl;
+ str8_serial_push_string(scratch.arena, &srl, str8_lit("\n"));
+
+ String8 result = str8_list_join(arena, &srl, 0);
+
+ scratch_end(scratch);
+ return result;
}
internal void
-lnk_merge_manifest_files(Arena *arena, String8 mt_path, String8 manifest_name, String8List manifest_path_list)
+lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest_path_list)
{
ProfBeginFunction();
-
- Temp scratch = scratch_begin(&arena,1);
+ Temp scratch = scratch_begin(0,0);
String8List invoke_cmd_line = {0};
- str8_list_push(arena, &invoke_cmd_line, mt_path);
- String8 work_dir = os_get_current_path(arena);
+ str8_list_push(scratch.arena, &invoke_cmd_line, mt_path);
+ str8_list_pushf(scratch.arena, &invoke_cmd_line, "-out:%S", out_name);
+ str8_list_pushf(scratch.arena, &invoke_cmd_line, "-nologo");
+
+ // register input manifest files on command line
+ String8 work_dir = os_get_current_path(scratch.arena);
for (String8Node *man_node = manifest_path_list.first;
man_node != 0;
man_node = man_node->next) {
- String8 full_path = path_absolute_dst_from_relative_dst_src(arena, man_node->string, work_dir);
- full_path = path_convert_slashes(arena, full_path, PathStyle_UnixAbsolute);
- str8_list_pushf(arena, &invoke_cmd_line, "-manifest");
- str8_list_push(arena, &invoke_cmd_line, full_path);
+ // resolve relativ path inputs
+ String8 full_path = path_absolute_dst_from_relative_dst_src(scratch.arena, man_node->string, work_dir);
+
+ // normalize slashes
+ full_path = path_convert_slashes(scratch.arena, full_path, PathStyle_UnixAbsolute);
+
+ // push input to command line
+ str8_list_pushf(scratch.arena, &invoke_cmd_line, "-manifest");
+ str8_list_push(scratch.arena, &invoke_cmd_line, full_path);
}
- str8_list_pushf(arena, &invoke_cmd_line, "-out:%S", manifest_name);
- str8_list_pushf(arena, &invoke_cmd_line, "-nologo");
+ // launch mt.exe with our command line
OS_ProcessLaunchParams launch_opts = {0};
launch_opts.cmd_line = invoke_cmd_line;
launch_opts.path = str8_chop_last_slash(mt_path);
launch_opts.inherit_env = 1;
launch_opts.consoleless = 1;
-
OS_Handle mt_handle = os_process_launch(&launch_opts);
- if (!os_handle_match(mt_handle, os_handle_zero())) {
- if (os_process_join(mt_handle, max_U64)) {
- if (!os_file_path_exists(manifest_name)) {
- lnk_error(LNK_Error_Mt, "something went wrong, manifest was not written to \"%S\"", manifest_name);
- }
- }
- os_process_detach(mt_handle);
+ if (os_handle_match(mt_handle, os_handle_zero())) {
+ lnk_error(LNK_Error_Mt, "unable to start process: %S", mt_path);
} else {
- lnk_error(LNK_Error_Mt, "unable to start process for %S", mt_path);
+ os_process_join(mt_handle, max_U64);
+ os_process_detach(mt_handle);
}
scratch_end(scratch);
ProfEnd();
}
+
+internal String8
+lnk_manifest_from_inputs(Arena *arena,
+ String8 mt_path,
+ String8 manifest_name,
+ B32 manifest_uac,
+ String8 manifest_level,
+ String8 manifest_ui_access,
+ String8List input_manifest_path_list,
+ String8List deps_list)
+{
+ String8 manifest_data;
+
+ if (input_manifest_path_list.node_count > 0) {
+ ProfBegin("Merge Manifests");
+ Temp scratch = scratch_begin(&arena, 1);
+
+ String8 linker_manifest = lnk_make_linker_manifest(scratch.arena, manifest_uac, manifest_level, manifest_ui_access, deps_list);
+
+ // write linker manifest to temp file
+ String8 linker_manifest_path = push_str8f(scratch.arena, "%S.manifest.temp", manifest_name);
+ lnk_write_data_to_file_path(linker_manifest_path, linker_manifest);
+
+ // push linker manifest
+ str8_list_push(scratch.arena, &input_manifest_path_list, linker_manifest_path);
+
+ // launch mt.exe to merge input manifests
+ String8 merged_manifest_path = push_str8f(scratch.arena, "%S.manifest.merged", manifest_name);
+ lnk_merge_manifest_files(mt_path, merged_manifest_path, input_manifest_path_list);
+
+ // read mt.exe output from disk
+ manifest_data = os_data_from_file_path(arena, merged_manifest_path);
+ if (manifest_data.size == 0) {
+ lnk_error(LNK_Error_Mt, "unable to find mt.exe output manifest on disk, expected path \"%S\"", merged_manifest_path);
+ }
+
+ // cleanup disk
+ os_delete_file_at_path(linker_manifest_path);
+ os_delete_file_at_path(merged_manifest_path);
+
+ scratch_end(scratch);
+ ProfEnd();
+ } else {
+ manifest_data = lnk_make_linker_manifest(arena, manifest_uac, manifest_level, manifest_ui_access, deps_list);
+ }
+
+ return manifest_data;
+}
+
internal String8
lnk_res_from_data(Arena *arena, String8 data)
{
@@ -3203,6 +3264,8 @@ l.count += 1; \
// inputs
String8List include_symbol_list = config->include_symbol_list;
String8List input_disallow_lib_list = config->disallow_lib_list;
+ String8List input_manifest_path_list = str8_list_copy(tp_arena->v[0], &config->input_list[LNK_Input_Manifest]);
+ String8List manifest_dep_list = str8_list_copy(scratch.arena, &config->manifest_dependency_list);
LNK_AltNameList alt_name_list = config->alt_name_list;
LNK_InputLibList input_libs[LNK_InputSource_Count] = {0};
LNK_InputObjList input_obj_list = {0};
@@ -3564,7 +3627,7 @@ l.count += 1; \
case State_InputObjs: {
ProfBegin("Input Objs [Count %llu]", input_obj_list.count);
- ProfBegin("Gather Objs");
+ ProfBegin("Collect Obj Paths");
LNK_InputObjList unique_obj_input_list = {0};
for (LNK_InputObj *input = input_obj_list.first, *next; input != 0; input = next) {
next = input->next;
@@ -3636,12 +3699,16 @@ l.count += 1; \
}
}
ProfEnd();
+
+ // collect manifest dependencies
+ String8List obj_dep_list = lnk_collect_manifest_dependency_list(tp, tp_arena, obj_node_arr);
+ str8_list_concat_in_place(&manifest_dep_list, &obj_dep_list);
- // gather libs for input
+ // collect libs for input
LNK_InputLibList lib_list = lnk_collect_default_lib_obj_arr(tp, tp_arena, obj_node_arr); // TODO: put these on temp arena
str8_list_concat_in_place(&input_libs[LNK_InputSource_Obj], &lib_list);
- // gather symbols for input
+ // collect symbols for input
LNK_SymbolList new_defn_list = lnk_run_symbol_collector(tp, tp_arena, obj_node_arr, LNK_Symbol_DefinedExtern);
LNK_SymbolList new_weak_list = lnk_run_symbol_collector(tp, tp_arena, obj_node_arr, LNK_Symbol_Weak);
LNK_SymbolList new_undef_list = lnk_run_symbol_collector(tp, tp_arena, obj_node_arr, LNK_Symbol_Undefined); // TODO: allocate these on temp arena
@@ -3778,77 +3845,60 @@ l.count += 1; \
String8List res_data_list = {0};
String8List res_path_list = {0};
- ProfBegin("Build * Resources *");
- {
- // load .res from disk
- for (String8Node *node = config->input_list[LNK_Input_Res].first; node != 0; node = node->next) {
- String8 res_data = os_data_from_file_path(tp_arena->v[0], node->string);
- if (res_data.size > 0) {
- if (pe_is_res(res_data)) {
- String8 stable_res_path = lnk_make_full_path(tp_arena->v[0], config->work_dir, config->path_style, node->string);
- str8_list_push(scratch.arena, &res_path_list, stable_res_path);
- str8_list_push(tp_arena->v[0], &res_data_list, res_data);
- } else {
- lnk_error(LNK_Error_IllData, "file is not of RES format: %S", node->string);
- }
+ // do we have manifest deps passed through pragma alone?
+ LNK_ManifestOpt manifest_opt = config->manifest_opt;
+ if (manifest_dep_list.node_count > 0 && manifest_opt == LNK_ManifestOpt_Null) {
+ manifest_opt = LNK_ManifestOpt_Embed;
+ }
+
+ switch (manifest_opt) {
+ case LNK_ManifestOpt_Embed: {
+ ProfBegin("Embed Manifest");
+ // TODO: currently we convert manifest to res and parse res again, this unnecessary instead push manifest
+ // resource to the tree directly
+ String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
+ String8 manifest_res = lnk_res_from_data(scratch.arena, manifest_data);
+ str8_list_push(scratch.arena, &res_data_list, manifest_res);
+ str8_list_push(scratch.arena, &res_path_list, str8_lit("* Manifest *"));
+ ProfEnd();
+ } break;
+ case LNK_ManifestOpt_WriteToFile: {
+ ProfBeginDynamic("Write Manifest To: %.*s", str8_varg(config->manifest_name));
+ Temp temp = temp_begin(scratch.arena);
+ String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
+ lnk_write_data_to_file_path(config->manifest_name, manifest_data);
+ temp_end(temp);
+ ProfEnd();
+ } break;
+ case LNK_ManifestOpt_Null: {
+ Assert(input_manifest_path_list.node_count == 0);
+ Assert(manifest_dep_list.node_count == 0);
+ } break;
+ case LNK_ManifestOpt_No: {
+ // omit manifest generation
+ } break;
+ }
+
+ ProfBegin("Load .res files from disk");
+ for (String8Node *node = config->input_list[LNK_Input_Res].first; node != 0; node = node->next) {
+ String8 res_data = os_data_from_file_path(scratch.arena, node->string);
+ if (res_data.size > 0) {
+ if (pe_is_res(res_data)) {
+ str8_list_push(scratch.arena, &res_data_list, res_data);
+ String8 stable_res_path = lnk_make_full_path(scratch.arena, config->work_dir, config->path_style, node->string);
+ str8_list_push(scratch.arena, &res_path_list, stable_res_path);
} else {
- lnk_error(LNK_Error_FileNotFound, "unable to open res file: %S", node->string);
+ lnk_error(LNK_Error_LoadRes, "file is not of RES format: %S", node->string);
}
+ } else {
+ lnk_error(LNK_Error_LoadRes, "unable to open res file: %S", node->string);
}
}
ProfEnd();
- // handle manifest
- ProfBegin("Manifest");
- {
- LNK_Obj **obj_arr = lnk_obj_arr_from_list(scratch.arena, obj_list);
- String8List obj_dep_list = lnk_collect_manifest_dependency_list(tp, tp_arena, obj_arr, obj_list.count);
- String8List cmd_dep_list = str8_list_copy(scratch.arena, &config->manifest_dependency_list);
-
- String8List dep_list = {0};
- str8_list_concat_in_place(&dep_list, &obj_dep_list);
- str8_list_concat_in_place(&dep_list, &cmd_dep_list);
-
- B32 create_manifest = config->input_list[LNK_Input_Manifest].node_count > 0 ||
- dep_list.node_count > 0 ||
- config->manifest_opt == LNK_ManifestOpt_Embed;
- if (create_manifest) {
- String8List input_manifest_path_list = str8_list_copy(tp_arena->v[0], &config->input_list[LNK_Input_Manifest]);
-
- // TODO: we write a temp file with manifest attributes collected from obj directives and command line switches
- // so we can pass file to mt.exe or llvm-mt.exe, when we have our own tool for merging manifest we can switch
- // to writing manifest file in memory to skip roun-trip to disk
- String8List linker_manifest_data_list = lnk_make_linker_manifest(tp_arena->v[0], config->manifest_uac, config->manifest_level, config->manifest_ui_access, dep_list);
- String8 linker_manifest_path = push_str8f(scratch.arena, "%S.manifest.temp", config->manifest_name);
- lnk_write_data_list_to_file_path(linker_manifest_path, linker_manifest_data_list);
- str8_list_push(tp_arena->v[0], &input_manifest_path_list, linker_manifest_path);
-
- String8 merged_manifest_path = push_str8f(scratch.arena, "%S.manifest.merged", config->manifest_name);
- lnk_merge_manifest_files(tp_arena->v[0], config->mt_path, merged_manifest_path, input_manifest_path_list);
-
- if (config->manifest_opt == LNK_ManifestOpt_Embed) {
- // TODO: currently we convert manifest to res and parse res again, this unnecessary instead push manifest
- // resource to the tree directly
-
- String8 manifest_data = os_data_from_file_path(scratch.arena, merged_manifest_path);
- if (manifest_data.size == 0) {
- lnk_error(LNK_Error_Mt, "unable to locate manifest to embed on disk, path \"%S\"", merged_manifest_path);
- }
- String8 manifest_res = lnk_res_from_data(tp_arena->v[0], manifest_data);
- str8_list_push(tp_arena->v[0], &res_data_list, manifest_res);
- str8_list_push(tp_arena->v[0], &res_path_list, merged_manifest_path);
- }
-
- // cleanup disk
- os_delete_file_at_path(linker_manifest_path);
- if (config->delete_manifest == LNK_SwitchState_Yes) {
- os_delete_file_at_path(merged_manifest_path);
- }
- }
- }
- ProfEnd(); // Manifest
-
if (res_data_list.node_count > 0) {
+ ProfBegin("Build * Resources *");
+
String8 obj_name = str8_lit("* Resources *");
String8 obj_data = lnk_obj_from_res_file_list(tp,
tp_arena->v[0],
@@ -3861,11 +3911,13 @@ l.count += 1; \
config->work_dir,
config->path_style,
obj_name);
-
+
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
- input->dedup_id = obj_name;
- input->path = obj_name;
- input->data = obj_data;
+ input->dedup_id = obj_name;
+ input->path = obj_name;
+ input->data = obj_data;
+
+ ProfEnd();
}
} break;
case State_BuildAndInputLinkerObj: {
@@ -4002,7 +4054,7 @@ l.count += 1; \
// remove empty section headers from output image
lnk_section_table_remove_empties(st, symtab);
- // gather output sections
+ // collect output sections
LNK_SectionArray out_sect_arr = lnk_section_table_get_output_sections(scratch.arena, st);
// push back null section where we store image header
@@ -4258,6 +4310,13 @@ l.count += 1; \
entry_search_attempts += 1;
continue;
}
+ if (unresolved_undef_list.count) {
+ if (report_unresolved_symbols) {
+ report_unresolved_symbols = 0;
+ state_list_push(scratch.arena, state_list, State_ReportUnresolvedSymbols);
+ continue;
+ }
+ }
if (build_res_obj) {
build_res_obj = 0;
state_list_push(scratch.arena, state_list, State_BuildAndInputResObj);
@@ -4268,23 +4327,16 @@ l.count += 1; \
state_list_push(scratch.arena, state_list, State_BuildAndInputLinkerObj);
continue;
}
- if (check_unused_delay_loads) {
- check_unused_delay_loads = 0;
- state_list_push(scratch.arena, state_list, State_CheckUnusedDelayLoads);
- continue;
- }
- if (unresolved_undef_list.count) {
- if (report_unresolved_symbols) {
- report_unresolved_symbols = 0;
- state_list_push(scratch.arena, state_list, State_ReportUnresolvedSymbols);
- continue;
- }
- }
if (do_comdat_rewire) {
do_comdat_rewire = 0;
state_list_push(scratch.arena, state_list, State_RewireComdats);
continue;
}
+ if (check_unused_delay_loads) {
+ check_unused_delay_loads = 0;
+ state_list_push(scratch.arena, state_list, State_CheckUnusedDelayLoads);
+ continue;
+ }
/// --- inputs are ready ---
diff --git a/src/linker/lnk.h b/src/linker/lnk.h
index dc4c07c3..a0875c6d 100644
--- a/src/linker/lnk.h
+++ b/src/linker/lnk.h
@@ -252,9 +252,9 @@ internal void lnk_push_loaded_lib(Arena *arena, HashTable *default_lib_ht, Ha
////////////////////////////////
// Manifest
-internal String8List lnk_make_linker_manifest(Arena *arena, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List manifest_dependency_list);
-internal void lnk_merge_manifest_files(Arena *arena, String8 mt_path, String8 manifest_name, String8List manifest_path_list);
-internal String8 lnk_res_from_data(Arena *arena, String8 data);
+internal String8 lnk_make_linker_manifest(Arena *arena, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List manifest_dependency_list);
+internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest_path_list);
+internal String8 lnk_res_from_data(Arena *arena, String8 data);
////////////////////////////////
// Resources
diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c
index aef66a52..45e099c7 100644
--- a/src/linker/lnk_config.c
+++ b/src/linker/lnk_config.c
@@ -125,7 +125,6 @@ read_only struct
{ LNK_CmdSwitch_Rad_Debug, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." },
{ LNK_CmdSwitch_Rad_DebugName, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." },
{ LNK_CmdSwitch_Rad_DelayBind, "RAD_DELAY_BIND", "[:NO]", "" },
- { LNK_CmdSwitch_Rad_DeleteManifest, "RAD_DELETE_MANIFEST", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_DoMerge, "RAD_DO_MERGE", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_EnvLib, "RAD_ENV_LIB", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Exe, "RAD_EXE", "[:NO]", "" },
@@ -472,16 +471,13 @@ lnk_get_mt_path(Arena *arena)
#pragma comment(lib, "shlwapi.lib")
#include
- String8 mt_path = str8(0,0);
- local_persist wchar_t raw_mt_path[MAX_PATH + 1] = L"mt.exe";
- B32 is_mt_found = PathFindOnPathW(&raw_mt_path[0], 0);
- if (is_mt_found) {
- String16 mt_path_16 = str16_cstring(&raw_mt_path[0]);
- mt_path = str8_from_16(arena, mt_path_16);
- mt_path = path_convert_slashes(arena, mt_path, PathStyle_WindowsAbsolute);
- } else {
- lnk_error(LNK_Error_Cmdl, "mt.exe not found, please specify path with /RAD_MT_PATH or run vcvarsall.bat");
- }
+ local_persist wchar_t raw_mt_path[MAX_PATH*2] = L"mt.exe";
+ PathFindOnPathW(&raw_mt_path[0], 0);
+
+ String16 mt_path_16 = str16_cstring_capped(&raw_mt_path[0], raw_mt_path + sizeof(raw_mt_path));
+ String8 mt_path = str8_from_16(arena, mt_path_16);
+
+ mt_path = path_convert_slashes(arena, mt_path, PathStyle_WindowsAbsolute);
#undef OS_WINDOWS
#define OS_WINDOWS 1
@@ -870,17 +866,16 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_PathStyle, "system");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SectVirtOff, "0x1000");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Workers, "%u", os_get_system_info()->logical_processor_count);
- lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Manifest, "embed");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_TargetOs, "windows");
- //lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Log, "debug");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SymbolTableCapDefined, "0x3ffff");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SymbolTableCapInternal, "0x1000");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SymbolTableCapWeak, "0x3ffff");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SymbolTableCapLib, "0x3ffff");
- lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_DeleteManifest, "");
-#if !BUILD_DEBUG
- //lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SuppressError, "37");
+#if BUILD_DEBUG
+ lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Log, "debug");
+#else
+ lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SuppressError, "37");
#endif
if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Rad_MtPath)) {
@@ -1135,9 +1130,6 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
if (param_arr.count > 0) {
if (str8_match(param_arr.v[0], str8_lit("embed"), StringMatchFlag_CaseInsensitive)) {
config->manifest_opt = LNK_ManifestOpt_Embed;
- if (config->delete_manifest == LNK_SwitchState_Null) {
- config->delete_manifest = 1;
- }
if (param_arr.count == 1) {
if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Dll)) {
@@ -1175,13 +1167,17 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, cmd_switch);
}
} else if (cmd->value_strings.node_count == 0) {
- config->manifest_opt = LNK_ManifestOpt_Embed;
+ config->manifest_opt = LNK_ManifestOpt_WriteToFile;
}
} break;
case LNK_CmdSwitch_ManifestDependency: {
String8List manifest_dependency_list = str8_list_copy(arena, &cmd->value_strings);
str8_list_concat_in_place(&config->manifest_dependency_list, &manifest_dependency_list);
+
+ if (config->manifest_opt == LNK_ManifestOpt_Null) {
+ config->manifest_opt = LNK_ManifestOpt_WriteToFile;
+ }
} break;
case LNK_CmdSwitch_ManifestFile: {
@@ -1419,10 +1415,6 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
lnk_cmd_switch_set_flag_64(cmd->value_strings, cmd_switch, &config->flags, LNK_ConfigFlag_DelayBind);
} break;
- case LNK_CmdSwitch_Rad_DeleteManifest: {
- lnk_cmd_switch_parse_flag(cmd->value_strings, cmd_switch, &config->delete_manifest);
- } break;
-
case LNK_CmdSwitch_Rad_DoMerge: {
lnk_cmd_switch_set_flag_64(cmd->value_strings, cmd_switch, &config->flags, LNK_ConfigFlag_Merge);
} break;
@@ -1611,14 +1603,7 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
// :manifest_input
if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_ManifestInput)) {
- switch (config->manifest_opt) {
- case LNK_ManifestOpt_Null: {
- lnk_error_cmd_switch(LNK_Error_Cmdl, LNK_CmdSwitch_ManifestInput, "missing /MANIFEST:EMBED");
- } break;
- case LNK_ManifestOpt_No: {
- lnk_error_cmd_switch(LNK_Warning_Cmdl, LNK_CmdSwitch_ManifestInput, "missing /MANIFEST:EMBED, ignoring inputs");
- } break;
- case LNK_ManifestOpt_Embed: {
+ if (config->manifest_opt == LNK_ManifestOpt_Embed) {
for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) {
LNK_CmdSwitchType cmd_switch = lnk_cmd_switch_type_from_string(cmd->string);
if (cmd_switch == LNK_CmdSwitch_ManifestInput) {
@@ -1626,7 +1611,8 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
str8_list_concat_in_place(&config->input_list[LNK_Input_Manifest], &manifest_list);
}
}
- } break;
+ } else {
+ lnk_error_cmd_switch(LNK_Error_Cmdl, LNK_CmdSwitch_ManifestInput, "missing /MANIFEST:EMBED");
}
}
@@ -1754,7 +1740,7 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
// handle empty /MANIFESTFILE
if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_ManifestFile)) {
- config->manifest_name = make_file_path_with_ext(arena, config->image_name, str8_lit("manifest"));
+ config->manifest_name = push_str8f(arena, "%S.manifest", config->image_name);
}
if (lnk_get_log_status(LNK_Log_Debug)) {
diff --git a/src/linker/lnk_config.h b/src/linker/lnk_config.h
index 895b76cd..eb3af973 100644
--- a/src/linker/lnk_config.h
+++ b/src/linker/lnk_config.h
@@ -123,7 +123,6 @@ typedef enum
LNK_CmdSwitch_Rad_Debug,
LNK_CmdSwitch_Rad_DebugName,
LNK_CmdSwitch_Rad_DelayBind,
- LNK_CmdSwitch_Rad_DeleteManifest,
LNK_CmdSwitch_Rad_DoMerge,
LNK_CmdSwitch_Rad_EnvLib,
LNK_CmdSwitch_Rad_Exe,
@@ -205,8 +204,9 @@ typedef U32 LNK_GuardFlags;
typedef enum
{
LNK_ManifestOpt_Null,
+ LNK_ManifestOpt_WriteToFile,
LNK_ManifestOpt_Embed,
- LNK_ManifestOpt_No
+ LNK_ManifestOpt_No,
} LNK_ManifestOpt;
typedef struct LNK_AltNameList
@@ -273,7 +273,6 @@ typedef struct LNK_Config
String8List disallow_lib_list;
String8List delay_load_dll_list;
String8List natvis_list;
- LNK_SwitchState delete_manifest;
String8 manifest_name;
B32 manifest_uac;
String8 manifest_level;
diff --git a/src/linker/lnk_error.h b/src/linker/lnk_error.h
index 9e75a312..89ed588d 100644
--- a/src/linker/lnk_error.h
+++ b/src/linker/lnk_error.h
@@ -28,6 +28,7 @@ typedef enum
LNK_Error_UnsupportedMachine,
LNK_Error_Mt,
LNK_Error_UnableToSerializeMsf,
+ LNK_Error_LoadRes,
LNK_Error_StopLast,
LNK_Error_First,
diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c
index 79250547..badcc9bb 100644
--- a/src/linker/lnk_obj.c
+++ b/src/linker/lnk_obj.c
@@ -259,11 +259,11 @@ THREAD_POOL_TASK_FUNC(lnk_manifest_dependency_collector)
Rng1U64 range = task->range_arr[task_id];
String8List *list = &task->out_arr[task_id];
- LNK_Obj **obj_ptr = &task->in_arr[range.min];
- LNK_Obj **obj_opl = &task->in_arr[range.max];
+ LNK_ObjNode *obj_ptr = &task->in_arr[range.min];
+ LNK_ObjNode *obj_opl = &task->in_arr[range.max];
for (; obj_ptr < obj_opl; obj_ptr += 1) {
- LNK_Obj *obj = *obj_ptr;
+ LNK_Obj *obj = &obj_ptr->data;
LNK_DirectiveList *dirs = &obj->directive_info.v[LNK_Directive_ManifestDependency];
for (LNK_Directive *dir = dirs->first; dir != 0; dir = dir->next) {
String8List dep = str8_list_copy(arena, &dir->value_list);
@@ -273,14 +273,14 @@ THREAD_POOL_TASK_FUNC(lnk_manifest_dependency_collector)
}
internal String8List
-lnk_collect_manifest_dependency_list(TP_Context *tp, TP_Arena *arena, LNK_Obj **obj_arr, U64 obj_count)
+lnk_collect_manifest_dependency_list(TP_Context *tp, TP_Arena *arena, LNK_ObjNodeArray obj_node_arr)
{
- Temp scratch = scratch_begin(0,0);
+ Temp scratch = scratch_begin(arena->v, arena->count);
LNK_ManifestDependencyCollector task_data = {0};
- task_data.in_arr = obj_arr;
+ task_data.in_arr = obj_node_arr.v;
task_data.out_arr = push_array(scratch.arena, String8List, tp->worker_count);
- task_data.range_arr = tp_divide_work(scratch.arena, obj_count, tp->worker_count);
+ task_data.range_arr = tp_divide_work(scratch.arena, obj_node_arr.count, tp->worker_count);
tp_for_parallel(tp, arena, tp->worker_count, lnk_manifest_dependency_collector, &task_data);
String8List result = str8_list_arr_concat(task_data.out_arr, tp->worker_count);
diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h
index 21cd8629..370059d1 100644
--- a/src/linker/lnk_obj.h
+++ b/src/linker/lnk_obj.h
@@ -151,7 +151,7 @@ typedef struct
typedef struct
{
- LNK_Obj **in_arr;
+ LNK_ObjNode *in_arr;
String8List *out_arr;
Rng1U64 *range_arr;
} LNK_ManifestDependencyCollector;