Attached is an ugly patch that would correct the problem I reported, at least
on Linux. Hopefully, someone better versed in CMake than I can come up with
something less hacky. Also, I don't know if my ugly patch would break other OS
builds. Thus, this patch is just to stimulate discussion - I don't propose
adopting it as is.
Basically, I just keep chopping numeric suffixes until I get down to the MAJOR
ABI version, which I leave intact. So, for typical Linux systems, the patch
removes the last two numbers from the file name, changing something like
libngspice.so.0.0.1 into libngspice.so.0
Btw, I tried using ABSOLUTE rather than REALPATH, but that is too aggressive.
It removed _all_ numbers from the file name, including the MAJOR ABI version.
Steve
On 8/23/21 2:36 PM, Steven A. Falco wrote:
Please look at eeschema/CMakeLists.txt around line 9. We have:
if( KICAD_SPICE )
set( INC_AFTER ${INC_AFTER} ${NGSPICE_INCLUDE_DIR} )
# Find out the exact libngspice file name
get_filename_component( NGSPICE_DLL_REALPATH "${NGSPICE_DLL}" REALPATH )
get_filename_component( NGSPICE_DLL_FILE "${NGSPICE_DLL_REALPATH}" NAME )
set_property( SOURCE sim/ngspice.cpp
APPEND PROPERTY COMPILE_DEFINITIONS
NGSPICE_DLL_FILE="${NGSPICE_DLL_FILE}"
)
endif()
Note that "REALPATH" is being used, which according to the CMake documentation resolves
symlinks. I.e.: "REALPATH = Full path to existing file with symlinks resolved"
So, it would seem that the root cause here is that CMake finds
/usr/lib64/libngspice.so and then resolves it by following the links and winds
up with a name like libngspice.so.0.0.0 or libngspice.so.0.0.1, which is too
specific for a hard-coded variable.
Why are we using REALPATH? Should that be changed to ABSOLUTE or something
else? I'm not a CMake expert btw, but it seems that REALPATH is not what we
want here.
Steve
On 8/23/21 1:42 PM, Steven A. Falco wrote:
Comments below.
On 8/23/21 11:45 AM, Reece R. Pollack wrote:
It doesn't matter what file name is used for the .so when linking an
application. The SONAME of the library is embedded in the library file itself,
and is extracted from the library when the application is linked.
Does the Fedora package that provides libngspice create the appropriate symlink
"libngspice.so.0" to the actual image file "libngspice.so.0.0.1"?
Here are the links on a failing machine. They look fine.
$ ls -l /lib64 | grep libngspice*
lrwxrwxrwx 1 root root 19 Aug 9 00:32 libngspice.so.0 ->
libngspice.so.0.0.1*
lrwxrwxrwx 1 root root 19 Aug 9 00:32 libngspice.so ->
libngspice.so.0.0.1*
-rwxr-xr-x 1 root root 10442176 Aug 9 00:51 libngspice.so.0.0.1*
What does ldd show on the failing systems (not your system)? The string to the right of the
"=>" is the name of the file that satisfies the requirement /on that system/ and is
determined by ldd at the time ldd is run. If this shows "not found", then there is a
libngspice configuration problem on that system.
ldd reports that /lib64/libngspice.so.0 will satisfy the dependency and is
present on the system. However, that is not how KiCAD actually loads the
library, as I'll discuss below.
$ ldd _eeschema.kiface | grep spice
libngspice.so.0 => /lib64/libngspice.so.0 (0x00007f075e3f7000)
My guess is that the symlinks are installed as part of the development package
for libngspice and not as part of the base package that provides the library
itself. This is a common packaging error.
The problem is that KiCAD manually tries to load the library, using a call to
m_dll.Load((), based on the NGSPICE_DLL_FILE variable, rather than using the
normal linking mechanism.
Please see NGSPICE::init_dll() around line 278 in eeschema/sim/ngspice.cpp.
Specifically, the #else clause at line 324 has m_dll.Load( NGSPICE_DLL_FILE
);. Unfortunately, at the time the build was made, the build system set
NGSPICE_DLL_FILE to libngspice.so.0.0.0, because that was the current version
at the time of the build. But that version is no longer present on the failing
system; now it has libngspice.so.0.0.1 instead.
The libngspice.so.0.0.0 version is therefore hard compiled into the program,
and no links can fix that.
Thus, for KiCAD to be able to manually load the library, we need to change the
way the NGSPICE_DLL_FILE variable is computed. It needs to be set to the more
generic libngspice.so.0 rather than libngspice.so.0.0.0 or libngspice.so.0.0.1,
because the latter are too specific, and won't necessarily survive a system
upgrade.
Steve
-Reece
On 8/23/21 11:06 AM, Steven A. Falco wrote:
I've done a bit of digging. According to ldd, the desired version is
appropriate, just specifying the first digit of the version info:
libngspice.so.0 => /lib64/libngspice.so.0 (0x00007f70913de000)
However, according to eeschema_kiface.dir/build.make we have
-DNGSPICE_DLL_FILE=\"libngspice.so.0.0.1\" as shown in this excerpt:
cd /builddir/build/BUILD/kicad-5.1.10/x86_64-redhat-linux-gnu/eeschema && /usr/bin/g++
$(CXX_DEFINES) -DNGSPICE_DLL_FILE=\"libngspice.so.0.0.1\" $(CXX_INCLUDES) $(CXX_FLAGS)
-MD -MT eeschema/CMakeFiles/eeschema_kiface.dir/sim/ngspice.cpp.o -MF
CMakeFiles/eeschema_kiface.dir/sim/ngspice.cpp.o.d -o
CMakeFiles/eeschema_kiface.dir/sim/ngspice.cpp.o -c
/builddir/build/BUILD/kicad-5.1.10/eeschema/sim/ngspice.cpp
Since eeschema/sim/ngspice.cpp explicitly uses the NGSPICE_DLL_FILE variable to
load the DLL, that is apparently why the more general ldd version is not used.
eeschema/sim/ngspice.cpp: m_dll.Load( NGSPICE_DLL_FILE );
So it seems the fix would be to truncate NGSPICE_DLL_FILE to remove the MAJOR.MINOR
component and just have -DNGSPICE_DLL_FILE=\"libngspice.so.0\"
Steve
On 8/23/21 10:29 AM, Steven A. Falco wrote:
I just got a bug report for the official Fedora version of KiCAD stating that
ngspice was not found. An attempt to perform a simulation results in KiCAD
crashing.
The Fedora KiCAD package specifies libngspice.so.0.0.0, but the library has now
bumped to libngspice.so.0.0.1. I would have expected that to be fine, because
the new library should be compatible. But apparently, the loader is looking
for an exact match, and refuses to use the newer library.
For now, I'm rebuilding the official package to match the new ngspice library,
but I'm wondering if there is a way to improve this situation, such that KiCAD
links with libngspice.0 rather than insisting on an exact match of the minor
number.
Steve
_______________________________________________
Mailing list: https://launchpad.net/~kicad-developers
Post to : kicad-developers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~kicad-developers
More help : https://help.launchpad.net/ListHelp
_______________________________________________
Mailing list: https://launchpad.net/~kicad-developers
Post to : kicad-developers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~kicad-developers
More help : https://help.launchpad.net/ListHelp
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index daf141f2ad..497d1a3e4c 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -10,6 +10,16 @@ if( KICAD_SPICE )
# Find out the exact libngspice file name
get_filename_component( NGSPICE_DLL_REALPATH "${NGSPICE_DLL}" REALPATH )
+ foreach(count_it RANGE 4)
+ # If the name has multiple number fields, we want to keep chopping
+ # until we get it down to just the one number field that represents
+ # an incompatible ABI release.
+ #
+ # On Linux, we typically need to do the replacement twice, but
+ # we'll put in 4 iterations. For example, we'd convert
+ # libngspice.so.0.0.1 to just libngspice.so.0
+ string( REGEX REPLACE "(.*\\.[0-9]+)\\.[0-9]+$" "\\1" NGSPICE_DLL_REALPATH "${NGSPICE_DLL_REALPATH}" )
+ endforeach(count_it)
get_filename_component( NGSPICE_DLL_FILE "${NGSPICE_DLL_REALPATH}" NAME )
set_property( SOURCE sim/ngspice.cpp
_______________________________________________
Mailing list: https://launchpad.net/~kicad-developers
Post to : kicad-developers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~kicad-developers
More help : https://help.launchpad.net/ListHelp