| ... | ... | @@ -11,6 +11,7 @@ pub const base_id: Step.Id = .translate_c; |
| 11 | 11 | step: Step, |
| 12 | 12 | source: std.Build.LazyPath, |
| 13 | 13 | include_dirs: std.array_list.Managed(std.Build.Module.IncludeDir), |
| 14 | system_libs: std.ArrayList(std.Build.Module.SystemLib), |
| 14 | 15 | c_macros: std.array_list.Managed([]const u8), |
| 15 | 16 | out_basename: []const u8, |
| 16 | 17 | target: std.Build.ResolvedTarget, |
| ... | ... | @@ -46,6 +47,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { |
| 46 | 47 | .output_file = .{ .step = &translate_c.step }, |
| 47 | 48 | .link_libc = options.link_libc, |
| 48 | 49 | .use_clang = options.use_clang, |
| 50 | .system_libs = .empty, |
| 49 | 51 | }; |
| 50 | 52 | source.addStepDependencies(&translate_c.step); |
| 51 | 53 | return translate_c; |
| ... | ... | @@ -67,24 +69,37 @@ pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath { |
| 67 | 69 | /// module set making it available to other packages which depend on this one. |
| 68 | 70 | /// `createModule` can be used instead to create a private module. |
| 69 | 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 | 73 | .root_source_file = translate_c.getOutput(), |
| 72 | 74 | .target = translate_c.target, |
| 73 | 75 | .optimize = translate_c.optimize, |
| 74 | 76 | .link_libc = translate_c.link_libc, |
| 75 | | }); |
| 77 | })); |
| 76 | 78 | } |
| 77 | 79 | |
| 78 | 80 | /// Creates a private module from the translated source to be used by the |
| 79 | 81 | /// current package, but not exposed to other packages depending on this one. |
| 80 | 82 | /// `addModule` can be used instead to create a public module. |
| 81 | 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 | 85 | .root_source_file = translate_c.getOutput(), |
| 84 | 86 | .target = translate_c.target, |
| 85 | 87 | .optimize = translate_c.optimize, |
| 86 | 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 | 105 | pub fn addAfterIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void { |
| ... | ... | @@ -152,6 +167,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 152 | 167 | const prog_node = options.progress_node; |
| 153 | 168 | const b = step.owner; |
| 154 | 169 | const translate_c: *TranslateC = @fieldParentPtr("step", step); |
| 170 | const arena = b.graph.arena; |
| 155 | 171 | |
| 156 | 172 | var argv_list = std.array_list.Managed([]const u8).init(b.allocator); |
| 157 | 173 | try argv_list.append(b.graph.zig_exe); |
| ... | ... | @@ -169,8 +185,6 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 169 | 185 | try argv_list.append("--global-cache-dir"); |
| 170 | 186 | try argv_list.append(b.graph.global_cache_root.path orelse "."); |
| 171 | 187 | |
| 172 | | try argv_list.append("--listen=-"); |
| 173 | | |
| 174 | 188 | if (!translate_c.target.query.isNative()) { |
| 175 | 189 | try argv_list.append("-target"); |
| 176 | 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 | 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 | 280 | const c_source_path = translate_c.source.getPath2(b, step); |
| 194 | 281 | try argv_list.append(c_source_path); |
| 195 | 282 | |
| 283 | try argv_list.append("--listen=-"); |
| 196 | 284 | const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false, options.web_server, options.gpa); |
| 197 | 285 | |
| 198 | 286 | const basename = std.fs.path.stem(std.fs.path.basename(c_source_path)); |
| 199 | 287 | translate_c.out_basename = b.fmt("{s}.zig", .{basename}); |
| 200 | 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 | } |