aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWalterPlinge <22519813+WalterPlinge@users.noreply.github.com>2022-05-25 02:00:13 +0100
committerWalterPlinge <22519813+WalterPlinge@users.noreply.github.com>2022-05-25 02:00:13 +0100
commit831a86599ecd6d5ddf3f691fc94cf9c0effda50b (patch)
tree804dd033e8b9b383e0fb0a9870c120bede038ba7 /src
parent3c5124ce68110b780f9cd5aaa3801f1f200b98fe (diff)
Add fallback build paths search using environment variables
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp221
1 files changed, 216 insertions, 5 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index b458d8308..4d560bc00 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -1186,7 +1186,201 @@ void init_build_context(TargetMetrics *cross_target) {
// 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(WalterPlinge): Environment variables can help to find Visual C++ and WinSDK paths for both
+// official and portable installations (like mmozeiko's portable msvc script). This will only use
+// the first paths it finds, and won't overwrite any values that `result` already has.
+bool find_portable_msvc_installation(gbAllocator allocator, Find_Result_Utf8 *result) {
+ if (build_context.metrics.arch != TargetArch_amd64 && build_context.metrics.arch != TargetArch_i386) {
+ return false;
+ }
+
+ bool sdk_found = false;
+ if(result->windows_sdk_root.len > 0
+ && result->windows_sdk_um_library_path.len > 0
+ && result->windows_sdk_ucrt_library_path.len > 0) {
+ sdk_found = true;
+ }
+
+ // We can find windows sdk using the following combination of env vars:
+ // (UniversalCRTSdkDir or WindowsSdkDir) and (WindowsSDKLibVersion or WindowsSDKVersion)
+ if (!sdk_found) {
+ // These appear to be suitable env vars used by Visual Studio
+ char const *win_sdk_ver_env = gb_get_env("WindowsSDKVersion", allocator);
+ char const *win_sdk_lib_env = gb_get_env("WindowsSDKLibVersion", allocator);
+ char const *win_sdk_dir_env = gb_get_env("WindowsSdkDir", allocator);
+ char const *crt_sdk_dir_env = gb_get_env("UniversalCRTSdkDir", allocator);
+ defer (gb_free(allocator, (void*)win_sdk_ver_env));
+ defer (gb_free(allocator, (void*)win_sdk_lib_env));
+ defer (gb_free(allocator, (void*)win_sdk_dir_env));
+ defer (gb_free(allocator, (void*)crt_sdk_dir_env));
+
+ // NOTE(WalterPlinge): If any combination is found, let's just assume they are correct
+ if ((win_sdk_ver_env || win_sdk_lib_env) && (win_sdk_dir_env || crt_sdk_dir_env)) {
+ //? Maybe we need to handle missing '\' at end of strings, so far it doesn't seem an issue
+ String dir = win_sdk_dir_env
+ ? make_string_c(win_sdk_dir_env)
+ : make_string_c(crt_sdk_dir_env);
+ String ver = win_sdk_ver_env
+ ? make_string_c(win_sdk_ver_env)
+ : make_string_c(win_sdk_lib_env);
+
+ // These have trailing '\' as we are just composing the path
+ String um_dir = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("um\\x64\\")
+ : make_string_c("um\\x86\\");
+ String ucrt_dir = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("ucrt\\x64\\")
+ : make_string_c("ucrt\\x86\\");
+
+ result->windows_sdk_root = concatenate3_strings(allocator, dir, make_string_c("Lib\\"), ver);
+ result->windows_sdk_um_library_path = concatenate_strings(allocator, result->windows_sdk_root, um_dir);
+ result->windows_sdk_ucrt_library_path = concatenate_strings(allocator, result->windows_sdk_root, ucrt_dir);
+
+ sdk_found = true;
+ }
+ }
+
+ // If we haven't found it yet, we can loop through LIB for specific folders
+ //? This may not be robust enough using `um\x64` and `ucrt\x64`
+ if (!sdk_found) {
+ char const *lib_env = gb_get_env("LIB", allocator);
+ defer (gb_free(allocator, (void*)lib_env));
+ if (lib_env) {
+ String lib = make_string_c(lib_env);
+
+ // NOTE(WalterPlinge): I don't know if there's a chance for the LIB variable
+ // to be set without a trailing '\' (apart from manually), so we can just
+ // check paths without it (see use of `String end` in the loop below)
+ String um_dir = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("um\\x64")
+ : make_string_c("um\\x86");
+ String ucrt_dir = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("ucrt\\x64")
+ : make_string_c("ucrt\\x86");
+
+ isize lo = {0};
+ isize hi = {0};
+ for (isize c = 0; c <= lib.len; c += 1) {
+ if (c != lib.len && lib[c] != ';') {
+ continue;
+ }
+ hi = c;
+ String dir = substring(lib, lo, hi);
+ defer (lo = hi + 1);
+
+ // Remove the last slash so we can match with the strings above
+ String end = dir[dir.len - 1] == '\\'
+ ? substring(dir, 0, dir.len - 1)
+ : substring(dir, 0, dir.len);
+
+ // Find one and we can make the other
+ if (string_ends_with(end, um_dir)) {
+ result->windows_sdk_um_library_path = concatenate_strings(allocator, end, make_string_c("\\"));
+ break;
+ } else if (string_ends_with(end, ucrt_dir)) {
+ result->windows_sdk_ucrt_library_path = concatenate_strings(allocator, end, make_string_c("\\"));
+ break;
+ }
+ }
+
+ // Get the root from the one we found, and make the other
+ if (result->windows_sdk_um_library_path.len > 0) {
+ result->windows_sdk_root = substring(result->windows_sdk_um_library_path, 0, result->windows_sdk_um_library_path.len - 1 - um_dir.len);
+ result->windows_sdk_ucrt_library_path = concatenate3_strings(allocator, result->windows_sdk_root, ucrt_dir, make_string_c("\\"));
+ } else if (result->windows_sdk_ucrt_library_path.len > 0) {
+ result->windows_sdk_root = substring(result->windows_sdk_ucrt_library_path, 0, result->windows_sdk_ucrt_library_path.len - 1 - ucrt_dir.len);
+ result->windows_sdk_um_library_path = concatenate3_strings(allocator, result->windows_sdk_root, um_dir, make_string_c("\\"));
+ }
+
+ if (result->windows_sdk_root.len > 0) {
+ sdk_found = true;
+ }
+ }
+ }
+
+ // NOTE(WalterPlinge): So far this function assumes it will only be called if MSVC was
+ // installed using mmozeiko's portable msvc script, which uses the windows 10 sdk.
+ // This may need to be changed later if it ends up causing problems.
+ if (sdk_found && result->windows_sdk_version == 0) {
+ result->windows_sdk_version = 10;
+ }
+
+ bool vs_found = false;
+ if (result->vs_exe_path.len > 0 && result->vs_library_path.len > 0) {
+ vs_found = true;
+ }
+
+ // We can find visual studio using VCToolsInstallDir
+ if (!vs_found) {
+ char const *vctid_env = gb_get_env("VCToolsInstallDir", allocator);
+ defer (gb_free(allocator, (void*)vctid_env));
+ if (vctid_env) {
+ String vctid = make_string_c(vctid_env);
+ String exe = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("bin\\Hostx64\\x64\\")
+ : make_string_c("bin\\Hostx86\\x86\\");
+ String lib = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("lib\\x64\\")
+ : make_string_c("lib\\x86\\");
+ result->vs_exe_path = concatenate_strings(allocator, vctid, exe);
+ result->vs_library_path = concatenate_strings(allocator, vctid, lib);
+ vs_found = true;
+ }
+ }
+
+ // If we haven't found it yet, we can loop through Path for specific folders
+ if (!vs_found) {
+ char const *path_env = gb_get_env("Path", allocator);
+ defer (gb_free(allocator, (void*)path_env));
+ if (path_env) {
+ String path = make_string_c(path_env);
+
+ String exe = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("bin\\Hostx64\\x64")
+ : make_string_c("bin\\Hostx86\\x86");
+ String lib = build_context.metrics.arch == TargetArch_amd64
+ ? make_string_c("lib\\x64")
+ : make_string_c("lib\\x86");
+
+ isize lo = {0};
+ isize hi = {0};
+ for (isize c = 0; c <= path.len; c += 1) {
+ if (c != path.len && path[c] != ';') {
+ continue;
+ }
+
+ hi = c;
+ String dir = substring(path, lo, hi);
+ defer (lo = hi + 1);
+
+ String end = dir[dir.len - 1] == '\\'
+ ? substring(dir, 0, dir.len - 1)
+ : substring(dir, 0, dir.len);
+
+ // check if cl.exe and link.exe exist in this folder
+ String cl = concatenate_strings(allocator, end, make_string_c("\\cl.exe"));
+ String link = concatenate_strings(allocator, end, make_string_c("\\link.exe"));
+ defer (gb_free(allocator, cl.text));
+ defer (gb_free(allocator, link.text));
+
+ if (!string_ends_with(end, exe) || !gb_file_exists((char *)cl.text) || !gb_file_exists((char *)link.text)) {
+ continue;
+ }
+
+ String root = substring(end, 0, end.len - exe.len);
+
+ result->vs_exe_path = concatenate_strings(allocator, end, make_string_c("\\"));
+ result->vs_library_path = concatenate3_strings(allocator, root, lib, make_string_c("\\"));
+
+ vs_found = true;
+ }
+ }
+ }
+
+ return sdk_found && vs_found;
+}
+#endif defined(GB_SYSTEM_WINDOWS)
// 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.
@@ -1227,11 +1421,28 @@ bool init_build_paths(String init_filename) {
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;
+ bool all_found =
+ find_result.windows_sdk_root.len > 0 &&
+ find_result.windows_sdk_um_library_path.len > 0 &&
+ find_result.windows_sdk_ucrt_library_path.len > 0 &&
+ find_result.vs_exe_path.len > 0 &&
+ find_result.vs_library_path.len > 0;
+
+ if (find_result.windows_sdk_version == 0 || !all_found) {
+ if (!find_portable_msvc_installation(ha, &find_result)) {
+ gb_printf_err("Windows SDK not found.\n");
+ return false;
+ }
}
+#if 0
+ printf("windows_sdk_root: %.*s\n", LIT(find_result.windows_sdk_root));
+ printf("windows_sdk_um_library_path: %.*s\n", LIT(find_result.windows_sdk_um_library_path));
+ printf("windows_sdk_ucrt_library_path: %.*s\n", LIT(find_result.windows_sdk_ucrt_library_path));
+ printf("vs_exe_path: %.*s\n", LIT(find_result.vs_exe_path));
+ printf("vs_library_path: %.*s\n", LIT(find_result.vs_library_path));
+
+ gb_exit(1);
+#endif
if (find_result.windows_sdk_um_library_path.len > 0) {
GB_ASSERT(find_result.windows_sdk_ucrt_library_path.len > 0);