SoapySDR
                                
                                 SoapySDR copied to clipboard
                                
                                    SoapySDR copied to clipboard
                            
                            
                            
                        SoapySDR::getRootPath() returns parent directory
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?
. 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.
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.
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
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.
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?
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:
- a cmake flag like -DENABLE_WINDOWS_LAYOUT=ON
- ifdef in LoadModules.cpp so getRootPath( ) looks in the current executable's directory
- 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.
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.
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
on the master branch I added the search path missing print and the ability to load paths that specify files