utilities.h
Go to the documentation of this file.
1 // ===========================================================================
2 // Copyright (c) 2011-2012 University of Pennsylvania
3 // Copyright (c) 2013-2016 Andreas Schuh
4 // All rights reserved.
5 //
6 // See COPYING file for license information or visit
7 // https://cmake-basis.github.io/download.html#license
8 // ===========================================================================
9 
10 /**
11  * @file utilities.h
12  * @brief Main module of project-independent BASIS utilities.
13  *
14  * This module defines project-independent implementations of the BASIS utility
15  * functions. They are intended for use outside a BASIS-based project only.
16  * Within source code of a BASIS-based project, the overloads declared by
17  * the basis.h module should be used instead as these are specifically configured
18  * by BASIS for this project during the build of the software.
19  *
20  * Note that this module includes all other BASIS utility header files.
21  * Hence, it is sufficient to include this file only.
22  *
23  * @ingroup BasisCxxUtilities
24  */
25 
26 #ifndef _BASIS_UTILITIES_H
27 #define _BASIS_UTILITIES_H
28 
29 // standard library
30 #include <string>
31 #include <iostream>
32 #include <vector>
33 
34 // build configuration - has to be included using full path in case the build
35 // tree of BASIS is used instead of an installation
36 #include <basis/config.h>
37 
38 // basic utilities
39 #include "assert.h"
40 #include "except.h"
41 #include "os.h"
42 
43 // command-line parsing
44 #include "CmdLine.h"
45 
46 
47 /// @addtogroup BasisCxxUtilities
48 /// @{
49 
50 
51 // the subnamespace is required to avoid conflict with configured
52 // project-specific utilities of BASIS itself
53 namespace basis { namespace util {
54 
55 
56 // ===========================================================================
57 // executable information
58 // ===========================================================================
59 
60 /**
61  * @brief Provides information about executable build targets.
62  *
63  * Within source code of a BASIS project, other SBIA executables are called
64  * only indirectly using the build target name which must be fixed and unique
65  * within the lab. The name of the output executable file of these targets may
66  * however vary and be finally set by BASIS, for example, depending on
67  * whether the project is build as part of a superproject or not. Therefore,
68  * each BASIS CMake function may adjust the output name in order to resolve
69  * name conflicts with other targets or SBIA executables.
70  *
71  * The idea is that a target name is supposed to be stable and known to the
72  * developer as soon as the target is added to a CMakeLists.txt file, while
73  * the name of the actual executable file is not known a priori as it is set
74  * by the BASIS CMake functions during the configure step. Thus, the developer
75  * should not rely on a particular name of the executable file. Instead, they
76  * can rely on the name of the corresponding build target which was chosen by
77  * themselves when adding the target to the build configuration.
78  *
79  * In order to get the actual file path of the built executable file, the
80  * function get_executable_path() is provided by the stdaux.h module.
81  * This function uses the static singleton instance of this class in order to
82  * map the given build target name to the name of the built and optionally
83  * installed executable. The code which initializes the required maps is
84  * generated automatically during the configuration of the build system.
85  *
86  * @sa exepath()
87  */
89 {
90  // -----------------------------------------------------------------------
91  // construction / destruction
92 protected:
93 
94  /// @brief Constructor
96 
97  /// @brief Destructor.
98  virtual ~IExecutableTargetInfo() {};
99 
100  // -----------------------------------------------------------------------
101  // public interface
102 public:
103 
104  /**
105  * @brief Get UID of build target.
106  *
107  * In order to be able to distinguish build targets with identical name
108  * but which are built as part of different BASIS projects, the UID of
109  * a build target is composed of the build target name as given as
110  * argument to the basis_add_* CMake functions and a namespace identifier
111  * (i.e., the project name in lowercase letters). If the specified build
112  * target name is neither known by this module nor a build target UID yet,
113  * this method prepends the namespace identifier corresponding to the
114  * project this module was built from, assuming that the caller refers
115  * to another target within the same project.
116  *
117  * @param [in] target Name/UID of build target.
118  *
119  * @returns UID of build target.
120  */
121  virtual std::string targetuid(const std::string& target) const = 0;
122 
123  /**
124  * @brief Determine whether a given build target is known.
125  *
126  * @param [in] target Name/UID of build target.
127  *
128  * @returns Whether the given build target is known by this module.
129  */
130  virtual bool istarget(const std::string& target) const = 0;
131 
132  /**
133  * @brief Get name of executable file without directory path.
134  *
135  * @param [in] target Name/UID of build target.
136  *
137  * @returns Name of built executable file without path.
138  */
139  virtual std::string basename(const std::string& target) const = 0;
140 
141  /**
142  * @brief Get absolute path to directory containing executable.
143  *
144  * @param [in] target Name/UID of build target.
145  *
146  * @returns Absolute path to directory containing executable file.
147  */
148  virtual std::string dirname(const std::string& target) const = 0;
149 
150 }; // class IExecutableTargetInfo
151 
152 
153 /**
154  * @brief Print contact information.
155  *
156  * @param [in] contact Name of contact.
157  */
158 void print_contact(const char* contact);
159 
160 /**
161  * @brief Print version information including copyright and license notices.
162  *
163  * @param [in] name Name of executable. Should not be set programmatically
164  * to the first argument of the @c main() function, but
165  * a string literal instead.
166  * @param [in] version Version of executable, e.g., release of project
167  * this executable belongs to.
168  * @param [in] project Name of project this executable belongs to.
169  * If @c NULL or an empty string, no project information
170  * is printed.
171  * @param [in] copyright The copyright notice, excluding the common prefix
172  * "Copyright (c) " and suffix ". All rights reserved.".
173  * If @c NULL or an empty string, no copyright notice
174  * is printed.
175  * @param [in] license Information regarding licensing. If @c NULL or an empty
176  * string, no license information is printed.
177  */
178 void print_version(const char* name,
179  const char* version,
180  const char* project = NULL,
181  const char* copyright = NULL,
182  const char* license = NULL);
183 
184 /**
185  * @brief Get UID of build target.
186  *
187  * The UID of a build target is its name prepended by a namespace identifier
188  * which should be unique for each project.
189  *
190  * @param [in] name Name of build target.
191  * @param [in] targets Structure providing information about executable targets.
192  *
193  * @returns UID of named build target.
194  */
195 std::string targetuid(const std::string& name, const IExecutableTargetInfo* targets = NULL);
196 
197 /**
198  * @brief Determine whether a given build target is known.
199  *
200  * @param [in] name Name of build target.
201  * @param [in] targets Structure providing information about executable targets.
202  *
203  * @returns Whether the named target is a known executable target.
204  */
205 bool istarget(const std::string& name, const IExecutableTargetInfo* targets = NULL);
206 
207 /**
208  * @brief Get absolute path of executable file.
209  *
210  * This function determines the absolute file path of an executable. If no
211  * arguments are given, the absolute path of this executable is returned.
212  * If the command names a known executable build target, the absolute path to
213  * the corresonding built (and installed) executable file is returned.
214  * Otherwise, the named command is searched in the system @c PATH and its
215  * absolute path returned if found. If the executable is not found, an
216  * empty string is returned.
217  *
218  * @todo This function currently makes use of the which command implemented
219  * in Python and called as subprocess in order to search a command
220  * in the system @c PATH. This which command is part of BASIS and
221  * can also be used on Windows. However, a native C++ implementation
222  * would be desireable.
223  *
224  * @param [in] name Name of command or @c NULL.
225  * @param [in] targets Structure providing information about executable targets.
226  *
227  * @returns Absolute path of executable or an empty string if not found.
228  * If @p name is @c NULL, the path of this executable is returned.
229  *
230  * @sa exename()
231  * @sa exedir()
232  */
233 std::string exepath(const std::string& name = std::string(),
234  const IExecutableTargetInfo* targets = NULL);
235 
236 /**
237  * @brief Get name of executable file.
238  *
239  * The name of the executable may or may not include the file name extension
240  * depending on the executable type and operating system. Hence, this function
241  * is neither an equivalent to os::path::basename(exepath()) nor
242  * os::path::filename(exepath()). In particular, on Windows, the .exe and .com
243  * extension is not included in the returned executable name.
244  *
245  * @param [in] name Name of command or @c NULL.
246  * @param [in] targets Structure providing information about executable targets.
247  *
248  * @returns Name of executable file or an empty string if not found.
249  * If @p name is @c NULL, the name of this executable is returned.
250  *
251  * @sa exepath()
252  */
253 std::string exename(const std::string& name = std::string(),
254  const IExecutableTargetInfo* targets = NULL);
255 
256 /**
257  * @brief Get directory of executable file.
258  *
259  * @param [in] name Name of command or @c NULL.
260  * @param [in] targets Structure providing information about executable targets.
261  *
262  * @returns Absolute path to directory containing executable or an empty string if not found.
263  * If @p name is @c NULL, the directory of this executable is returned.
264  *
265  * @sa exepath()
266  */
267 std::string exedir(const std::string& name = std::string(),
268  const IExecutableTargetInfo* targets = NULL);
269 
270 // ===========================================================================
271 // command execution
272 // ===========================================================================
273 
274 /**
275  * @class SubprocessError
276  * @brief Exception type thrown by execute().
277  */
278 class SubprocessError : public std::exception
279 {
280 public:
281  SubprocessError(const std::string& msg) : msg_(msg) {}
282  ~SubprocessError() throw () {}
283 
284 private:
285  std::string msg_; ///< Error message.
286 }; // class SubprocessError
287 
288 /**
289  * @brief Convert array of arguments to quoted string.
290  *
291  * @param [in] args Array of arguments.
292  *
293  * @returns Double quoted string, i.e., string where arguments are separated
294  * by a space character and surrounded by double quotes if necessary.
295  * Double quotes within an argument are escaped with a backslash.
296  *
297  * @sa split()
298  */
299 std::string tostring(const std::vector<std::string>& args);
300 
301 /**
302  * @brief Split quoted string.
303  *
304  * @param [in] args Quoted string of arguments.
305  *
306  * @returns Array of arguments.
307  *
308  * @sa tostring()
309  */
310 std::vector<std::string> qsplit(const std::string& args);
311 
312 /**
313  * @brief Execute command as subprocess.
314  *
315  * This function is a replacement for system() on Unix and is furthermore
316  * less platform dependent. The first argument of the given command-line string
317  * is mapped to an absolute executable file using exepath() if the given first
318  * argument is a know build target name. Otherwise, the command-line is used
319  * unmodified.
320  *
321  * @param [in] cmd Command-line given as double quoted string. Arguments
322  * containing whitespaces have to be quoted using double
323  * quotes. Use a backslash (\\) to escape double quotes
324  * inside an argument as well as to escape a backslash
325  * itself (required if backslash at end of double quoted
326  * argument, e.g., "this argument \\").
327  * @param [in] quiet Turns off output of stdout of child process to stdout
328  * of parent process.
329  * @param [out] out Output stream where command output is written to.
330  * @param [in] allow_fail If true, no exception is thrown if the exit code
331  * of the child process is non-zero. Otherwise,
332  * a SubprocessException object is thrown in that case.
333  * @param [in] verbose Verbosity of output messages. Does not affect
334  * verbosity of executed command.
335  * @param [in] simulate Whether to simulate command execution only.
336  * @param [in] targets Structure providing information about executable targets.
337  *
338  * @returns Exit code of command or -1 if subprocess creation failed.
339  *
340  * @throws SubprocessError If subprocess creation failed or command returned
341  * a non-zero exit code while @p allow_fail is false.
342  */
343 int execute(const std::string& cmd,
344  bool quiet = false,
345  // attention: stdout is a macro defined by windows.h
346  std::ostream* out = NULL,
347  bool allow_fail = false,
348  int verbose = 0,
349  bool simulate = false,
350  const IExecutableTargetInfo* targets = NULL);
351 
352 /**
353  * @brief Execute command as subprocess.
354  *
355  * This function is a replacement for system() on Unix and is furthermore
356  * less platform dependent. The first argument of the given command-line string
357  * is mapped to an absolute executable file using exepath() if the given first
358  * argument is a know build target name. Otherwise, the command-line is used
359  * unmodified.
360  *
361  * @param [in] args Command-line given as argument vector. The first
362  * argument has to be either a build target name or the
363  * name/path of the command to execute. Note that as a
364  * side effect, the first argument of the input vector
365  * is replaced by the absolute path of the actual
366  * executable file if applicable.
367  * @param [in] quiet Turns off output of stdout of child process to
368  * stdout of parent process.
369  * @param [out] out Output stream where command output is written to.
370  * @param [in] allow_fail If true, no exception is thrown if the exit code
371  * of the child process is non-zero. Otherwise,
372  * a SubprocessException object is thrown in that case.
373  * @param [in] verbose Verbosity of output messages. Does not affect
374  * verbosity of executed command.
375  * @param [in] simulate Whether to simulate command execution only.
376  * @param [in] targets Structure providing information about executable targets.
377  *
378  * @returns Exit code of command or -1 if subprocess creation failed.
379  *
380  * @throws SubprocessError If subprocess creation failed or command returned
381  * a non-zero exit code while @p allow_fail is false.
382  */
383 int execute(std::vector<std::string> args,
384  bool quiet = false,
385  // attention: stdout is a macro defined by windows.h
386  std::ostream* out = NULL,
387  bool allow_fail = false,
388  int verbose = 0,
389  bool simulate = false,
390  const IExecutableTargetInfo* targets = NULL);
391 
392 
393 } } // end of namespaces
394 
395 
396 /// @}
397 // end of Doxygen group
398 
399 #endif // _BASIS_UTILITIES_H
Basic exceptions and related helper macros.
virtual bool istarget(const std::string &target) const =0
Determine whether a given build target is known.
std::string exedir(const std::string &name=std::string(), const IExecutableTargetInfo *targets=NULL)
Get directory of executable file.
Definition: utilities.cxx:115
virtual std::string basename(const std::string &target) const =0
Get name of executable file without directory path.
virtual std::string targetuid(const std::string &target) const =0
Get UID of build target.
virtual ~IExecutableTargetInfo()
Destructor.
Definition: utilities.h:98
std::vector< std::string > qsplit(const std::string &args)
Split quoted string.
Definition: utilities.cxx:132
void print_contact(const char *contact)
Print contact information.
Definition: utilities.cxx:33
int execute(const std::string &cmd, bool quiet=false, std::ostream *out=NULL, bool allow_fail=false, int verbose=0, bool simulate=false, const IExecutableTargetInfo *targets=NULL)
Execute command as subprocess.
Definition: utilities.cxx:138
System related macro definitions.
Exception type thrown by execute().
Definition: utilities.h:278
Definition: basis.h:34
Defines macros used for assertions.
Provides information about executable build targets.
Definition: utilities.h:88
std::string exepath(const std::string &name=std::string(), const IExecutableTargetInfo *targets=NULL)
Get absolute path of executable file.
Definition: utilities.cxx:64
Operating system dependent functions.
SubprocessError(const std::string &msg)
Definition: utilities.h:281
std::string tostring(const std::vector< std::string > &args)
Convert array of arguments to quoted string.
Definition: utilities.cxx:126
cmake msg
MultiSwitchArg verbose("v", "verbose", "Increase verbosity of output messages.", false)
std::string exename(const std::string &name=std::string(), const IExecutableTargetInfo *targets=NULL)
Get name of executable file.
Definition: utilities.cxx:102
virtual std::string dirname(const std::string &target) const =0
Get absolute path to directory containing executable.
Manages command line definition and parsing of arguments.
void print_version(const char *name, const char *version, const char *project=NULL, const char *copyright=NULL, const char *license=NULL)
Print version information including copyright and license notices.
Definition: utilities.cxx:39
IExecutableTargetInfo()
Constructor.
Definition: utilities.h:95