Show HN: TinyClock – a tiny true 5-arch universal Mac OS X single-binary GUI app (tycho.sytes.net)

192 points by zeymejbdv ↗ HN
1. Single universal binary, that can be natively executed on every hardware platform Mac OS X was made for (32/64 bit, PowerPC/x86/AppleSilicon).

2. Minimalistic gadget-style design. If launched as a tool, there is no menubar, no dock icon, no nothing, just the clock window.

3. Support for hidpi and dark mode for environments, that have them.

4. Window title bar for moving the window with a mouse, and a handle to resize it (latter for OS versions, that have it).

5. Can be easily ported to GNUStep and thus other OSes (sources under GPLv3).

6. Simple Makefile build system.

81 comments

[ 3.2 ms ] story [ 147 ms ] thread
(comment deleted)
Would it be possible to create a true universal binary that also runs on NeXT/Openstep on 68k, SPARC, PA-RISC and x86 as well as Rhapsody on PPC and x86?
This requires some investigation. Technically, I believe it is possible if the following 2 conditions are met:

1. The Mach-O executable format was not changed between all those OS versions (likely).

2. It is possible to gather sub-binaries for one CPU type but different OS types (less likely).

And SDK's and compillers (in emulator or on hardware) are required to try.

(comment deleted)
I had a closer look at the earliest available NeXTstep version (0.8) running in the previous emulator - I still need to refurbish the MO drive in my Cube to run it natively (I have a 68030 CPU board)... C and ObjC compilers (though the objc.exe (!) provided seems to be a source-to-source compiler) are included in the image available on winworldpc and I can compile the included demo source code.

It seems that this early version is significantly different from later NeXTstep (3.3) and OpenStep versions. For example, it does not use app bundles. System apps installed in the /Apps folder, such as Terminal, are simple Mach-O executable m68k binaries.

If we wanted to target such an early NeXTstep, in addition, the source code of TinyClock would have to be changed significantly. One problem is that early versions of AppKit used "NX" instead of "NS" prefixes. More difficult is that a number of classes used by TinyClock seem to be unimplemented - not even NSString (resp. NXString) seems to be available. More complex classes such as NSCalendarDate or NSBezierPath also seem to be a later addition (unless the 0.8 install image is missing some header files, the earliest documentation I could find was on 1.0).

So it seems that a completely universal binary is out of the question, unfortunately.

(comment deleted)
OT, but as someone who's never used Bazaar, how does this work?

    bzr clone https://tycho.sytes.net/TinyClock/
EDIT: To clarify, I'm curious since this is the same URL I'm opening in my browser.
Same as `git clone <repo>` - it downloads a local copy of the repo into a folder called ./TinyClock, which it will create if it doesn't exist.
One (IMO reasonable) objection/confusion might be that the the repo URL is the exact same as the web page, i.e. the actual posted article.

When coming from git/Mercurial/subversion etc as I do, it is at least mildly weird that the Bazaar repo address is the same as the address of a web document. The two objects are not (at least in my world) the same, so why should they share URIs?

Edit: deduped.

Because sending different content based on the content-type the user-agent asks for, e.g. with the "Accept:" header, has explicitly been part of the HTTP spec since version 1.1 in 1997?

https://datatracker.ietf.org/doc/html/rfc2068#section-12

https://datatracker.ietf.org/doc/html/rfc2068#section-14.1

See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_ne...

(FWIW - I don't know if that's how `bzr` does this, but it might, and the concept is 25 years old now.)

Edit: s/different content/different representations of the same resource/

True of course, didn't think about that. I'm not a web developer. :) Still think it's weird and kind of against my feeling for the spirit of a URI, but that's just me. Thanks.
You can git clone normal GitHub URLs without the .git at the end too.
Honestly, the most surprising thing to me was that people still use bzr. It looks like Canonical abandoned it back in 2016 [0]. It seems like it was suceeded by breezy [1], at least.

[0] https://en.wikipedia.org/wiki/GNU_Bazaar

[2] https://github.com/breezy-team/breezy

Same URL, different port. The website is at 80(http) or 443(https). Bzr seems to run on 4155.
I successfully cloned the repo using breezy. Did I get punked? It's empty.

    > bzr log
    ------------------------------------------------------------
    revno: 1
    committer: TinyClock <TinyClock@tycho.sytes.net>
    branch nick: TinyClock
    timestamp: Wed 2022-09-07 20:18:32 +0300
    message:
      initial commit
(comment deleted)

    > bzr clone https://tycho.sytes.net/TinyClock/
    > cd TinyClock
    > bzr checkout
    > ls
    controller.h  LICENSE  Makefile   view.h
    controller.m  main.m   README.md  view.m
(comment deleted)
>Launches faster, than Safari.

As it should, since one is a clock, the other a web browser.

Interesting stuff. Cross platform development is inspiring.

> As it should, since one is a clock, the other a web browser

Yeah. Surely a better statistic to be had.here. System preferences?

As it should, but not a given now that it's common for apps to bundle a whole browser as a runtime.
Not mine.

I write native.

I do tend to release apps in UIKit, so I don't quite achieve Buzzword Bingo, but I have always been a fan of native apps, and have watched the various efforts to avoid native, with the kind of sick fascination usually reserved for train wrecks.

Do you rewrite your apps for other platforms? I don't think anyone avoids native, it's just that cross platform is a much more important goal for many.
No. I don't write apps for other platforms.

I am quite aware that it is not the ideal "business posture," but that's how I roll.

I've been writing for Apple platforms, pretty much exclusively, since 1986.

Can’t remember the last time I thought about app launch speed outside of network access issues.
And instantly GIMP comes to my mind.
I agree that a clock should absolutely open faster than a browser, but it would be good to know what this metric actually represents. I don't know much about this style of universal binaries, so I don't know if the binary being "true 5-arch universal binaries" is the focus of the application start time metric.
Support for different architectures doesn't impact start time much. The code for the different archs is in different chunks of the file.

Linking more libraries slows down launch due to initialization that happens to get the libraries ready to use. Besides that it's mostly what the app itself is doing on startup.

So yes, beating Safari for a tiny app is… a good thing, but not very impressive.

Safari “getting snappier” with every OS update is a running gag in at least the MacRumors community. Or has been for quite a while. Maybe it’s retired now, much like the old gold “but will it run Crysis?” one.

By now, Safari should be so snappy it opens your pages and have their document tree ready two seconds before you think of doing it.

(comment deleted)
(comment deleted)
What does 5-arch mean? Single Google yielded nothing (which may be more of a comment on Google's quality as of late)
(comment deleted)
This binary is so universal that `file` utility gets confused about it.

    $ file /Volumes/TinyClock/TinyClock.app/Contents/MacOS/TinyClock 
    /Volumes/TinyClock/TinyClock.app/Contents/MacOS/TinyClock: Mach-O universal binary with 3 architectures: [i386:Mach-O executable i386
    - Mach-O executable i386] [ppc:Mach-O executable ppc
    - Mach-O executable ppc] [arm64:Mach-O 64-bit executable arm64Mach-O 64-bit executable arm64]
    /Volumes/TinyClock/TinyClock.app/Contents/MacOS/TinyClock (for architecture i386): Mach-O executable i386
    /Volumes/TinyClock/TinyClock.app/Contents/MacOS/TinyClock (for architecture ppc): Mach-O executable ppc
    /Volumes/TinyClock/TinyClock.app/Contents/MacOS/TinyClock (for architecture arm64): Mach-O 64-bit executable arm64
It's not confused; as noted in Known Bugs:

> Unlike done in previous project, netop Tiger SDKs (used to build several intermediate binaries) don’t contain 64-bit AppKit versions, and thus ppc64 and x86_64 binaries are excluded from the binary release.

The binary release is only three-architecture; it does not run on current Intel MacOS since it's missing an x86_64 segment. (You get a "this app needs to be updated" dialog if you try.)

It's not a common term. They're saying the exact same code will run successfully on 5 different CPU types (architectures).

I'm reminded of the Feynman "why" video. The other answers are technically more accurate than mine, and even mine assumes you understand the concept of CPU types. It's difficult to pitch answers at the right level.

Imagine you translate a book into 5 different languages. Then bind the five translations into a single volume. At the front, you put a brief table of contents listing the page number at which each translation begins. Each reader opens the book, checks the table of contents, then jumps to the page containing the translation in their language. All readers are reading the same book, but each reads the translation in their language. Unless you don’t know any of those five languages, in which case the book is unreadable for you.

Technically more accurate and complete than your answer, but an analogy I expect most non-technical people could understand.

AKA any instruction manual in Europe? (French/English/German/Spanish/Italian and so on).
It's a very impressive accomplishment. I support retro mac ppc/32/64, Windows 32 and 64, Linux on Intel and on Raspberry Pi, and signed mac Intel and Apple Silicon, for every (audio DSP, generic interface, mac AU and VST2.4) plugin I make. https://www.airwindows.com/

But I do it with lots of different available downloads, not as a single binary. That's what I find impressive about this. Somebody's running that XCode mod where you can bring in all the libraries from all the previous versions back to the dawn of time. I'm not even going to pretend to try to keep something like that working: I do my retro builds (and original design) on an antique machine dedicated to the purpose, and the modern stuff on a modern laptop dedicated to staying current.

144K altogther. Delightful achievement! Most app icons are bigger than that nowadays.
I want System 6 support for my SE/30 from 1989.
Check out Retro68, I still write classic mac apps using this toolchain.
> To obtain the full source tree do:

> bzr clone https://tycho.sytes.net/TinyClock/

I am surprised to find git not having built in support for cloning Bazaar repos. Almost as surprised as I am at finding a Bazaar repo in the wild.

(comment deleted)
Curiously it doesn't seem to run on my Intel Macbook running Big Sur - the icon is crossed out and I get

> “TinyClock.app” needs to be updated.

> The developer of this app needs to update it to work with this version of macOS. Contact the developer for more information.

https://jdon.at/Uff03u

Same on 2019 Intel iMac running Monterey.
It only has i386, ppc, and arm64 slices. So, an Intel Mac running recent macOS won't be able to launch it as it does not have an x86_64 slice (32-bit x86 execution having been removed).

Whether an app containing code for 3 architectures qualifies as "true 5-arch universal" is in the eye of the beholder I guess.

Interesting! I wonder why they didn't include x86_64. Doesn't seem likely to be problematic since it supports PPC64 and ARM64.

Edit: answered my own question by reading the actual page — "Unlike done in previous project, netop Tiger SDKs (used to build several intermediate binaries) don’t contain 64-bit AppKit versions, and thus ppc64 and x86_64 binaries are excluded from the binary release."

Seems like it’s literally not “5-arch” then. 32 bit PPC, 64 bit PPC, 32 bit X86, 64 bit ARM.
It actually doesn’t have ppc64 either. Just 3 slices.
The binaries were updated and now include all the slices:

lipo -info TinyClock.app/Contents/MacOS/TinyClock Architectures in the fat file: TinyClock.app/Contents/MacOS/TinyClock are: i386 x86_64 ppc64 ppc arm64

(comment deleted)
A much more impressive universal macOS application in my mind is the X Lossless Decoder (XLD), which you can run natively on PowerPC (32), Intel (32/64) and ARM (64). Not only is it a great app if you need to rip CDs or transcode audio, but the fact that it still runs on every Mac architecture is rather impressive.

https://tmkk.undo.jp/xld/index_e.html

I happened to have my 12" PowerBook G4 out, I just installed Sorbet Leopard* on it. I downloaded TinyClock and it's working on it.

*Sorbet Leopard is a modern update of Leopard, incorporating speedups from Tiger and the unreleased PPC Snow Leopard.

(comment deleted)
If we had a Busybox for every platform, and you compiled your app for every platform, you could bundle it all as one compressed shell script. Not as cool as one binary that works everywhere, but much simpler.

  #!/usr/bin/env sh
  set -eu
  FILE="${OS:-$(uname -s)}/${ARCH:-$(uname -p)}/${MACH:-$(uname -m)}/exe"
  unzip -d "${TMPDIR:-/tmp}" -X -b -o "$0" "$FILE"
  [ $? -gt 1 ] || exec "${TMPDIR:-/tmp}/$FILE"
  echo "$0: Error: could not execute '$FILE'" ; exit 126
  ########################################################
  # After here the Zip file is concatenated into the file
(comment deleted)
Doesn't work on 10.0: https://0x0.st/ofjW.png

Not only does the binary not load, but the dmg itself won't extract, it just opens to a blank Disk Copy window no matter what you try to do.

IMO CarbonLib is more impressive as you can target MacOS 8.1-9 as well as X (up until x86 support was dropped).

For a bit of comparison, Windows 2.03's (analog!) clock:

    CLOCK    EXE      8960   9-04-87  11:11a
...will run on Windows 2.0 up to Windows 10 x86.
OClock and "aclock" statically built can be run under older kernels up to today's distros.

Oh, and it will run and render over the network with paleolitic Unixen thanks to X :).

Yeah but doing a static build is probably hard because you need a static build against x?
X's IPC is very stable (which is half the point of X); the instance on shared libraries has more to do with it being a memory hog on the kinds of systems that existed the first couple decades of it's life.
This. If you rum SIMH to emulate a Vax (and some other Unix), most Unix programs requiring X can be perfectly forwarded to use the host's X server. Or some Xephyr server.
I used to bring up openvms running Motif on a vax through xfree86.
X works seamlessly, it's a client/server arch. Even if you run emulators, by exporting $DISPLAY to your host (and by running xhost +$EMULATOR_IP) you can run, for example, tools for older Unixen.

Except for SGI, but I am not that sure.

(comment deleted)