From a8187e7dc47cd344fd309a2be3675e4687f95aaa Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 7 Nov 2020 16:31:35 -0500 Subject: moved dlls stuff to MOApplication --- src/moapplication.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'src/moapplication.cpp') diff --git a/src/moapplication.cpp b/src/moapplication.cpp index 659b5a12..f514050f 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -19,6 +19,7 @@ along with Mod Organizer. If not, see . #include "moapplication.h" #include "settings.h" +#include "env.h" #include #include #include @@ -32,6 +33,12 @@ along with Mod Organizer. If not, see . #include #include +// see addDllsToPath() below +#pragma comment(linker, "/manifestDependency:\"" \ + "name='dlls' " \ + "processorArchitecture='x86' " \ + "version='1.0.0.0' " \ + "type='win32' \"") using namespace MOBase; @@ -73,6 +80,45 @@ public: }; +// This adds the `dlls` directory to the path so the dlls can be found. How +// MO is able to find dlls in there is a bit convoluted: +// +// Dependencies on DLLs can be baked into an executable by passing a +// `manifestdependency` option to the linker. This can be done on the command +// line or with a pragma. Typically, the dependency will not be a hardcoded +// filename, but an assembly name, such as Microsoft.Windows.Common-Controls. +// +// When Windows loads the exe, it will look for this assembly in a variety of +// places, such as in the WinSxS folder, but also in the program's folder. It +// will look for `assemblyname.dll` or `assemblyname/assemblyname.dll` and try +// to load that. +// +// If these files don't exist, then the loader gets creative and looks for +// `assemblyname.manifest` and `assemblyname/assemblyname.manifest`. A manifest +// file is just an XML file that can contain a list of DLLs to load for this +// assembly. +// +// In MO's case, there's a `pragma` at the beginning of this file which adds +// `dlls` as an "assembly" dependency. This is a bit of a hack to just force +// the loader to eventually find `dlls/dlls.manifest`, which contains the list +// of all the DLLs MO requires to load. +// +// This file was handwritten in `modorganizer/src/dlls.manifest.qt5` and +// is copied and renamed in CMakeLists.txt into `bin/dlls/dlls.manifest`. Note +// that the useless and incorrect .qt5 extension is removed. +// +void addDllsToPath() +{ + const auto dllsPath = QDir::toNativeSeparators( + QCoreApplication::applicationDirPath() + "/dlls"); + + QCoreApplication::setLibraryPaths( + QStringList(dllsPath) + QCoreApplication::libraryPaths()); + + env::prependToPath(dllsPath); +} + + MOApplication::MOApplication(int& argc, char** argv) : QApplication(argc, argv) { @@ -83,11 +129,13 @@ MOApplication::MOApplication(int& argc, char** argv) m_DefaultStyle = style()->objectName(); setStyle(new ProxyStyle(style())); + addDllsToPath(); } MOApplication MOApplication::create(int& argc, char** argv) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + return MOApplication(argc, argv); } -- cgit v1.3.1