Merge branch 'check-osg-plugins' into 'master'

Check for dynamic OSG plugins on launch

Closes #7736

See merge request OpenMW/openmw!3748
fix-osga-rotate-wildly
psi29a 10 months ago
commit 61f5a13c02

@ -2,6 +2,7 @@
#include <components/fallback/fallback.hpp> #include <components/fallback/fallback.hpp>
#include <components/fallback/validate.hpp> #include <components/fallback/validate.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/misc/osgpluginchecker.hpp>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/platform/platform.hpp> #include <components/platform/platform.hpp>
#include <components/version/version.hpp> #include <components/version/version.hpp>
@ -228,6 +229,9 @@ int runApplication(int argc, char* argv[])
if (parseOptions(argc, argv, *engine, cfgMgr)) if (parseOptions(argc, argv, *engine, cfgMgr))
{ {
if (!Misc::checkRequiredOSGPluginsArePresent())
return 1;
engine->go(); engine->go();
} }

@ -43,6 +43,24 @@ endif (GIT_CHECKOUT)
list (APPEND COMPONENT_FILES "${OpenMW_BINARY_DIR}/${VERSION_CPP_FILE}") list (APPEND COMPONENT_FILES "${OpenMW_BINARY_DIR}/${VERSION_CPP_FILE}")
# OSG plugin checker
# Helpfully, OSG doesn't export this to its CMake config as it doesn't have one
set(OSG_PLUGIN_PREFIX "")
if (CYGWIN)
SET(OSG_PLUGIN_PREFIX "cygwin_")
elseif(MINGW)
SET(OSG_PLUGIN_PREFIX "mingw_")
endif()
list(TRANSFORM USED_OSG_PLUGINS PREPEND "${OSG_PLUGIN_PREFIX}" OUTPUT_VARIABLE USED_OSG_PLUGIN_FILENAMES)
list(TRANSFORM USED_OSG_PLUGIN_FILENAMES APPEND "${CMAKE_SHARED_MODULE_SUFFIX}")
list(TRANSFORM USED_OSG_PLUGIN_FILENAMES PREPEND "\"" OUTPUT_VARIABLE USED_OSG_PLUGIN_FILENAMES_FORMATTED)
list(TRANSFORM USED_OSG_PLUGIN_FILENAMES_FORMATTED APPEND "\"")
list(JOIN USED_OSG_PLUGIN_FILENAMES_FORMATTED ", " USED_OSG_PLUGIN_FILENAMES_FORMATTED)
set(OSG_PLUGIN_CHECKER_CPP_FILE "components/misc/osgpluginchecker.cpp")
configure_file("${OpenMW_SOURCE_DIR}/${OSG_PLUGIN_CHECKER_CPP_FILE}.in" "${OpenMW_BINARY_DIR}/${OSG_PLUGIN_CHECKER_CPP_FILE}")
list(APPEND COMPONENT_FILES "${OpenMW_BINARY_DIR}/${OSG_PLUGIN_CHECKER_CPP_FILE}")
# source files # source files
add_component_dir (lua add_component_dir (lua
@ -277,8 +295,8 @@ add_component_dir (esm4
add_component_dir (misc add_component_dir (misc
barrier budgetmeasurement color compression constants convert coordinateconverter display endianness float16 frameratelimiter barrier budgetmeasurement color compression constants convert coordinateconverter display endianness float16 frameratelimiter
guarded math mathutil messageformatparser notnullptr objectpool osguservalues progressreporter resourcehelpers rng guarded math mathutil messageformatparser notnullptr objectpool osgpluginchecker osguservalues progressreporter resourcehelpers
strongtypedef thread timeconvert timer tuplehelpers tuplemeta utf8stream weakcache windows rng strongtypedef thread timeconvert timer tuplehelpers tuplemeta utf8stream weakcache windows
) )
add_component_dir (misc/strings add_component_dir (misc/strings

@ -0,0 +1,86 @@
#include "components/misc/osgpluginchecker.hpp"
#include <components/debug/debuglog.hpp>
#include <components/misc/strings/conversion.hpp>
#include <osg/Config>
#include <osg/Version>
#include <osgDB/FileUtils>
#include <osgDB/PluginQuery>
#include <algorithm>
#include <array>
#include <filesystem>
#include <string_view>
namespace Misc
{
#if defined(OSG_LIBRARY_STATIC) || defined(__APPLE__)
bool checkRequiredOSGPluginsArePresent()
{
// assume they were linked in at build time and CMake would have failed if they were missing
// true-ish for MacOS - they're copied into the package and that'd fail if they were missing,
// but if you don't actually make a MacOS package and run a local build, this won't notice.
// the workaround in the real implementation isn't powerful enough to make MacOS work, though.
return true;
}
#else
namespace
{
constexpr auto USED_OSG_PLUGIN_FILENAMES = std::to_array<std::string_view>({${USED_OSG_PLUGIN_FILENAMES_FORMATTED}});
}
bool checkRequiredOSGPluginsArePresent()
{
// work around osgDB::listAllAvailablePlugins() not working on some platforms due to a suspected OSG bug
std::filesystem::path pluginDirectoryName = std::string("osgPlugins-") + std::string(osgGetVersion());
osgDB::FilePathList& filepath = osgDB::getLibraryFilePathList();
for (const auto& path : filepath)
{
#ifdef OSG_USE_UTF8_FILENAME
std::filesystem::path osgPath{ stringToU8String(path) };
#else
std::filesystem::path osgPath{ path };
#endif
if (!osgPath.has_filename())
osgPath = osgPath.parent_path();
if (osgPath.filename() == pluginDirectoryName)
{
osgPath = osgPath.parent_path();
#ifdef OSG_USE_UTF8_FILENAME
std::string extraPath = u8StringToString(osgPath.u8string_view());
#else
std::string extraPath = osgPath.string();
#endif
filepath.emplace_back(std::move(extraPath));
}
}
auto availableOSGPlugins = osgDB::listAllAvailablePlugins();
bool haveAllPlugins = true;
for (std::string_view plugin : USED_OSG_PLUGIN_FILENAMES)
{
if (std::find_if(availableOSGPlugins.begin(), availableOSGPlugins.end(),
[&](std::string_view availablePlugin) {
#ifdef OSG_USE_UTF8_FILENAME
std::filesystem::path pluginPath{ stringToU8String(availablePlugin) };
#else
std::filesystem::path pluginPath {availablePlugin};
#endif
return pluginPath.filename() == plugin;
})
== availableOSGPlugins.end())
{
Log(Debug::Error) << "Missing OSG plugin: " << plugin;
haveAllPlugins = false;
}
}
return haveAllPlugins;
}
#endif
}

@ -0,0 +1,9 @@
#ifndef OPENMW_COMPONENTS_MISC_OSGPLUGINCHECKER_HPP
#define OPENMW_COMPONENTS_MISC_OSGPLUGINCHECKER_HPP
namespace Misc
{
bool checkRequiredOSGPluginsArePresent();
}
#endif
Loading…
Cancel
Save