Warn for type mismatch for gmx printf like functions 2/3
[gromacs.git] / src / gromacs / utility / binaryinformation.cpp
blob28c4f32e06cfb24318d26a0a6d030c03b7033e60
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 /*! \internal \file
38 * \brief Implements functionality for printing information about the
39 * currently running binary
41 * \ingroup module_utility
43 #include "gmxpre.h"
45 #include "binaryinformation.h"
47 #include "config.h"
49 #if GMX_FFT_FFTW3
50 // Needed for construction of the FFT library description string
51 #include <fftw3.h>
52 #endif
54 #ifdef HAVE_LIBMKL
55 #include <mkl.h>
56 #endif
58 #if HAVE_EXTRAE
59 #include <extrae_user_events.h>
60 #endif
62 #if GMX_USE_HWLOC
63 #include <hwloc.h>
64 #endif
66 #include <cstdio>
67 #include <cstdlib>
68 #include <cstring>
70 #include <algorithm>
71 #include <string>
73 /* This file is completely threadsafe - keep it that way! */
75 #include "buildinfo.h"
76 #include "gromacs/utility/arraysize.h"
77 #include "gromacs/utility/baseversion.h"
78 #include "gromacs/utility/exceptions.h"
79 #include "gromacs/utility/gmxassert.h"
80 #include "gromacs/utility/path.h"
81 #include "gromacs/utility/programcontext.h"
82 #include "gromacs/utility/stringutil.h"
83 #include "gromacs/utility/textwriter.h"
85 #include "cuda_version_information.h"
87 namespace
90 using gmx::formatString;
92 //! \cond Doxygen does not need to care about most of this stuff, and the macro usage is painful to document
94 int centeringOffset(int width, int length)
96 return std::max(width - length, 0) / 2;
99 std::string formatCentered(int width, const char *text)
101 const int offset = centeringOffset(width, std::strlen(text));
102 return formatString("%*s%s", offset, "", text);
105 void printCopyright(gmx::TextWriter *writer)
107 static const char * const Contributors[] = {
108 "Emile Apol",
109 "Rossen Apostolov",
110 "Paul Bauer",
111 "Herman J.C. Berendsen",
112 "Par Bjelkmar",
113 "Aldert van Buuren",
114 "Rudi van Drunen",
115 "Anton Feenstra",
116 "Gerrit Groenhof",
117 "Aleksei Iupinov",
118 "Christoph Junghans",
119 "Anca Hamuraru",
120 "Vincent Hindriksen",
121 "Dimitrios Karkoulis",
122 "Peter Kasson",
123 "Jiri Kraus",
124 "Carsten Kutzner",
125 "Per Larsson",
126 "Justin A. Lemkul",
127 "Viveca Lindahl",
128 "Magnus Lundborg",
129 "Pieter Meulenhoff",
130 "Erik Marklund",
131 "Teemu Murtola",
132 "Szilard Pall",
133 "Sander Pronk",
134 "Roland Schulz",
135 "Alexey Shvetsov",
136 "Michael Shirts",
137 "Alfons Sijbers",
138 "Peter Tieleman",
139 "Teemu Virolainen",
140 "Christian Wennberg",
141 "Maarten Wolf"
143 static const char * const CopyrightText[] = {
144 "Copyright (c) 1991-2000, University of Groningen, The Netherlands.",
145 "Copyright (c) 2001-2017, The GROMACS development team at",
146 "Uppsala University, Stockholm University and",
147 "the Royal Institute of Technology, Sweden.",
148 "check out http://www.gromacs.org for more information."
150 static const char * const LicenseText[] = {
151 "GROMACS is free software; you can redistribute it and/or modify it",
152 "under the terms of the GNU Lesser General Public License",
153 "as published by the Free Software Foundation; either version 2.1",
154 "of the License, or (at your option) any later version."
157 #define NCONTRIBUTORS static_cast<int>(asize(Contributors))
158 #define NCR static_cast<int>(asize(CopyrightText))
160 // FAH has an exception permission from LGPL to allow digital signatures in Gromacs.
161 #ifdef GMX_FAHCORE
162 #define NLICENSE 0
163 #else
164 #define NLICENSE static_cast<int>(asize(LicenseText))
165 #endif
167 // TODO a centering behaviour of TextWriter could be useful here
168 writer->writeLine(formatCentered(78, "GROMACS is written by:"));
169 for (int i = 0; i < NCONTRIBUTORS; )
171 for (int j = 0; j < 4 && i < NCONTRIBUTORS; ++j, ++i)
173 const int width = 18;
174 char buf[30];
175 const int offset = centeringOffset(width, strlen(Contributors[i]));
176 GMX_RELEASE_ASSERT(strlen(Contributors[i]) + offset < asize(buf),
177 "Formatting buffer is not long enough");
178 std::fill(buf, buf+width, ' ');
179 std::strcpy(buf+offset, Contributors[i]);
180 writer->writeString(formatString(" %-*s", width, buf));
182 writer->ensureLineBreak();
184 writer->writeLine(formatCentered(78, "and the project leaders:"));
185 writer->writeLine(formatCentered(78, "Mark Abraham, Berk Hess, Erik Lindahl, and David van der Spoel"));
186 writer->ensureEmptyLine();
187 for (int i = 0; i < NCR; ++i)
189 writer->writeLine(CopyrightText[i]);
191 writer->ensureEmptyLine();
192 for (int i = 0; i < NLICENSE; ++i)
194 writer->writeLine(LicenseText[i]);
198 // Construct a string that describes the library that provides FFT support to this build
199 const char *getFftDescriptionString()
201 // Define the FFT description string
202 #if GMX_FFT_FFTW3
203 # if GMX_NATIVE_WINDOWS
204 // Don't buy trouble
205 return "fftw3";
206 # else
207 // Use the version string provided by libfftw3
208 # if GMX_DOUBLE
209 return fftw_version;
210 # else
211 return fftwf_version;
212 # endif
213 # endif
214 #endif
215 #if GMX_FFT_MKL
216 return "Intel MKL";
217 #endif
218 #if GMX_FFT_FFTPACK
219 return "fftpack (built-in)";
220 #endif
223 void gmx_print_version_info(gmx::TextWriter *writer)
225 writer->writeLine(formatString("GROMACS version: %s", gmx_version()));
226 const char *const git_hash = gmx_version_git_full_hash();
227 if (git_hash[0] != '\0')
229 writer->writeLine(formatString("GIT SHA1 hash: %s", git_hash));
231 const char *const base_hash = gmx_version_git_central_base_hash();
232 if (base_hash[0] != '\0')
234 writer->writeLine(formatString("Branched from: %s", base_hash));
237 #if GMX_DOUBLE
238 writer->writeLine("Precision: double");
239 #else
240 writer->writeLine("Precision: single");
241 #endif
242 writer->writeLine(formatString("Memory model: %u bit", static_cast<unsigned>(8*sizeof(void *))));
244 #if GMX_THREAD_MPI
245 writer->writeLine("MPI library: thread_mpi");
246 #elif GMX_MPI
247 writer->writeLine("MPI library: MPI");
248 #else
249 writer->writeLine("MPI library: none");
250 #endif
251 #if GMX_OPENMP
252 writer->writeLine(formatString("OpenMP support: enabled (GMX_OPENMP_MAX_THREADS = %d)", GMX_OPENMP_MAX_THREADS));
253 #else
254 writer->writeLine("OpenMP support: disabled");
255 #endif
256 writer->writeLine(formatString("GPU support: %s", getGpuImplementationString()));
257 writer->writeLine(formatString("SIMD instructions: %s", GMX_SIMD_STRING));
258 writer->writeLine(formatString("FFT library: %s", getFftDescriptionString()));
259 writer->writeLine(formatString("RDTSCP usage: %s", HAVE_RDTSCP ? "enabled" : "disabled"));
260 #if GMX_USE_TNG
261 writer->writeLine("TNG support: enabled");
262 #else
263 writer->writeLine("TNG support: disabled");
264 #endif
265 #if GMX_USE_HWLOC
266 writer->writeLine(formatString("Hwloc support: hwloc-%s", HWLOC_VERSION));
267 #else
268 writer->writeLine("Hwloc support: disabled");
269 #endif
270 #if HAVE_EXTRAE
271 unsigned major, minor, revision;
272 Extrae_get_version(&major, &minor, &revision);
273 writer->writeLine(formatString("Tracing support: enabled. Using Extrae-%d.%d.%d", major, minor, revision));
274 #else
275 writer->writeLine("Tracing support: disabled");
276 #endif
279 writer->writeLine(formatString("Built on: %s", BUILD_TIME));
280 writer->writeLine(formatString("Built by: %s", BUILD_USER));
281 writer->writeLine(formatString("Build OS/arch: %s", BUILD_HOST));
282 writer->writeLine(formatString("Build CPU vendor: %s", BUILD_CPU_VENDOR));
283 writer->writeLine(formatString("Build CPU brand: %s", BUILD_CPU_BRAND));
284 writer->writeLine(formatString("Build CPU family: %d Model: %d Stepping: %d",
285 BUILD_CPU_FAMILY, BUILD_CPU_MODEL, BUILD_CPU_STEPPING));
286 /* TODO: The below strings can be quite long, so it would be nice to wrap
287 * them. Can wait for later, as the master branch has ready code to do all
288 * that. */
289 writer->writeLine(formatString("Build CPU features: %s", BUILD_CPU_FEATURES));
290 writer->writeLine(formatString("C compiler: %s", BUILD_C_COMPILER));
291 writer->writeLine(formatString("C compiler flags: %s", BUILD_CFLAGS));
292 writer->writeLine(formatString("C++ compiler: %s", BUILD_CXX_COMPILER));
293 writer->writeLine(formatString("C++ compiler flags: %s", BUILD_CXXFLAGS));
294 #ifdef HAVE_LIBMKL
295 /* MKL might be used for LAPACK/BLAS even if FFTs use FFTW, so keep it separate */
296 writer->writeLine(formatString("Linked with Intel MKL version %d.%d.%d.",
297 __INTEL_MKL__, __INTEL_MKL_MINOR__, __INTEL_MKL_UPDATE__));
298 #endif
299 #if GMX_GPU == GMX_GPU_OPENCL
300 writer->writeLine(formatString("OpenCL include dir: %s", OPENCL_INCLUDE_DIR));
301 writer->writeLine(formatString("OpenCL library: %s", OPENCL_LIBRARY));
302 writer->writeLine(formatString("OpenCL version: %s", OPENCL_VERSION_STRING));
303 #endif
304 #if GMX_GPU == GMX_GPU_CUDA
305 writer->writeLine(formatString("CUDA compiler: %s", CUDA_COMPILER_INFO));
306 writer->writeLine(formatString("CUDA compiler flags:%s", CUDA_COMPILER_FLAGS));
307 writer->writeLine("CUDA driver: " + gmx::getCudaDriverVersionString());
308 writer->writeLine("CUDA runtime: " + gmx::getCudaRuntimeVersionString());
309 #endif
312 //! \endcond
314 } // namespace
316 namespace gmx
319 BinaryInformationSettings::BinaryInformationSettings()
320 : bExtendedInfo_(false), bCopyright_(false),
321 bGeneratedByHeader_(false), prefix_(""), suffix_("")
325 void printBinaryInformation(FILE *fp,
326 const IProgramContext &programContext)
328 TextWriter writer(fp);
329 printBinaryInformation(&writer, programContext, BinaryInformationSettings());
332 void printBinaryInformation(FILE *fp,
333 const IProgramContext &programContext,
334 const BinaryInformationSettings &settings)
338 TextWriter writer(fp);
339 printBinaryInformation(&writer, programContext, settings);
341 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
344 void printBinaryInformation(TextWriter *writer,
345 const IProgramContext &programContext,
346 const BinaryInformationSettings &settings)
348 // TODO Perhaps the writer could be configured with the prefix and
349 // suffix strings from the settings?
350 const char *prefix = settings.prefix_;
351 const char *suffix = settings.suffix_;
352 const char *precisionString = "";
353 #if GMX_DOUBLE
354 precisionString = " (double precision)";
355 #endif
356 const char *const name = programContext.displayName();
357 if (settings.bGeneratedByHeader_)
359 writer->writeLine(formatString("%sCreated by:%s", prefix, suffix));
361 // TODO: It would be nice to know here whether we are really running a
362 // Gromacs binary or some other binary that is calling Gromacs; we
363 // could then print "%s is part of GROMACS" or some alternative text.
364 std::string title
365 = formatString(":-) GROMACS - %s, %s%s (-:", name, gmx_version(), precisionString);
366 const int indent
367 = centeringOffset(78 - std::strlen(prefix) - std::strlen(suffix), title.length()) + 1;
368 writer->writeLine(formatString("%s%*c%s%s", prefix, indent, ' ', title.c_str(), suffix));
369 writer->writeLine(formatString("%s%s", prefix, suffix));
370 if (settings.bCopyright_)
372 GMX_RELEASE_ASSERT(prefix[0] == '\0' && suffix[0] == '\0',
373 "Prefix/suffix not supported with copyright");
374 printCopyright(writer);
375 writer->ensureEmptyLine();
376 // This line is printed again after the copyright notice to make it
377 // appear together with all the other information, so that it is not
378 // necessary to read stuff above the copyright notice.
379 // The line above the copyright notice puts the copyright notice is
380 // context, though.
381 writer->writeLine(formatString("%sGROMACS: %s, version %s%s%s", prefix, name,
382 gmx_version(), precisionString, suffix));
384 const char *const binaryPath = programContext.fullBinaryPath();
385 if (!gmx::isNullOrEmpty(binaryPath))
387 writer->writeLine(formatString("%sExecutable: %s%s", prefix, binaryPath, suffix));
389 const gmx::InstallationPrefixInfo installPrefix = programContext.installationPrefix();
390 if (!gmx::isNullOrEmpty(installPrefix.path))
392 writer->writeLine(formatString("%sData prefix: %s%s%s", prefix, installPrefix.path,
393 installPrefix.bSourceLayout ? " (source tree)" : "", suffix));
395 const std::string workingDir = Path::getWorkingDirectory();
396 if (!workingDir.empty())
398 writer->writeLine(formatString("%sWorking dir: %s%s", prefix, workingDir.c_str(), suffix));
400 const char *const commandLine = programContext.commandLine();
401 if (!gmx::isNullOrEmpty(commandLine))
403 writer->writeLine(formatString("%sCommand line:%s\n%s %s%s",
404 prefix, suffix, prefix, commandLine, suffix));
406 if (settings.bExtendedInfo_)
408 GMX_RELEASE_ASSERT(prefix[0] == '\0' && suffix[0] == '\0',
409 "Prefix/suffix not supported with extended info");
410 writer->ensureEmptyLine();
411 gmx_print_version_info(writer);
415 } // namespace gmx