# Distributed under the GDAL/OGR MIT style License. See accompanying # file LICENSE.TXT. #[=======================================================================[.rst: GdalDriverHelper ----------------- target_name should be as same as plugin name. name gdal_* as recognized as raster driver and name ogr_* as vector one. and lookup register function from filename. Symptoms add_gdal_driver( TARGET [SOURCES [[...]]] BUILTIN | PLUGIN_CAPABLE | [PLUGIN_CAPABLE_IF ] [NO_DEPS] ) gdal_standard_includes() gdal_target_link_libraries( PRIVATE [ [..]]) Drivers should specify one and only one of: - BUILTIN: the driver is built-in into library, and cannot be built as a plugin - PLUGIN_CAPABLE: the driver can be built as a plugin. This only happens if the GDAL_ENABLE_DRIVER_{foo}_PLUGIN or OGR_ENABLE_DRIVER_{foo}_PLUGIN variable is set to ON. The default value of that variable is : - the value of GDAL_ENABLE_PLUGINS option when NO_DEPS is not specified (e.g ECW, HDF4, etc.) - the value of GDAL_ENABLE_PLUGINS_NO_DEPS option when NO_DEPS is specified - PLUGIN_CAPABLE_IF: similar to PLUGIN_CAPABLE, but extra conditions provided in (e.g "NOT GDAL_USE_JSONC_INTERNAL") are needed The NO_DEPS option express that the driver has no non-core external dependencies. There are several examples to show how to write build cmake script. ex.1 Driver which is referenced by other drivers Such driver should built-in into library to resolve reference. add_gdal_driver(TARGET gdal_iso8211 SOURCES iso8211.cpp BUILTIN) ex.2 Driver that refer other driver as dependency Please do not specify LIBRARIES for linking target for other driver, That should be built into libgdal. add_gdal_driver(TARGET gdal_ADRG SOURCES foo.cpp BUILTIN) target_include_directories(gdal_ADRG PRIVATE $) ex.3 Driver which is depend on some external libraries These definitions are detected in cmake/macro/CheckDependentLibraries.cmake If you cannot find your favorite library in the macro, please add it to CheckDependentLibraries.cmake. add_gdal_driver(TARGET gdal_WEBP SOURCES gdal_webp.c gdal_webp.h PLUGIN_CAPABLE) gdal_standard_includes(gdal_WEBP) gdal_target_link_libraries(gdal_WEBP PRIVATE WEBP::WebP) ex.4 Driver which is depend on internal bundled thirdparty libraries To refer thirdparty library dev files, pls use '$' cmake directive. You may use 'IF(GDAL_USE_SOME_LIBRARY_INTERNAL)...ELSE()...ENDIF()' cmake directive too. add_gdal_driver(TARGET gdal_CALS SOURCES calsdataset.cpp BUILTIN) gdal_standard_includes(gdal_CALS) gdal_include_directories(gdal_CALS PRIVATE $) #]=======================================================================] function(add_gdal_driver) set(_options BUILTIN PLUGIN_CAPABLE NO_DEPS STRONG_CXX_WFLAGS CXX_WFLAGS_EFFCXX NO_CXX_WFLAGS) set(_oneValueArgs TARGET DESCRIPTION DEF PLUGIN_CAPABLE_IF DRIVER_NAME_OPTION) set(_multiValueArgs SOURCES) cmake_parse_arguments(_DRIVER "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) # Check mandatory arguments if (NOT _DRIVER_TARGET) message(FATAL_ERROR "ADD_GDAL_DRIVER(): TARGET is a mandatory argument.") endif () if (NOT _DRIVER_SOURCES) message(FATAL_ERROR "ADD_GDAL_DRIVER(): SOURCES is a mandatory argument.") endif () # Set *_FORMATS properties for summary and gdal_config utility string(FIND "${_DRIVER_TARGET}" "ogr" IS_OGR) if (IS_OGR EQUAL -1) # raster string(REPLACE "gdal_" "" _FORMAT ${_DRIVER_TARGET}) set_property(GLOBAL APPEND PROPERTY GDAL_FORMATS ${_FORMAT}) else () # vector string(REPLACE "ogr_" "" _FORMAT ${_DRIVER_TARGET}) set_property(GLOBAL APPEND PROPERTY OGR_FORMATS ${_FORMAT}) endif () string(TOUPPER ${_FORMAT} _KEY) if ((NOT _DRIVER_PLUGIN_CAPABLE) AND (NOT _DRIVER_BUILTIN) AND (NOT _DRIVER_PLUGIN_CAPABLE_IF)) message(FATAL_ERROR "Driver ${_DRIVER_TARGET} should declare BUILTIN, PLUGIN_CAPABLE or PLUGIN_CAPABLE_IF") endif() # Determine whether plugin or built-in set(_DRIVER_PLUGIN_BUILD OFF) set(_COND) if (_DRIVER_PLUGIN_CAPABLE_IF) set(_COND ${_DRIVER_PLUGIN_CAPABLE_IF}) endif() get_target_property(PLUGIN_OUTPUT_DIR ${GDAL_LIB_TARGET_NAME} PLUGIN_OUTPUT_DIR) if (_DRIVER_PLUGIN_CAPABLE OR _DRIVER_PLUGIN_CAPABLE_IF) set(_INITIAL_VALUE OFF) if( GDAL_ENABLE_PLUGINS AND NOT _DRIVER_NO_DEPS ) set(_INITIAL_VALUE ON) elseif( GDAL_ENABLE_PLUGINS_NO_DEPS AND _DRIVER_NO_DEPS ) set(_INITIAL_VALUE ON) endif() if( _DRIVER_DRIVER_NAME_OPTION ) string(TOUPPER ${_DRIVER_DRIVER_NAME_OPTION} _KEY) endif() if( IS_OGR EQUAL -1) # raster set(_plugin_var_prefix GDAL) else() set(_plugin_var_prefix OGR) endif() set(_enable_plugin_var ${_plugin_var_prefix}_ENABLE_DRIVER_${_KEY}) if( NOT DEFINED ${_enable_plugin_var} ) message(FATAL_ERROR "Option ${_enable_plugin_var} does not exist") endif() cmake_dependent_option(${_enable_plugin_var}_PLUGIN "Set ON to build ${_plugin_var_prefix} ${_KEY} driver as plugin" ${_INITIAL_VALUE} "${_enable_plugin_var};${_COND}" OFF) if( ${_enable_plugin_var}_PLUGIN ) set(_DRIVER_PLUGIN_BUILD ON) endif() # If the GDAL/OGR_ENABLE_DRIVER_xxx_PLUGIN value has changed from its previous # value, and is now to OFF, make sure to clean stale plugins. if( ${_enable_plugin_var}_PLUGIN_OLD_VAL AND NOT ${_enable_plugin_var}_PLUGIN ) foreach (_build_type IN ITEMS "" "Release/" "Debug/") set(_plugin_filename "${PLUGIN_OUTPUT_DIR}/${_build_type}${_DRIVER_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}") if( EXISTS "${_plugin_filename}" ) message(STATUS "**Removing stale plugin**: ${_plugin_filename}") file(REMOVE "${_plugin_filename}") endif() endforeach() endif() # Save new value of GDAL/OGR_ENABLE_DRIVER_xxx_PLUGIN set(${_enable_plugin_var}_PLUGIN_OLD_VAL ${${_enable_plugin_var}_PLUGIN} CACHE INTERNAL "Old value of option ${_enable_plugin_var}_PLUGIN") # If a driver is built in core libgdal, at install time, remove # potentiall corresponding stale installed plugin. if(NOT _DRIVER_PLUGIN_BUILD) install(CODE " set(_tmp \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${INSTALL_PLUGIN_DIR}/${_DRIVER_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}\") if( EXISTS \"\${_tmp}\") message(STATUS \"**Removing stale plugin**: \${_tmp}\") file(REMOVE \"\${_tmp}\") endif() ") endif() endif() # target configuration if (_DRIVER_PLUGIN_BUILD) # target become *.so *.dll or *.dylib add_library(${_DRIVER_TARGET} MODULE ${_DRIVER_SOURCES}) set_target_properties(${_DRIVER_TARGET} PROPERTIES PREFIX "" LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_DIR} SKIP_BUILD_RPATH YES ) # The following doesn't work: we have to manually tweak will install_name_tool #if (GDAL_ENABLE_MACOSX_FRAMEWORK) # set_target_properties(${_DRIVER_TARGET} # PROPERTIES # INSTALL_RPATH "@loader_path/../../../..") #endif() target_link_libraries(${_DRIVER_TARGET} PRIVATE $) install(FILES $ DESTINATION ${INSTALL_PLUGIN_DIR} RENAME "${_DRIVER_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}" NAMELINK_SKIP) if (GDAL_ENABLE_MACOSX_FRAMEWORK) file(RELATIVE_PATH relDir ${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_PLUGIN_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${FRAMEWORK_DESTINATION}) install(CODE "execute_process(COMMAND install_name_tool -add_rpath \"@loader_path/${relDir}\" \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${INSTALL_PLUGIN_DIR}/${_DRIVER_TARGET}${CMAKE_SHARED_LIBRARY_SUFFIX}\")") endif() set_property(GLOBAL APPEND PROPERTY PLUGIN_MODULES ${_DRIVER_TARGET}) else () add_library(${_DRIVER_TARGET} OBJECT ${_DRIVER_SOURCES}) set_property(TARGET ${_DRIVER_TARGET} PROPERTY POSITION_INDEPENDENT_CODE ON) target_sources(${GDAL_LIB_TARGET_NAME} PRIVATE $) if (_DRIVER_DEF) if (IS_OGR EQUAL -1) # raster target_compile_definitions(gdal_frmts PRIVATE -D${_DRIVER_DEF}) else () target_compile_definitions(ogrsf_frmts PRIVATE -D${_DRIVER_DEF}) endif () else () if (IS_OGR EQUAL -1) # raster string(TOLOWER ${_DRIVER_TARGET} _FORMAT) string(REPLACE "gdal" "FRMT" _DEF ${_FORMAT}) target_compile_definitions(gdal_frmts PRIVATE -D${_DEF}) else () # vector string(REPLACE "ogr_" "" _FORMAT ${_DRIVER_TARGET}) target_compile_definitions(ogrsf_frmts PRIVATE -D${_KEY}_ENABLED) endif () endif () endif () if (_DRIVER_CXX_WFLAGS_EFFCXX) target_compile_options(${_DRIVER_TARGET} PRIVATE $<$:${GDAL_CXX_WARNING_FLAGS} ${WFLAG_EFFCXX}>) elseif (_DRIVER_STRONG_CXX_WFLAGS) target_compile_options(${_DRIVER_TARGET} PRIVATE $<$:${GDAL_CXX_WARNING_FLAGS} ${WFLAG_OLD_STYLE_CAST} ${WFLAG_EFFCXX}>) elseif( NOT _DRIVER_NO_CXX_WFLAGS ) target_compile_options(${_DRIVER_TARGET} PRIVATE $<$:${GDAL_CXX_WARNING_FLAGS}>) endif() target_compile_options(${_DRIVER_TARGET} PRIVATE $<$:${GDAL_C_WARNING_FLAGS}>) add_dependencies(${_DRIVER_TARGET} generate_gdal_version_h) endfunction() # Detect whether driver is built as PLUGIN or not. function(is_plugin _result _target) get_property(_PLUGIN_MODULES GLOBAL PROPERTY PLUGIN_MODULES) list(FIND _PLUGIN_MODULES ${_target} _IS_DRIVER_PLUGIN) if (_IS_DRIVER_PLUGIN EQUAL -1) set(${_result} FALSE PARENT_SCOPE) else () set(${_result} TRUE PARENT_SCOPE) endif () endfunction() function(gdal_target_interfaces _TARGET) foreach (_LIB IN ITEMS ${ARGN}) if (TARGET ${_LIB}) get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_INCLUDE_DIRECTORIES) if (_res) target_include_directories(${_TARGET} PRIVATE ${_res}) endif () get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_COMPILE_DEFINITIONS) if (_res) target_compile_definitions(${_TARGET} PRIVATE ${_res}) endif () get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_COMPILE_OPTIONS) if (_res) target_compile_options(${_TARGET} PRIVATE ${_res}) endif () get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_LINK_LIBRARIES) if (_res) gdal_target_interfaces(${_TARGET} ${_res}) endif () endif () endforeach () endfunction() # To use a vendorized/internal library function(gdal_add_vendored_lib _TARGET) foreach (_LIB IN ITEMS ${ARGN}) if (TARGET ${_LIB}) get_property(_res TARGET ${_LIB} PROPERTY SOURCE_DIR) if (_res) target_include_directories(${_TARGET} PRIVATE ${_res}) endif () get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_COMPILE_DEFINITIONS) if (_res) target_compile_definitions(${_TARGET} PRIVATE ${_res}) endif () get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_COMPILE_OPTIONS) if (_res) target_compile_options(${_TARGET} PRIVATE ${_res}) endif () endif () endforeach () endfunction() function(gdal_target_link_libraries target) set(_oneValueArgs) set(_multiValueArgs PRIVATE) cmake_parse_arguments(_DRIVER "" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) if (NOT _DRIVER_PRIVATE) message(FATAL_ERROR "gdal_target_link_libraries(): PRIVATE is a mandatory argument.") endif () is_plugin(RES ${target}) if (RES) target_link_libraries(${target} PRIVATE ${_DRIVER_PRIVATE}) foreach (_LIB IN ITEMS ${_DRIVER_PRIVATE}) if (TARGET ${_LIB}) get_property(_res TARGET ${_LIB} PROPERTY INTERFACE_COMPILE_DEFINITIONS) if (_res) target_compile_definitions(${target} PRIVATE ${_res}) endif () endif() endforeach() else () gdal_target_interfaces(${target} ${_DRIVER_PRIVATE}) gdal_add_private_link_libraries(${_DRIVER_PRIVATE}) endif () # For debugging purposes if(SHOW_DEPS_PER_TARGET) foreach (_LIB IN ITEMS ${_DRIVER_PRIVATE}) if (TARGET ${_LIB}) include(GdalGenerateConfig) gdal_get_lflags(_libs ${_LIB}) message(STATUS "Target ${target}: links against ${_libs} (target ${_LIB})") else() message(STATUS "Target ${target}: links against ${_LIB}") endif() endforeach() endif() endfunction() macro(gdal_driver_standard_includes _TARGET) include(GdalStandardIncludes) gdal_standard_includes(${_TARGET}) endmacro() # Macro for including driver directories. # Following macro should use only in the directories: # # ogr/ogrsf_frmts/ # frmts/ # include(CMakeDependentOption) macro(check_depend_condition variable depends) foreach(_dep IN ITEMS ${depends}) if( "${_dep}" MATCHES "GDAL_ENABLE_DRIVER_" OR "${_dep}" MATCHES "OGR_ENABLE_DRIVER_") if(NOT DEFINED "${_dep}") message(FATAL_ERROR "Condition ${depends} refers to variable ${_dep} which is not defined") endif() endif() endforeach() if(${variable}) cmake_dependent_option(TO_BE_REMOVED "" ON "${depends}" OFF) if(NOT ${TO_BE_REMOVED}) unset(TO_BE_REMOVED CACHE) if (NOT GDAL_IGNORE_FAILED_CONDITIONS) message(FATAL_ERROR "${variable} cannot be enabled because condition ${depends} is not met. To ignore this error (but the driver will not be built), set the GDAL_IGNORE_FAILED_CONDITIONS variable") else() message(WARNING "${variable} cannot be enabled because condition ${depends} is not met.") endif() endif() unset(TO_BE_REMOVED CACHE) endif() endmacro() # gdal_dependent_format(format desc depend) do followings: # - add subdirectory 'format' # - define option "GDAL_ENABLE_DRIVER_NAME" then set to default OFF/ON # - when enabled, add definition"-DFRMT_format" # - when dependency specified by depend fails, force OFF macro(gdal_dependent_format format desc depends) set(_options SKIP_ADD_SUBDIRECTORY) set(_oneValueArgs DRIVER_NAME_OPTION) set(_multiValueArgs) cmake_parse_arguments(_GDF "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) if( _GDF_DRIVER_NAME_OPTION ) string(TOUPPER ${_GDF_DRIVER_NAME_OPTION} key) else() string(TOUPPER ${format} key) endif() check_depend_condition(GDAL_ENABLE_DRIVER_${key} "${depends}") cmake_dependent_option(GDAL_ENABLE_DRIVER_${key} "Set ON to build ${desc} format" ${GDAL_BUILD_OPTIONAL_DRIVERS} "${depends}" OFF) add_feature_info(gdal_${key} GDAL_ENABLE_DRIVER_${key} "${desc}") if (GDAL_ENABLE_DRIVER_${key} AND NOT _GDF_SKIP_ADD_SUBDIRECTORY) add_subdirectory(${format}) endif () endmacro() macro(gdal_format format desc) string(TOUPPER ${format} key desc) set(GDAL_ENABLE_DRIVER_${key} ON CACHE BOOL "" FORCE) add_feature_info(gdal_${key} GDAL_ENABLE_DRIVER_${key} "${desc}") add_subdirectory(${format}) endmacro() macro(gdal_optional_format format desc) set(_options) set(_oneValueArgs DRIVER_NAME_OPTION) set(_multiValueArgs) cmake_parse_arguments(_GOF "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) if( _GOF_DRIVER_NAME_OPTION ) string(TOUPPER ${_GOF_DRIVER_NAME_OPTION} key) else() string(TOUPPER ${format} key) endif() option(GDAL_ENABLE_DRIVER_${key} "Set ON to build ${desc} format" ${GDAL_BUILD_OPTIONAL_DRIVERS}) add_feature_info(gdal_${key} GDAL_ENABLE_DRIVER_${key} "${desc}") if (GDAL_ENABLE_DRIVER_${key}) add_subdirectory(${format}) endif () endmacro() # ogr_dependent_driver(NAME desc depend) do followings: # - define option "OGR_ENABLE_DRIVER_" with default OFF # - add subdirectory 'name' # - when dependency specified by depend fails, force OFF macro(ogr_dependent_driver name desc depend) string(TOUPPER ${name} key) check_depend_condition(OGR_ENABLE_DRIVER_${key} "${depend}") if( NOT("${key}" STREQUAL "GPKG" OR "${key}" STREQUAL "SQLITE" OR "${key}" STREQUAL "AVC") ) cmake_dependent_option(OGR_ENABLE_DRIVER_${key} "Set ON to build OGR ${desc} driver" ${OGR_BUILD_OPTIONAL_DRIVERS} "${depend}" OFF) endif() add_feature_info(ogr_${key} OGR_ENABLE_DRIVER_${key} "${desc}") if (OGR_ENABLE_DRIVER_${key}) add_subdirectory(${name}) endif () endmacro() # ogr_optional_driver(name desc) do followings: # - define option "OGR_ENABLE_DRIVER_" with default OFF # - add subdirectory 'name' when enabled macro(ogr_optional_driver name desc) string(TOUPPER ${name} key) option(OGR_ENABLE_DRIVER_${key} "Set ON to build OGR ${desc} driver" ${OGR_BUILD_OPTIONAL_DRIVERS}) add_feature_info(ogr_${key} OGR_ENABLE_DRIVER_${key} "${desc}") if (OGR_ENABLE_DRIVER_${key}) add_subdirectory(${name}) endif () endmacro() # ogr_default_driver(name desc) # - set "OGR_ENABLE_DRIVER_" is ON but configurable. # - add subdirectory "name" macro(ogr_default_driver name desc) string(TOUPPER ${name} key) set(OGR_ENABLE_DRIVER_${key} ON CACHE BOOL "${desc}" FORCE) add_feature_info(ogr_${key} OGR_ENABLE_DRIVER_${key} "${desc}") add_subdirectory(${name}) endmacro() macro(ogr_default_driver2 name key desc) set(OGR_ENABLE_DRIVER_${key} ON CACHE BOOL "${desc}" FORCE) add_feature_info(ogr_${key} OGR_ENABLE_DRIVER_${key} "${desc}") add_subdirectory(${name}) endmacro()