Skip to content

Commit

Permalink
CMake: add a way of defining an external defered driver by setting on…
Browse files Browse the repository at this point in the history
…e or several ADD_EXTERNAL_DEFERRED_PLUGIN_XXX CMake variables that will cause the pointed file to be built in libgdal, and a DeclareDeferredXXX() C function in it to be called by GDALAllRegister()
  • Loading branch information
rouault committed Nov 7, 2023
1 parent 82de1f3 commit 7f9c686
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
21 changes: 21 additions & 0 deletions .github/workflows/alpine/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,32 @@

set -e

cat << EOF > /tmp/foo.cpp
#include <cstdio>
extern "C" void DeclareDeferredFOO(void);
void DeclareDeferredFOO()
{
FILE* f = fopen("/tmp/DeclareDeferredFOO_has_been_run.bin", "wb");
if (f)
fclose(f);
}
EOF

cmake ${GDAL_SOURCE_DIR:=..} \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=/usr \
-DIconv_INCLUDE_DIR=/usr/include/gnu-libiconv \
-DIconv_LIBRARY=/usr/lib/libiconv.so \
-DADD_EXTERNAL_DEFERRED_PLUGIN_FOO=/tmp/foo.cpp \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror -DWERROR_DEV_FLAG="-Werror=dev"
make -j$(nproc)

apps/gdalinfo

if test -f /tmp/DeclareDeferredFOO_has_been_run.bin; then
echo "DeclareDeferredFOO() has been run"
else
echo "DeclareDeferredFOO() has NOT been run"
exit 1
fi
15 changes: 15 additions & 0 deletions doc/source/development/building_from_source.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,21 @@ OGR_REGISTER_DRIVER_<driver_name>_FOR_LATER_PLUGIN can be declared at
libgdal build time without requiring the dependent libraries needed to build
the pluging later to be available.

Out-of-tree deferred loaded plugins
+++++++++++++++++++++++++++++++++++

Out-of-tree drivers can also benefit from the deferred loading capability, provided
libgdal is built with CMake variable(s) pointing to external code containing the
code for registering a proxy driver.

This can be done with the following option:

.. option:: ADD_EXTERNAL_DEFERRED_PLUGIN_<driver_name>:FILEPATH=/path/to/some/file.cpp

The pointed file must declare a ``void DeclareDeferred<driver_name>(void)``
method with C linkage that takes care of creating a GDALPluginDriverProxy
instance and calling :cpp:func:`GDALDriverManager::DeclareDeferredPluginDriver` on it.

.. _building-python-bindings:

Python bindings options
Expand Down
28 changes: 27 additions & 1 deletion frmts/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
# CMake4GDAL project is distributed under MIT license. See accompanying file LICENSE.txt.

add_library(gdal_frmts OBJECT gdalallregister.cpp)
set(FRMT_SOURCES gdalallregister.cpp)

get_cmake_property(_variableNames VARIABLES)
set(EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE "")
foreach (_variableName ${_variableNames})
unset(MATCHED)
string(REGEX MATCH "ADD_EXTERNAL_DEFERRED_PLUGIN_(.*)" MATCHED ${_variableName})
if (NOT MATCHED)
continue()
endif()
if (EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE STREQUAL "")
set(EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE "// File generated by frmts/CMakeLists.txt. DO NOT EDIT !\nextern void DeclareDeferredPlugins();\nvoid DeclareDeferredPlugins()\n{\n")
endif()
string(APPEND EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE " // Plugin ${CMAKE_MATCH_1}\n extern void DeclareDeferred${CMAKE_MATCH_1}();\n DeclareDeferred${CMAKE_MATCH_1}();\n")
list(APPEND FRMT_SOURCES "${${_variableName}}")
endforeach()
if (NOT EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE STREQUAL "")
string(APPEND EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE "}\n")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/external_deferred_plugins.c" "${EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE}")
list(APPEND FRMT_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/external_deferred_plugins.c")
endif()

add_library(gdal_frmts OBJECT ${FRMT_SOURCES})
if (NOT EXTERNAL_DEFERRED_PLUGINS_SOURCE_CODE STREQUAL "")
target_compile_definitions(gdal_frmts PRIVATE -DHAVE_EXTERNAL_DEFERRED_PLUGINS)
endif()

include(GdalDriverHelper)
include(CMakeDependentOption)

Expand Down
8 changes: 8 additions & 0 deletions frmts/gdalallregister.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
static char *szConfiguredFormats = "GDAL_FORMATS";
#endif

#if defined(HAVE_EXTERNAL_DEFERRED_PLUGINS)
extern "C" void DeclareDeferredPlugins(void);
#endif

/************************************************************************/
/* GDALRegisterPlugin() */
/* */
Expand Down Expand Up @@ -124,6 +128,10 @@ void CPL_STDCALL GDALAllRegister()
{
auto poDriverManager = GetGDALDriverManager();

#if defined(HAVE_EXTERNAL_DEFERRED_PLUGINS)
DeclareDeferredPlugins();
#endif

#if defined(DEFERRED_ARROW_DRIVER)
DeclareDeferredOGRArrowPlugin();
#endif
Expand Down

0 comments on commit 7f9c686

Please sign in to comment.