SoapySDR icon indicating copy to clipboard operation
SoapySDR copied to clipboard

SoapySDR::getRootPath() returns parent directory

Open gvanem opened this issue 7 years ago • 9 comments

Trying to use SoapySDR in the excellent DAB+ receiver Welle-IO has given me lots of griefs.

I have my SoapySDR sources checked out under f:\gv\dx-radio\SoapySDR. My PATH contains f:\gv\dx-radio\SoapySDR. Thus welle-io.exe finds SoapySDR.dll there. But crashes since SoapySDR.dll only returns a null driver!

Also from SoapySDRutil --info (with no %SOAPY_SDR_PLUGIN_PATH%), I get this:

Install root: F:\gv\dx-radio

Why do getRootPath() return my parent directory? I

I then added some TRACE() in lib/Modules.in.cpp and discovered some fishy use of find_last_of("\\/"). I must be missing some knowledge on std::string, but how come you assume GetModuleFileNameA() returns paths with / in them?

Simplifying the meat of this function into:

        const DWORD size = GetModuleFileNameA(hm, path, sizeof(path));
        if (size != 0)
        {
            const std::string libPath(path, size);
            const size_t slash0Pos = libPath.find_last_of("\\");
            if (slash0Pos != std::string::npos)
               return libPath.substr(0, slash0Pos);
        }

gave the correct result of "f:\gv\dx-radio\SoapySDR" in getRootPath().

PS Why doesn't SoapySDR::searchModulePath() simply search for "*.dll" under Windows?

gvanem avatar Feb 16 '18 12:02 gvanem

. Thus welle-io.exe finds SoapySDR.dll there. But crashes since SoapySDR.dll only returns a null driver!

I will admit, thats a weird nuance. If you use the args to specify a specific driver like driver=foo, you should get an error. But when nothing is found and no args are provided, there is this null driver, specifically for applications to have a dummy instantiated.

Install root: F:\gv\dx-radio Why do getRootPath() return my parent directory?

It expects to be in INSTALL_PREFIX/bin/SoapySDR.dll, and so the root of the install is up one directory.

Did you use the install target for soapyremote/soapysdr? I think the root cause are that you copied files into unexpected places, and so they don't know how to find their resources properly. Can you share the install tree (command tree if you have cygwin/gnu tools installed)?

The inspiration is the FHS https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard (specifically how /usr/ is organized) Many projects can co exist in one directory this way, and most of the projects in this ecosystem, when they build on windows, still follow this standard.

how come you assume GetModuleFileNameA() returns paths with / in them?

I dont. libPath.find_last_of("/\\") looks for both types of slashes.

PS Why doesn't SoapySDR::searchModulePath() simply search for "*.dll" under Windows?

Its not safe to LoadLibrary() every dll we can find, its takes time, there could be side effects from load initialization. so its only specific expected paths in the filesystem hierarchy or specified by environment variable/registry keys.

PS There might be merit in having an alternative file system layout and the build would need support for that. I'm curious about the use case to hear about it. But for for the time being FHS is required.

guruofquality avatar Feb 16 '18 15:02 guruofquality

Its not safe to LoadLibrary() every dll we can find, its takes time,

Agreed, but I was referring to the pattern to FindFirstFile(). Why simply not "*.dll"? If you assume for a second (the current Cmake build-system aside and no make install), that both *.map and the very useful *.pdb files end up with the module *.dll files. Then a FindFirstFile (*.*, &fd) produces too much noise.

AFAICS, only *.dll and *.so can be modules. No?

I come back to your other items later.

gvanem avatar Feb 16 '18 17:02 gvanem

Oh sure, I agree that the glob pattern is lazy. We got away with this laziness because module search paths are usually cleanly installed. Changing the file layout, setting a particular module path, or potential debugging techniques could make this annoying. Good idea

guruofquality avatar Feb 16 '18 20:02 guruofquality

It expects to be in INSTALL_PREFIX/bin/SoapySDR.dll, and so the root of the install is up one directory.

Did you use the install target for soapyremote/soapysdr? I think the root cause are that you copied files into unexpected places,

The impression I got from your Pothos distro (way bigger than just SoapySDR), it that the layout must be something like this:

<Install-Root>\bin\SoapySDR.dll
<Install-Root>\lib\SoapySDR\modules0.7\*.dll

If so, where besides the obfuscated CMake-system is this documented? I don't know what is "expected" when the code in lib/Modules.in.cpp doesn't mention these expected places. All this is highly confusing in my opinion. It may be in line with FHS, but from a Windows perspective it seems odd.

And is also a make install required before using it in e.g. Welle-IO? Why not be able to use it from the build-dir before we're sure the build works (by setting PATH and SOAPY_SDR_PLUGIN_PATH? I dislike packages that must be installed before use. A waste of time and disk-space.

gvanem avatar Feb 17 '18 05:02 gvanem

Any new thoughts on this? Is there a chance that only SOAPY_SDR_PLUGIN_PATH (or SOAPY_SDR_MODULE_PATH) could be used to search for *support.dll files?

gvanem avatar Jun 28 '18 11:06 gvanem

Any new thoughts on this?

I dont know. Some projects can be run easily from their build tree, others need to be installed or they are just a mess. I often create something like c:\local for testing a group of related software, and just make the install/copy part of my build script or build commands. And just test in the c:\local

If its just for development testing, using SOAPY_SDR_PLUGIN_PATH env var is a good solution. If SoapySDR needs a new supported layout for custom packaging, I think thats probably worth a change:

  1. a cmake flag like -DENABLE_WINDOWS_LAYOUT=ON
  2. ifdef in LoadModules.cpp so getRootPath( ) looks in the current executable's directory
  3. and perhaps matching changes to install rules if thats relevant

Is there a chance that only SOAPY_SDR_PLUGIN_PATH (or SOAPY_SDR_MODULE_PATH) could be used to search for *support.dll files?

I cant guarantee that all of the modules are named "*support.dll", thats just a word that was copied into many of the different hardware support projects. So its not really a good ideal to put a filter like that in the Modules.cpp code.

But the SOAPY_SDR_PLUGIN_PATH can take a list of semicolon separated paths -- which is good if each support.dll is in a different directory.

Short of that, I think if the loaded code was modified to take path and files then SOAPY_SDR_PLUGIN_PATH could also be a semicolon list of dll files.

guruofquality avatar Jun 29 '18 16:06 guruofquality

But the SOAPY_SDR_PLUGIN_PATH can take a list of semicolon separated paths

Yes, good. But what if 32-bit and 64-bit DLLs are in those same paths. What should a 64-bit compiled Module.cpp do for a 32-bit DLL? Try to load it w/o checking the bitness? Or check for correct bitness and search further?

Just some thoughts on how e.g. SoapySDRutil --info now behaves. Not so good with regard to $SOAPY_SDR_PLUGIN_PATH. For example, it doesn't report missing directories in that path.

gvanem avatar Jun 29 '18 18:06 gvanem

Yes, good. But what if 32-bit and 64-bit DLLs are in those same paths. What should a 64-bit compiled Module.cpp do for a 32-bit DLL? Try to load it w/o checking the bitness? Or check for correct bitness and search further?

Supposing that the environment variable would have paths with both 64 and 32 bit dlls, then if the architecture does not match, I think LoadLibrary will just report an error, which SoapySDR will just report to the logger. The loader does not stop on error, it tries to load everything that it finds.

Just some thoughts on how e.g. SoapySDRutil --info now behaves. Not so good with regard to $SOAPY_SDR_PLUGIN_PATH. For example, it doesn't report missing directories in that path.

Thats a good idea in general

guruofquality avatar Jul 02 '18 18:07 guruofquality

on the master branch I added the search path missing print and the ability to load paths that specify files

guruofquality avatar Jul 04 '18 16:07 guruofquality