Commit d08c57741a

Andrew Kelley <superjoe30@gmail.com>
2017-10-16 07:14:28
ability to make a DLL
See #302
1 parent 78b753a
src/all_types.hpp
@@ -1456,6 +1456,7 @@ struct CodeGen {
     bool have_c_main;
     bool have_winmain;
     bool have_winmain_crt_startup;
+    bool have_dllmain_crt_startup;
     bool have_pub_panic;
     Buf *libc_lib_dir;
     Buf *libc_static_lib_dir;
src/analyze.cpp
@@ -3200,6 +3200,10 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a
                 buf_eql_str(proto_name, "WinMainCRTStartup") && g->zig_target.os == ZigLLVM_Win32)
             {
                 g->have_winmain_crt_startup = true;
+            } else if (proto_node->data.fn_proto.visib_mod == VisibModExport &&
+                buf_eql_str(proto_name, "DllMainCRTStartup") && g->zig_target.os == ZigLLVM_Win32)
+            {
+                g->have_dllmain_crt_startup = true;
             }
 
         }
src/codegen.cpp
@@ -5228,6 +5228,9 @@ static void gen_root_source(CodeGen *g) {
     {
         g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
     }
+    if (g->zig_target.os == ZigLLVM_Win32 && !g->have_dllmain_crt_startup && g->out_type == OutTypeLib) {
+        g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
+    }
     ImportTableEntry *import_with_panic;
     if (g->have_pub_panic) {
         import_with_panic = g->root_import;
src/link.cpp
@@ -372,6 +372,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
     // how to handle --target-environ gnu
     // These comments are a clue
 
+    bool is_library = g->out_type == OutTypeLib;
     //bool dll = g->out_type == OutTypeLib;
     //bool shared = !g->is_static && dll;
     //if (g->is_static) {
@@ -422,13 +423,19 @@ static void construct_linker_job_coff(LinkJob *lj) {
         //lj->args.append(get_libc_static_file(g, "crtbegin.o"));
     } else {
         lj->args.append("-NODEFAULTLIB");
-        if (g->have_winmain) {
-            lj->args.append("-ENTRY:WinMain");
-        } else {
-            lj->args.append("-ENTRY:WinMainCRTStartup");
+        if (!is_library) {
+            if (g->have_winmain) {
+                lj->args.append("-ENTRY:WinMain");
+            } else {
+                lj->args.append("-ENTRY:WinMainCRTStartup");
+            }
         }
     }
 
+    if (is_library && !g->is_static) {
+        lj->args.append("-DLL");
+    }
+
     for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
         const char *lib_dir = g->lib_dirs.at(i);
         lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
std/special/bootstrap_lib.zig
@@ -0,0 +1,9 @@
+// This file is included in the compilation unit when exporting a library on windows.
+
+const std = @import("std");
+
+export stdcallcc fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD,
+    lpReserved: std.os.windows.LPVOID) -> std.os.windows.BOOL
+{
+    return std.os.windows.TRUE;
+}
std/build.zig
@@ -636,6 +636,20 @@ pub const Builder = struct {
     pub fn fmt(self: &Builder, comptime format: []const u8, args: ...) -> []u8 {
         return %%fmt_lib.allocPrint(self.allocator, format, args);
     }
+
+    fn getCCExe(self: &Builder) -> []const u8 {
+        if (builtin.environ == builtin.Environ.msvc) {
+            return "cl.exe";
+        } else {
+            return os.getEnvVarOwned(self.builder.allocator, "CC") %% |err| {
+                if (err == error.EnvironmentVariableNotFound) {
+                    ([]const u8)("cc")
+                } else {
+                    return err
+                }
+            };
+        }
+    }
 };
 
 const Version = struct {
@@ -685,6 +699,17 @@ const Target = enum {
             else => false,
         };
     }
+
+    pub fn isWindows(self: &const Target) -> bool {
+        return switch (self.getOs()) {
+            builtin.Os.windows => true,
+            else => false,
+        };
+    }
+
+    pub fn wantSharedLibSymLinks(self: &const Target) -> bool {
+        return !self.isWindows();
+    }
 };
 
 pub const LibExeObjStep = struct {
@@ -885,7 +910,7 @@ pub const LibExeObjStep = struct {
                             self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
                         },
                         builtin.Os.windows => {
-                            self.out_filename = self.builder.fmt("lib{}.dll", self.name);
+                            self.out_filename = self.builder.fmt("{}.dll", self.name);
                         },
                         else => {
                             self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}",
@@ -1200,7 +1225,7 @@ pub const LibExeObjStep = struct {
 
         %return builder.spawnChild(zig_args.toSliceConst());
 
-        if (self.kind == Kind.Lib and !self.static) {
+        if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) {
             %return doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
                 self.name_only_filename);
         }
@@ -1252,15 +1277,10 @@ pub const LibExeObjStep = struct {
     }
 
     fn makeC(self: &LibExeObjStep) -> %void {
-        const cc = os.getEnvVarOwned(self.builder.allocator, "CC") %% |err| {
-            if (err == error.EnvironmentVariableNotFound) {
-                ([]const u8)("cc")
-            } else {
-                return err
-            }
-        };
         const builder = self.builder;
 
+        const cc = builder.getCCExe();
+
         assert(!self.is_zig);
 
         var cc_args = ArrayList([]const u8).init(builder.allocator);
@@ -1390,8 +1410,10 @@ pub const LibExeObjStep = struct {
 
                     %return builder.spawnChild(cc_args.toSliceConst());
 
-                    %return doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
-                        self.name_only_filename);
+                    if (self.target.wantSharedLibSymLinks()) {
+                        %return doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
+                            self.name_only_filename);
+                    }
                 }
             },
             Kind.Exe => {
CMakeLists.txt
@@ -587,6 +587,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/util.zig" DESTINATION "${ZIG_S
 install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
 install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
+install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap_lib.zig" DESTINATION "${ZIG_STD_DEST}/special")
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special")
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special")