Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 87 additions & 48 deletions gen/gbox3

Large diffs are not rendered by default.

140 changes: 111 additions & 29 deletions gen/gconsts3

Large diffs are not rendered by default.

Binary file added gen/gtk3_julia_ser10
Binary file not shown.
75 changes: 39 additions & 36 deletions gen/gtk_auto_gen.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env julia
using Clang
using GTK3_jll
import Serialization

import Clang, Clang.cindex
include("gtk_list_gen.jl")
include("gtk_get_set_gen.jl")
include("gtk_consts_gen.jl")
Expand All @@ -19,72 +20,74 @@ function without_linenums!(ex::Expr)
ex
end

gtk_libpaths = ("/opt/local", "/usr/lib")
# If there is an error about missing some std headers, e.g. fatal error: 'time.h' file not found,
# set this to `stdlib/include/on/your/specific/platform` (see https://github.com/JuliaInterop/Clang.jl)
const STD_INCLUDE = ""

const LIBGTK3_INCLUDE = joinpath(GTK3_jll.artifact_dir, "include", "gtk-3.0", "gtk")
const SOURCES = vcat(GTK3_jll.PATH_list, GTK3_jll.LIBPATH_list)
const DEPENDENCIES = vcat([readdir(dep; join=true) for dep in joinpath.(SOURCES, "..", "include") if isdir(dep)]...) .|> normpath
# glibconfig.h
const ADDITIONAL = vcat([joinpath.(readdir(dep; join=true), "include") for dep in joinpath.(SOURCES, "..", "lib") if isdir(dep)]...) .|> normpath
const gtk_h = joinpath(LIBGTK3_INCLUDE, "gtk.h")

toplevels = Any[]
cppargs = []
let gtk_version = 3
header = gtk_libdir = ""
for pth in gtk_libpaths
header = joinpath(pth,"..","include","gtk-$gtk_version.0","gtk","gtk.h")
if isfile(header)
gtk_libdir = pth
break
end
end
isfile(header) || error("gtk.h not found, please specify path")
args = read(`pkg-config --cflags gtk+-$gtk_version.0`, String)
if args[end] == '\n'
args = args[1:end-1]
end
args = ASCIIString[split(args,' ')...,cppargs...]
global gtk_h, gtk_macro_h
global trans_unit, root_cursor
# parse headers
cd(Sys.BINDIR) do
gtk_h = cindex.parse_header(header, diagnostics=true, args=args, flags=0x41)
global trans_unit = parse_header(gtk_h,
args=["-I", joinpath(LIBGTK3_INCLUDE, ".."), "-I$(STD_INCLUDE)"],
includes=vcat(LIBGTK3_INCLUDE, CLANG_INCLUDE, DEPENDENCIES, ADDITIONAL),
flags=0x41)
end

root_cursor = getcursor(trans_unit)

gboxpath = "gbox$(gtk_version)"
gconstspath = "gconsts$(gtk_version)"
cachepath = "gtk$(gtk_version)"

g_types = gen_g_type_lists(gtk_h)
g_types = gen_g_type_lists(root_cursor)
for z in g_types
for (s, ex) in z
without_linenums!(ex)
end
end

body = Expr(:block,
Expr(:import, :., :., :Gtk),
Expr(:import, :., :., :Gtk, :GObject),
Meta.parse("import ..Gtk"),
Meta.parse("import ..Gtk.GObject"),
)

gbox = Expr(:toplevel,Expr(:module, true, :GAccessor, body))
count_fcns = gen_get_set(body, gtk_h)
count_fcns = gen_get_set(body, root_cursor)
println("Generated $gboxpath with $count_fcns function definitions")
without_linenums!(gbox)

body = Expr(:block)
gconsts = Expr(:toplevel,Expr(:module, true, :GConstants, body))
count_consts = gen_consts(body, gtk_h)
count_consts = gen_consts(body, root_cursor)
println("Generated $gconstspath with $count_consts constants")
without_linenums!(gconsts)

open(joinpath(splitdir(@__FILE__)[1], gboxpath), "w") do cache
open(joinpath(@__DIR__, gboxpath), "w") do cache
Base.println(cache,"quote")
Base.show_unquoted(cache, gbox)
println(cache)
Base.println(cache,"end")
end
open(joinpath(splitdir(@__FILE__)[1], gconstspath), "w") do cache
open(joinpath(@__DIR__, gconstspath), "w") do cache
Base.println(cache,"quote")
Base.show_unquoted(cache, gconsts)
println(cache)
Base.println(cache,"end")
end
ser_version = Base.Serializer.ser_version
open(joinpath(splitdir(@__FILE__)[1], "$(cachepath)_julia_ser$(ser_version)"), "w") do cache
serialize(cache, gbox)
serialize(cache, gconsts)
ser_version = Serialization.ser_version
open(joinpath(@__DIR__, "$(cachepath)_julia_ser$(ser_version)"), "w") do cache
Serialization.serialize(cache, gbox)
Serialization.serialize(cache, gconsts)
end
push!(toplevels,(gbox,gconsts,g_types,gtk_h))
push!(toplevels, (gbox, gconsts, g_types, gtk_h))
end
toplevels
46 changes: 30 additions & 16 deletions gen/gtk_consts_gen.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
const PLATFORM_SPECIFIC = Dict{String, Any}(
"G_DIR_SEPARATOR" => :(Base.Filesystem.path_separator[1]),
"G_DIR_SEPARATOR_S" => :(Base.Filesystem.path_separator),
"G_SEARCHPATH_SEPARATOR" => :(Sys.iswindows() ? ';' : ':'),
"G_SEARCHPATH_SEPARATOR_S" => :(Sys.iswindows() ? ";" : ":"),
"G_MODULE_SUFFIX" => :(Sys.iswindows() ? "dll" : "so"), #For "most" Unices and Linux this is "so".
"G_PID_FORMAT" => :(Sys.iswindows() ? "p" : "i"), #Incorrectly stated as only "i" in Glib reference.
)

function gen_consts(body, gtk_h)
count = 0
exports = Expr(:export)
push!(body.args,exports)

tdecls = cindex.search(gtk_h, cindex.TypedefDecl)
tdecls = Clang.search(gtk_h, Clang.CXCursor_TypedefDecl)
for tdecl in tdecls
ctype = cindex.getCanonicalType(cindex.getCursorType(tdecl))
if isa(ctype,cindex.Enum)
name = cindex.spelling(tdecl)
ctype = canonical(type(tdecl))
if isa(ctype, CLEnum)
name = spelling(tdecl)
m = match(r"^(G\w+)$", name)
if m === nothing
continue
Expand All @@ -16,13 +25,13 @@ function gen_consts(body, gtk_h)
push!(exports.args, name)
consts = Expr(:block)
push!(body.args, Expr(:toplevel, Expr(:module, false, name, consts)))
children = cindex.children(cindex.getTypeDeclaration(ctype))
children = Clang.children(typedecl(ctype))
mask = true
c1 = cindex.spelling(children[1])
c1 = spelling(children[1])
splitc1 = split(c1,'_')
prefix = length(splitc1)
for child in children
c2 = cindex.spelling(child)
c2 = spelling(child)
if !endswith(c2,"_MASK")
mask = false
end
Expand All @@ -44,13 +53,13 @@ function gen_consts(body, gtk_h)
lprefix += length(splitc1[i])+1
end
for child in children
decl = cindex.spelling(child)
decl = spelling(child)
if mask
shortdecl = decl[lprefix:end-5]
else
shortdecl = decl[lprefix:end]
end
jldecl = Expr(:const, Expr(:(=), Symbol(decl), Expr(:call, :(Main.Base.convert), :(Main.Base.Int32), cindex.value(child))))
jldecl = Expr(:const, Expr(:(=), Symbol(decl), Expr(:call, :(Main.Base.convert), :(Main.Base.Int32), value(child))))
if occursin(r"^[A-Za-z]", shortdecl)
push!(consts.args, Expr(:const, Expr(:(=), Symbol(shortdecl), jldecl)))
else
Expand All @@ -63,14 +72,19 @@ function gen_consts(body, gtk_h)
count += 1
end
end
mdecls = cindex.search(gtk_h, cindex.MacroDefinition)

mdecls = Clang.search(gtk_h, Clang.CXCursor_MacroDefinition)
for mdecl in mdecls
name = cindex.spelling(mdecl)
name = spelling(mdecl)
if occursin(r"^G\w*[A-Za-z]$", name)
tokens = cindex.tokenize(mdecl)
if length(tokens) == 3 && isa(tokens[2], cindex.Literal)
tok2 = Clang.wrap_c.handle_macro_exprn(tokens, 2)[1]
tok2 = replace(tok2, "\$", "\\\$")
if haskey(PLATFORM_SPECIFIC, name)
push!(body.args, Expr(:const, Expr(:(=), Symbol(name), PLATFORM_SPECIFIC[name])))
continue
end
tokens = tokenize(mdecl)
if length(tokens) == 2 && isa(tokens[2], Literal)
tok2 = Clang.handle_macro_exprn(tokens, 2)[1]
tok2 = replace(tok2, "\$"=>"\\\$")
push!(body.args, Expr(:const, Expr(:(=), Symbol(name), Meta.parse(tok2))))
else
#println("Skipping: ", name, " = ", [tokens...])
Expand Down
Loading