# customizing the install locations.
set(LIB_INSTALL_DIR ${GMX_LIB_INSTALL_DIR})
set(BIN_INSTALL_DIR bin)
+# This variable also gets written into config.h for use in finding the data
+# directories.
set(DATA_INSTALL_DIR share/${GMX_DATA_INSTALL_DIR})
set(MAN_INSTALL_DIR share/man)
# If the nesting level wrt. the installation root is changed,
set(PKGCONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/pkgconfig)
set(INCL_INSTALL_DIR include)
-# These variables get written into config.h for use in finding the data
-# directories.
-set(GMXLIB_SEARCH_DIR share/${GMX_DATA_INSTALL_DIR}/top)
-set(GMXLIB_FALLBACK ${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/top)
-
list(APPEND INSTALLED_HEADER_INCLUDE_DIRS ${INCL_INSTALL_DIR})
# Binary and library suffix options
/* TODO: For now, disable Doxygen warnings from here */
/*! \cond */
-/* Default location of data files */
-#define GMXLIB_SEARCH_DIR "@GMXLIB_SEARCH_DIR@"
-
-/* Default location of data files */
-#define GMXLIB_FALLBACK "@GMXLIB_FALLBACK@"
-
/* Binary suffix for the created binaries */
#define GMX_BINARY_SUFFIX "@GMX_BINARY_SUFFIX@"
+/* Installation prefix (default location of data files) */
+#define CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
+
+/* Location of data files in the installation directory */
+#define DATA_INSTALL_DIR "@DATA_INSTALL_DIR@"
+
/* Source directory for the build */
#cmakedefine CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* Returns whether given path prefix contains files from `share/top/`.
*
* \param[in] path Path prefix to check.
- * \param[out] result If return value is `true`, the pointee is set to the
- * actual data directory. Otherwise, the pointee is not modified.
* \returns `true` if \p path contains the data files.
*
* Checks whether \p path could be the installation prefix where `share/top/`
* files have been installed: appends the relative installation path of the
* data files and calls isAcceptableLibraryPath().
*/
-bool isAcceptableLibraryPathPrefix(const std::string &path, std::string *result)
+bool isAcceptableLibraryPathPrefix(const std::string &path)
{
- std::string testPath = Path::join(path, GMXLIB_SEARCH_DIR);
+ std::string testPath = Path::join(path, DATA_INSTALL_DIR, "top");
if (isAcceptableLibraryPath(testPath))
{
- *result = testPath;
return true;
}
return false;
}
/*! \brief
- * Returns a fallback data path.
+ * Returns a fallback installation prefix path.
*
* Checks a few standard locations for the data files before returning a
* configure-time hard-coded path. The hard-coded path is preferred if it
* actually contains the data files, though.
*/
-std::string findFallbackLibraryDataPath()
+std::string findFallbackInstallationPrefixPath()
{
#ifndef GMX_NATIVE_WINDOWS
- if (!isAcceptableLibraryPath(GMXLIB_FALLBACK))
+ if (!isAcceptableLibraryPathPrefix(CMAKE_INSTALL_PREFIX))
{
- std::string foundPath;
- if (isAcceptableLibraryPathPrefix("/usr/local", &foundPath))
+ if (isAcceptableLibraryPathPrefix("/usr/local"))
{
- return foundPath;
+ return "/usr/local";
}
- if (isAcceptableLibraryPathPrefix("/usr", &foundPath))
+ if (isAcceptableLibraryPathPrefix("/usr"))
{
- return foundPath;
+ return "/usr";
}
- if (isAcceptableLibraryPathPrefix("/opt", &foundPath))
+ if (isAcceptableLibraryPathPrefix("/opt"))
{
- return foundPath;
+ return "/opt";
}
}
#endif
- return GMXLIB_FALLBACK;
+ return CMAKE_INSTALL_PREFIX;
}
/*! \brief
* Finds the library data files based on path of the binary.
*
- * \param[in] binaryPath Absolute path to the binary.
+ * \param[in] binaryPath Absolute path to the binary.
+ * \param[out] bSourceLayout Set to `true` if the binary is run from
+ * the build tree and the original source directory can be found.
* \returns Path to the `share/top/` data files.
*
* The search based on the path only works if the binary is in the same
* Extra logic is present to allow running binaries from the build tree such
* that they use up-to-date data files from the source tree.
*/
-std::string findDefaultLibraryDataPath(const std::string &binaryPath)
+std::string findInstallationPrefixPath(const std::string &binaryPath,
+ bool *bSourceLayout)
{
+ *bSourceLayout = false;
// If the input path is not absolute, the binary could not be found.
// Don't search anything.
if (Path::isAbsolute(binaryPath))
std::string testPath = Path::join(CMAKE_SOURCE_DIR, "share/top");
if (isAcceptableLibraryPath(testPath))
{
- return testPath;
+ *bSourceLayout = true;
+ return CMAKE_SOURCE_DIR;
}
}
#endif
// Use the executable path to (try to) find the library dir.
+ // TODO: Consider only going up exactly the required number of levels.
while (!searchPath.empty())
{
- std::string testPath = Path::join(searchPath, GMXLIB_SEARCH_DIR);
- if (isAcceptableLibraryPath(testPath))
+ if (isAcceptableLibraryPathPrefix(searchPath))
{
- return testPath;
+ return searchPath;
}
searchPath = Path::getParentPath(searchPath);
}
// End of smart searching. If we didn't find it in our parent tree,
// or if the program name wasn't set, return a fallback.
- return findFallbackLibraryDataPath();
+ return findFallbackInstallationPrefixPath();
}
//! \}
std::string displayName_;
std::string commandLine_;
mutable std::string fullBinaryPath_;
- mutable std::string defaultLibraryDataPath_;
+ mutable std::string installationPrefix_;
+ mutable bool bSourceLayout_;
mutable tMPI::mutex binaryPathMutex_;
};
CommandLineProgramContext::Impl::Impl()
- : programName_("GROMACS")
+ : programName_("GROMACS"), bSourceLayout_(false)
{
}
CommandLineProgramContext::Impl::Impl(int argc, const char *const argv[],
ExecutableEnvironmentPointer env)
- : executableEnv_(env)
+ : executableEnv_(env), bSourceLayout_(false)
{
invokedName_ = (argc != 0 ? argv[0] : "");
programName_ = Path::getFilename(invokedName_);
return impl_->fullBinaryPath_.c_str();
}
-const char *CommandLineProgramContext::defaultLibraryDataPath() const
+InstallationPrefixInfo CommandLineProgramContext::installationPrefix() const
{
tMPI::lock_guard<tMPI::mutex> lock(impl_->binaryPathMutex_);
- if (impl_->defaultLibraryDataPath_.empty())
+ if (impl_->installationPrefix_.empty())
{
impl_->findBinaryPath();
- impl_->defaultLibraryDataPath_ =
- Path::normalize(findDefaultLibraryDataPath(impl_->fullBinaryPath_));
+ impl_->installationPrefix_ =
+ Path::normalize(findInstallationPrefixPath(impl_->fullBinaryPath_,
+ &impl_->bSourceLayout_));
}
- return impl_->defaultLibraryDataPath_.c_str();
+ return InstallationPrefixInfo(
+ impl_->installationPrefix_.c_str(),
+ impl_->bSourceLayout_);
}
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
virtual const char *fullBinaryPath() const;
/*! \brief
- * Returns the default path for \Gromacs data files.
+ * Returns the installation prefix (for finding \Gromacs data files).
*
* \throws std::bad_alloc if out of memory.
* \throws tMPI::system_error on thread synchronization errors.
* Returns a hardcoded path set during configuration time if there is
* an error in finding the library data files.
*/
- virtual const char *defaultLibraryDataPath() const;
+ virtual InstallationPrefixInfo installationPrefix() const;
/*! \brief
* Returns the full command line used to invoke the binary.
*
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
static gmx_bool be_cool(void)
{
fprintf(fp, "%sGROMACS: %s, %s%s%s\n", prefix, name,
gmx_version(), precisionString, suffix);
const char *const binaryPath = programContext.fullBinaryPath();
- if (binaryPath != NULL && binaryPath[0] != '\0')
+ if (!gmx::isNullOrEmpty(binaryPath))
{
fprintf(fp, "%sExecutable: %s%s\n", prefix, binaryPath, suffix);
}
- const char *const libraryPath = programContext.defaultLibraryDataPath();
- if (libraryPath != NULL && libraryPath[0] != '\0')
+ const gmx::InstallationPrefixInfo installPrefix = programContext.installationPrefix();
+ if (!gmx::isNullOrEmpty(installPrefix.path))
{
- fprintf(fp, "%sLibrary dir: %s%s\n", prefix, libraryPath, suffix);
+ fprintf(fp, "%sData prefix: %s%s%s\n", prefix, installPrefix.path,
+ installPrefix.bSourceLayout ? " (source tree)" : "", suffix);
}
const char *const commandLine = programContext.commandLine();
- if (commandLine != NULL && commandLine[0] != '\0')
+ if (!gmx::isNullOrEmpty(commandLine))
{
fprintf(fp, "%sCommand line:%s\n%s %s%s\n",
prefix, suffix, prefix, commandLine, suffix);
#include "datafilefinder.h"
+#include "config.h"
+
#include <cstdlib>
#include <string>
class DataFileFinder::Impl
{
public:
+ static std::string getDefaultPath();
+
Impl() : envName_(NULL), bEnvIsSet_(false) {}
const char *envName_;
std::vector<std::string> searchPath_;
};
+std::string DataFileFinder::Impl::getDefaultPath()
+{
+ const InstallationPrefixInfo installPrefix
+ = getProgramContext().installationPrefix();
+ if (!isNullOrEmpty(installPrefix.path))
+ {
+ const char *const dataPath
+ = installPrefix.bSourceLayout ? "share" : DATA_INSTALL_DIR;
+ return Path::join(installPrefix.path, dataPath, "top");
+ }
+ return std::string();
+}
+
/********************************************************************
* DataFileFinder
*/
}
}
}
- const char *const defaultPath = getProgramContext().defaultLibraryDataPath();
- if (defaultPath != NULL && defaultPath[0] != '\0')
+ const std::string &defaultPath = Impl::getDefaultPath();
+ if (!defaultPath.empty())
{
std::string testPath = Path::join(defaultPath, options.filename_);
if (Path::exists(testPath))
message.append(*i);
}
}
- if (defaultPath != NULL && defaultPath[0] != '\0')
+ if (!defaultPath.empty())
{
message.append("\n ");
message.append(defaultPath);
}
}
}
- const char *const defaultPath = getProgramContext().defaultLibraryDataPath();
- if (defaultPath != NULL && defaultPath[0] != '\0')
+ const std::string &defaultPath = Impl::getDefaultPath();
+ if (!defaultPath.empty())
{
std::vector<std::string> files
= DirectoryEnumerator::enumerateFilesWithExtension(
- defaultPath, options.filename_, false);
+ defaultPath.c_str(), options.filename_, false);
for (i = files.begin(); i != files.end(); ++i)
{
result.push_back(DataFileInfo(defaultPath, *i, true));
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
virtual const char *programName() const { return "GROMACS"; }
virtual const char *displayName() const { return "GROMACS"; }
virtual const char *fullBinaryPath() const { return ""; }
- virtual const char *defaultLibraryDataPath() const { return ""; }
+ virtual InstallationPrefixInfo installationPrefix() const
+ {
+ return InstallationPrefixInfo("", false);
+ }
virtual const char *commandLine() const { return ""; }
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! \addtogroup module_utility
//! \{
+/*! \brief
+ * Provides information about installation prefix (see
+ * ProgramContextInterface::installationPrefix()).
+ *
+ * \inpublicapi
+ */
+struct InstallationPrefixInfo
+{
+ //! Initializes the structure with given values.
+ InstallationPrefixInfo(const char *path, bool bSource)
+ : path(path), bSourceLayout(bSource)
+ {
+ }
+
+ /*! \brief
+ * Path to the installation prefix of the current \Gromacs instance.
+ *
+ * If this is `NULL` or empty, data files cannot be looked up from the
+ * install tree and \Gromacs functions that access such files may fail.
+ * This can also contain a path to the source tree (see \a bSourceLayout).
+ */
+ const char *const path;
+ /*! \brief
+ * Whether \a path points to a source tree -like layout.
+ *
+ * For testing, it is useful to read data files from the source tree.
+ * For such cases, the program context can return the source tree root path
+ * in \a path, and set this to `true` to indicate that the data files
+ * should be searched using the layout of the source tree instead of the
+ * installation.
+ */
+ const bool bSourceLayout;
+};
+
+
/*! \brief
* Provides context information about the program that is calling the library.
*
*/
virtual const char *fullBinaryPath() const = 0;
/*! \brief
- * Returns the default path for \Gromacs data files.
+ * Returns the installation prefix for \Gromacs.
*
* This path is used to locate the data files that are in `share/top/`
* in the source directory.
* The implementation can provide an empty string if the path is not
* available; in such a case, functions that require data files may
* fail.
+ *
+ * The returned structure also contains a flag to indicate whether the
+ * prefix actually points to the source tree. This is used for tests
+ * and to support running binaries directly from the build tree.
*/
- virtual const char *defaultLibraryDataPath() const = 0;
+ virtual InstallationPrefixInfo installationPrefix() const = 0;
/*! \brief
* Returns the full command line used to invoke the binary.
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! \addtogroup module_utility
//! \{
+/*! \brief
+ * Tests whether a string is null or empty.
+ *
+ * Does not throw.
+ */
+bool inline isNullOrEmpty(const char *str)
+{
+ return str == NULL || str[0] == '\0';
+}
+
/*! \brief
* Tests whether a string starts with another string.
*
/*! \brief
* Custom program context for test binaries.
*
- * This context overrides the defaultLibraryDataPath() implementation to always
+ * This context overrides the installationPrefix() implementation to always
* load data files from the source directory, as the test binaries are never
* installed. It also support overriding the directory through a command-line
* option to the test binary.
* \param[in] context Current \Gromacs program context.
*/
explicit TestProgramContext(const ProgramContextInterface &context)
- : context_(context),
- dataPath_(Path::join(CMAKE_SOURCE_DIR, "share/top"))
+ : context_(context), dataPath_(CMAKE_SOURCE_DIR)
{
}
*/
void overrideSourceRoot(const std::string &sourceRoot)
{
- dataPath_ = Path::join(sourceRoot, "share/top");
+ dataPath_ = sourceRoot;
}
virtual const char *programName() const
{
return context_.fullBinaryPath();
}
- virtual const char *defaultLibraryDataPath() const
+ virtual InstallationPrefixInfo installationPrefix() const
{
- return dataPath_.c_str();
+ return InstallationPrefixInfo(dataPath_.c_str(), true);
}
virtual const char *commandLine() const
{