Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@phetdam
Copy link
Contributor

@phetdam phetdam commented Jun 9, 2025

Summary

Clean re-application of changes in #1192 after the 4.1 release.

See #1192 for the summary details with the following exceptions:

  • soci_backend has been replaced with soci_define_backend_target
  • callbacks.h now has failover_callback fully inline so no SOCI_DECL is necessary anymore
  • soci_tests_common_static doesn't exist anymore since SOCI builds shared/static separately using CMake

#1192 (comment) is still applicable here. One extra change is done to ensure that the CMake configuration step fails if the SOCI source tree was checked out without --recurse-submodules when an external SQLite3 installation is not available.

Also, since SOCI_<backend>_SOURCE is defined using DEFINE_SYMBOL, it is not available when building static libraries. This means changes to soci-sqlite3.h and the SQLite3 backend sources to have the sqlite3.h header included in the sqlite3_api namespace, and only included in the C++ source files, leaving only forward declarations in soci-sqlite3.h.

phetdam added 12 commits June 8, 2025 22:47
… found at all (usually means --recurse-submodules wasn't used)
…r dynamic build

modified:   include/soci/soci-platform.h
    Ensure SOCI_DLL controls all visibility + update comments

modified:   src/core/CMakeLists.txt
    Use DEFINE_SYMBOL to handle SOCI_SOURCE definition

modified:   src/core/backend-loader.cpp
modified:   src/core/blob.cpp
modified:   src/core/common.cpp
modified:   src/core/connection-parameters.cpp
modified:   src/core/connection-pool.cpp
modified:   src/core/error.cpp
modified:   src/core/into-type.cpp
modified:   src/core/logger.cpp
modified:   src/core/once-temp-type.cpp
modified:   src/core/prepare-temp-type.cpp
modified:   src/core/procedure.cpp
modified:   src/core/ref-counted-prepare-info.cpp
modified:   src/core/ref-counted-statement.cpp
modified:   src/core/row.cpp
modified:   src/core/rowid.cpp
modified:   src/core/session.cpp
modified:   src/core/soci-simple.cpp
modified:   src/core/statement.cpp
modified:   src/core/transaction.cpp
modified:   src/core/unicode.cpp
modified:   src/core/use-type.cpp
modified:   src/core/values.cpp
    Remove SOCI_SOURCE definition
modified:   src/backends/db2/blob.cpp
modified:   src/backends/db2/factory.cpp
modified:   src/backends/db2/row-id.cpp
modified:   src/backends/db2/session.cpp
modified:   src/backends/db2/standard-into-type.cpp
modified:   src/backends/db2/standard-use-type.cpp
modified:   src/backends/db2/statement.cpp
modified:   src/backends/db2/vector-into-type.cpp
modified:   src/backends/db2/vector-use-type.cpp
modified:   src/backends/empty/blob.cpp
modified:   src/backends/empty/factory.cpp
modified:   src/backends/empty/row-id.cpp
modified:   src/backends/empty/session.cpp
modified:   src/backends/empty/standard-into-type.cpp
modified:   src/backends/empty/standard-use-type.cpp
modified:   src/backends/empty/statement.cpp
modified:   src/backends/empty/vector-into-type.cpp
modified:   src/backends/empty/vector-use-type.cpp
modified:   src/backends/firebird/blob.cpp
modified:   src/backends/firebird/common.cpp
modified:   src/backends/firebird/error-firebird.cpp
modified:   src/backends/firebird/factory.cpp
modified:   src/backends/firebird/session.cpp
modified:   src/backends/firebird/standard-into-type.cpp
modified:   src/backends/firebird/standard-use-type.cpp
modified:   src/backends/firebird/statement.cpp
modified:   src/backends/firebird/vector-into-type.cpp
modified:   src/backends/firebird/vector-use-type.cpp
modified:   src/backends/mysql/blob.cpp
modified:   src/backends/mysql/common.cpp
modified:   src/backends/mysql/error.cpp
modified:   src/backends/mysql/factory.cpp
modified:   src/backends/mysql/row-id.cpp
modified:   src/backends/mysql/session.cpp
modified:   src/backends/mysql/standard-into-type.cpp
modified:   src/backends/mysql/standard-use-type.cpp
modified:   src/backends/mysql/statement.cpp
modified:   src/backends/mysql/vector-into-type.cpp
modified:   src/backends/mysql/vector-use-type.cpp
modified:   src/backends/odbc/blob.cpp
modified:   src/backends/odbc/error.cpp
modified:   src/backends/odbc/factory.cpp
modified:   src/backends/odbc/row-id.cpp
modified:   src/backends/odbc/session.cpp
modified:   src/backends/odbc/standard-into-type.cpp
modified:   src/backends/odbc/standard-use-type.cpp
modified:   src/backends/odbc/statement.cpp
modified:   src/backends/odbc/vector-into-type.cpp
modified:   src/backends/odbc/vector-use-type.cpp
modified:   src/backends/oracle/blob.cpp
modified:   src/backends/oracle/error.cpp
modified:   src/backends/oracle/factory.cpp
modified:   src/backends/oracle/row-id.cpp
modified:   src/backends/oracle/session.cpp
modified:   src/backends/oracle/standard-into-type.cpp
modified:   src/backends/oracle/standard-use-type.cpp
modified:   src/backends/oracle/statement.cpp
modified:   src/backends/oracle/vector-into-type.cpp
modified:   src/backends/oracle/vector-use-type.cpp
modified:   src/backends/postgresql/blob.cpp
modified:   src/backends/postgresql/error.cpp
modified:   src/backends/postgresql/factory.cpp
modified:   src/backends/postgresql/row-id.cpp
modified:   src/backends/postgresql/session.cpp
modified:   src/backends/postgresql/standard-into-type.cpp
modified:   src/backends/postgresql/standard-use-type.cpp
modified:   src/backends/postgresql/statement.cpp
modified:   src/backends/postgresql/vector-into-type.cpp
modified:   src/backends/postgresql/vector-use-type.cpp
modified:   src/backends/sqlite3/blob.cpp
modified:   src/backends/sqlite3/error.cpp
modified:   src/backends/sqlite3/factory.cpp
modified:   src/backends/sqlite3/row-id.cpp
modified:   src/backends/sqlite3/session.cpp
modified:   src/backends/sqlite3/standard-into-type.cpp
modified:   src/backends/sqlite3/standard-use-type.cpp
modified:   src/backends/sqlite3/statement.cpp
modified:   src/backends/sqlite3/vector-into-type.cpp
modified:   src/backends/sqlite3/vector-use-type.cpp
@phetdam
Copy link
Contributor Author

phetdam commented Jun 9, 2025

Ah, the failing CI stuff for SQLite3 seems like an IWYU error. I'll ensure <sqlite3.h> is included in the affected files.

@phetdam
Copy link
Contributor Author

phetdam commented Jun 9, 2025

Ah, the failing CI stuff for SQLite3 seems like an IWYU error. I'll ensure <sqlite3.h> is included in the affected files.

In relation to this is #include <sqlite3.h> no longer being done inside the sqlite_api namespace in include/soci/sqlite3/soci-sqlite3.h. I'm not entirely sure why having extern "C" decls in a namespace was the right move in 2006, given that these names can still be referred to unqualified (due to C linkage).

Either way, that means the sqlite3.h includes need to be as follows:

namespace sqlite_api
{

#include <sqlite3.h>

} // namespace sqlite_api

phetdam added 2 commits June 9, 2025 01:11
…nclude

modified:   src/backends/sqlite3/error.cpp
modified:   src/backends/sqlite3/session.cpp
modified:   src/backends/sqlite3/standard-into-type.cpp
modified:   src/backends/sqlite3/standard-use-type.cpp
modified:   src/backends/sqlite3/statement.cpp
modified:   src/backends/sqlite3/vector-use-type.cpp
Copy link
Member

@vadz vadz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, while I don't have any real objections to this PR, I just don't understand what do we gain by applying it. AFAICS the only real change is that SOCI_DLL is now defined under Unix too — which is, on one hand, weird (DLL is just not a Unix term) and, OTOH, could be done on its own without affecting anything else.

The PR summary speaks of consistent export, but what is inconsistent about it now? I.e. what problem does this fix?

FWIW this will create extra work for me, personally, as I don't use SOCI CMake build system in my own project, so I'll have to update it to define SOCI_XXX_SOURCE too and while this probably won't be very difficult, I don't see what justifies spending extra time on this when we could just... not apply this PR?

#else // !SOCI_SQLITE3_SOURCE
// We need just a couple of forward declarations to make this header itself
// compile.
// We don't include sqlite3.h from outside SOCI since this header may not
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we keep this unchanged by just checking for SOCI_SOURCE instead of SOCI_SQLITE3_SOURCE? It looks like this would reduce the number of changes without any real drawbacks.

Copy link
Contributor Author

@phetdam phetdam Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each separate backend/library does need its own unique build-time macro to be defined to properly control symbol import/export (visibility, rather). So each possible DSO needs a separate macro name, as if for N libraries the same macro was used, where some of the libraries might rely on others' headers, you will get a lot of compile errors because the dependent libraries' symbols are being marked for export instead of import.

As mentioned below I can revert the #include-related changes for the sqlite3 backend sources by unconditionally defining SOCI_<backend>_SOURCE during the backend compilation, even if the backends are built as static libraries.

@phetdam
Copy link
Contributor Author

phetdam commented Jun 10, 2025

what is inconsistent about it now? I.e. what problem does this fix?

To me the inconsistency is when symbol visibility is applied. On Windows, SOCI_DLL is defined to achieve this, but it makes sense to me that when using the library as shared in general (where symbol visibility matter), SOCI_DLL being defined should be part of the usage requirements. This is also shown in the TnFOX example in the GCC visibility wiki.

FWIW this will create extra work for me

Sorry, was not aware of this :( But let me try my best to make some points.

what justifies spending extra time on this

It's pretty repetitive to have to manually #define a special symbol when building SOCI core or one of the backends. Although DEFINE_SYMBOL is CMake-specific, it mirrors a common practice in libraries that can be built static or shared in that for one of these flavors (typically shared, which is why I assume DEFINE_SYMBOL applies only the shared libraries), some macro is defined during compilation that adjusts the project-specific visibility macro being used to drive symbol export. curl has an example, albeit in reverse as generally it is used via the shared library instead of statically being linked.

I've gone back and thought about some things, and given how the SOCI_SOURCE and SOCI_<backend>_SOURCE macros have been originally used, I'll just consistently define these across static/shared builds. It will also rectify the situation going on with the soci-sqlite3.h header, and I can revert the #include-related commits I've made there.

Let me also address some of the code-related comments too.

@phetdam
Copy link
Contributor Author

phetdam commented Jun 10, 2025

Ugh... did not remove the SOCI_HAVE_VISIBILITY_SUPPORT check.

@vadz
Copy link
Member

vadz commented Jun 10, 2025

what is inconsistent about it now? I.e. what problem does this fix?

To me the inconsistency is when symbol visibility is applied. On Windows, SOCI_DLL is defined to achieve this, but it makes sense to me that when using the library as shared in general (where symbol visibility matter), SOCI_DLL being defined should be part of the usage requirements.

So let's just define SOCI_DLL when shared libraries are used and leave the rest alone?

It's pretty repetitive to have to manually #define a special symbol when building SOCI core or one of the backends.

But this is already done and new source files (let alone new backends) are not added very often. So as it is, this just creates extra code churn without any apparent gain.

@Krzmbrzl
Copy link
Contributor

To be fair, when adding new source files it can take quite some time to figure out that one has forgotten to define SOCI_SOURCE, especially given that this issue will only surface on Windows. So I do think that this counts as a streamlining of the buildsystem/build process and as such is valuable to have (as it decreases maintenance cost and/or reduces the barrier of entry for new developers).

@vadz
Copy link
Member

vadz commented Jun 11, 2025

BTW, compiling under Windows right now defines symbols like soci_postgresql_EXPORTS that comes from CMake itself (see DEFINE_SYMBOL). So maybe we don't need to define any symbols of our own. Although this one is defined for shared libraries only (but under all platforms).

@phetdam
Copy link
Contributor Author

phetdam commented Jun 12, 2025

streamlining of the buildsystem/build process

Yep, this was the overall intention. In general my opinion is that stuff like macros defined during compilation should be handled by the build system so one can focus on writing the code itself, especially the case of import/export visibility macros, as a separate SOCI_<backend>_SOURCE is needed for each backend beyond just SOCI_SOURCE for the core library.

@phetdam
Copy link
Contributor Author

phetdam commented Jun 12, 2025

BTW, compiling under Windows right now defines symbols like soci_postgresql_EXPORTS

Yes, so originally I was relying on DEFINE_SYMBOL, but I realized this leads to an issue with the sqlite3 backend that I mentioned in a previous comment. Because SOCI_SQLITE3_SOURCE controlled the namespaced inclusion of sqlite3.h, using DEFINE_SYMBOL to define it only during shared builds meant that I had to remove the conditional include from soci-sqlite3.h and then correctly do the namespaced include of sqlite3.h myself in several of the sqlite3 backend sources, i.e.

namespace sqlite_api
{

#include <sqlite3.h>

} // namespace sqlite_api

I think one decision that needs to be made is whether SOCI_SOURCE and SOCI_<backend>_SOURCE should be considered as a macro defined during compilation in general or only used for shared libraries to handle symbol visibility.

@vadz vadz added the CMake label Jun 13, 2025
@vadz
Copy link
Member

vadz commented Jun 13, 2025

Sorry for complaining so much, but these CMake-related changes seem to be taking inordinate amount of the time which could (should?) be better spent on something more productive. It looks like 80% of the time I spend on SOCI is spent on struggling with CMake :-( And the Great CMake Rewrite didn't really improve this (I actually suspect the contrary, but maybe it's just because I'm particularly fed up with it right now).

I'll probably end up applying this because I don't want your work to go to waste, but I'd like to return to this a bit later, once I am capable of thinking about CMake-related issues without so much loathing again.

@phetdam
Copy link
Contributor Author

phetdam commented Jun 16, 2025

Sorry for complaining so much, but these CMake-related changes seem to be taking inordinate amount of the time

Haha, don't worry about it. CMake definitely helps with the messy reality of building C/C++ projects, but as much as I appreciate its usefulness, I also have moments where I wonder why some CMake things take so much work.

I'll probably end up applying this because I don't want your work to go to waste, but I'd like to return to this a bit later, once I am capable of thinking about CMake-related issues without so much loathing again.

No problem; I'll periodically keep the branch up-to-date with HEAD but won't be adding to it.

Copy link
Member

@vadz vadz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've looked at this again and this seems to be incomplete: if we remove, say, SOCI_FIREBIRD_SOURCE, we should remove the test for it in include/soci/firebird/soci-firebird.h and use SOCI_DECL instead of SOCI_FIREBIRD_DECL in this header etc (i.e. the same thing for all the other backends), shouldn't we?

Am I missing something here?

vadz pushed a commit that referenced this pull request Aug 1, 2025
Use FATAL_ERROR if SQLite3 is not found at all (usually means
--recurse-submodules wasn't used).

See #1273.
@phetdam
Copy link
Contributor Author

phetdam commented Aug 5, 2025

Hey, thanks for reviewing. I'm a bit busy right now due to some work-related things but I'll get back to this when I can.

@phetdam
Copy link
Contributor Author

phetdam commented Aug 9, 2025

I've looked at this again and this seems to be incomplete: if we remove, say, SOCI_FIREBIRD_SOURCE, we should remove the test for it in include/soci/firebird/soci-firebird.h and use SOCI_DECL instead of SOCI_FIREBIRD_DECL in this header etc (i.e. the same thing for all the other backends), shouldn't we?

Do you mean this part of the header?

#ifdef SOCI_FIREBIRD_SOURCE
# define SOCI_FIREBIRD_DECL SOCI_DECL_EXPORT
#else
# define SOCI_FIREBIRD_DECL SOCI_DECL_IMPORT
#endif

If so, no; this should remain as-is. It's because when building as shared, each of the backends is built as a separate shared library. If, for example, they all used SOCI_DECL, which only marks symbols for export when SOCI_SOURCE is defined, and they all relied on SOCI_SOURCE being defined during compilation, then MSVC would incorrectly mark all SOCI_DECL symbols as being exported from all the backends too. The general rule is for each DLL being built, you need a unique import/export macro, which is controlled by a unique build-time macro when indicating symbols are being exported.

So in SOCI's case:

  1. Each backend must have its own SOCI_<backend>_DECL visibility macro for symbol import/export
  2. SOCI_<backend>_DECL must resolve on Windows to __declspec(dllexport) when SOCI_<backend>_SOURCE is defined
  3. SOCI_<backend>_SOURCE is defined only during compilation for the given

This ensures that in the case of shared libraries being built, that for each backend, the corresponding SOCI_<backend>_DECL resolves to __declspec(dllimport) during compilation of any source not part of the backend library, while resolving to __declspec(dllexport) during compilation of any source that is part of the backend library.

Admittedly, the DLL design is a bit confusing at times. Although the idea of symbol visibility is good, the other option if not using the MSVC __declspec extension is to use a .def file, which is rather tedious to use.

@vadz
Copy link
Member

vadz commented Aug 13, 2025

Do you mean this part of the header?

Sorry, rather embarrassingly, I have to admit that I don't know what I meant any more :-( Maybe I wanted to use a single SOCI_BACKEND_DECL (with "BACKEND" being a literal string and not a placeholder) for all backends, but I'm not really sure and, anyhow, thinking about it again I don't see how is it really better than the current SOCI_${BACKEND}_DECL.

So this is probably fine as is, although I'm still not sure if this results in any real changes in behaviour: I see that we won't be using __attribute__ (( visibility("default") )) any more in static builds, but as these builds don't use hidden visibility by default anyhow, this probably doesn't change anything.

I'll try to update my own project build system to predefine SOCI_${BACKEND}_SOURCE and will merge this then.

@phetdam
Copy link
Contributor Author

phetdam commented Aug 14, 2025

I don't see how is it really better than the current SOCI_${BACKEND}_DECL.

Yeah, unfortunately every backend library needs its own SOCI_<BACKEND>_DECL.

I see that we won't be using __attribute__ (( visibility("default") )) any more in static builds

This shouldn't be an issue unless someone is trying to build a DSO using SOCI object files and for whatever reason relies on some SOCI symbols being visible by default when compiling with -fvisibility=hidden. But in that case, they would still need to build SOCI objects with -fPIC, and I don't think this is an expected or supported consumption pattern in most cases.

I'll try to update my own project build system to predefine SOCI_${BACKEND}_SOURCE and will merge this then.

Thanks for your patience!

@vadz vadz closed this in 018e532 Aug 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants