| ... | @@ -11,6 +11,7 @@ pub const base_id: Step.Id = .translate_c; | ... | @@ -11,6 +11,7 @@ pub const base_id: Step.Id = .translate_c; |
| 11 | step: Step, | 11 | step: Step, |
| 12 | source: std.Build.LazyPath, | 12 | source: std.Build.LazyPath, |
| 13 | include_dirs: std.array_list.Managed(std.Build.Module.IncludeDir), | 13 | include_dirs: std.array_list.Managed(std.Build.Module.IncludeDir), |
| | 14 | system_libs: std.ArrayList(std.Build.Module.SystemLib), |
| 14 | c_macros: std.array_list.Managed([]const u8), | 15 | c_macros: std.array_list.Managed([]const u8), |
| 15 | out_basename: []const u8, | 16 | out_basename: []const u8, |
| 16 | target: std.Build.ResolvedTarget, | 17 | target: std.Build.ResolvedTarget, |
| ... | @@ -46,6 +47,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { | ... | @@ -46,6 +47,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { |
| 46 | .output_file = .{ .step = &translate_c.step }, | 47 | .output_file = .{ .step = &translate_c.step }, |
| 47 | .link_libc = options.link_libc, | 48 | .link_libc = options.link_libc, |
| 48 | .use_clang = options.use_clang, | 49 | .use_clang = options.use_clang, |
| | 50 | .system_libs = .empty, |
| 49 | }; | 51 | }; |
| 50 | source.addStepDependencies(&translate_c.step); | 52 | source.addStepDependencies(&translate_c.step); |
| 51 | return translate_c; | 53 | return translate_c; |
| ... | @@ -67,24 +69,37 @@ pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath { | ... | @@ -67,24 +69,37 @@ pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath { |
| 67 | /// module set making it available to other packages which depend on this one. | 69 | /// module set making it available to other packages which depend on this one. |
| 68 | /// `createModule` can be used instead to create a private module. | 70 | /// `createModule` can be used instead to create a private module. |
| 69 | pub fn addModule(translate_c: *TranslateC, name: []const u8) *std.Build.Module { | 71 | pub fn addModule(translate_c: *TranslateC, name: []const u8) *std.Build.Module { |
| 70 | return translate_c.step.owner.addModule(name, .{ | 72 | return setUpModule(translate_c, translate_c.step.owner.addModule(name, .{ |
| 71 | .root_source_file = translate_c.getOutput(), | 73 | .root_source_file = translate_c.getOutput(), |
| 72 | .target = translate_c.target, | 74 | .target = translate_c.target, |
| 73 | .optimize = translate_c.optimize, | 75 | .optimize = translate_c.optimize, |
| 74 | .link_libc = translate_c.link_libc, | 76 | .link_libc = translate_c.link_libc, |
| 75 | }); | 77 | })); |
| 76 | } | 78 | } |
| 77 | | 79 | |
| 78 | /// Creates a private module from the translated source to be used by the | 80 | /// Creates a private module from the translated source to be used by the |
| 79 | /// current package, but not exposed to other packages depending on this one. | 81 | /// current package, but not exposed to other packages depending on this one. |
| 80 | /// `addModule` can be used instead to create a public module. | 82 | /// `addModule` can be used instead to create a public module. |
| 81 | pub fn createModule(translate_c: *TranslateC) *std.Build.Module { | 83 | pub fn createModule(translate_c: *TranslateC) *std.Build.Module { |
| 82 | return translate_c.step.owner.createModule(.{ | 84 | return setUpModule(translate_c, translate_c.step.owner.createModule(.{ |
| 83 | .root_source_file = translate_c.getOutput(), | 85 | .root_source_file = translate_c.getOutput(), |
| 84 | .target = translate_c.target, | 86 | .target = translate_c.target, |
| 85 | .optimize = translate_c.optimize, | 87 | .optimize = translate_c.optimize, |
| 86 | .link_libc = translate_c.link_libc, | 88 | .link_libc = translate_c.link_libc, |
| 87 | }); | 89 | })); |
| | 90 | } |
| | 91 | |
| | 92 | fn setUpModule(translate_c: *TranslateC, module: *std.Build.Module) *std.Build.Module { |
| | 93 | const b = translate_c.step.owner; |
| | 94 | const arena = b.graph.arena; |
| | 95 | |
| | 96 | if (translate_c.link_libc) module.link_libc = true; |
| | 97 | |
| | 98 | for (translate_c.system_libs.items) |system_lib| { |
| | 99 | module.link_objects.append(arena, .{ .system_lib = system_lib }) catch @panic("OOM"); |
| | 100 | } |
| | 101 | |
| | 102 | return module; |
| 88 | } | 103 | } |
| 89 | | 104 | |
| 90 | pub fn addAfterIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void { | 105 | pub fn addAfterIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void { |
| ... | @@ -152,6 +167,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -152,6 +167,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 152 | const prog_node = options.progress_node; | 167 | const prog_node = options.progress_node; |
| 153 | const b = step.owner; | 168 | const b = step.owner; |
| 154 | const translate_c: *TranslateC = @fieldParentPtr("step", step); | 169 | const translate_c: *TranslateC = @fieldParentPtr("step", step); |
| | 170 | const arena = b.graph.arena; |
| 155 | | 171 | |
| 156 | var argv_list = std.array_list.Managed([]const u8).init(b.allocator); | 172 | var argv_list = std.array_list.Managed([]const u8).init(b.allocator); |
| 157 | try argv_list.append(b.graph.zig_exe); | 173 | try argv_list.append(b.graph.zig_exe); |
| ... | @@ -169,8 +185,6 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -169,8 +185,6 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 169 | try argv_list.append("--global-cache-dir"); | 185 | try argv_list.append("--global-cache-dir"); |
| 170 | try argv_list.append(b.graph.global_cache_root.path orelse "."); | 186 | try argv_list.append(b.graph.global_cache_root.path orelse "."); |
| 171 | | 187 | |
| 172 | try argv_list.append("--listen=-"); | | |
| 173 | | | |
| 174 | if (!translate_c.target.query.isNative()) { | 188 | if (!translate_c.target.query.isNative()) { |
| 175 | try argv_list.append("-target"); | 189 | try argv_list.append("-target"); |
| 176 | try argv_list.append(try translate_c.target.query.zigTriple(b.allocator)); | 190 | try argv_list.append(try translate_c.target.query.zigTriple(b.allocator)); |
| ... | @@ -190,12 +204,102 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -190,12 +204,102 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 190 | try argv_list.append(c_macro); | 204 | try argv_list.append(c_macro); |
| 191 | } | 205 | } |
| 192 | | 206 | |
| | 207 | var prev_search_strategy: std.Build.Module.SystemLib.SearchStrategy = .paths_first; |
| | 208 | var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic; |
| | 209 | |
| | 210 | for (translate_c.system_libs.items) |*system_lib| { |
| | 211 | var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty; |
| | 212 | const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name); |
| | 213 | if (system_lib_gop.found_existing) { |
| | 214 | try argv_list.appendSlice(system_lib_gop.value_ptr.*); |
| | 215 | continue; |
| | 216 | } else { |
| | 217 | system_lib_gop.value_ptr.* = &.{}; |
| | 218 | } |
| | 219 | |
| | 220 | if (system_lib.search_strategy != prev_search_strategy or |
| | 221 | system_lib.preferred_link_mode != prev_preferred_link_mode) |
| | 222 | { |
| | 223 | switch (system_lib.search_strategy) { |
| | 224 | .no_fallback => switch (system_lib.preferred_link_mode) { |
| | 225 | .dynamic => try argv_list.append("-search_dylibs_only"), |
| | 226 | .static => try argv_list.append("-search_static_only"), |
| | 227 | }, |
| | 228 | .paths_first => switch (system_lib.preferred_link_mode) { |
| | 229 | .dynamic => try argv_list.append("-search_paths_first"), |
| | 230 | .static => try argv_list.append("-search_paths_first_static"), |
| | 231 | }, |
| | 232 | .mode_first => switch (system_lib.preferred_link_mode) { |
| | 233 | .dynamic => try argv_list.append("-search_dylibs_first"), |
| | 234 | .static => try argv_list.append("-search_static_first"), |
| | 235 | }, |
| | 236 | } |
| | 237 | prev_search_strategy = system_lib.search_strategy; |
| | 238 | prev_preferred_link_mode = system_lib.preferred_link_mode; |
| | 239 | } |
| | 240 | |
| | 241 | const prefix: []const u8 = prefix: { |
| | 242 | if (system_lib.needed) break :prefix "-needed-l"; |
| | 243 | if (system_lib.weak) break :prefix "-weak-l"; |
| | 244 | break :prefix "-l"; |
| | 245 | }; |
| | 246 | switch (system_lib.use_pkg_config) { |
| | 247 | .no => try argv_list.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })), |
| | 248 | .yes, .force => { |
| | 249 | if (Step.Compile.runPkgConfig(&translate_c.step, system_lib.name)) |result| { |
| | 250 | try argv_list.appendSlice(result.cflags); |
| | 251 | try argv_list.appendSlice(result.libs); |
| | 252 | try seen_system_libs.put(arena, system_lib.name, result.cflags); |
| | 253 | } else |err| switch (err) { |
| | 254 | error.PkgConfigInvalidOutput, |
| | 255 | error.PkgConfigCrashed, |
| | 256 | error.PkgConfigFailed, |
| | 257 | error.PkgConfigNotInstalled, |
| | 258 | error.PackageNotFound, |
| | 259 | => switch (system_lib.use_pkg_config) { |
| | 260 | .yes => { |
| | 261 | // pkg-config failed, so fall back to linking the library |
| | 262 | // by name directly. |
| | 263 | try argv_list.append(b.fmt("{s}{s}", .{ |
| | 264 | prefix, |
| | 265 | system_lib.name, |
| | 266 | })); |
| | 267 | }, |
| | 268 | .force => { |
| | 269 | std.debug.panic("pkg-config failed for library {s}", .{system_lib.name}); |
| | 270 | }, |
| | 271 | .no => unreachable, |
| | 272 | }, |
| | 273 | |
| | 274 | else => |e| return e, |
| | 275 | } |
| | 276 | }, |
| | 277 | } |
| | 278 | } |
| | 279 | |
| 193 | const c_source_path = translate_c.source.getPath2(b, step); | 280 | const c_source_path = translate_c.source.getPath2(b, step); |
| 194 | try argv_list.append(c_source_path); | 281 | try argv_list.append(c_source_path); |
| 195 | | 282 | |
| | 283 | try argv_list.append("--listen=-"); |
| 196 | const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false, options.web_server, options.gpa); | 284 | const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false, options.web_server, options.gpa); |
| 197 | | 285 | |
| 198 | const basename = std.fs.path.stem(std.fs.path.basename(c_source_path)); | 286 | const basename = std.fs.path.stem(std.fs.path.basename(c_source_path)); |
| 199 | translate_c.out_basename = b.fmt("{s}.zig", .{basename}); | 287 | translate_c.out_basename = b.fmt("{s}.zig", .{basename}); |
| 200 | translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM"); | 288 | translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM"); |
| 201 | } | 289 | } |
| | 290 | |
| | 291 | pub fn linkSystemLibrary( |
| | 292 | translate_c: *TranslateC, |
| | 293 | name: []const u8, |
| | 294 | options: std.Build.Module.LinkSystemLibraryOptions, |
| | 295 | ) void { |
| | 296 | const b = translate_c.step.owner; |
| | 297 | translate_c.system_libs.append(b.allocator, .{ |
| | 298 | .name = b.dupe(name), |
| | 299 | .needed = options.needed, |
| | 300 | .weak = options.weak, |
| | 301 | .use_pkg_config = options.use_pkg_config, |
| | 302 | .preferred_link_mode = options.preferred_link_mode, |
| | 303 | .search_strategy = options.search_strategy, |
| | 304 | }) catch @panic("OOM"); |
| | 305 | } |