authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-10-11 19:13:59+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-11 15:52:55-04:00
log8aa20227ed45294da9606222d0b20eb922cecb2e
treedf1b9dd077fe0cb2dd8982971ff572d3028dae27
parent01b2c291d55e9f1b02c877537ba2b1b48079bb8b

Fix cross-compilation to i386-windows-msvc

Use Mingw's .def files to build a .lib when possible and show an error otherwise.

2 files changed, 88 insertions(+), 72 deletions(-)

src/link.cpp+78-72
......@@ -2098,6 +2098,60 @@ static bool is_linking_system_lib(CodeGen *g, const char *name) {
20982098 return false;
20992099}
21002100
2101static Error find_mingw_lib_def(LinkJob *lj, const char *name, Buf *out_path) {
2102 CodeGen *g = lj->codegen;
2103 Buf override_path = BUF_INIT;
2104 Error err;
2105
2106 char const *lib_path = nullptr;
2107 if (g->zig_target->arch == ZigLLVM_x86) {
2108 lib_path = "lib32";
2109 } else if (g->zig_target->arch == ZigLLVM_x86_64) {
2110 lib_path = "lib64";
2111 } else if (target_is_arm(g->zig_target)) {
2112 const bool is_32 = target_arch_pointer_bit_width(g->zig_target->arch) == 32;
2113 lib_path = is_32 ? "libarm32" : "libarm64";
2114 } else {
2115 zig_unreachable();
2116 }
2117
2118 // Try the archtecture-specific path first
2119 buf_resize(&override_path, 0);
2120 buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), lib_path, name);
2121
2122 bool does_exist;
2123 if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) {
2124 return err;
2125 }
2126
2127 if (!does_exist) {
2128 // Try the generic version
2129 buf_resize(&override_path, 0);
2130 buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "lib-common" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), name);
2131
2132 if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) {
2133 return err;
2134 }
2135 }
2136
2137 if (!does_exist) {
2138 // Try the generic version and preprocess it
2139 buf_resize(&override_path, 0);
2140 buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "lib-common" OS_SEP "%s.def.in", buf_ptr(g->zig_lib_dir), name);
2141
2142 if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) {
2143 return err;
2144 }
2145 }
2146
2147 if (!does_exist) {
2148 return ErrorFileNotFound;
2149 }
2150
2151 buf_init_from_buf(out_path, &override_path);
2152 return ErrorNone;
2153}
2154
21012155static void add_mingw_link_args(LinkJob *lj, bool is_library) {
21022156 CodeGen *g = lj->codegen;
21032157
......@@ -2125,55 +2179,18 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) {
21252179 const char *name = mingw_def_list[def_i].name;
21262180 const bool always_link = mingw_def_list[def_i].always_link;
21272181
2128 Buf override_path = BUF_INIT;
2182 Buf lib_path = BUF_INIT;
2183 Error err = find_mingw_lib_def(lj, name, &lib_path);
21292184
2130 char const *lib_path = nullptr;
2131 if (g->zig_target->arch == ZigLLVM_x86) {
2132 lib_path = "lib32";
2133 } else if (g->zig_target->arch == ZigLLVM_x86_64) {
2134 lib_path = "lib64";
2135 } else if (target_is_arm(g->zig_target)) {
2136 const bool is_32 = target_arch_pointer_bit_width(g->zig_target->arch) == 32;
2137 lib_path = is_32 ? "libarm32" : "libarm64";
2138 } else {
2139 zig_unreachable();
2140 }
2141
2142 // Try the archtecture-specific path first
2143 buf_resize(&override_path, 0);
2144 buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), lib_path, name);
2145
2146 bool does_exist;
2147 if (os_file_exists(&override_path, &does_exist) != ErrorNone) {
2148 zig_panic("link: unable to check if file exists: %s", buf_ptr(&override_path));
2149 }
2150
2151 if (!does_exist) {
2152 // Try the generic version
2153 buf_resize(&override_path, 0);
2154 buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "lib-common" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), name);
2155
2156 if (os_file_exists(&override_path, &does_exist) != ErrorNone) {
2157 zig_panic("link: unable to check if file exists: %s", buf_ptr(&override_path));
2158 }
2159 }
2160
2161 if (!does_exist) {
2162 // Try the generic version and preprocess it
2163 buf_resize(&override_path, 0);
2164 buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "lib-common" OS_SEP "%s.def.in", buf_ptr(g->zig_lib_dir), name);
2165
2166 if (os_file_exists(&override_path, &does_exist) != ErrorNone) {
2167 zig_panic("link: unable to check if file exists: %s", buf_ptr(&override_path));
2168 }
2169 }
2170
2171 if (!does_exist) {
2185 if (err == ErrorFileNotFound) {
21722186 zig_panic("link: could not find .def file to build %s\n", name);
2187 } else if (err != ErrorNone) {
2188 zig_panic("link: unable to check if .def file for %s exists: %s",
2189 name, err_str(err));
21732190 }
21742191
21752192 if (always_link || is_linking_system_lib(g, name)) {
2176 lj->args.append(get_def_lib(g, name, &override_path));
2193 lj->args.append(get_def_lib(g, name, &lib_path));
21772194 }
21782195 }
21792196}
......@@ -2307,8 +2324,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
23072324 lj->args.append(buf_ptr(compiler_rt_o_path));
23082325 }
23092326
2310 Buf *def_contents = buf_alloc();
2311 ZigList<const char *> gen_lib_args = {0};
23122327 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
23132328 LinkLib *link_lib = g->link_libs_list.at(lib_i);
23142329 if (buf_eql_str(link_lib->name, "c")) {
......@@ -2331,36 +2346,27 @@ static void construct_linker_job_coff(LinkJob *lj) {
23312346 continue;
23322347 }
23332348
2334 buf_resize(def_contents, 0);
2335 buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name));
2336 for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) {
2337 Buf *symbol_name = link_lib->symbols.at(exp_i);
2338 buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name));
2339 }
2340 buf_appendf(def_contents, "\n");
2341
2342 Buf *def_path = buf_alloc();
2343 os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
2344 if ((err = os_write_file(def_path, def_contents))) {
2345 zig_panic("error writing def file: %s", err_str(err));
2346 }
2349 // This library may be a system one and we may have a suitable .lib file
23472350
2348 Buf *generated_lib_path = buf_alloc();
2349 os_path_join(g->output_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
2351 // Normalize the library name to lower case, the FS may be
2352 // case-sensitive
2353 char *name = strdup(buf_ptr(link_lib->name));
2354 assert(name != nullptr);
2355 for (char *ch = name; *ch; ++ch) *ch = tolower(*ch);
23502356
2351 gen_lib_args.resize(0);
2352 gen_lib_args.append("link");
2357 Buf lib_path = BUF_INIT;
2358 err = find_mingw_lib_def(lj, name, &lib_path);
23532359
2354 coff_append_machine_arg(g, &gen_lib_args);
2355 gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
2356 gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
2357 Buf diag = BUF_INIT;
2358 ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target);
2359 if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) {
2360 fprintf(stderr, "%s\n", buf_ptr(&diag));
2361 exit(1);
2360 if (err == ErrorFileNotFound) {
2361 zig_panic("link: could not find .def file to build %s\n", name);
2362 } else if (err != ErrorNone) {
2363 zig_panic("link: unable to check if .def file for %s exists: %s",
2364 name, err_str(err));
23622365 }
2363 lj->args.append(buf_ptr(generated_lib_path));
2366
2367 lj->args.append(get_def_lib(g, name, &lib_path));
2368
2369 free(name);
23642370 }
23652371}
23662372
test/tests.zig+10
......@@ -163,6 +163,16 @@ const test_targets = [_]TestTarget{
163163 .disable_native = true,
164164 },
165165
166 TestTarget{
167 .target = Target{
168 .Cross = CrossTarget{
169 .os = .windows,
170 .arch = .i386,
171 .abi = .msvc,
172 },
173 },
174 },
175
166176 TestTarget{
167177 .target = Target{
168178 .Cross = CrossTarget{