| /* |
| This is free and unencumbered software released into the public domain. |
| |
| Anyone is free to copy, modify, publish, use, compile, sell, or |
| distribute this software, either in source code form or as a compiled |
| binary, for any purpose, commercial or non-commercial, and by any |
| means. |
| |
| In jurisdictions that recognize copyright laws, the author or authors |
| of this software dedicate any and all copyright interest in the |
| software to the public domain. We make this dedication for the benefit |
| of the public at large and to the detriment of our heirs and |
| successors. We intend this dedication to be an overt act of |
| relinquishment in perpetuity of all present and future rights to this |
| software under copyright law. |
| |
| Unless you really want to, do not even mention that the copied content |
| originates from this skeleton library. Its sole purpose is to be copied |
| into other projects. |
| |
| The above statements apply to all content in this skeleton library, even |
| when the COPYING files, or the headers in the files state otherwise, |
| they are just common examples. |
| */ |
| |
| Questions, feedback, patches please email: |
| linux-hotplug@vger.kernel.org |
| or: |
| Kay Sievers <kay.sievers@vrfy.org> |
| Lennart Poettering <lennart@poettering.net> |
| |
| Why bother? |
| - To make things easy for library users, distribution packagers and |
| developers of library bindings for other programming languages. If |
| you want your stuff to be used and commonly available, try to play |
| nice, and give them what they are used to. It makes their life a |
| lot easier. |
| |
| use autotools |
| - Every custom config/makefile/build system is worse for everybody |
| than autotools is. |
| - We are all used to autotools, it works, nobody cares. |
| - It's only two simple files to edit and include in git, which are |
| well understood by many many people, not just you. |
| - Ignore all crap autotools create in the source tree. never check |
| the created files into git. |
| - Never, ever, install config.h. That's internal to your sources |
| and is nothing to install. |
| - And really, anything but autotools is realy an option. Just get |
| over it. Everything else is an experiment, and it will come back |
| to you sooner or later. Why? think cross compilation, installation/ |
| uninstallation, build root integration, separate object trees, |
| standard adherence, tarball handling, make distcheck, testing, |
| portability between distros, ... |
| |
| If you use the GPL, always use the GPL's "(or later)" clause |
| - Developers are not lawyers, libraries should be able to be linked |
| to any version of the GPL. Remember that GPL2-only is incompatible |
| with LGPL3! |
| |
| Use LGPL (for the shared libraries) if you don't care about politics |
| - It protects the code, but does not restrict its use. Low-level |
| library interfaces are mostly used like kernel syscall or proc/sysfs |
| interfaces, which are usually without any restrictions. |
| |
| Zero global state -- Make your library threads-aware, but *not* thread-safe! |
| - An app can use liba and libb. libb internally can also use liba -- |
| without you knowing. Both you and libb can run liba code at the |
| very same time in different threads and operate at the same global |
| variables, without telling you about that. Loadable modules make |
| this problem even more prominent, since the libraries they pull in |
| are generally completely unknown by the main application. And |
| *every* program has loadable modules, think NSS! |
| - Avoid locking and mutexes, they are very unlikely to work correctly, |
| and incredibly hard to get right. |
| - Always use a library context object. every thread should then |
| operate on its own context. Do not imply context objects via TLS. It |
| won't work. TLS inheritance to new threads will get in your way. TLS |
| is a problem in itself, not a solution. |
| - Do not use gcc constructors, or destructors, you can only loose if |
| you do. Do not use _fini() or _ini(), don't even use your own |
| explicit library initializer/destructor functions. It just won't |
| work if your library is pulled in indirectly from another library |
| or even a shared module (i.e. dlopen()) |
| - Always use O_CLOEXEC, SOCK_CLOEXEC and friends. It's not an |
| option, it's a must. |
| - Don't use global variables (it includes static variables defined |
| inside functions). Ever. And under no circumstances export global |
| variables. It's madness. |
| |
| Use a common prefix for _all_ exported symbols |
| - Avoids namespace clashes |
| - Also, hacking is not a contest of finding the shortest possible |
| function name. And nobody cares about your 80ch line limit! |
| - If you use a drop-in library in your own library make sure to hide its |
| symbols with symbol versioning. Don't forget to hide *all* symbols, and |
| don't install the header file of the used drop-in library. |
| |
| Do not expose any complex structures in your API |
| - Use get() and set() instead. |
| - All objects should be opaque. |
| - Exporting structs in headers is OK in very few cases only: usually |
| those where you define standard binary formats (think: file |
| formats, datagram headers, ...) or where you define well-known |
| primitive types (think struct timeval, struct iovec, uuid |
| type). |
| - Why bother? Because struct stat, struct dirent and friends are |
| disasters. Particularly horrible are structs with fixed-size |
| strings. |
| |
| Use the de-facto standardized function names |
| - It's abc_new(), abc_free(), abc_ref(), abc_unref(). Don't invent |
| your own names, and don't use the confusing kernel-style ref |
| counting. Function names: _get() is for accessing properties of |
| objects, not for refcounting. |
| |
| Stick to kernel coding style |
| - Just because you are otherwise not bound by the kernel guidelines |
| when your write userspace libraries doesn't mean you have to give |
| up the good things it defines. |
| |
| Avoid callbacks in your API |
| - Language bindings want iterators. |
| - Programmers want iterators too. |
| |
| Never call exit(), abort(), be very careful with assert() |
| - Always return error codes. |
| - Libraries need to be safe for usage in critical processes that |
| need to recover from errors instead of getting killed (think PID 1!). |
| |
| Avoid thinking about main loops/event dispatchers. |
| - Get your stuff right in the kernel: fds are awesome, expose them |
| in userspace and in the library, because people can easily integrate |
| them with their own poll() loops of whatever kind they have. |
| - Don't hide file descriptors away in your headers. |
| - Never add blocking kernel syscalls, and never add blocking library |
| calls either (with very few exceptions). Userspace code is primarily |
| asynchronous around event loops, and blocking calls are generally |
| incompatible with that. |
| - Corollary of that: always O_NONBLOCK! |
| |
| Functions should return int and negative errors instead of NULL |
| - Return NULL in malloc() is fine, return NULL in fopen() is not! |
| - Pass allocated objects as parameter (yes, ctx_t** is OK!) |
| - Returning kernel style negative <errno.h> error codes is cool in |
| userspace too. Do it! |
| |
| Provide pkgconfig files |
| - Apps want to add a single line to their configure file, |
| they do not want to fiddle with the parameters, dependencies |
| to setup and link your library. |
| - It's just how we do these things today on Linux, and everything |
| else is just horribly messy. |
| |
| Avoid *hidden* fork()/exec() in libraries |
| - Apps generally do not expect signals and react allergic to them. |
| - Mutexes, locks, threads of the app might get confused. Mixing |
| mutexes and fork() equals failure. It just can't work, and |
| pthread_atfork() is not a solution for that, because it's broken |
| (even POSIX acknowledges that, just read the POSIX man |
| pages!). fork() safety for mutex-ridden code is not an |
| afterthought, it's a broken right from the beginning. |
| |
| Make your code safe for unexpected termination and any point: |
| - Do not leave files dirty or temporary files around. |
| - This is a tricky, since you need to design your stuff like this |
| from the beginning, it's not an afterthought, since you generally |
| do not have a place to clean up your stuff on exit. gcc |
| destructors are NOT the answer. |
| |
| Use symbol versioning |
| - Only with that, RPM can handle dependencies for added symbols |
| - Hide all internal symbols! *This is important!* |
| |
| Always provide logging/debugging, but do not clutter stderr |
| - Allow the app to hook the libs logging into its logging facility. |
| - Use conditional logging, do not filter too late. |
| - Do not burn cycles with printf() to /dev/null. |
| - By default: do not generate any output on stdout/stderr. |
| |
| Always use 'make distcheck' to create tarballs |
| - Never release anything that does not pass distcheck. It will |
| likely be broken for others too |
| |
| Use ./autogen.sh to bootstrap the git repo |
| - Always test bootstrapping with 'git clean -x -f -d' before |
| release (careful, it force-deletes all uncommitted files). |
| |
| Avoid any spec files or debian/ subdirs in git trees |
| - Distribution specific things do not belong in upstream trees, |
| but into distro packages |
| |
| Update NEWS to let developers know what has changed |
| - It's the history of the project, stuff that packagers need to know |
| when putting a new version in the distro. The interesting changes |
| or added/removed functionality from version to version. This is |
| not a commit changelog. |
| - If you want to provide ChangeLog, use the one generated |
| by git, do not maintain your own. |
| |
| use standard types |
| - The kernel's u8, u16, ... correspond to uint8_t, uint16_t in |
| userspace from <inttypes.h>. Don't define your own typedefs |
| for that, don't include the kernel types in common headers. |
| - Use enums, not #define for constants, wherever possible. In |
| userspace you have debuggers, and they are much nicer to use if |
| you have proper enum identifiers instead of macro definitions, |
| because the debugger can translate binary values back to enum |
| identifiers, but not macros. However, be careful with enums in |
| function prototypes: they might change the int type they are |
| resolved to as you add new enum values. |
| |
| Always guard for multiple inclusions of headers |
| - You must place '#ifndef libabc, #define libabc, #endif' in your |
| header files. There is no way around that. |
| |
| Be careful with variadic functions |
| - It's great if you provide them, but you must accompany them with |
| "v" variants (i.e. functions taking a va_arg object), and provide |
| non-variadic variants as well. This is important to get language |
| wrappers right. |
| |
| Don't put "extern" in front of your function prototypes in headers |
| - It has no effect, no effect at all. |
| |
| Never use sysv IPC, always use POSIX IPC |
| - Shmops and semops are horrors. Don't use them, ever. POSIX IPC is |
| much much much nicer. |
| |
| Avoid multiplexed functions ala ioctl()/prctl() style variadic functions |
| - Type-safety is awesome! |
| |
| Executing out-of-process tools and parsing their output is usually |
| not acceptable in libraries |
| - Tools should be built on top of their own lib. |
| - Always separate 'mechanism' from 'policy'. Make access to functionality |
| simple, but do not try to hide things that need to be decided by the |
| caller. Keep automagic at its minimum. Don't do hidden fork() do not |
| implicitly maintain cache files, ... |
| |
| Function calls with 15 arguments are a bad idea. If you have tons of |
| booleans in a function call, then replace them by a flag argument! |
| - Think about the invocation! foo(0, 1, 0, 1, 0, 0, 0, 1) is unreadable! |
| foo(FOO_QUUX|FOO_BAR|FOO_WALDO) much nicer. |
| |
| Don't be afraid of C99. Use it. |
| - It's 12 years old. And it's nice. |
| |
| Never expose fixed size strings in your API |
| - Pass malloc()ed strings out, or ask the caller to provide you with |
| a buffer, and return ENOSPC if too short. |
| |
| Glibc has byteswapping calls, don't invent your own: |
| - le32toh(), htole32() all those are documented in endian(3) |
| - bswap_32(), bswap_16(), bswap_64(). #include <byteswap.h> |
| - Don't use the versions provided by the linux kernel headers cpu_to_*() , *_to_cpu. |
| stick to the glibc API. |
| |
| Don't typedef pointers to structs! |
| |
| Don't write your own LISP interpreter and do not include it in your |
| library. :) |