def _build_gdef(ufo, skipExportGlyphs=None):
from glyphsLib import glyphdata<EOL>bases, ligatures, marks, carets = set(), set(), set(), {}<EOL>category_key = GLYPHLIB_PREFIX + "<STR_LIT>"<EOL>subCategory_key = GLYPHLIB_PREFIX + "<STR_LIT>"<EOL>for glyph in ufo:<EOL><INDENT>if skipExportGlyphs is not None:<EOL><INDENT>if glyph.name in skipExportGlyphs:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>has_attaching_anchor = False<EOL>for anchor in glyph.anchors:<EOL><INDENT>name = anchor.name<EOL>if name and not name.startswith("<STR_LIT:_>"):<EOL><INDENT>has_attaching_anchor = True<EOL><DEDENT>if name and name.startswith("<STR_LIT>") and "<STR_LIT:x>" in anchor:<EOL><INDENT>carets.setdefault(glyph.name, []).append(round(anchor["<STR_LIT:x>"]))<EOL><DEDENT><DEDENT>glyphinfo = glyphdata.get_glyph(glyph.name)<EOL>category = glyph.lib.get(category_key) or glyphinfo.category<EOL>subCategory = glyph.lib.get(subCategory_key) or glyphinfo.subCategory<EOL>if subCategory == "<STR_LIT>" and has_attaching_anchor:<EOL><INDENT>ligatures.add(glyph.name)<EOL><DEDENT>elif category == "<STR_LIT>" and (<EOL>subCategory == "<STR_LIT>" or subCategory == "<STR_LIT>"<EOL>):<EOL><INDENT>marks.add(glyph.name)<EOL><DEDENT>elif has_attaching_anchor:<EOL><INDENT>bases.add(glyph.name)<EOL><DEDENT><DEDENT>if not any((bases, ligatures, marks, carets)):<EOL><INDENT>return None<EOL><DEDENT>def fmt(g):<EOL><INDENT>return ("<STR_LIT>" % "<STR_LIT:U+0020>".join(sorted(g, key=ufo.glyphOrder.index))) if g else "<STR_LIT>"<EOL><DEDENT>lines = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>" % fmt(bases),<EOL>"<STR_LIT>" % fmt(ligatures),<EOL>"<STR_LIT>" % fmt(marks),<EOL>"<STR_LIT>",<EOL>]<EOL>for glyph, caretPos in sorted(carets.items()):<EOL><INDENT>lines.append(<EOL>"<STR_LIT>"<EOL>% (glyph, "<STR_LIT:U+0020>".join(unicode(p) for p in sorted(caretPos)))<EOL>)<EOL><DEDENT>lines.append("<STR_LIT>")<EOL>return "<STR_LIT:\n>".join(lines)<EOL>
Build a GDEF table statement (GlyphClassDef and LigatureCaretByPos).

    Building GlyphClassDef requires anchor propagation or user care to work as
    expected, as Glyphs.app also looks at anchors for classification:

    * Base: any glyph that has an attaching anchor (such as "top"; "_top" does
      not count) and is neither classified as Ligature nor Mark using the
      definitions below;
    * Ligature: if subCategory is "Ligature" and the glyph has at least one
      attaching anchor;
    * Mark: if category is "Mark" and subCategory is either "Nonspacing" or
      "Spacing Combining";
    * Compound: never assigned by Glyphs.app.

    See:

    * https://github.com/googlei18n/glyphsLib/issues/85
    * https://github.com/googlei18n/glyphsLib/pull/100#issuecomment-275430289