Creating an installer for a V3 AudioUnit

I've got a bunch of AudioUnit projects approaching release, and am attempting to build an installer for them.

All are based on the AudioUnit template in Xcode 14.

What actually governs how the system detects an AudioUnit? The instructions I have seen say that the built .appex should be renamed to have the extension .component and installed into /Library/Audio/Plug-Ins/Components/ - great, I am able to build a signed installer that does that (i.e. strip out the built Application project that is part of the AudioUnit template but useless to, say, a Logic Pro user), include the .appex that declares the plugin and embeds a Framework that contains the actual code (so it can be loaded in-process).

auval -l does not show it after running the installer, nor does Console show anything logged suggesting that it was found but malformed or something like that.

Meanwhile, simply building the project causes auval -l to show an install of it in the build directory, and I have noticed that if I delete that, auval -l would still show the plugin installed, but now in the location I exported an archive of the project (!!). What black magic is this?

However, deleting both the recent build and the archive, after running the installer, and there is no indication that AudioComponentRegistry even sees the copy of it in one of the two locations actually documented to be valid install locations for an AudioUnit.

I have, however, installed one third-party free AUv3 which installed into /Library/Audio/Plug-Ins/Components/

Am I misunderstanding something about how this works? Is there some string other than AudioComponentRegistry I should filter on in Console that might provide a clue why my AudioUnit installed there is not picked up? Must I ship the semi-pointless Application that is part of the Xcode template project, and whatever magical mechanism detects it when I build will work its magic on end-users' machines?

Or could the problem be that the Framework with the actual code under Contents/Frameworks inside the audio unit, rather than installed independently into /Library/Frameworks?

Hello @timboudreau, you asked:

What actually governs how the system detects an AudioUnit?

AUv3 plug-ins are app extensions. They belong to the app that contains them in its .app bundle. The first time you run the host app on macOS, the system registers the extension. At this point, other apps can load the extension out-of-process via XPC, as the main binary inside the .appex bundle is an XPC executable. Similarly, if you delete the host app, the system unregisters the AUv3.

On macOS, you can structure an AUv3 such that it can run in-process. To do that, you put all the AUv3 code in a framework and add the AudioComponentBundle key to your AUv3's Info.plist file. The value of the AudioComponentBundle key is the bundle ID of your framework:

<dict>
	<key>NSExtension</key>
	<dict>
		<key>NSExtensionAttributes</key>
		<dict>
            <key>AudioComponentBundle</key>
            <string>your framework's bundle ID</string>
			<key>AudioComponents</key>
			<array>
			    ...
			</array>
		</dict>
		...
	</dict>
</dict>

You also need to include at least one symbol in your app extension so that it builds. This can be a dummy function or variable.

The instructions I have seen say that the built .appex should be renamed to have the extension .component and installed into /Library/Audio/Plug-Ins/Components/

No, this is incorrect. When you build an AUv2, which is not an app extension but a loadable bundle, you replace the .bundle extension with .component and place it in /Library/Audio/Plug-Ins/Components/. Normally this requires an installer.

An AUv3 extension, on the other hand, depends on its host app. So to ship the AUv3, you ship the host app. Even when the AUv3 can be loaded in-process, the framework and app extension bundles will still be inside the host's .app bundle, and not in /Library/Audio/Plug-Ins/Components/.

Creating an installer for a V3 AudioUnit
 
 
Q