Skip to content

Commit

Permalink
Mostfiles regenerated successfully
Browse files Browse the repository at this point in the history
This commit closes #9 by adding the new girgen/file.go FileGenerator,
which is completely refactored from the ground up to be much smaller,
cleaner and side effects-free.

This commit closes #8 as well by introducing the SourceNamespace and
CurrentNamespace API inside typeconv.Converter, which allows the
converter to pick the right namespace for resolving and generating.
  • Loading branch information
diamondburned committed Jul 4, 2021
1 parent ef8ea3f commit 3d2f6a2
Show file tree
Hide file tree
Showing 908 changed files with 291,173 additions and 288,671 deletions.
113 changes: 59 additions & 54 deletions cmd/gir_generate/config.go
Original file line number Diff line number Diff line change
@@ -1,82 +1,87 @@
package main

import "github.com/diamondburned/gotk4/gir/girgen"
import . "github.com/diamondburned/gotk4/gir/girgen/types"

// packages lists pkg-config packages and optionally the namespaces to be
// generated. If the list of namespaces is nil, then everything is generated.
var packages = []Package{
{"gobject-introspection-1.0", []string{
"GLib-2.0",
"GObject-2.0",
"Gio-2.0",
"cairo-1.0",
"GLib-2",
"GObject-2",
"Gio-2",
"cairo-1",
}},
{"gdk-pixbuf-2.0", nil},
{"graphene-1.0", nil},
{"pango", []string{
"Pango-1.0",
"PangoCairo-1.0",
"Pango-1",
"PangoCairo-1",
}},
{"gtk4", nil}, // includes Gdk
{"gtk+-3.0", nil}, // includes Gdk
}

// preprocessors defines a list of preprocessors that the main generator will
// use. It's mostly used for renaming colliding types/identifiers.
var preprocessors = []Preprocessor{
// Collision due to case conversions.
TypeRenamer("GLib-2.file_test", "test_file"),
}

// filters defines a list of GIR types to be filtered. The map key is the
// namespace, and the values are list of names.
var filters = []girgen.FilterMatcher{
girgen.AbsoluteFilter("C.cairo_image_surface_create"),
var filters = []FilterMatcher{
AbsoluteFilter("C.cairo_image_surface_create"),

// Broadway is not included, so we don't generate code for it.
girgen.FileFilter("../gsk/broadway/gskbroadwayrenderer.h"),
FileFilter("gsk/broadway/gskbroadwayrenderer.h"),
// Output buffer parameter is not actually array.
girgen.AbsoluteFilter("GLib.unichar_to_utf8"),
// Collision due to case conversions.
girgen.TypeRenamer("GLib.file_test", "test_file"),
AbsoluteFilter("GLib.unichar_to_utf8"),
// Requires special header, is optional function.
girgen.AbsoluteFilter("Gio.networking_init"),
AbsoluteFilter("Gio.networking_init"),
// Not an array type but expects an array.
girgen.AbsoluteFilter("Gio.SimpleProxyResolver.set_ignore_hosts"),
AbsoluteFilter("Gio.SimpleProxyResolver.set_ignore_hosts"),
// These are not found.
girgen.AbsoluteFilter("GdkPixbuf.PixbufNonAnim"),
girgen.AbsoluteFilter("GdkPixbuf.PixbufModulePattern"),
girgen.AbsoluteFilter("C.gdk_pixbuf_non_anim_get_type"),
AbsoluteFilter("GdkPixbuf.PixbufNonAnim"),
AbsoluteFilter("GdkPixbuf.PixbufModulePattern"),
AbsoluteFilter("C.gdk_pixbuf_non_anim_get_type"),

girgen.FileFilter("garray.h"),
girgen.FileFilter("gasyncqueue.h"),
girgen.FileFilter("gatomic.h"),
girgen.FileFilter("gbacktrace.h"),
girgen.FileFilter("gbitlock.h"),
girgen.FileFilter("gbytes.h"),
girgen.FileFilter("gdataset.h"),
girgen.FileFilter("gdate.h"),
girgen.FileFilter("gdatetime.h"),
girgen.FileFilter("gerror.h"), // already handled internally
girgen.FileFilter("ghook.h"),
girgen.FileFilter("glib-unix.h"),
girgen.FileFilter("glist.h"),
girgen.FileFilter("gmacros.h"),
girgen.FileFilter("gmem.h"),
girgen.FileFilter("gnetworking.h"), // needs header
girgen.FileFilter("gprintf.h"),
girgen.FileFilter("grcbox.h"),
girgen.FileFilter("grefcount.h"),
girgen.FileFilter("grefstring.h"),
girgen.FileFilter("gsettingsbackend.h"),
girgen.FileFilter("gslice.h"),
girgen.FileFilter("gslist.h"),
girgen.FileFilter("gstdio.h"),
girgen.FileFilter("gstrfuncs.h"),
girgen.FileFilter("gstringchunk.h"),
girgen.FileFilter("gstring.h"),
girgen.FileFilter("gstrvbuilder.h"),
girgen.FileFilter("gtestutils.h"),
girgen.FileFilter("gthread.h"),
girgen.FileFilter("gthreadpool.h"),
girgen.FileFilter("gtrashstack.h"),
FileFilter("garray.h"),
FileFilter("gasyncqueue.h"),
FileFilter("gatomic.h"),
FileFilter("gbacktrace.h"),
FileFilter("gbitlock.h"),
FileFilter("gbytes.h"),
FileFilter("gdataset.h"),
FileFilter("gdate.h"),
FileFilter("gdatetime.h"),
FileFilter("gerror.h"), // already handled internally
FileFilter("ghook.h"),
FileFilter("glib-unix.h"),
FileFilter("glist.h"),
FileFilter("gmacros.h"),
FileFilter("gmem.h"),
FileFilter("gnetworking.h"), // needs header
FileFilter("gprintf.h"),
FileFilter("grcbox.h"),
FileFilter("grefcount.h"),
FileFilter("grefstring.h"),
FileFilter("gsettingsbackend.h"),
FileFilter("gslice.h"),
FileFilter("gslist.h"),
FileFilter("gstdio.h"),
FileFilter("gstrfuncs.h"),
FileFilter("gstringchunk.h"),
FileFilter("gstring.h"),
FileFilter("gstrvbuilder.h"),
FileFilter("gtestutils.h"),
FileFilter("gthread.h"),
FileFilter("gthreadpool.h"),
FileFilter("gtrashstack.h"),

// These are missing on build for some reason.
girgen.AbsoluteFilter("C.g_array_get_type"),
girgen.AbsoluteFilter("C.g_byte_array_get_type"),
girgen.AbsoluteFilter("C.g_bytes_get_type"),
girgen.AbsoluteFilter("C.g_ptr_array_get_type"),
AbsoluteFilter("C.g_array_get_type"),
AbsoluteFilter("C.g_byte_array_get_type"),
AbsoluteFilter("C.g_bytes_get_type"),
AbsoluteFilter("C.g_ptr_array_get_type"),
}
41 changes: 25 additions & 16 deletions cmd/gir_generate/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"flag"
"fmt"
"log"
Expand All @@ -13,21 +14,25 @@ import (

"github.com/diamondburned/gotk4/gir"
"github.com/diamondburned/gotk4/gir/girgen"
"github.com/diamondburned/gotk4/gir/girgen/logger"
"github.com/pkg/errors"
"golang.org/x/sync/semaphore"
)

var (
output string
module string
verbose bool
listPkg bool
output string
module string
verbose bool
listPkg bool
parallel = int64(runtime.GOMAXPROCS(-1))
)

func init() {
flag.StringVar(&output, "o", "", "output directory to mkdir in")
flag.StringVar(&module, "m", "github.com/diamondburned/gotk4", "go module name")
flag.BoolVar(&verbose, "v", verbose, "log verbosely (debug mode)")
flag.BoolVar(&listPkg, "l", listPkg, "only list packages and exit")
flag.Int64Var(&parallel, "p", parallel, "number of generator goroutines to spawn")
flag.Parse()

if !listPkg && output == "" {
Expand Down Expand Up @@ -79,27 +84,29 @@ func main() {
var errMut sync.Mutex
var errors []error

sema := make(chan struct{}, runtime.GOMAXPROCS(-1))

gen := girgen.NewGenerator(repos, modulePath)
gen.Color = true
gen.Logger = log.New(os.Stderr, "girgen: ", log.Lmsgprefix)
gen.AddFilters(filters)

if verbose {
gen.LogLevel = girgen.LogDebug
gen.LogLevel = logger.Debug
}

// Do a clean-up of the target directory.
if err := os.RemoveAll(output); err != nil {
log.Println("non-fatal: failed to rm -rf output dir:", err)
}

sema := semaphore.NewWeighted(parallel)

for _, repo := range repos {
for _, namespace := range repo.Namespaces {
ng := gen.UseNamespace(namespace.Name, namespace.Version)
if ng == nil {
log.Fatalln("cannot find namespace", namespace.Name, "v"+namespace.Version)
}

sema <- struct{}{}
sema.Acquire(context.Background(), 1)
wg.Add(1)

go func() {
Expand All @@ -109,7 +116,7 @@ func main() {
errMut.Unlock()
}

<-sema
sema.Release(1)
wg.Done()
}()
}
Expand All @@ -127,8 +134,7 @@ func main() {
}

func writeNamespace(ng *girgen.NamespaceGenerator) error {
pkg := ng.PackageName()
dir := filepath.Join(output, pkg)
dir := filepath.Join(output, ng.PkgName)

if version := majorVer(ng.Namespace().Namespace); version > 1 {
// Follow Go's convention of a versioned package, so we can generate
Expand All @@ -140,14 +146,17 @@ func writeNamespace(ng *girgen.NamespaceGenerator) error {
return errors.Wrapf(err, "failed to mkdir -p %q", dir)
}

b, genErr := ng.Generate()
files, err := ng.Generate()

if err := os.WriteFile(filepath.Join(dir, pkg+".go"), b, 0666); err != nil {
return errors.Wrapf(err, "failed to write pkg %q", pkg)
for name, file := range files {
dst := filepath.Join(dir, name)
if err := os.WriteFile(dst, file, 0666); err != nil {
return errors.Wrapf(err, "failed to write to %s", dst)
}
}

// Preserve the generation error, but give it last priority.
return genErr
return err
}

func modulePath(namespace *gir.Namespace) string {
Expand Down
21 changes: 19 additions & 2 deletions core/pen/pen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"log"
"strings"
"text/template"
)

Expand Down Expand Up @@ -34,16 +35,32 @@ func NewPen(w PenWriter) *Pen {
var NoopPen = NewPen(noopWriter{})

// Words writes a list of words into a single line.
func (p *Pen) Words(words ...string) {
func (p *Pen) Words(words ...interface{}) {
for i, word := range words {
if i != 0 {
p.WriteByte(' ')
}
p.WriteString(word)

switch word := word.(type) {
case string:
p.WriteString(word)
case []string:
p.WriteString(strings.Join(word, " "))
default:
log.Panicf("unknown type %T given", word)
}
}

p.EmptyLine()
}

// Lines writes multiple lines.
func (p *Pen) Lines(lines []string) {
for _, line := range lines {
p.Line(line)
}
}

// Line writes a single line.
func (p *Pen) Line(line string) { p.Linef(line) }

Expand Down
31 changes: 19 additions & 12 deletions gir/gir.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gir

import (
"fmt"
"log"
"path"
"strconv"
"strings"
Expand Down Expand Up @@ -71,25 +72,31 @@ func VersionedNamespace(namespace *Namespace) string {

// VersionedName returns the name appended with the version suffix.
func VersionedName(name, version string) string {
return name + MajorVersion(version)
return name + "-" + MajorVersion(version)
}

// ParseVersionName parses the given fullName to return the original name and
// the version separately. If no versions are available, then the empty string
// is returned.
func ParseVersionName(fullName string) (name, majorVersion string) {
verIx := strings.IndexFunc(fullName, unicode.IsDigit)
if verIx == -1 {
return fullName, ""
// ParseVersionName parses the given full namespace to return the original name
// and the version separately. If no versions are available, then the empty
// string is returned.
func ParseVersionName(fullNamespace string) (name, majorVersion string) {
parts := strings.SplitN(fullNamespace, "-", 2)
if len(parts) == 0 {
return "", ""
}
if len(parts) == 1 {
return parts[0], ""
}

// Trim the minor versions off.
version := MajorVersion(parts[1])

// Verify the number is valid.
_, err := strconv.Atoi(fullName[verIx:])
_, err := strconv.Atoi(version)
if err != nil {
panic("verIx points to invalid int")
log.Panicf("version %q is invalid int", version)
}

return fullName[:verIx], fullName[verIx:]
return parts[0], version
}

// Repositories contains a list of known repositories.
Expand Down Expand Up @@ -459,7 +466,7 @@ func (repos Repositories) FindFullType(fullType string) *TypeFindResult {
}

v, _, _ = typeResultFlight.Do(fullType, func() (interface{}, error) {
result := repos.FindFullType(fullType)
result := repos.findFullType(fullType)
if result != nil {
typeResultCache.Store(fullType, result)
}
Expand Down
Loading

0 comments on commit 3d2f6a2

Please sign in to comment.