Typically, kernel extensions and software bundles in OS X are named using reverse DNS notation (e.g., com.apple.dock.plist). This goes for property lists but is also the standard for naming kernel extensions (i.e., including the name of C++ classes within the extension that are registered with the I/O registry). As I understand it, this is done to prevent naming conflicts.
For open-source projects involving many individuals (developers) this is a challenge because there isn't a domain or company name that one can readily associate with the bundle/kext.
Has anyone seen guidance from Apple documentation, or is there some other standard that open-source projects for OS X do or should follow, particularly with respect to kernel extensions?
I haven't heard anything authoritative. And to be honest, I don't think Apple cares all that much. I've given the subject some thought in the past, and have formed my own opinion, which I'll share:
The main objective of name prefixing is to avoid name collisions. This especially applies to the kext bundles themselves, but as you mention, also to C++ classes, which have a single namespace in the kernel's OSMetaObject
run-time type system. The thing with open source code is that there are forks, so you can't control what other people might do with your code, and if carelessly name-clashing builds of incompatible forks suddenly turn up, it can cause problems on users' systems. So that's the case we're trying to avoid, right?
So the focus really is on the builds, not so much the source code. I find reverse-DNS-prefixed names irritating anyway, so I've always used #define SaneClassName tld_domain_driver_ClassName
to make my code a little more readable. I've since extended this to use a macro, something like this:
#define SaneClassName PREFIXED_NAME(ClassName)
Where the PREFIXED_NAME
macro is defined thusly:
#ifndef NAME_PREFIX
#error Must #define a unique, reverse-DNS-style NAME_PREFIX, e.g. com_example_driver_
#endif
#define PREFIXED_NAME_CONCAT2(prefix,name) prefix ## name
#define PREFIXED_NAME_CONCAT(prefix,name) PREFIXED_NAME_CONCAT2(prefix, name)
#define PREFIXED_NAME(name) PREFIXED_NAME_CONCAT(NAME_PREFIX, name)
You can make the NAME_PREFIX
a configuration option in your build system and pass it to the compiler via -DNAME_PREFIX=com_example_driver_
, such that if someone forks the code, it fails to build by default, unless they pick a suitable prefix. If you like, stress in the #error message that the prefix must be unique. You'll also need to ensure the bundle identifier that ends up both in the info.plist and in the kext binary is similarly set by the build system based on user configuration.
If you don't have a domain name associated with your project, you could pick names based on where it's hosted (com_github_organisationname_project_), or based on an email address. If you're worried about individual developers on the project releasing conflicting binary builds, you can request they use where they host their public forks, the email address rule or give them "subdomains" (com_github_organisationname_project_person_).
What you of course can't control despite these efforts, is which kext gets loaded on the user's system if builds of two forks are installed on a user's machine, and they match the same device. If it becomes a problem, you'll just have to educate your users. Seems unlikely!