-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ninja Builder #569
Ninja Builder #569
Conversation
Building all Rubik targets with gftools-builder: 1m 52s. |
I think you'll need to update |
Lib/gftools/builder/ninja.py
Outdated
from fontTools.designspaceLib import DesignSpaceDocument | ||
from pathlib import Path | ||
|
||
UNSUPPORTED = ["stylespaceFile", "statFormat4", "ttfaUseScript", "vttSources"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mind adding these at some point if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine. It's just a matter of moving the code we have inside the buider into distinct gftools-* command line utilities. Which arguably they should be already.
Lib/gftools/builder/ninja.py
Outdated
) | ||
raise NotImplementedError() | ||
|
||
self.w = Writer(open("build.ninja", "w")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You maybe want to put this in a https://docs.python.org/3/library/tempfile.html?highlight=tempdir#tempfile.TemporaryDirectory so parallel invocations of gfbuild don't overwrite each other. The dir can then be deleted after asuccessful run (del
it) or stay in place otherwise for diagnostics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to do that, precisely because I want a second successive run to be fast and only generate what needs to be generated.
There is still some problem here with instance UFO filenames. Sometimes fontmake puts them into |
7b5e2af
to
2fb5d74
Compare
Lib/gftools/builder/ninja.py
Outdated
self.designspaces.append((designspace_path, designspace)) | ||
self.w.newline() | ||
|
||
def fontmake_args(self, args): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this function where we could add the additional argument to --expand-features-to-instances
?
See #581 for more background on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's where it should go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I only intended to highlight Line 131 here.
I tried hacking this in the download within my local venv, but at least in initial tests, it wasn't working as I had hoped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, yeah, I’ve edited this in my venv, but I can’t even get it to print debugging statements (even using a config.yaml
file with logLevel
set to DEBUG
. I’m not entirely sure if the Ninja builder is even running, or even how I would determine that.
def fontmake_args(self, args):
my_args = []
my_args.append("--expand-features-to-instances") # TESTING;
my_args.append("--filter ...")
if self.config["flattenComponents"]:
my_args.append("--filter FlattenComponentsFilter")
if self.config["decomposeTransformedComponents"]:
my_args.append("--filter DecomposeTransformedComponentsFilter")
if "output_dir" in args:
my_args.append("--output-dir " + args["output_dir"])
if "output_path" in args:
my_args.append("--output-path " + args["output_path"])
print(" ".join(my_args)) # DEBUGGING;
return " ".join(my_args)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks very much like you’re not running the ninja builder. Try python -m gftools.builder.ninja (configfile).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the tip! I’ll give that a try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, that definitely ran the Ninja builder, including my hacks!
However (this may be stuff you already know), it seems that:
- it will only run on a config file, not a designspace
- add the arg as suggested yields the following part way through the build:
fontmake: error: "--expand-features-to-instances" option invalid for UFO source
- It expects/requires stat table info in the config
ninja: build stopped: subcommand failed.
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/Users/stephennixon/type-repos/shantell-sans/venv-ninja/lib/python3.10/site-packages/gftools/builder/ninja.py", line 289, in <module>
NinjaBuilder(sys.argv[1]).build()
File "/Users/stephennixon/type-repos/shantell-sans/venv-ninja/lib/python3.10/site-packages/gftools/builder/ninja.py", line 47, in build
os.remove(temporary)
FileNotFoundError: [Errno 2] No such file or directory: './fonts/builder/variable/shantell_sans-ital_wght_BNCE_IRGL_TRAK--static-ninja[wght].ttf.statstamp'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Yeah, that's true when you run it as
python3 -m gftools.builder.ninja
, but it's meant to work asgftools-builder
as well. - Urgh. We need to add that only when creating UFOs.
- No, that's a problem removing temporary files, which I think I fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Thanks for the insights here! I might try to hack away at this on my end, but don't let my issues block an otherwise solid PR.
Just an update on this: I've used it to build hundreds of Noto fonts, and for that it works well. I haven't tracked down the issue with instance UFOs ending up in the wrong place, because I'm scrambling to get lots of fonts built and released and don't really have any bandwidth for anything else. If anyone wants to play with it, clone the googlefonts-project-template and try building that. |
Hey, sorry to have complicated this PR. I really appreciate you taking a bit of time to respond to my questions! I definitely don't want to block it when it's already proving useful for a bunch of projects. Mine is a somewhat weird use case (it is also for Google Fonts, FWIW), so I can try to hack on it on my end if what I need isn't applicable to your projects. Thanks for all your great work here! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just had a quick look and it looks decent. Since it will use the original builder if it encounters an unsupported feature, I'm happy to merge this.
We can always improve it in 2023 Q1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch the above. I've just started playing with some files I have locally and it crashed.
Traceback (most recent call last):
File "/Users/marcfoley/Type/tools/venv/bin/gftools-gen-stat.py", line 7, in <module>
exec(compile(f.read(), __file__, 'exec'))
File "/Users/marcfoley/Type/tools/bin/gftools-gen-stat.py", line 92, in <module>
main()
File "/Users/marcfoley/Type/tools/bin/gftools-gen-stat.py", line 66, in main
fonts = [TTFont(f) for f in args.fonts]
File "/Users/marcfoley/Type/tools/bin/gftools-gen-stat.py", line 66, in <listcomp>
fonts = [TTFont(f) for f in args.fonts]
File "/Users/marcfoley/Type/tools/venv/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 130, in __init__
file = open(file, "rb")
FileNotFoundError: [Errno 2] No such file or directory: '[{name:'
When I was adding ninja to diffenator2, it didn't like relative paths so it could be this. I'll inspect it now.
Start with looking at the |
OK, I've fixed the stat table issue, but there's another problem, which is that sometimes glyphs2ufo produces a designspace file with instance filenames like this:
(Note "instance_ufos".) When you run I don't know if that's a glyphsLib bug or a fontmake bug or both. (@anthrotype?) I suppose we could probably work around it by passing (Edit: Actually, we don't use glyphs2ufo directly, we use |
Boggle
|
And another issue: if we have a .designspace file where there are instances but no filenames defined (e.g. the Roboto Serif designspace), I don't know how to work out what the eventual UFO file names will be. (We need those as targets, so we can then add rules to convert them to TTF.) |
if there's an instance
I'm fixing that in googlefonts/fontmake#102. If an instance does not have any filename attribute defined, we make up its name from the instance ufo's family/style name (similarly to how we make up the OTF/TTF output path from a UFO input). In addition to this, you will be able to pass --output-path if you are building one instance UFO (you know you can already filter which instance(s) to build with -i option which takes a regex matching instance.name attr). I hope that helps.. |
and you will also be able to pass --output-dir option to override in which directory the instance UFOs gets saved when building |
Module needs renaming to stop "import ninja" importing itself, for some odd reason I don't understand
895e575
to
ba4f7b8
Compare
Well this is frustrating; coming back to try to fix it, I now can't make it fail in the way that I'm sure it used to. It correctly builds:
So... it works? |
frustrating but in a good way 😉 |
Seems to be failing the builder tests. I put these in place so we don't cause regressions for The Type founders, #670 |
Thanks. It seems like it works for .glyphs and .designspace files but not for individual .ufos. |
OK, apart from Windows which I'll disable because, well, Windows users shouldn't expect |
FWIW, when fiddling with filename attributes with designspaceLib, set the filename on |
Is there any notes about switching to ninja-builder? How can I build now with what used to be |
The switch to ninja builder happened over a year ago, and we've moved to builder2 since then - sorry to leave you behind! Arguments should be moved into the
to your config file. |
Ah ok no worries, thank you! |
An experimental version of gftools.builder which uses ninja to orchestrate font builds instead of fontmake's top-level methods.
Currently only does the variable font bit; the real speedup is with the statics.