tapi generates .tbd lacking expected UUIDs

I'm trying to use tapi to generate a .tbd for a multi-arch dynamic library. The dynamic library has LC_UUIDs for both architectures, but the generated .tbd does not have a uuids section. I have tried generating .tbd versions 2, 3, and 4. (Which version should I use if I want to support older macOS releases?)

I'm using the command tools from Xcode 15.0.1 on macOS 14.1 on arm64.

Replies

Why do you care about this lack of a uuids section? What function does it perform in your setup?

For context, the .tbd files in our SDKs don’t contain this section because it’s effectively deprecated.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I like that answer!

My explanation is a bit complicated. As you may know, the JavaNativeFoundation framework does not run natively on arm64. So, I am trying to figure out how to compile the open-source for it in a way that can be used on all architectures and macOS releases back to 10.10. I found that the only way to compile a framework to support 10.10 was to use an old version of Xcode (13.4.1 worked). When I build the framework using that Xcode, it creates a .tbd that includes UUIDs. Instead of using an old Xcode, I thought I would instead create the package using individual command tools (such as tapi) from the current Xcode. I figured that if I was unable to generate equivalent files, I must be doing something wrong. So, I'm happy to hear that the lack of UUIDs in the .tbd is not a problem.

Now, you may be thinking that I should not need a JNF framework that runs on 10.10, as 10.10 already has a JNF. That seems reasonable, assuming that the dynamic linker ignores frameworks on the path that don't support the current OS and arch.

However, someday I may wish to replace JNF with my own, much smaller framework, and I want that framework to run on 10.10 and later. So, my questions are:

  1. Do I need a .tbd file in a framework to run on some releases of macOS?
  2. If so, which version of the .tbd file should I use for maximum compatibility with older macOS release?

Thank you for your assistance!

First up, I recommend that your read through An Apple Library Primer because I’m going to assume stuff from that post.

  1. Do I need a .tbd file in a framework to run on some releases of macOS?

  2. If so, which version of the .tbd file should I use for maximum compatibility with older macOS release?

These questions don’t make sense to me.

A .tbd file is a stub library. It’s only relevant at compile time. So, the version of the .tbd is irrelevant to macOS. Rather, it controls what tools you’ll be compatible with at build time.

Now, a poorly constructed .tbd file can cause the tools to build a Mach-O image that’s incompatible with a specific macOS release, but that’s a very different issue.

In general, you shouldn’t ship the .tbd file in your final product. It doesn’t do bad, but it doesn’t do anything good either. It just takes up space. See the discussion of “compile-time and run-time roles” in An Apple Library Primer.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

In general, you shouldn’t ship the .tbd file in your final product.

I'm not sure what you mean by final product. In this case, my final product is a framework, and the immediate "customers" for that product are developers. The developers would be building things that use the framework (compile time role) and/or including it in applications (run time role). So, if I combine various things you have written, it sounds like a reasonable choice is for me to imitiate what the current Xcode does when it builds a framework. That means creating a V4 .tbd file with no UUIDs. Yes?

In this case, my final product is a framework

So how do your developers use your framework? Do they embed it within their app? Or is the app expecting the framework to be installed elsewhere on the system?

This matters because it affects your path forward:

  • In the embed case, the framework you ship should include the Mach-O because that’s what Xcode will copy into your developer’s app. In that case you don’t need a .tbd file.

  • If the installed elsewhere case, it’s better to include a .tbd file rather than a Mach-O because it makes your framework smaller. In that case, assuming your developers are using relatively modern tools, a modern .tbd file with no UUIDs is fine.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"