Namespaces and inter-library private symbols

Nicolas Williams Nicolas.Williams at
Fri Nov 13 11:43:02 EST 2009

On Fri, Nov 13, 2009 at 01:13:59AM -0500, Greg Hudson wrote:
> On Tue, 2009-11-10 at 16:48 -0500, Nicolas Williams wrote:
> > Vendors should just not ship k5-int.h and that's that.  Developers
> > should have enough warning from the fact that they cannot find C
> > prototype declarations for functions that they think might be useful to
> > them but which ware internal.
> Jeff Altman wrote:
> > Symbols that are exported by libraries are inevitably used even when
> > they are declared private.  The only way to ensure that third parties
> > do not place dependencies on a function is to not export it.

If you don't declare them in public/installed/shipped headers, then they
can only be used by folks who are willing to dig into the source to find
declarations.  If you don't export them then they can't be used period.

I definitely recommend not exporting symbols that need not be used
outside libkrb5 (and plugins, via the accessor).

Are there symbols which must be exported but aren't public?  (What we
might call "consolidation private" or "contracted private" in the Sun
world of development).  If not, then I strongly recommend Jeff's
proposal.  If there are, can you remove or promote them all so that you
only have libkrb5-private and public interfaces only?

> So, those are the two extremes.  I think if we name a function

I fully agree with Jeff though, but only for symbols that are not
"contracted" to other parties (see above).

> krb5int_foo, that's a pretty clear indication that it's not part of the
> stable API or ABI.  Adding an extra layer of hassle (such as the
> accessor) isn't going to stop a truly determined application writer from
> using internal functionality.

To be clear, I don't _mind_ the 'int' suffix to the krb5 prefix.  I just
don't think it's necessary: either way you're relying on convention
(header naming vs. symbol naming) or on not making relevant declarations
available (by not installing/shipping k5-int.h) to get third parties to
stay away from private symbols.

> Merely failing to prototype a function in krb5.h is not, in my opinion,
> a clear indication.  It also runs afoul of autoconf tests for functions
> entering the public API in later versions of krb5.  For instance, Luke

It depends on the autoconf test.  If it's looking only for a symbol in a
shared object's exported symbol table, then yes, autoconf will find it,
but any source code actually trying to use it will fail to compile.

> chose not to make krb5_get_credentials_for_proxy part of the public API
> for 1.8 so that we can retain the freedom to change it.  But suppose we
> change the function signature and then make it part of the public API in
> 1.9.  How can an application tell whether krb5_get_credentials_for_proxy
> is available in the API of the libkrb5 it is building against?  The

It can't have used krb5_get_credentials_for_proxy when built against

> usual AC_CHECK_FUNC autoconf test will find the symbol in krb5 1.8, even
> though it's not part of that version's API.
> I am awaiting clarification on an offlist comment about the accessor,
> and I'll probably bring this up again with the MIT staff, but my
> expectation is that we will standardize on using exported symbols with
> the krb5int_ prefix for tree-internal inter-library functions.

The accessor is important for plug-in access (to public and private
interfaces both) as a way to avoid DLL hell.  I'm OK with the accessor
being used to access private functions, provided there's convenience
macros for using them (but then too you'll still be relying on
convention to keep third parties from using private interfaces).

> Nico wrote:
> > I recommend that you concentrate efforts on actual, useful features
> > and bug fixes over mass symbol rename excercises.
> For the moment, I'm just interested in standardizing a practice for
> future work, although it's possible we will rename some newer non-public
> krb5_ symbols to krb5int_ to avoid the autoconf problem described above.

The autoconf problem is a non-problem.  The key, above all, is to not
install private headers while defining private symbols in private

C doesn't have a neat way to deal with private vs. public interfaces
other than by declaration segregation through headers.  That's the
least, and also the most that can be done.  The rest is lexical
convention -- how desirable that is will vary with your p.o.v., but it's
certainly not the main thing to do, nor does guarantee anything, it's
just convention.


More information about the krbdev mailing list