So after fiddling around with it for quite some time we managed to get XPC to work properly. The key is to put all binaries in an app group, let's say $(TeamIdentifierPrefix)com.example.myapp.xpc and use that as a prefix for the mach service names passed to NSXPCListener(machServiceName:). So service1 would use $(TeamIdentifierPrefix)com.example.myapp.xpc.service1.
We then added a new target that contained our root daemon and user agent binaries in its Resources folder along with proper plists in Library/Launch{Agents,Daemons}.
However, when we tried to use register them, all we got was Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}. Turns out when the app calling register() on the service is sandbox, the service itself must also be sandboxed. But even after disabling sandboxing for all targets it still failed with the same error on the latest macOS 13 and 14.
So we decided to stick with building ordinary pkgs because a) it's already working and b) at least pkgbuild and productbuild only do what they have been told. As a benefit, we don't need to spend hours fighting with sfltool dumpbtm and sfltool resetbtm because some service picked up something in Xcode's DerivedData and immediately registers it. Or even better, Xcode calling RegisterWithLaunchServices by itself.
We also don't have to sift through pages of forum posts looking for how stuff works because a) documentation is either lacking, scattered over many different places with sometimes slightly different information, or outright wrong (e.g. the documentation for SMAppService.register and .unregister)
Topic:
App & System Services
SubTopic:
Core OS
Tags: