summaryrefslogtreecommitdiffstats
path: root/README
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-11-13 15:00:57 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2014-01-27 11:52:06 +0100
commit136ce91fb5d9194546bfcf49ac87a614a3a458c5 (patch)
treeb243649344d993e48469f77fd6eace4a4d9f56da /README
parent6c37a935b85774f56871a75f2069c8041068d34c (diff)
downloaddt-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--README262
1 files changed, 262 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..bb06cad
--- /dev/null
+++ b/README
@@ -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. :)