aboutsummaryrefslogtreecommitdiff
path: root/src/build_settings.cpp
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-26 14:52:58 +0200
committerGitHub <noreply@github.com>2022-04-26 14:52:58 +0200
commitf1c1cfb6d2e865e966593ee9815e619b6c581304 (patch)
tree0b99532c281b427fb97d8ada3d6fbd53fbb19d9b /src/build_settings.cpp
parent80df9fbc651aa9c919eaaab822a46d7f5cdad645 (diff)
parentba5e33bc3518c327057102f56ac2c1cce55dc76f (diff)
Merge pull request #1747 from Kelimion/filename-merge
Filename generation
Diffstat (limited to 'src/build_settings.cpp')
-rw-r--r--src/build_settings.cpp236
1 files changed, 208 insertions, 28 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 2f3eb03a5..89d370144 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -3,7 +3,6 @@
#include <sys/sysctl.h>
#endif
-
// #if defined(GB_SYSTEM_WINDOWS)
// #define DEFAULT_TO_THREADED_CHECKER
// #endif
@@ -198,6 +197,22 @@ enum RelocMode : u8 {
RelocMode_DynamicNoPIC,
};
+enum BuildPath : u8 {
+ BuildPath_Main_Package, // Input Path to the package directory (or file) we're building.
+ BuildPath_RC, // Input Path for .rc file, can be set with `-resource:`.
+ BuildPath_RES, // Output Path for .res file, generated from previous.
+ BuildPath_Win_SDK_Root, // windows_sdk_root
+ BuildPath_Win_SDK_UM_Lib, // windows_sdk_um_library_path
+ BuildPath_Win_SDK_UCRT_Lib, // windows_sdk_ucrt_library_path
+ BuildPath_VS_EXE, // vs_exe_path
+ BuildPath_VS_LIB, // vs_library_path
+
+ BuildPath_Output, // Output Path for .exe, .dll, .so, etc. Can be overridden with `-out:`.
+ BuildPath_PDB, // Output Path for .pdb file, can be overridden with `-pdb-name:`.
+
+ BuildPathCOUNT,
+};
+
// This stores the information for the specify architecture of this build
struct BuildContext {
// Constants
@@ -226,9 +241,13 @@ struct BuildContext {
bool show_help;
+ Array<Path> build_paths; // Contains `Path` objects to output filename, pdb, resource and intermediate files.
+ // BuildPath enum contains the indices of paths we know *before* the work starts.
+
String out_filepath;
String resource_filepath;
String pdb_filepath;
+
bool has_resource;
String link_flags;
String extra_linker_flags;
@@ -300,8 +319,6 @@ struct BuildContext {
};
-
-
gb_global BuildContext build_context = {0};
bool global_warnings_as_errors(void) {
@@ -605,28 +622,6 @@ bool allow_check_foreign_filepath(void) {
// is_abs_path
// has_subdir
-enum TargetFileValidity : u8 {
- TargetFileValidity_Invalid,
-
- TargetFileValidity_Writable_File,
- TargetFileValidity_No_Write_Permission,
- TargetFileValidity_Directory,
-
- TargetTargetFileValidity_COUNT,
-};
-
-TargetFileValidity set_output_filename(void) {
- // Assembles the output filename from build_context information.
- // Returns `true` if it doesn't exist or is a file.
- // Returns `false` if a directory or write-protected file.
-
-
-
-
- return TargetFileValidity_Writable_File;
-}
-
-
String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1};
String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1};
@@ -973,7 +968,6 @@ char *token_pos_to_string(TokenPos const &pos) {
return s;
}
-
void init_build_context(TargetMetrics *cross_target) {
BuildContext *bc = &build_context;
@@ -1152,8 +1146,194 @@ void init_build_context(TargetMetrics *cross_target) {
bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3);
-
-
#undef LINK_FLAG_X64
#undef LINK_FLAG_386
}
+
+#if defined(GB_SYSTEM_WINDOWS)
+// NOTE(IC): In order to find Visual C++ paths without relying on environment variables.
+// NOTE(Jeroen): No longer needed in `main.cpp -> linker_stage`. We now resolve those paths in `init_build_paths`.
+#include "microsoft_craziness.h"
+#endif
+
+// NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate.
+// We've previously called `parse_build_flags`, so `out_filepath` should be set.
+bool init_build_paths(String init_filename) {
+ gbAllocator ha = heap_allocator();
+ BuildContext *bc = &build_context;
+
+ // NOTE(Jeroen): We're pre-allocating BuildPathCOUNT slots so that certain paths are always at the same enumerated index.
+ array_init(&bc->build_paths, permanent_allocator(), BuildPathCOUNT);
+
+ // [BuildPathMainPackage] Turn given init path into a `Path`, which includes normalizing it into a full path.
+ bc->build_paths[BuildPath_Main_Package] = path_from_string(ha, init_filename);
+
+ bool produces_output_file = false;
+ if (bc->command_kind == Command_doc && bc->cmd_doc_flags & CmdDocFlag_DocFormat) {
+ produces_output_file = true;
+ } else if (bc->command_kind & Command__does_build) {
+ produces_output_file = true;
+ }
+
+ if (!produces_output_file) {
+ // Command doesn't produce output files. We're done.
+ return true;
+ }
+
+ #if defined(GB_SYSTEM_WINDOWS)
+ if (bc->resource_filepath.len > 0) {
+ bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath);
+ bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath);
+ bc->build_paths[BuildPath_RC].ext = copy_string(ha, STR_LIT("rc"));
+ bc->build_paths[BuildPath_RES].ext = copy_string(ha, STR_LIT("res"));
+ }
+
+ if (bc->pdb_filepath.len > 0) {
+ bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath);
+ }
+
+ if ((bc->command_kind & Command__does_build) && (!bc->ignore_microsoft_magic)) {
+ // NOTE(ic): It would be nice to extend this so that we could specify the Visual Studio version that we want instead of defaulting to the latest.
+ Find_Result_Utf8 find_result = find_visual_studio_and_windows_sdk_utf8();
+
+ if (find_result.windows_sdk_version == 0) {
+ gb_printf_err("Windows SDK not found.\n");
+ return false;
+ }
+
+ GB_ASSERT(find_result.windows_sdk_um_library_path.len > 0);
+ GB_ASSERT(find_result.windows_sdk_ucrt_library_path.len > 0);
+
+ if (find_result.windows_sdk_root.len > 0) {
+ bc->build_paths[BuildPath_Win_SDK_Root] = path_from_string(ha, find_result.windows_sdk_root);
+ }
+
+ if (find_result.windows_sdk_um_library_path.len > 0) {
+ bc->build_paths[BuildPath_Win_SDK_UM_Lib] = path_from_string(ha, find_result.windows_sdk_um_library_path);
+ }
+
+ if (find_result.windows_sdk_ucrt_library_path.len > 0) {
+ bc->build_paths[BuildPath_Win_SDK_UCRT_Lib] = path_from_string(ha, find_result.windows_sdk_ucrt_library_path);
+ }
+
+ if (find_result.vs_exe_path.len > 0) {
+ bc->build_paths[BuildPath_VS_EXE] = path_from_string(ha, find_result.vs_exe_path);
+ }
+
+ if (find_result.vs_library_path.len > 0) {
+ bc->build_paths[BuildPath_VS_LIB] = path_from_string(ha, find_result.vs_library_path);
+ }
+
+ gb_free(ha, find_result.windows_sdk_root.text);
+ gb_free(ha, find_result.windows_sdk_um_library_path.text);
+ gb_free(ha, find_result.windows_sdk_ucrt_library_path.text);
+ gb_free(ha, find_result.vs_exe_path.text);
+ gb_free(ha, find_result.vs_library_path.text);
+
+ }
+ #endif
+
+ // All the build targets and OSes.
+ String output_extension;
+
+ if (bc->command_kind == Command_doc && bc->cmd_doc_flags & CmdDocFlag_DocFormat) {
+ output_extension = STR_LIT("odin-doc");
+ } else if (is_arch_wasm()) {
+ output_extension = STR_LIT("wasm");
+ } else if (build_context.build_mode == BuildMode_Executable) {
+ // By default use a .bin executable extension.
+ output_extension = STR_LIT("bin");
+
+ if (build_context.metrics.os == TargetOs_windows) {
+ output_extension = STR_LIT("exe");
+ } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) {
+ output_extension = make_string(nullptr, 0);
+ }
+ } else if (build_context.build_mode == BuildMode_DynamicLibrary) {
+ // By default use a .so shared library extension.
+ output_extension = STR_LIT("so");
+
+ if (build_context.metrics.os == TargetOs_windows) {
+ output_extension = STR_LIT("dll");
+ } else if (build_context.metrics.os == TargetOs_darwin) {
+ output_extension = STR_LIT("dylib");
+ }
+ } else if (build_context.build_mode == BuildMode_Object) {
+ // By default use a .o object extension.
+ output_extension = STR_LIT("o");
+
+ if (build_context.metrics.os == TargetOs_windows) {
+ output_extension = STR_LIT("obj");
+ }
+ } else if (build_context.build_mode == BuildMode_Assembly) {
+ // By default use a .S asm extension.
+ output_extension = STR_LIT("S");
+ } else if (build_context.build_mode == BuildMode_LLVM_IR) {
+ output_extension = STR_LIT("ll");
+ } else {
+ GB_PANIC("Unhandled build mode/target combination.\n");
+ }
+
+ if (bc->out_filepath.len > 0) {
+ bc->build_paths[BuildPath_Output] = path_from_string(ha, bc->out_filepath);
+ if (build_context.metrics.os == TargetOs_windows) {
+ String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
+ defer (gb_free(ha, output_file.text));
+ if (path_is_directory(bc->build_paths[BuildPath_Output])) {
+ gb_printf_err("Output path %.*s is a directory.\n", LIT(output_file));
+ return false;
+ } else if (bc->build_paths[BuildPath_Output].ext.len == 0) {
+ gb_printf_err("Output path %.*s must have an appropriate extension.\n", LIT(output_file));
+ return false;
+ }
+ }
+ } else {
+ Path output_path;
+
+ if (str_eq(init_filename, str_lit("."))) {
+ // We must name the output file after the current directory.
+ debugf("Output name will be created from current base name %.*s.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename));
+ String last_element = last_path_element(bc->build_paths[BuildPath_Main_Package].basename);
+
+ if (last_element.len == 0) {
+ gb_printf_err("The output name is created from the last path element. `%.*s` has none. Use `-out:output_name.ext` to set it.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename));
+ return false;
+ }
+ output_path.basename = copy_string(ha, bc->build_paths[BuildPath_Main_Package].basename);
+ output_path.name = copy_string(ha, last_element);
+
+ } else {
+ // Init filename was not 'current path'.
+ // Contruct the output name from the path elements as usual.
+ String output_name = remove_directory_from_path(init_filename);
+ output_name = remove_extension_from_path(output_name);
+ output_name = copy_string(ha, string_trim_whitespace(output_name));
+ output_path = path_from_string(ha, output_name);
+
+ // Replace extension.
+ if (output_path.ext.len > 0) {
+ gb_free(ha, output_path.ext.text);
+ }
+ }
+ output_path.ext = copy_string(ha, output_extension);
+
+ bc->build_paths[BuildPath_Output] = output_path;
+ }
+
+ // Do we have an extension? We might not if the output filename was supplied.
+ if (bc->build_paths[BuildPath_Output].ext.len == 0) {
+ if (build_context.metrics.os == TargetOs_windows || build_context.build_mode != BuildMode_Executable) {
+ bc->build_paths[BuildPath_Output].ext = copy_string(ha, output_extension);
+ }
+ }
+
+ // Check if output path is a directory.
+ if (path_is_directory(bc->build_paths[BuildPath_Output])) {
+ String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
+ defer (gb_free(ha, output_file.text));
+ gb_printf_err("Output path %.*s is a directory.\n", LIT(output_file));
+ return false;
+ }
+
+ return true;
+} \ No newline at end of file