iOS Build Environment Help Center

A better interpreter for the build system

append delete Pierre-Marie Baty

Endorsing the "living off the land" philosophy (i.e. always use the immediately available tools to do the job instead of depending on extra software), when I initially created this builder in 2009, it was rather a proof of concept (version 1.x) than a real product and at that time using Batch scripts to order the tasks necessary to build an app seemed a sensible choice.

Then came the interest from Unity users, and a demand for which I simply wasn't prepared. I spent much time expanding the master build script so as to handle all sort of situations (even hotpatching problems that were caused by incorrect project generation rather than builder insufficiencies), and even if my Batch skills levelled up quite a bit it soon became obvious that the Windows command interpreter would be in no way part of a sane future for this toolchain.

The need was, and still _is_, for an interpreter:
- that works identically on every platform since Windows 7 and can be reasonably easily ported to other platforms should the need arise
- easy to write and maintain and easy to understand for users to be able to expand the build script to suit their needs, i.e as common and standard as possible (something like POSIX shell would be ideal)
- not requiring dozen of files and megabytes worth of filesystem dependencies (a single interpreter executable, portable to other platforms, would be ideal)
- correctly handling long pathnames (>260 characters)
- fast to load *and* to execute. We're building stuff after all.

Declined candidates:
- WSL Bash. Does not match criteria #1 (no Win7 support). Granted, this will be less and less of a problem in the future as Win7 fades away, but we're not there yet.
- MS Powershell. Does not match criteria #2.
- Perl. Does not match criteria #3 and #5.
- Python. Does not match criteria #3.
- Git Bash. Does not match criteria #3 and #5. Git Bash is _terribly slow_!
- GNU Make, BSD Make, NMake. Very limited in terms of logic and requires to write all rules in platform-specific code, thus does not match #1.
- CMake. Fails at #3 and requires to write rules in platform-specific code, thus fails #1.
- Ninja. Solves only the last half the problem (building itself), the first half of the problem remaining unsolved, i.e. conditionally deciding what and how to build. I like the performance though.

Recently a Win32 port of BusyBox was made and I had great expectations about it. A full-featured POSIX shell with enough UNIX tools to do the job identically on all platforms, self-contained in a single executable. I downloaded the source code and gave it a try. After spending some time porting enough of the build script to POSIX shell, it turns out that it doesn't match criteria #4 and #5.

About #4, the lack of long pathname support was particularly disappointing. A lot of CocoaPods-based Xcode projects have files nested in deep directory structures that easily blow away this ages-old Microsoft limit. I could patch that BusyBox port so as to add long pathname support but would be happier if that feature was merged upstream instead (especially considering it's GPL). I emailed the author with a patch proposal but got no reply yet.

About #5, the lack of performance turned out to be really unexpected. The current Batch command interpreter is at least twice faster than Win32 BusyBox. I suppose one of the causes is in the way BusyBox continuously needs to spawn new processes as POSIX tools are being called along the script, and the fact that Batch files are so limited in possibilities that they can actually afford to be interpreted fast.

We're not out of ammo. Another candidate, the last-chance one, is to write the build logic in a tailor-made C program. No more process spawning, optimal performance, and provided it's cleanly written, portable and will behave identically across platforms. I'm slowly moving towards adopting this idea, not completely sure it's the right choice still.

If you have other ideas, suggestions, feel free to write them here!

:: @Pierre-Marie Baty added on 10 Jun ’21 · 13:54

Among the rejected candidates, I forgot to add Cygwin/MinGW/MSYS. Same problem as BusyBox dash, too slow, and the implementation choices of their POSIX compatibility layer (for filesystem representation and symbolic links) turned out to cause problems.

I actually wonder if a portable, self-contained interpreter that's at the same time lightweight, standard, more powerful *and* faster than cmd.exe actually _exists_. Each of these criteria taken alone is easily matched. Even when you combine them all, theory beats it. The problem is that, practical tests don't.

Reply RSS

Replies

append delete #1. Pierre-Marie Baty

I'm making progress on this. It took me quite some work but I successfully ported the original Debian Almquist shell (dash) to Win32 and basically did what BusyBox did by bundling a selection of POSIX tools, but this time with a BSD userland (and exclusively BSD licenses) from Apple (when available) and FreeBSD (when not) instead of a Linux userland. Anybody having looked once at the BusyBox source code will understand the immense interest of having a "different" codebase. It still has a lot of bugs, but it's functional enough to behave like a real POSIX shell. This dash.exe is included in versions 3.64 onwards of the builder -- feedback and bug reports are welcome.

It's faster than BusyBox dash (but slower than a real shell because of Windows and NTFS particularities), handles long pathnames (to some extent), and foremost handles my emulated symlinks the same way the toolchain tools do. I learned a lot of low level things while working on it, and still am.

Reply

(Leave this as-is, it’s a trap!)

There is no need to “register”, just enter the same name + password of your choice every time.

Pro tip: Use markup to add links, quotes and more.

Moderators: Pierre-Marie Baty