diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-11-13 15:00:57 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-01-27 11:52:06 +0100 |
commit | 136ce91fb5d9194546bfcf49ac87a614a3a458c5 (patch) | |
tree | b243649344d993e48469f77fd6eace4a4d9f56da /README | |
parent | 6c37a935b85774f56871a75f2069c8041068d34c (diff) | |
download | dt-utils-136ce91fb5d9194546bfcf49ac87a614a3a458c5.tar.gz dt-utils-136ce91fb5d9194546bfcf49ac87a614a3a458c5.tar.xz |
2nd commitv0.2.0
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'README')
-rw-r--r-- | README | 262 |
1 files changed, 262 insertions, 0 deletions
@@ -0,0 +1,262 @@ +/* + 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. :) |