aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig86
1 files changed, 77 insertions, 9 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 17d298b66d..6a078e8581 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -243,6 +243,17 @@ pub const RcSourceFile = struct {
extra_flags: []const []const u8 = &.{},
};
+pub const RcIncludes = enum {
+ /// Use MSVC if available, fall back to MinGW.
+ any,
+ /// Use MSVC include paths (MSVC install + Windows SDK, must be present on the system).
+ msvc,
+ /// Use MinGW include paths (distributed with Zig).
+ gnu,
+ /// Do not use any autodetected include paths.
+ none,
+};
+
const Job = union(enum) {
/// Write the constant value for a Decl to the output file.
codegen_decl: Module.Decl.Index,
@@ -568,6 +579,7 @@ pub const InitOptions = struct {
symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},
c_source_files: []const CSourceFile = &[0]CSourceFile{},
rc_source_files: []const RcSourceFile = &[0]RcSourceFile{},
+ rc_includes: RcIncludes = .any,
link_objects: []LinkObject = &[0]LinkObject{},
framework_dirs: []const []const u8 = &[0][]const u8{},
frameworks: []const Framework = &.{},
@@ -1001,16 +1013,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
options.libc_installation,
);
- const rc_dirs = try detectLibCIncludeDirs(
+ const rc_dirs = try detectWin32ResourceIncludeDirs(
arena,
- options.zig_lib_directory.path.?,
- options.target,
- options.is_native_abi,
- // Set "link libc" to true here whenever there are rc files to compile, since
- // the .rc preprocessor will need to know the libc include dirs even if we
- // are not linking libc
- options.rc_source_files.len > 0,
- options.libc_installation,
+ options,
);
const sysroot = options.sysroot orelse libc_dirs.sysroot;
@@ -2450,6 +2455,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
man.hash.addListOfBytes(key.src.extra_flags);
}
+ man.hash.addListOfBytes(comp.rc_include_dir_list);
+
cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm);
cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
@@ -5156,6 +5163,67 @@ fn failCObjWithOwnedErrorMsg(
return error.AnalysisFail;
}
+/// The include directories used when preprocessing .rc files are separate from the
+/// target. Which include directories are used is determined by `options.rc_includes`.
+///
+/// Note: It should be okay that the include directories used when compiling .rc
+/// files differ from the include directories used when compiling the main
+/// binary, since the .res format is not dependent on anything ABI-related. The
+/// only relevant differences would be things like `#define` constants being
+/// different in the MinGW headers vs the MSVC headers, but any such
+/// differences would likely be a MinGW bug.
+fn detectWin32ResourceIncludeDirs(arena: Allocator, options: InitOptions) !LibCDirs {
+ // Set the includes to .none here when there are no rc files to compile
+ var includes = if (options.rc_source_files.len > 0) options.rc_includes else .none;
+ if (builtin.target.os.tag != .windows) {
+ switch (includes) {
+ // MSVC can't be found when the host isn't Windows, so short-circuit.
+ .msvc => return error.WindowsSdkNotFound,
+ // Skip straight to gnu since we won't be able to detect MSVC on non-Windows hosts.
+ .any => includes = .gnu,
+ .none, .gnu => {},
+ }
+ }
+ while (true) {
+ switch (includes) {
+ .any, .msvc => return detectLibCIncludeDirs(
+ arena,
+ options.zig_lib_directory.path.?,
+ .{
+ .cpu = options.target.cpu,
+ .os = options.target.os,
+ .abi = .msvc,
+ .ofmt = options.target.ofmt,
+ },
+ options.is_native_abi,
+ // The .rc preprocessor will need to know the libc include dirs even if we
+ // are not linking libc, so force 'link_libc' to true
+ true,
+ options.libc_installation,
+ ) catch |err| {
+ if (includes == .any) {
+ // fall back to mingw
+ includes = .gnu;
+ continue;
+ }
+ return err;
+ },
+ .gnu => return detectLibCFromBuilding(arena, options.zig_lib_directory.path.?, .{
+ .cpu = options.target.cpu,
+ .os = options.target.os,
+ .abi = .gnu,
+ .ofmt = options.target.ofmt,
+ }),
+ .none => return LibCDirs{
+ .libc_include_dir_list = &[0][]u8{},
+ .libc_installation = null,
+ .libc_framework_dir_list = &.{},
+ .sysroot = null,
+ },
+ }
+ }
+}
+
fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) SemaError {
@setCold(true);
var bundle: ErrorBundle.Wip = undefined;