From 57a95782d648d5ac7ee0305cc14e8511f433c6ca Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 31 Jan 2023 14:52:11 -0500 Subject: [PATCH] Add function to distinguish shared vs static linking at runtime This is important because extensions can only be loaded correctly when Cantera is linked as a shared library. --- include/cantera/base/global.h | 5 +++++ src/SConscript | 10 +++++++--- src/base/application.cpp | 5 +++++ src/extensions/canteraShared.cpp | 18 ++++++++++++++++++ src/extensions/canteraStatic.cpp | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/extensions/canteraShared.cpp create mode 100644 src/extensions/canteraStatic.cpp diff --git a/include/cantera/base/global.h b/include/cantera/base/global.h index 4021d8513b..f27e82adf2 100644 --- a/include/cantera/base/global.h +++ b/include/cantera/base/global.h @@ -87,6 +87,11 @@ void loadExtension(const std::string& extType, const std::string& name); //! @since New in Cantera 3.0 void loadExtensions(const AnyMap& node); +//! Returns `true` if Cantera was loaded as a shared library in the current +//! application. Returns `false` if it was statically linked. +//! @since New in Cantera 3.0 +bool usingSharedLibrary(); + //! Delete and free all memory associated with the application /*! * Delete all global data. It should be called at the end of the diff --git a/src/SConscript b/src/SConscript index e9e82dc11c..63e70bd701 100644 --- a/src/SConscript +++ b/src/SConscript @@ -41,6 +41,7 @@ libs = [('base', ['cpp'], baseSetup), localenv = env.Clone() localenv.Prepend(CPPPATH=[Dir('#include'), Dir('#include/cantera/ext'), Dir('.')]) localenv.Append(CCFLAGS=env['warning_flags']) +indicatorEnv = localenv.Clone() # Get this before any of the PCH complications if env['CC'] == 'cl' and env['debug']: env['use_pch'] = False # PCH doesn't work with per-file PDB @@ -113,7 +114,8 @@ if env["python_package"] == "full": # build the Cantera static library -lib = build(localenv.StaticLibrary('../lib/cantera', libraryTargets, +staticIndicator = indicatorEnv.SharedObject('extensions/canteraStatic.cpp') +lib = build(localenv.StaticLibrary('../lib/cantera', libraryTargets + staticIndicator, SPAWN=get_spawn(localenv))) localenv.Depends(lib, localenv['config_h_target']) install('$inst_libdir', lib) @@ -154,6 +156,8 @@ if localenv['layout'] != 'debian': else: sharedName = '../lib/cantera' + sharedIndicator = indicatorEnv.SharedObject('extensions/canteraShared.cpp') + if env['CC'] == 'cl': # For MSVC, use the static library to create a .def file listing all # symbols to export in the shared library. @@ -164,12 +168,12 @@ if localenv['layout'] != 'debian': '/IGNORE:4102']) if localenv['versioned_shared_library']: - lib = build(localenv.SharedLibrary(sharedName, libraryTargets, + lib = build(localenv.SharedLibrary(sharedName, libraryTargets + sharedIndicator, SPAWN=get_spawn(localenv), SHLIBVERSION=localenv['cantera_pure_version'])) install(localenv.InstallVersionedLib, '$inst_libdir', lib) else: - lib = build(localenv.SharedLibrary(sharedName, libraryTargets, + lib = build(localenv.SharedLibrary(sharedName, libraryTargets + sharedIndicator, SPAWN=get_spawn(localenv))) install('$inst_libdir', lib) diff --git a/src/base/application.cpp b/src/base/application.cpp index 387cf21fcd..d011c1a3e5 100644 --- a/src/base/application.cpp +++ b/src/base/application.cpp @@ -402,6 +402,11 @@ std::string Application::findInputFile(const std::string& name) void Application::loadExtension(const string& extType, const string& name) { + if (!usingSharedLibrary()) { + throw CanteraError("Application::loadExtension", + "Loading extensions requires linking to the Cantera shared library\n" + "rather than the static library"); + } if (m_loaded_extensions.count({extType, name})) { return; } diff --git a/src/extensions/canteraShared.cpp b/src/extensions/canteraShared.cpp new file mode 100644 index 0000000000..daf921a32b --- /dev/null +++ b/src/extensions/canteraShared.cpp @@ -0,0 +1,18 @@ +//! @file canteraShared.cpp + +// This file is part of Cantera. See License.txt in the top-level directory or +// at https://cantera.org/license.txt for license and copyright information. + +#include "cantera/base/ct_defs.h" + +namespace Cantera +{ + +bool usingSharedLibrary() +{ + // This implementation of usingSharedLibrary is compiled and embedded + // only in the Cantera shared library + return true; +} + +} diff --git a/src/extensions/canteraStatic.cpp b/src/extensions/canteraStatic.cpp new file mode 100644 index 0000000000..0818ee5759 --- /dev/null +++ b/src/extensions/canteraStatic.cpp @@ -0,0 +1,18 @@ +//! @file canteraStatic.cpp + +// This file is part of Cantera. See License.txt in the top-level directory or +// at https://cantera.org/license.txt for license and copyright information. + +#include "cantera/base/ct_defs.h" + +namespace Cantera +{ + +bool usingSharedLibrary() +{ + // This implementation of usingSharedLibrary is compiled and embedded + // only in the Cantera static library + return false; +} + +}