Skip to content

Forward declaration of struct defined in dependency causes duplicate code generation #489

@Octogonapus

Description

@Octogonapus

I have found that if the JLL I'm generating bindings for contains a forward declaration to a struct which is defined in one of its dependencies (which I include as system headers), a struct definition is still generated even though it should be skipped due to being in the system headers. Using Clang.jl v0.18.3 with generate_isystem_symbols = false.

I'm generating bindings for aws-c-http.
This struct is forward declared here in aws-c-http.
aws-c-http includes the following file from aws-c-io.
This struct is forward declared here in aws-c-io.
This struct is defined here in aws-c-io.

For now I can work around this using output_ignorelist.

The relevant part of my code is:

for target in JLLEnvs.JLL_ENV_TRIPLES
    if should_skip_target(target)
        continue
    end
    options = load_options(joinpath(@__DIR__, "generator.toml"))
    options["general"]["output_file_path"] = joinpath(@__DIR__, "..", "lib", "$target.jl")
    options["general"]["callback_documentation"] = get_docs

    args = get_default_args(target)
    inc = JLLEnvs.get_pkg_include_dir(aws_c_common_jll, target)
    push!(args, "-isystem$inc")
    inc = JLLEnvs.get_pkg_include_dir(aws_c_io_jll, target)
    push!(args, "-isystem$inc")
    inc = JLLEnvs.get_pkg_include_dir(aws_c_compression_jll, target)
    push!(args, "-isystem$inc")
    inc = JLLEnvs.get_pkg_include_dir(aws_c_cal_jll, target)
    push!(args, "-isystem$inc")

    header_dirs = []
    inc = JLLEnvs.get_pkg_include_dir(aws_c_http_jll, target)
    push!(args, "-I$inc")
    push!(header_dirs, inc)

    headers = String[]
    for header_dir in header_dirs
        for (root, dirs, files) in walkdir(header_dir)
            for file in files
                if endswith(file, ".h")
                    push!(headers, joinpath(root, file))
                end
            end
        end
    end
    unique!(headers)

    ctx = create_context(headers, args, options)
    build!(ctx)
end

I've done some debugging and found that aws_client_bootstrap is not in dag.sys, so it can't be ignored by generate_isystem_symbols.
Also this struct is always parsed as a forward declaration:

┌ Info: collect_top_level_nodes!
│   ty = Clang.Generators.StructForwardDecl()
└   id = :aws_client_bootstrap
# ... two more times

Which is confusing because no code should be generated for those given:

skip_check(dag::ExprDAG, node::ExprNode{StructForwardDecl}) = true

So I must have missed something. That's as far as I got tonight.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions