esp32-zig-starter icon indicating copy to clipboard operation
esp32-zig-starter copied to clipboard

Problem finding c headers

Open wiiggee1 opened this issue 9 months ago • 0 comments

Hi, I am writing my Master Thesis and trying to setup Zig with esp idf. Write now I am facing the problem of not finding certain c headers such as freertos. My build.zig looks like this.

const std = @import("std");

// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) !void {
    // Standard target options allows the person running `zig build` to choose
    // what target to build for. Here we do not override the defaults, which
    // means any target is allowed, and the default is native. Other options
    // for restricting supported target set are available.
    const esp32s3_target = std.Target.Query{
        .cpu_arch = .xtensa,
        .cpu_model = .{ .explicit = &std.Target.xtensa.cpu.esp32s3 },
        .os_tag = .freestanding,
        .abi = .none,
    };

    const target = b.resolveTargetQuery(esp32s3_target);
    const optimize = b.standardOptimizeOption(.{});

    // Ensure that Zig can find the necessary ESP-IDF header files.
    // const home_directory = std.process.getEnvVarOwned(b.allocator, "HOME") catch "";
    const esp_idf_path = std.process.getEnvVarOwned(b.allocator, "IDF_PATH") catch "";
    std.debug.print("esp_idf_path: {s}\n", .{esp_idf_path});

    //Here goes a static library to be linked with c / c++ app.
    const esp_idf_lib = b.addStaticLibrary(.{
        .name = "zig_main",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
        .link_libc = true,
    });

    if (!std.mem.eql(u8, esp_idf_path, "")) {
        esp_idf_lib.linkLibC();
        try searched_idf_include(b, esp_idf_lib, esp_idf_path);
        //try searched_idf_libs(b, esp_idf_lib);
        //try add_c_includes(b, esp_idf_lib);
    }

    b.installArtifact(esp_idf_lib);

    esp_idf_lib.setLinkerScript(b.path("linker.ld"));

    const link = b.addSystemCommand(&[_][]const u8{
        "xtensa-esp32-elf-gcc",
        "-T",
        "linker.ld",
        "-o",
        "esp32_s3_app",
        "main.o",
    });

    link.step.dependOn(&esp_idf_lib.step);

    const link_step = b.step("link", "Linking the ELF binary from the .o (object) files.");
    link_step.dependOn(&link.step);

    // This *creates* a Run step in the build graph, to be executed when another
    // step is evaluated that depends on it. The next line below will establish
    // such a dependency.
    //const run_cmd = b.addRunArtifact(exe);

    // By making the run step depend on the install step, it will be run from the
    // installation directory rather than directly from within the cache directory.
    // This is not necessary, however, if the application depends on other installed
    // files, this ensures they will be present and in the expected location.
    //run_cmd.step.dependOn(b.getInstallStep());

    // This allows the user to pass arguments to the application in the build
    // command itself, like this: `zig build run -- arg1 arg2 etc`
    // if (b.args) |args| {
    //     run_cmd.addArgs(args);
    // }

    // This creates a build step. It will be visible in the `zig build --help` menu,
    // and can be selected like this: `zig build run`
    // This will evaluate the `run` step rather than the default, which is "install".
    // const run_step = b.step("run", "Run the app");
    // run_step.dependOn(&run_cmd.step);

    // Creates a step for unit testing. This only builds the test executable
    // but does not run it.
    // const lib_unit_tests = b.addTest(.{
    //     .root_source_file = b.path("src/root.zig"),
    //     .target = target,
    //     .optimize = optimize,
    // });

    //const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);

    // const exe_unit_tests = b.addTest(.{
    //     .root_source_file = b.path("src/main.zig"),
    //     .target = target,
    //     .optimize = optimize,
    // });

    // const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);

    // Similar to creating the run step earlier, this exposes a `test` step to
    // the `zig build --help` menu, providing a way for the user to request
    // running the unit tests.
    // const test_step = b.step("test", "Run unit tests");
    //test_step.dependOn(&run_lib_unit_tests.step);
    // test_step.dependOn(&run_exe_unit_tests.step);
}

pub fn add_c_includes(b: *std.Build, lib: *std.Build.Step.Compile) !void {
    //const home_directory = std.process.getEnvVarOwned(b.allocator, "HOME") catch "";
    const esp_idf_path = std.process.getEnvVarOwned(b.allocator, "IDF_PATH") catch "/home/wiiggee1/esp-idf/";
    const esp_components = std.fmt.allocPrint(b.allocator, "{s}/components", .{esp_idf_path}) catch @panic("Out of Memory");

    var comp_dir = std.fs.openDirAbsolute(esp_components, .{ .iterate = true }) catch @panic("Failed to open dir!");
    std.debug.print("component iterator buffer: {s}\n", .{comp_dir.iterate().buf});

    var dir_it = comp_dir.iterate();
    while (dir_it.next()) |dir| {
        const comp = dir orelse break;
        const comp_name: []const u8 = comp.name;
        //const esp_comp_lib = std.fmt.allocPrint(b.allocator, "lib{s}", .{comp_name}) catch @panic("Out of Memory");

        const esp_comp = std.fmt.allocPrint(b.allocator, "{s}/{s}/include/", .{ esp_components, comp_name }) catch @panic("Out of Memory");

        // const esp_comp_src = std.fmt.allocPrint(b.allocator, "{s}/{s}/", .{ esp_components, comp_name }) catch @panic("Out of Memory");

        if (comp.kind != .directory) {
            continue;
        }
        // std.debug.print("kind: {any}\n", .{comp.kind});
        //std.debug.print("esp_component name: {s}\n", .{comp_name});
        //std.debug.print("esp_comp path: {s}\n", .{esp_comp});
        //esp_idf_lib.addSystemIncludePath(.{ .cwd_relative = esp_comp });
        lib.addIncludePath(.{ .cwd_relative = esp_comp });
    } else |err| {
        std.debug.print("Got error: {s}", .{@errorName(err)});
        return;
    }
    comp_dir.close();

    lib.linkLibC();
}

pub fn searched_idf_include(b: *std.Build, lib: *std.Build.Step.Compile, idf_path: []const u8) !void {
    const comp = b.pathJoin(&.{ idf_path, "components" });
    var dir = try std.fs.cwd().openDir(comp, .{
        .iterate = true,
    });
    defer dir.close();
    var walker = try dir.walk(b.allocator);
    defer walker.deinit();

    while (try walker.next()) |entry| {
        _ = std.fs.path.extension(entry.basename);
        if (entry.kind == .directory) {
            if (std.mem.indexOf(u8, entry.path, "/include") != null) {
                const include_directory = b.pathJoin(&.{ comp, std.fs.path.dirname(b.dupe(entry.path)).? });
                std.debug.print("Adding include path: {s}\n", .{include_directory});
                lib.addSystemIncludePath(.{ .cwd_relative = include_directory });
            }
        }

        // const include_file = inline for (&.{".h"}) |e| {
        //     //std.debug.print("ext == e: ; {s} == {s}, break true", .{ ext, e });
        //     if (std.mem.eql(u8, ext, e))
        //         break true;
        // } else false;
        // //###############################
        // if (include_file) {
        //     const include_dir = b.pathJoin(&.{ comp, std.fs.path.dirname(b.dupe(entry.path)).? });
        //     //std.debug.print("component include dir: {s}\n", .{include_dir});
        //     //_ = lib.out_filename;
        //     // lib.addSystemIncludePath(.{ .cwd_relative = include_dir });
        //     lib.addIncludePath(.{ .cwd_relative = include_dir });
        // }
    }
}

pub fn searched_idf_libs(b: *std.Build, lib: *std.Build.Step.Compile) !void {
    var dir = try std.fs.cwd().openDir("../build", .{
        .iterate = true,
    });
    defer dir.close();
    var walker = try dir.walk(b.allocator);
    defer walker.deinit();

    while (try walker.next()) |entry| {
        const ext = std.fs.path.extension(entry.basename);
        const lib_ext = inline for (&.{".obj"}) |e| {
            if (std.mem.eql(u8, ext, e))
                break true;
        } else false;
        if (lib_ext) {
            const src_path = std.fs.path.dirname(@src().file) orelse b.pathResolve(&.{".."});
            const cwd_path = b.pathJoin(&.{ src_path, "build", b.dupe(entry.path) });
            const lib_file: std.Build.LazyPath = .{ .cwd_relative = cwd_path };
            lib.addObjectFile(lib_file);
        }
    }
}

Do you have any tips / suggestions?

To clarify things. It doesn't seem to find some header files.

Image

VS

Image

and :

Image

This is what I get trying to compile:

Image

wiiggee1 avatar Feb 09 '25 00:02 wiiggee1