BASIS  r3148
utilities.h
Go to the documentation of this file.
00001 /**
00002  * @file  utilities.h
00003  * @brief Main module of project-independent BASIS utilities.
00004  *
00005  * This module defines project-independent implementations of the BASIS utility
00006  * functions. They are intended for use outside a BASIS-based project only.
00007  * Within source code of a BASIS-based project, the overloads declared by
00008  * the basis.h module should be used instead as these are specifically configured
00009  * by BASIS for this project during the build of the software.
00010  *
00011  * Note that this module includes all other BASIS utility header files.
00012  * Hence, it is sufficient to include this file only.
00013  *
00014  * Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br />
00015  * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00016  *
00017  * Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00018  *
00019  * @ingroup BasisCxxUtilities
00020  */
00021 
00022 #ifndef _BASIS_UTILITIES_H
00023 #define _BASIS_UTILITIES_H
00024 
00025 // standard library
00026 #include <string>
00027 #include <iostream>
00028 #include <vector>
00029 
00030 // build configuration - has to be included using full path in case the build
00031 //                       tree of BASIS is used instead of an installation
00032 #include <basis/config.h>
00033 
00034 // basic utilities
00035 #include "assert.h"
00036 #include "except.h"
00037 #include "os.h"
00038 
00039 // command-line parsing
00040 #include "CmdLine.h"
00041 
00042 
00043 /// @addtogroup BasisCxxUtilities
00044 /// @{
00045 
00046 
00047 // the subnamespace is required to avoid conflict with configured
00048 // project-specific utilities of BASIS itself
00049 namespace basis { namespace util {
00050 
00051 
00052 // ===========================================================================
00053 // executable information
00054 // ===========================================================================
00055 
00056 /**
00057  * @brief Provides information about executable build targets.
00058  *
00059  * Within source code of a BASIS project, other SBIA executables are called
00060  * only indirectly using the build target name which must be fixed and unique
00061  * within the lab. The name of the output executable file of these targets may
00062  * however vary and be finally set by BASIS, for example, depending on
00063  * whether the project is build as part of a superproject or not. Therefore,
00064  * each BASIS CMake function may adjust the output name in order to resolve
00065  * name conflicts with other targets or SBIA executables.
00066  *
00067  * The idea is that a target name is supposed to be stable and known to the
00068  * developer as soon as the target is added to a CMakeLists.txt file, while
00069  * the name of the actual executable file is not known a priori as it is set
00070  * by the BASIS CMake functions during the configure step. Thus, the developer
00071  * should not rely on a particular name of the executable file. Instead, they
00072  * can rely on the name of the corresponding build target which was chosen by
00073  * themselves when adding the target to the build configuration.
00074  *
00075  * In order to get the actual file path of the built executable file, the
00076  * function get_executable_path() is provided by the stdaux.h module.
00077  * This function uses the static singleton instance of this class in order to
00078  * map the given build target name to the name of the built and optionally
00079  * installed executable. The code which initializes the required maps is
00080  * generated automatically during the configuration of the build system.
00081  *
00082  * @sa exepath()
00083  */
00084 class IExecutableTargetInfo
00085 {
00086     // -----------------------------------------------------------------------
00087     // construction / destruction
00088 protected:
00089 
00090     /// @brief Constructor
00091     IExecutableTargetInfo() {}
00092 
00093     /// @brief Destructor.
00094     virtual ~IExecutableTargetInfo() {};
00095 
00096     // -----------------------------------------------------------------------
00097     // public interface
00098 public:
00099 
00100     /**
00101      * @brief Get UID of build target.
00102      *
00103      * In order to be able to distinguish build targets with identical name
00104      * but which are built as part of different BASIS projects, the UID of
00105      * a build target is composed of the build target name as given as
00106      * argument to the basis_add_* CMake functions and a namespace identifier
00107      * (i.e., the project name in lowercase letters). If the specified build
00108      * target name is neither known by this module nor a build target UID yet,
00109      * this method prepends the namespace identifier corresponding to the
00110      * project this module was built from, assuming that the caller refers
00111      * to another target within the same project.
00112      *
00113      * @param [in] target Name/UID of build target.
00114      *
00115      * @returns UID of build target.
00116      */
00117     virtual std::string targetuid(const std::string& target) const = 0;
00118 
00119     /**
00120      * @brief Determine whether a given build target is known.
00121      *
00122      * @param [in] target Name/UID of build target.
00123      *
00124      * @returns Whether the given build target is known by this module.
00125      */
00126     virtual bool istarget(const std::string& target) const = 0;
00127 
00128     /**
00129      * @brief Get name of executable file without directory path.
00130      *
00131      * @param [in] target Name/UID of build target.
00132      *
00133      * @returns Name of built executable file without path.
00134      */
00135     virtual std::string basename(const std::string& target) const = 0;
00136 
00137     /**
00138      * @brief Get absolute path of directory containing executable.
00139      *
00140      * @param [in] target Name/UID of build target.
00141      *
00142      * @returns Absolute path of directory containing executable file.
00143      */
00144     virtual std::string dirname(const std::string& target) const = 0;
00145 
00146 }; // class IExecutableTargetInfo
00147 
00148 
00149 /**
00150  * @brief Print contact information.
00151  *
00152  * @param [in] contact Name of contact.
00153  */
00154 void print_contact(const char* contact);
00155 
00156 /**
00157  * @brief Print version information including copyright and license notices.
00158  *
00159  * @param [in] name      Name of executable. Should not be set programmatically
00160  *                       to the first argument of the @c main() function, but
00161  *                       a string literal instead.
00162  * @param [in] version   Version of executable, e.g., release of project
00163  *                       this executable belongs to.
00164  * @param [in] project   Name of project this executable belongs to.
00165  *                       If @c NULL or an empty string, no project information
00166  *                       is printed.
00167  * @param [in] copyright The copyright notice, excluding the common prefix
00168  *                       "Copyright (c) " and suffix ". All rights reserved.".
00169  *                       If @c NULL or an empty string, no copyright notice
00170  *                       is printed.
00171  * @param [in] license   Information regarding licensing. If @c NULL or an empty
00172  *                       string, no license information is printed.
00173  */
00174 void print_version(const char* name,
00175                    const char* version,
00176                    const char* project   = NULL,
00177                    const char* copyright = NULL,
00178                    const char* license   = NULL);
00179 
00180 /**
00181  * @brief Get UID of build target.
00182  *
00183  * The UID of a build target is its name prepended by a namespace identifier
00184  * which should be unique for each project.
00185  *
00186  * @param [in] name    Name of build target.
00187  * @param [in] targets Structure providing information about executable targets.
00188  *
00189  * @returns UID of named build target.
00190  */
00191 std::string targetuid(const std::string& name, const IExecutableTargetInfo* targets = NULL);
00192 
00193 /**
00194  * @brief Determine whether a given build target is known.
00195  *
00196  * @param [in] name    Name of build target.
00197  * @param [in] targets Structure providing information about executable targets.
00198  *
00199  * @returns Whether the named target is a known executable target.
00200  */
00201 bool istarget(const std::string& name, const IExecutableTargetInfo* targets = NULL);
00202 
00203 /**
00204  * @brief Get absolute path of executable file.
00205  *
00206  * This function determines the absolute file path of an executable. If no
00207  * arguments are given, the absolute path of this executable is returned.
00208  * If the command names a known executable build target, the absolute path to
00209  * the corresonding built (and installed) executable file is returned.
00210  * Otherwise, the named command is searched in the system @c PATH and its
00211  * absolute path returned if found. If the executable is not found, an
00212  * empty string is returned.
00213  *
00214  * @todo This function currently makes use of the which command implemented
00215  *       in Python and called as subprocess in order to search a command
00216  *       in the system @c PATH. This which command is part of BASIS and
00217  *       can also be used on Windows. However, a native C++ implementation
00218  *       would be desireable.
00219  *
00220  * @param [in] name    Name of command or @c NULL.
00221  * @param [in] targets Structure providing information about executable targets.
00222  *
00223  * @returns Absolute path of executable or an empty string if not found.
00224  *          If @p name is @c NULL, the path of this executable is returned.
00225  *
00226  * @sa exename()
00227  * @sa exedir()
00228  */
00229 std::string exepath(const std::string&           name    = std::string(),
00230                     const IExecutableTargetInfo* targets = NULL);
00231 
00232 /**
00233  * @brief Get name of executable file.
00234  *
00235  * The name of the executable may or may not include the file name extension
00236  * depending on the executable type and operating system. Hence, this function
00237  * is neither an equivalent to os::path::basename(exepath()) nor
00238  * os::path::filename(exepath()). In particular, on Windows, the .exe and .com
00239  * extension is not included in the returned executable name.
00240  *
00241  * @param [in] name    Name of command or @c NULL.
00242  * @param [in] targets Structure providing information about executable targets.
00243  *
00244  * @returns Name of executable file or an empty string if not found.
00245  *          If @p name is @c NULL, the name of this executable is returned.
00246  *
00247  * @sa exepath()
00248  */
00249 std::string exename(const std::string&           name    = std::string(),
00250                     const IExecutableTargetInfo* targets = NULL);
00251 
00252 /**
00253  * @brief Get directory of executable file.
00254  *
00255  * @param [in] name    Name of command or @c NULL.
00256  * @param [in] targets Structure providing information about executable targets.
00257  *
00258  * @returns Absolute path of directory containing executable or an empty string if not found.
00259  *          If @p name is @c NULL, the directory of this executable is returned.
00260  *
00261  * @sa exepath()
00262  */
00263 std::string exedir(const std::string&           name    = std::string(),
00264                    const IExecutableTargetInfo* targets = NULL);
00265 
00266 // ===========================================================================
00267 // command execution
00268 // ===========================================================================
00269 
00270 /**
00271  * @class SubprocessError
00272  * @brief Exception type thrown by execute().
00273  */
00274 class SubprocessError : public std::exception
00275 {
00276 public:
00277     SubprocessError(const std::string& msg) : msg_(msg) {}
00278     ~SubprocessError() throw () {}
00279 
00280 private:
00281     std::string msg_; ///< Error message.
00282 }; // class SubprocessError
00283 
00284 /**
00285  * @brief Convert array of arguments to quoted string.
00286  *
00287  * @param [in] args Array of arguments.
00288  *
00289  * @returns Double quoted string, i.e., string where arguments are separated
00290  *          by a space character and surrounded by double quotes if necessary.
00291  *          Double quotes within an argument are escaped with a backslash.
00292  *
00293  * @sa split()
00294  */
00295 std::string tostring(const std::vector<std::string>& args);
00296 
00297 /**
00298  * @brief Split quoted string.
00299  *
00300  * @param [in] args Quoted string of arguments.
00301  *
00302  * @returns Array of arguments.
00303  *
00304  * @sa tostring()
00305  */
00306 std::vector<std::string> qsplit(const std::string& args);
00307 
00308 /**
00309  * @brief Execute command as subprocess.
00310  *
00311  * This function is a replacement for system() on Unix and is furthermore
00312  * less platform dependent. The first argument of the given command-line string
00313  * is mapped to an absolute executable file using exepath() if the given first
00314  * argument is a know build target name. Otherwise, the command-line is used
00315  * unmodified.
00316  *
00317  * @param [in] cmd         Command-line given as double quoted string. Arguments
00318  *                         containing whitespaces have to be quoted using double
00319  *                         quotes. Use a backslash (\\) to escape double quotes
00320  *                         inside an argument as well as to escape a backslash
00321  *                         itself (required if backslash at end of double quoted
00322  *                         argument, e.g., "this argument \\").
00323  * @param [in]  quiet      Turns off output of stdout of child process to stdout
00324  *                         of parent process.
00325  * @param [out] out        Output stream where command output is written to.
00326  * @param [in]  allow_fail If true, no exception is thrown if the exit code
00327  *                         of the child process is non-zero. Otherwise,
00328  *                         a SubprocessException object is thrown in that case.
00329  * @param [in]  verbose    Verbosity of output messages. Does not affect
00330  *                         verbosity of executed command.
00331  * @param [in]  simulate   Whether to simulate command execution only.
00332  * @param [in]  targets    Structure providing information about executable targets.
00333  *
00334  * @returns Exit code of command or -1 if subprocess creation failed.
00335  *
00336  * @throws SubprocessError If subprocess creation failed or command returned
00337  *                         a non-zero exit code while @p allow_fail is false.
00338  */
00339 int execute(const std::string&           cmd,
00340             bool                         quiet      = false,
00341             // attention: stdout is a macro defined by windows.h
00342             std::ostream*                out        = NULL,
00343             bool                         allow_fail = false,
00344             int                          verbose    = 0,
00345             bool                         simulate   = false,
00346             const IExecutableTargetInfo* targets    = NULL);
00347 
00348 /**
00349  * @brief Execute command as subprocess.
00350  *
00351  * This function is a replacement for system() on Unix and is furthermore
00352  * less platform dependent. The first argument of the given command-line string
00353  * is mapped to an absolute executable file using exepath() if the given first
00354  * argument is a know build target name. Otherwise, the command-line is used
00355  * unmodified.
00356  *
00357  * @param [in]  args       Command-line given as argument vector. The first
00358  *                         argument has to be either a build target name or the
00359  *                         name/path of the command to execute. Note that as a
00360  *                         side effect, the first argument of the input vector
00361  *                         is replaced by the absolute path of the actual
00362  *                         executable file if applicable.
00363  * @param [in]  quiet      Turns off output of stdout of child process to
00364  *                         stdout of parent process.
00365  * @param [out] out        Output stream where command output is written to.
00366  * @param [in]  allow_fail If true, no exception is thrown if the exit code
00367  *                         of the child process is non-zero. Otherwise,
00368  *                         a SubprocessException object is thrown in that case.
00369  * @param [in]  verbose    Verbosity of output messages. Does not affect
00370  *                         verbosity of executed command.
00371  * @param [in]  simulate   Whether to simulate command execution only.
00372  * @param [in]  targets    Structure providing information about executable targets.
00373  *
00374  * @returns Exit code of command or -1 if subprocess creation failed.
00375  *
00376  * @throws SubprocessError If subprocess creation failed or command returned
00377  *                         a non-zero exit code while @p allow_fail is false.
00378  */
00379 int execute(std::vector<std::string>        args,
00380             bool                            quiet      = false,
00381             // attention: stdout is a macro defined by windows.h
00382             std::ostream*                   out        = NULL,
00383             bool                            allow_fail = false,
00384             int                             verbose    = 0,
00385             bool                            simulate   = false,
00386             const IExecutableTargetInfo*    targets    = NULL);
00387 
00388 
00389 } } // end of namespaces
00390 
00391 
00392 /// @}
00393 // end of Doxygen group
00394 
00395 #endif // _BASIS_UTILITIES_H