Cantera / cantera

Chemical kinetics, thermodynamics, and transport tool suite
https://cantera.org
Other
582 stars 342 forks source link

[SCons] SONAME 'libcantera_python' if 'versioned_shared_library' #1613

Closed band-a-prend closed 9 months ago

band-a-prend commented 10 months ago

Changes proposed in this pull request

Closes # none

If applicable, provide an example illustrating new features this pull request is introducing

Checklist

speth commented 10 months ago

This library is only ever loaded dynamically, i.e. using dlopen, from libcantera.so. It should never be linked to directly by ld. So I think most of the normal reasons to set the SONAME and generate that set of symlinks don't exist.

When I was configuring the Ubuntu packages to handle this, I found that the Debian recommendations are for plugin libraries like this to be installed outside of the normal library directories. Since the preferred location is rather system-dependent, I handled this by moving the file as part of the Debian build script and applying a patch to the Application::loadExtension method in application.cpp to specify this full, system-dependent path. You may want to consider a similar approach for Gentoo.

band-a-prend commented 10 months ago

@speth thank you for clarification!

It's then could be distributive specific where such libraries should be placed and distributive QA requirements.

band-a-prend commented 9 months ago

@speth Is there any simple CPP example of related libcantera-pyhton library feature for Cantera being system installed?

I currently test the default installation of /usr/lib64/libcantera_python3_11.so of Cantera into system without any path patching. It's to bee sure that after path patching I will get the same result.

I tried to check minimal example (built as g++ custom_yaml.cpp -lcantera -lgtest -lgmock) based on TEST(Reaction, PythonExtensibleRate) from Cantera-3.0.0 tarball test/kinetics/kineticsFromYaml.cpp:

#include "gtest/gtest.h"
#include "cantera/base/Units.h"
#include "cantera/base/Solution.h"
#include "cantera/base/Interface.h"
#include "cantera/kinetics/KineticsFactory.h"
#include "cantera/kinetics/GasKinetics.h"
#include "cantera/kinetics/Arrhenius.h"
#include "cantera/kinetics/ChebyshevRate.h"
#include "cantera/kinetics/Custom.h"
#include "cantera/kinetics/Falloff.h"
#include "cantera/kinetics/InterfaceRate.h"
#include "cantera/kinetics/PlogRate.h"
#include "cantera/kinetics/TwoTempPlasmaRate.h"
#include "cantera/thermo/SurfPhase.h"
#include "cantera/thermo/ThermoFactory.h"
#include "cantera/base/Array.h"

using namespace Cantera;

TEST(Reaction, PythonExtensibleRate)
{
    auto sol = newSolution("extensible-reactions.yaml");
    auto R = sol->kinetics()->reaction(0);
    EXPECT_EQ(R->type(), "square-rate");
    auto rate = R->rate();
    EXPECT_EQ(rate->type(), "square-rate");
    EXPECT_DOUBLE_EQ(rate->eval(300), 3.14 * 300 * 300);
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);

  return RUN_ALL_TESTS();
}

I placed user_ext.py (from tarball test/python) and extensible-reactions.yaml file to the same directory as built test binary a.out, made $ export PYTHONPATH=$PYTHONPATH:. and after running a.out got an error:

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from Reaction
[ RUN      ] Reaction.PythonExtensibleRate
unknown file: Failure
C++ exception with description "
*******************************************************************************
NotImplementedError thrown by ReactionDataDelegator:
Not implemented for delegated reaction rates
*******************************************************************************
" thrown in the test body.
[  FAILED  ] Reaction.PythonExtensibleRate (215 ms)
[----------] 1 test from Reaction (215 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (215 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] Reaction.PythonExtensibleRate

 1 FAILED TEST

What if missed for successfully running this test?

The common testing procedure under Cantera build directory is OK.

speth commented 9 months ago

Unfortunately I don't have a good standalone example yet that can be used after installing the library. For a post-install test in the conda-forge package, I use a modified version of the kinetics1.cpp example, which you can see in the feedstock repo: https://github.com/conda-forge/cantera-feedstock/blob/main/recipe/test-lib/extensible-rate.cpp, along with the extensible-reactions.yaml and user_ext.py files.

The test you have is simpler, though, and just needs a small change to work. Instead of:

EXPECT_DOUBLE_EQ(rate->eval(300), 3.14 * 300 * 300);

you can write:

vector<double> rateConstants(sol->kinetics()->nReactions());
sol->kinetics()->getFwdRateConstants(rateConstants.data());
EXPECT_DOUBLE_EQ(rateConstants[0], 3.14 * 300 * 300);
band-a-prend commented 9 months ago

@speth Great thanks for example and correction to work test standalone!

I close the PR as providing installation of libcantera_python3_XY.so elsewhere separate is distributive specific thing and for common case requires more accurate modification of build scripts too to make system installed library be working and to be visible while testing in build environment.

band-a-prend commented 8 months ago

@speth Finally I use the following solution to keep libcantera_python3_XY.so under /usr/lib64/cantera/ directory, to make it working in system (thanks for your examples again!) and to successfully run tests under isolated sandbox environment:

  1. I patch the src/SConscript with

    diff -Naur a/src/SConscript b/src/SConscript
    --- a/src/SConscript
    +++ b/src/SConscript
    @@ -89,7 +89,7 @@
     shim = pyenv.SharedObject("extensions/pythonShim.cpp")
     pylibname = f"../lib/cantera_python{pyenv['py_version_short'].replace('.', '_')}"
     lib = build(pyenv.SharedLibrary(pylibname, shim, SPAWN=get_spawn(pyenv)))
    -    install("$inst_shlibdir", lib)
    +    install("$inst_shlibdir/cantera", lib)
    
    # build the Cantera static library
  2. add to scons build parameters the additional strings -- use_rpath_linkage="yes" and extra_lib_dirs="/usr/lib64/cantera.

It's because I have no success to patch application.cpp with appropriate way to load plugin from cantera subfolder of system search paths and properly load it in test env at the same time.