#!/bin/bash ###################################################################### # Generate helper code for making builtin DSO plugins available. # # Sometimes it is necessary to split a plugin to several source # files. Usually this is the case when the functionality provided # by the plugin is complex enough to require subdividing the plugin # into internal modules for the best maintainability. # # In these cases we cannot avoid making several functions and # variables globally available within the plugin so we cannot just # limit the scope of visibility by making them static. Still, we do # want to avoid conflicts between these symbols of different plugins. # To accomplish this we compile and link such plugins into shared # libraries (with our normal symbol visibility conventions) and then # link the murphy daemon against them. # # Since none of the code linked into murphy proper references # any of the symbols in any of these plugins without any further # special arrangements these plugins wouldn't be demand-loaded # and consequently would be unavailable when the daemon starts up. # # To overcome this every such plugin gets automatically augmented # by a plugin-specifig globally visible symbol and the murphy daemon # gets augmented by a symbol that references these plugin-specific # symbols. This forces the dynamic loader to load the plugins and # the normal builtin-plugin autoregistration mechanism takes care of # the rest. # # A bit too spaceship-ish, I admit... but nevertheless necessary # unless we want to give up the idea of builtin/linkedin plugins... # error () { echo "error: $*" 1>&2 } info () { echo "$*" 1>&2 } warning () { echo "warning: $*" 1>&2 } usage () { info "usage: $0 -p -o , or" info "usage: $0 -o -d " exit ${1:-1} } emit () { echo "$*" >> $OUTPUT } emit_plugin_loader () { case $OUTPUT in *.c) emit "int mrp_linkedin_plugin_${1//-/_}_symbol = 0;" ;; *.h) emit "extern int mrp_linkedin_plugin_${1//-/_}_symbol;" ;; esac } emit_murphy_loader () { local _p for _p in $*; do emit "#include \"linkedin-$_p-loader.h\"" done emit "" emit "int mrp_load_linkedin_plugins(void)" emit "{" emit " return \\" for _p in $*; do emit " mrp_linkedin_plugin_${_p//-/_}_symbol + \\" done emit " 0;" emit "}" } OUTPUT="" PLUGIN="" PLUGIN_LIST="" daemon=no #echo "*** $0 $* ***" # parse command line while [ -n "${1#-}" ]; do case $1 in -o) if [ -z "$OUTPUT" ]; then shift OUTPUT="$1" else error "Multiple output files requested." usage fi ;; -p) if [ -z "$PLUGIN" -a "$daemon" = "no" ]; then shift PLUGIN="$1" else if [ -n "$PLUGIN" ]; then error "Multiple builtin plugins specified." else error "Both builtin plugin and plugin list specified." fi usage fi ;; -h) usage 0 ;; -q) QUIET="yes" ;; -d) daemon=yes ;; -*) error "Unknown option '$1'." usage ;; *) if [ "$daemon" = "yes" ]; then PLUGIN_LIST="$PLUGIN_LIST $1" else error "Unexpected argument '$1'." usage fi ;; esac shift done # check that we've got everything mandatory if [ -z "$OUTPUT" ]; then error "No output file specified (use the -o option)." usage fi if [ -z "$PLUGIN" -a "$daemon" = "no" ]; then error "Neither builtin plugin nor plugin list is specified." usage fi # generate the output rm -f $OUTPUT touch $OUTPUT if [ "$daemon" = "no" ]; then emit_plugin_loader $PLUGIN else emit_murphy_loader $PLUGIN_LIST fi