Commit eb1d0948 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit
Browse files

Adding vtkResourceFileLocator

vtkResourceFileLocator is a utility class that makes it easier to locate
resource files in VTK applications.
parent aeb58fd4
......@@ -4,6 +4,7 @@ set(Module_SRCS
vtkFunctionParser.cxx
vtkHeap.cxx
vtkPolygonBuilder.cxx
vtkResourceFileLocator.cxx
)
set_source_files_properties(
......
......@@ -4,6 +4,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
TestPolygonBuilder2.cxx
TestPolygonBuilder3.cxx
TestPolygonBuilder4.cxx
TestResourceFileLocator.cxx
UnitTestFunctionParser.cxx
)
vtk_test_cxx_executable(${vtk-module}CxxTests tests)
#include "vtkNew.h"
#include "vtkResourceFileLocator.h"
#include "vtkVersion.h"
#include <vtksys/SystemTools.hxx>
int TestResourceFileLocator(int, char* [])
{
auto vtklib = vtkGetLibraryPathForSymbol(GetVTKVersion);
if (vtklib.empty())
{
cerr << "FAILED to locate `GetVTKVersion`." << endl;
return EXIT_FAILURE;
}
const std::string vtkdir = vtksys::SystemTools::GetFilenamePath(vtklib);
vtkNew<vtkResourceFileLocator> locator;
locator->PrintDebugInformationOn();
auto path = locator->Locate(vtkdir, "Testing/Temporary");
if (path.empty())
{
cerr << "FAILED to locate 'Testing/Temporary' dir." << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
......@@ -8,4 +8,6 @@ vtk_module(vtkCommonMisc
DEPENDS
vtkCommonCore
vtkCommonMath
)
\ No newline at end of file
PRIVATE_DEPENDS
vtksys
)
/*=========================================================================
Program: Visualization Toolkit
Module: vtkResourceFileLocator.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkResourceFileLocator.h"
#include "vtkObjectFactory.h"
#include <vtksys/SystemTools.hxx>
#if defined(_WIN32) && !defined(__CYGWIN__)
#define VTK_PATH_SEPARATOR "\\"
#else
#define VTK_PATH_SEPARATOR "/"
#endif
#define VTK_FILE_LOCATOR_DEBUG_MESSAGE(x) \
if (this->PrintDebugInformation) \
{ \
cout << "# vtk: " x << endl; \
}
#if defined(_WIN32) && !defined(__CYGWIN__)
// Implementation for Windows win32 code but not cygwin
#include <windows.h>
#else
#include <dlfcn.h>
#endif
vtkStandardNewMacro(vtkResourceFileLocator);
//----------------------------------------------------------------------------
vtkResourceFileLocator::vtkResourceFileLocator()
: PrintDebugInformation(false)
{
}
//----------------------------------------------------------------------------
vtkResourceFileLocator::~vtkResourceFileLocator()
{
}
//----------------------------------------------------------------------------
std::string vtkResourceFileLocator::Locate(
const std::string& anchor, const std::string& landmark, const std::string& defaultDir)
{
return this->Locate(anchor, { std::string() }, landmark, defaultDir);
}
//----------------------------------------------------------------------------
std::string vtkResourceFileLocator::Locate(const std::string& anchor,
const std::vector<std::string>& landmark_prefixes, const std::string& landmark,
const std::string& defaultDir)
{
VTK_FILE_LOCATOR_DEBUG_MESSAGE("looking for '" << landmark << "'");
std::vector<std::string> path_components;
vtksys::SystemTools::SplitPath(anchor, path_components);
while (!path_components.empty())
{
std::string curanchor = vtksys::SystemTools::JoinPath(path_components);
for (const std::string& curprefix : landmark_prefixes)
{
const std::string landmarkdir =
curprefix.empty() ? curanchor : curanchor + VTK_PATH_SEPARATOR + curprefix;
const std::string landmarktocheck = landmarkdir + VTK_PATH_SEPARATOR + landmark;
if (vtksys::SystemTools::FileExists(landmarktocheck))
{
VTK_FILE_LOCATOR_DEBUG_MESSAGE("trying file " << landmarktocheck << " -- success!");
return landmarkdir;
}
else
{
VTK_FILE_LOCATOR_DEBUG_MESSAGE("trying file " << landmarktocheck << " -- failed!");
}
}
path_components.pop_back();
}
return defaultDir;
}
//----------------------------------------------------------------------------
std::string vtkResourceFileLocator::GetLibraryPathForSymbolUnix(const char* symbolname)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
(void)symbolname;
return std::string();
#else
void* handle = dlsym(RTLD_DEFAULT, symbolname);
if (!handle)
{
return std::string();
}
Dl_info di;
int ret = dladdr(handle, &di);
if (ret == 0 || !di.dli_saddr || !di.dli_fname)
{
return std::string();
}
return std::string(di.dli_fname);
#endif
}
//----------------------------------------------------------------------------
std::string vtkResourceFileLocator::GetLibraryPathForSymbolWin32(const void* fptr)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(fptr, &mbi, sizeof(mbi));
char pathBuf[16384];
if (!GetModuleFileName(static_cast<HMODULE>(mbi.AllocationBase), pathBuf, sizeof(pathBuf)))
{
return std::string();
}
return std::string(pathBuf);
#else
(void)fptr;
return std::string();
#endif
}
//----------------------------------------------------------------------------
void vtkResourceFileLocator::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "PrintDebugInformation: " << this->PrintDebugInformation << endl;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkResourceFileLocator.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkResourceFileLocator
* @brief utility to locate resource files.
*
* VTK based application often need to locate resource files, such configuration
* files, Python modules, etc. vtkResourceFileLocator provides methods that can
* be used to locate such resource files at runtime.
*
* Using `Locate`, one can locate files relative to an
* anchor directory such as the executable directory, or the library directory.
*
* `GetLibraryPathForSymbolUnix` and `GetLibraryPathForSymbolWin32` methods can
* be used to locate the library that provides a particular symbol. For example,
* this is used by `vtkPythonInterpreter` to ensure that the `vtk` Python package
* is located relative the VTK libraries, irrespective of the application location.
*/
#ifndef vtkResourceFileLocator_h
#define vtkResourceFileLocator_h
#include "vtkCommonMiscModule.h" // For export macro
#include "vtkObject.h"
#include <string> // needed for std::string
#include <vector> // needed for std::vector
class VTKCOMMONMISC_EXPORT vtkResourceFileLocator : public vtkObject
{
public:
static vtkResourceFileLocator* New();
vtkTypeMacro(vtkResourceFileLocator, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@{
/**
* Enable/disable printing of testing of various path during `Locate`
* to `stdout`.
*/
vtkSetMacro(PrintDebugInformation, bool);
vtkGetMacro(PrintDebugInformation, bool);
vtkBooleanMacro(PrintDebugInformation, bool);
//@}
//@{
/**
* Given a starting anchor directory, look for the landmark file relative to
* the anchor. If found return the anchor. If not found, go one directory up
* and then look the landmark file again.
*/
virtual std::string Locate(const std::string& anchor, const std::string& landmark,
const std::string& defaultDir = std::string());
//@}
//@{
/**
* This variant is used to look for landmark relative to the anchor using
* additional prefixes for the landmark file. For example, if you're looking for
* `vtk/__init__.py`, but it can be placed relative to your anchor location
* (let's say the executable directory), under "lib" or "lib/python", then
* use this variant with "lib", and "lib/python" passed in as the landmark
* prefixes. On success, the returned value will be anchor + matching prefix.
*/
virtual std::string Locate(const std::string& anchor,
const std::vector<std::string>& landmark_prefixes, const std::string& landmark,
const std::string& defaultDir = std::string());
//@}
//@{
/**
* Returns the name of the library providing the symbol. For example, if you
* want to locate where the VTK libraries located call
* `GetLibraryPathForSymbolUnix("GetVTKVersion")` on Unixes and
* `GetLibraryPathForSymbolUnix(GetVTKVersion)` on Window. Alternatively, you
* can simply use the `vtkGetLibraryPathForSymbol(GetVTKVersion)` macro
* that makes the appropriate call as per the current platform.
*/
static std::string GetLibraryPathForSymbolUnix(const char* symbolname);
static std::string GetLibraryPathForSymbolWin32(const void* fptr);
//@}
protected:
vtkResourceFileLocator();
~vtkResourceFileLocator();
bool PrintDebugInformation;
private:
vtkResourceFileLocator(const vtkResourceFileLocator&) = delete;
void operator=(const vtkResourceFileLocator&) = delete;
};
#if defined(_WIN32) && !defined(__CYGWIN__)
#define vtkGetLibraryPathForSymbol(function) \
vtkResourceFileLocator::GetLibraryPathForSymbolWin32(&function)
#else
#define vtkGetLibraryPathForSymbol(function) \
vtkResourceFileLocator::GetLibraryPathForSymbolUnix(#function)
#endif
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment