├── .github └── workflows │ ├── test-pixi.yaml │ └── update-pixi-lockfile.yaml ├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── AddInstallRPATHSupport.cmake ├── AddUninstallTarget.cmake └── InstallBasicPackageFiles.cmake ├── examples ├── CMakeLists.txt ├── MyMath.cpp ├── MyMath.h ├── MyMathCustom.cpp ├── MyMathCustom.h ├── math_test.cpp └── math_test_custom.cpp ├── pixi.lock ├── pixi.toml └── src ├── CMakeLists.txt ├── SharedLibrary.cpp ├── SharedLibraryFactory.cpp ├── sharedlibpp ├── SharedLibrary.h ├── SharedLibraryClass-inl.h ├── SharedLibraryClass.h ├── SharedLibraryClassApi.h ├── SharedLibraryClassFactory-inl.h ├── SharedLibraryClassFactory.h ├── SharedLibraryFactory.h ├── api.h ├── config.h.in └── version.h.in └── version.cpp /.github/workflows/test-pixi.yaml: -------------------------------------------------------------------------------- 1 | name: Run tests with pixi 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | 7 | jobs: 8 | pixi-test: 9 | name: '[pixi:${{ matrix.os }}]' 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | os: [ 15 | ubuntu-22.04, 16 | macos-latest, 17 | windows-2019 18 | ] 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Set up pixi 23 | uses: prefix-dev/setup-pixi@v0.8.1 24 | with: 25 | run-install: true 26 | cache: false 27 | 28 | - name: Print pixi info 29 | run: pixi info 30 | 31 | - name: Build and test the project 32 | run: pixi run test 33 | -------------------------------------------------------------------------------- /.github/workflows/update-pixi-lockfile.yaml: -------------------------------------------------------------------------------- 1 | name: Update lockfiles 2 | 3 | permissions: 4 | contents: write 5 | pull-requests: write 6 | 7 | on: 8 | workflow_dispatch: 9 | schedule: 10 | - cron: 0 5 1 * * 11 | 12 | jobs: 13 | pixi-update: 14 | runs-on: ubuntu-22.04 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Set up pixi 19 | uses: prefix-dev/setup-pixi@v0.8.1 20 | with: 21 | run-install: false 22 | 23 | - name: Install pixi-diff-to-markdown 24 | run: pixi global install pixi-diff-to-markdown 25 | 26 | - name: Update lockfiles 27 | run: | 28 | set -o pipefail 29 | pixi update --json | pixi exec pixi-diff-to-markdown >> diff.md 30 | 31 | - name: Create pull request 32 | uses: peter-evans/create-pull-request@v6 33 | with: 34 | token: ${{ secrets.GITHUB_TOKEN }} 35 | commit-message: Update pixi lockfile 36 | title: Update pixi lockfile 37 | body-path: diff.md 38 | branch: update-pixi 39 | base: main 40 | labels: pixi 41 | delete-branch: true 42 | add-paths: pixi.lock 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.*~ 3 | .pixi 4 | .build 5 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Author and contributor list 2 | --------------------------- 3 | 4 | Ali Paikan 5 | Daniele E. Domenichelli 6 | Paul Fitzpatrick 7 | Damiano Enerli 8 | Francesco Romano 9 | Nicolò Genesio 10 | Silvio Traversaro 11 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 2 | # All rights reserved. 3 | # 4 | # This software may be modified and distributed under the terms of the 5 | # BSD-3-Clause license. See the accompanying LICENSE file for details. 6 | 7 | cmake_minimum_required(VERSION 3.5...3.31) 8 | 9 | project(sharedlibpp 10 | VERSION 0.0.3 11 | DESCRIPTION "Tiny cross-platform plug-in system (dll, so, dylib)" 12 | LANGUAGES CXX) 13 | 14 | # For now keep YCM as a soft dependency 15 | find_package(YCM 0.8.1 QUIET) 16 | if(NOT YCM_FOUND) 17 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") 18 | endif() 19 | 20 | # Set output directories for targets 21 | include(GNUInstallDirs) 22 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") 23 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") 24 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") 25 | 26 | # Set postfix for debug builds on MSVC 27 | if(MSVC) 28 | set(CMAKE_DEBUG_POSTFIX "d") 29 | endif() 30 | 31 | # Encourage user to specify a build type (e.g. Release, Debug, etc.), otherwise set it to Release. 32 | if(NOT CMAKE_CONFIGURATION_TYPES) 33 | if(NOT CMAKE_BUILD_TYPE) 34 | message(STATUS "Setting build type to 'Release' as none was specified.") 35 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY VALUE "Release") 36 | endif() 37 | endif() 38 | 39 | # Shared/Dynamic or Static library? 40 | option(BUILD_SHARED_LIBS "Build libraries as shared as opposed to static" ON) 41 | 42 | # Enable RPATH Support 43 | include(AddInstallRPATHSupport) 44 | add_install_rpath_support(BIN_DIRS "${CMAKE_INSTALL_FULL_LIBDIR}" 45 | LIB_DIRS "${CMAKE_INSTALL_FULL_BINDIR}" 46 | INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}" 47 | USE_LINK_PATH) 48 | 49 | # Build in pure c++11 50 | set(CMAKE_CXX_EXTENSIONS OFF) 51 | set(CMAKE_CXX_STANDARD 11) 52 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 53 | 54 | # Build position independent code 55 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 56 | 57 | # Hide all symbols by default 58 | set(CMAKE_CXX_VISIBILITY_PRESET hidden) 59 | set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) 60 | 61 | add_subdirectory(src) 62 | 63 | # Install CMake config files for the library 64 | include(InstallBasicPackageFiles) 65 | install_basic_package_files(sharedlibpp 66 | VERSION ${sharedlibpp_VERSION} 67 | COMPATIBILITY AnyNewerVersion 68 | EXPORT sharedlibpp 69 | NO_CHECK_REQUIRED_COMPONENTS_MACRO) 70 | 71 | # Add uninstall target 72 | include(AddUninstallTarget) 73 | 74 | # Do not put tests and examples in the same output directories as the main 75 | # targets 76 | unset(CMAKE_RUNTIME_OUTPUT_DIRECTORY) 77 | unset(CMAKE_LIBRARY_OUTPUT_DIRECTORY) 78 | unset(CMAKE_ARCHIVE_OUTPUT_DIRECTORY) 79 | 80 | 81 | # Create examples 82 | option(BUILD_EXAMPLES "Build examples" ON) 83 | if(BUILD_EXAMPLES) 84 | add_subdirectory(examples) 85 | endif() 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the University nor the names of its contributors 13 | may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Simple cross platform plug-in system 2 | ==================================== 3 | 4 | `sharedlibpp` is a tiny cross-platform library to create and load shared 5 | libraries for different platform (Linux/Mac/Windows). `sharedlibpp` provides 6 | an easy and portable way to create plug-ins which encapsulate your c++ classes 7 | inside a shared library (so, dylib, dll). 8 | The original code is taken and from 9 | [YARP (Yet Another Robot Platform)](http://www.yarp.it/). 10 | The code is simplified by removing dependencies and some helper functions are 11 | added to report the native OS error messages on failures. 12 | 13 | Building on Linux/Mac 14 | --------------------- 15 | $ cd sharedlibpp 16 | $ cmake -Bbuild -S. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install 17 | $ cmake --build . --config Release 18 | $ cmake --install . 19 | 20 | 21 | Running example 22 | --------------- 23 | The build system by default compiles and build the examples. 24 | 25 | * On Linux/Mac 26 | ``` 27 | $ cd sharedlibpp/build/examples 28 | $ ./math_test mymath 29 | $ ./math_test_custom mymathcustom 30 | ``` 31 | * On Windows first switch to directory where example is created and then 32 | ``` 33 | > math_test mymath 34 | > math_test_custom mymathcustom 35 | ``` 36 | 37 | Versioning policy 38 | ----------------- 39 | 40 | Any ABI or API incompatible change will result in a major release bump. 41 | -------------------------------------------------------------------------------- /cmake/AddInstallRPATHSupport.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # AddInstallRPATHSupport 3 | # ---------------------- 4 | # 5 | # Add support to RPATH during installation to your project:: 6 | # 7 | # add_install_rpath_support([BIN_DIRS dir [dir]] 8 | # [LIB_DIRS dir [dir]] 9 | # [INSTALL_NAME_DIR [dir]] 10 | # [DEPENDS condition [condition]] 11 | # [USE_LINK_PATH]) 12 | # 13 | # Normally (depending on the platform) when you install a shared 14 | # library you can either specify its absolute path as the install name, 15 | # or leave just the library name itself. In the former case the library 16 | # will be correctly linked during run time by all executables and other 17 | # shared libraries, but it must not change its install location. This 18 | # is often the case for libraries installed in the system default 19 | # library directory (e.g. ``/usr/lib``). 20 | # In the latter case, instead, the library can be moved anywhere in the 21 | # file system but at run time the dynamic linker must be able to find 22 | # it. This is often accomplished by setting environmental variables 23 | # (i.e. ``LD_LIBRARY_PATH`` on Linux). 24 | # This procedure is usually not desirable for two main reasons: 25 | # 26 | # - by setting the variable you are changing the default behaviour 27 | # of the dynamic linker thus potentially breaking executables (not as 28 | # destructive as ``LD_PRELOAD``) 29 | # - the variable will be used only by applications spawned by the shell 30 | # and not by other processes. 31 | # 32 | # RPATH aims in solving the issues introduced by the second 33 | # installation method. Using run-path dependent libraries you can 34 | # create a directory structure containing executables and dependent 35 | # libraries that users can relocate without breaking it. 36 | # A run-path dependent library is a dependent library whose complete 37 | # install name is not known when the library is created. 38 | # Instead, the library specifies that the dynamic loader must resolve 39 | # the library’s install name when it loads the executable that depends 40 | # on the library. The executable or the other shared library will 41 | # hardcode in the binary itself the additional search directories 42 | # to be passed to the dynamic linker. This works great in conjunction 43 | # with relative paths. 44 | # This command will enable support to RPATH to your project. 45 | # It will enable the following things: 46 | # 47 | # - If the project builds shared libraries it will generate a run-path 48 | # enabled shared library, i.e. its install name will be resolved 49 | # only at run time. 50 | # - In all cases (building executables and/or shared libraries) 51 | # dependent shared libraries with RPATH support will have their name 52 | # resolved only at run time, by embedding the search path directly 53 | # into the built binary. 54 | # 55 | # The command has the following parameters: 56 | # 57 | # Options: 58 | # - ``USE_LINK_PATH``: if passed the command will automatically adds to 59 | # the RPATH the path to all the dependent libraries. 60 | # 61 | # Arguments: 62 | # - ``BIN_DIRS`` list of directories when the targets (executable and 63 | # plugins) will be installed. 64 | # - ``LIB_DIRS`` list of directories to be added to the RPATH. These 65 | # directories will be added "relative" w.r.t. the ``BIN_DIRS`` and 66 | # ``LIB_DIRS``. 67 | # - ``INSTALL_NAME_DIR`` directory where the libraries will be installed. 68 | # This variable will be used only if ``CMAKE_SKIP_RPATH`` or 69 | # ``CMAKE_SKIP_INSTALL_RPATH`` is set to ``TRUE`` as it will set the 70 | # ``INSTALL_NAME_DIR`` on all targets 71 | # - ``DEPENDS`` list of conditions that should be ``TRUE`` to enable 72 | # RPATH, for example ``FOO; NOT BAR``. 73 | # 74 | # Note: see https://gitlab.kitware.com/cmake/cmake/issues/16589 for further 75 | # details. 76 | 77 | #======================================================================= 78 | # Copyright 2014 Istituto Italiano di Tecnologia (IIT) 79 | # @author Francesco Romano 80 | # 81 | # Distributed under the OSI-approved BSD License (the "License"); 82 | # see accompanying file Copyright.txt for details. 83 | # 84 | # This software is distributed WITHOUT ANY WARRANTY; without even the 85 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 86 | # See the License for more information. 87 | #======================================================================= 88 | # (To distribute this file outside of CMake, substitute the full 89 | # License text for the above reference.) 90 | 91 | 92 | include(CMakeParseArguments) 93 | 94 | 95 | function(ADD_INSTALL_RPATH_SUPPORT) 96 | 97 | set(_options USE_LINK_PATH) 98 | set(_oneValueArgs INSTALL_NAME_DIR) 99 | set(_multiValueArgs BIN_DIRS 100 | LIB_DIRS 101 | DEPENDS) 102 | 103 | cmake_parse_arguments(_ARS "${_options}" 104 | "${_oneValueArgs}" 105 | "${_multiValueArgs}" 106 | "${ARGN}") 107 | 108 | # if either RPATH or INSTALL_RPATH is disabled 109 | # and the INSTALL_NAME_DIR variable is set, then hardcode the install name 110 | if(CMAKE_SKIP_RPATH OR CMAKE_SKIP_INSTALL_RPATH) 111 | if(DEFINED _ARS_INSTALL_NAME_DIR) 112 | set(CMAKE_INSTALL_NAME_DIR ${_ARS_INSTALL_NAME_DIR} PARENT_SCOPE) 113 | endif() 114 | endif() 115 | 116 | if (CMAKE_SKIP_RPATH OR (CMAKE_SKIP_INSTALL_RPATH AND CMAKE_SKIP_BUILD_RPATH)) 117 | return() 118 | endif() 119 | 120 | 121 | set(_rpath_available 1) 122 | if(DEFINED _ARS_DEPENDS) 123 | foreach(_dep ${_ARS_DEPENDS}) 124 | string(REGEX REPLACE " +" ";" _dep "${_dep}") 125 | if(NOT (${_dep})) 126 | set(_rpath_available 0) 127 | endif() 128 | endforeach() 129 | endif() 130 | 131 | if(_rpath_available) 132 | 133 | # Enable RPATH on OSX. 134 | set(CMAKE_MACOSX_RPATH TRUE PARENT_SCOPE) 135 | 136 | # Find system implicit lib directories 137 | set(_system_lib_dirs ${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}) 138 | if(EXISTS "/etc/debian_version") # is this a debian system ? 139 | if(CMAKE_LIBRARY_ARCHITECTURE) 140 | list(APPEND _system_lib_dirs "/lib/${CMAKE_LIBRARY_ARCHITECTURE}" 141 | "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}") 142 | endif() 143 | endif() 144 | # This is relative RPATH for libraries built in the same project 145 | foreach(lib_dir ${_ARS_LIB_DIRS}) 146 | list(FIND _system_lib_dirs "${lib_dir}" isSystemDir) 147 | if("${isSystemDir}" STREQUAL "-1") 148 | foreach(bin_dir ${_ARS_LIB_DIRS} ${_ARS_BIN_DIRS}) 149 | file(RELATIVE_PATH _rel_path ${bin_dir} ${lib_dir}) 150 | if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 151 | list(APPEND CMAKE_INSTALL_RPATH "@loader_path/${_rel_path}") 152 | else() 153 | list(APPEND CMAKE_INSTALL_RPATH "\$ORIGIN/${_rel_path}") 154 | endif() 155 | endforeach() 156 | endif() 157 | endforeach() 158 | if(NOT "${CMAKE_INSTALL_RPATH}" STREQUAL "") 159 | list(REMOVE_DUPLICATES CMAKE_INSTALL_RPATH) 160 | endif() 161 | set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} PARENT_SCOPE) 162 | 163 | # add the automatically determined parts of the RPATH 164 | # which point to directories outside the build tree to the install RPATH 165 | set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ${_ARS_USE_LINK_PATH} PARENT_SCOPE) 166 | 167 | endif() 168 | 169 | endfunction() 170 | -------------------------------------------------------------------------------- /cmake/AddUninstallTarget.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # AddUninstallTarget 3 | # ------------------ 4 | # 5 | # Add the "uninstall" target for your project:: 6 | # 7 | # include(AddUninstallTarget) 8 | # 9 | # 10 | # will create a file cmake_uninstall.cmake in the build directory and add a 11 | # custom target uninstall that will remove the files installed by your package 12 | # (using install_manifest.txt) 13 | 14 | #============================================================================= 15 | # Copyright 2008-2013 Kitware, Inc. 16 | # Copyright 2013 Istituto Italiano di Tecnologia (IIT) 17 | # Authors: Daniele E. Domenichelli 18 | # 19 | # Distributed under the OSI-approved BSD License (the "License"); 20 | # see accompanying file Copyright.txt for details. 21 | # 22 | # This software is distributed WITHOUT ANY WARRANTY; without even the 23 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 24 | # See the License for more information. 25 | #============================================================================= 26 | # (To distribute this file outside of CMake, substitute the full 27 | # License text for the above reference.) 28 | 29 | 30 | if(DEFINED __ADD_UNINSTALL_TARGET_INCLUDED) 31 | return() 32 | endif() 33 | set(__ADD_UNINSTALL_TARGET_INCLUDED TRUE) 34 | 35 | 36 | set(_filename ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) 37 | 38 | file(WRITE ${_filename} 39 | "if(NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\") 40 | message(WARNING \"Cannot find install manifest: \\\"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\\\"\") 41 | return() 42 | endif() 43 | 44 | file(READ \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\" files) 45 | string(STRIP \"\${files}\" files) 46 | string(REGEX REPLACE \"\\n\" \";\" files \"\${files}\") 47 | list(REVERSE files) 48 | foreach(file \${files}) 49 | message(STATUS \"Uninstalling: \$ENV{DESTDIR}\${file}\") 50 | if(EXISTS \"\$ENV{DESTDIR}\${file}\") 51 | execute_process( 52 | COMMAND \${CMAKE_COMMAND} -E remove \"\$ENV{DESTDIR}\${file}\" 53 | OUTPUT_VARIABLE rm_out 54 | RESULT_VARIABLE rm_retval) 55 | if(NOT \"\${rm_retval}\" EQUAL 0) 56 | message(FATAL_ERROR \"Problem when removing \\\"\$ENV{DESTDIR}\${file}\\\"\") 57 | endif() 58 | else() 59 | message(STATUS \"File \\\"\$ENV{DESTDIR}\${file}\\\" does not exist.\") 60 | endif() 61 | endforeach(file) 62 | ") 63 | 64 | if("${CMAKE_GENERATOR}" MATCHES "^(Visual Studio|Xcode)") 65 | set(_uninstall "UNINSTALL") 66 | else() 67 | set(_uninstall "uninstall") 68 | endif() 69 | add_custom_target(${_uninstall} COMMAND "${CMAKE_COMMAND}" -P "${_filename}") 70 | set_property(TARGET ${_uninstall} PROPERTY FOLDER "CMakePredefinedTargets") 71 | -------------------------------------------------------------------------------- /cmake/InstallBasicPackageFiles.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # InstallBasicPackageFiles 3 | # ------------------------ 4 | # 5 | # A helper module to make your package easier to be found by other 6 | # projects. 7 | # 8 | # 9 | # .. command:: install_basic_package_files 10 | # 11 | # Create and install a basic version of cmake config files for your 12 | # project:: 13 | # 14 | # install_basic_package_files( 15 | # VERSION 16 | # COMPATIBILITY 17 | # [EXPORT ] # (default = "") 18 | # [FIRST_TARGET ] # (default = "") 19 | # [TARGETS ...] 20 | # [TARGETS_PROPERTY ] 21 | # [TARGETS_PROPERTIES ...] 22 | # [NO_SET_AND_CHECK_MACRO] 23 | # [NO_CHECK_REQUIRED_COMPONENTS_MACRO] 24 | # [VARS_PREFIX ] # (default = "") 25 | # [EXPORT_DESTINATION ] 26 | # [INSTALL_DESTINATION ] 27 | # [NAMESPACE ] # (default = "::") 28 | # [EXTRA_PATH_VARS_SUFFIX path1 [path2 ...]] 29 | # [CONFIG_TEMPLATE ] 30 | # [UPPERCASE_FILENAMES | LOWERCASE_FILENAMES] 31 | # [DEPENDENCIES " [...]" ...] 32 | # [PRIVATE_DEPENDENCIES " [...]" ...] 33 | # [INCLUDE_FILE ] 34 | # [COMPONENT ] # (default = "") 35 | # [NO_COMPATIBILITY_VARS] 36 | # ) 37 | # 38 | # Depending on UPPERCASE_FILENAMES and LOWERCASE_FILENAMES, this 39 | # function generates 3 files: 40 | # 41 | # - ``ConfigVersion.cmake`` or ``-config-version.cmake`` 42 | # - ``Config.cmake`` or ``-config.cmake`` 43 | # - ``Targets.cmake`` or ``-targets.cmake`` 44 | # 45 | # If neither ``UPPERCASE_FILENAMES`` nor ``LOWERCASE_FILENAMES`` is 46 | # set, a file ``ConfigVersion.cmake.in`` or 47 | # ``-config-version.cmake.in`` is searched, and the convention 48 | # is chosed according to the file found. If no file was found, the 49 | # uppercase convention is used. 50 | # 51 | # The ``DEPENDENCIES`` argument can be used to set a list of dependencies 52 | # that will be searched using the :command:`find_dependency` command 53 | # from the :module:`CMakeFindDependencyMacro` module. 54 | # Dependencies can be followed by any of the possible :command:`find_dependency` 55 | # argument. 56 | # In this case, all the arguments must be specified within double quotes (e.g. 57 | # " 1.0.0 EXACT", " CONFIG"). 58 | # The ``PRIVATE_DEPENDENCIES`` argument is similar to ``DEPENDENCIES``, but 59 | # these dependencies are included only when libraries are built ``STATIC``, i.e. 60 | # if ``BUILD_SHARED_LIBS`` is ``OFF`` or if the ``TYPE`` property for one or 61 | # more of the targets is ``STATIC_LIBRARY``. 62 | # When using a custom template file, the ``@PACKAGE_DEPENDENCIES@`` 63 | # string is replaced with the code checking for the dependencies 64 | # specified by these two argument. 65 | # 66 | # Each file is generated twice, one for the build directory and one for 67 | # the installation directory. The ``INSTALL_DESTINATION`` argument can be 68 | # passed to install the files in a location different from the default 69 | # one (``CMake`` on Windows, ``${CMAKE_INSTALL_LIBDIR}/cmake/${Name}`` 70 | # on other platforms. The ``EXPORT_DESTINATION`` argument can be passed to 71 | # generate the files in the build tree in a location different from the default 72 | # one (``CMAKE_BINARY_DIR``). If this is a relative path, it is considered 73 | # relative to the ``CMAKE_BINARY_DIR`` directory. 74 | # 75 | # The ``ConfigVersion.cmake`` is generated using 76 | # ``write_basic_package_version_file``. The ``VERSION``, 77 | # ``COMPATIBILITY``, ``NO_SET_AND_CHECK_MACRO``, and 78 | # ``NO_CHECK_REQUIRED_COMPONENTS_MACRO`` are passed to this function 79 | # and are used internally by :module:`CMakePackageConfigHelpers` module. 80 | # 81 | # ``VERSION`` shall be in the form ``[.[.[.]]]]``. 82 | # If no ``VERSION`` is given, the ``PROJECT_VERSION`` variable is used. 83 | # If this hasn’t been set, it errors out. The ``VERSION`` argument is also used 84 | # to replace the ``@PACKAGE_VERSION@`` string in the configuration file. 85 | # 86 | # ``COMPATIBILITY`` shall be any of ````. 88 | # The ``COMPATIBILITY`` mode ``AnyNewerVersion`` means that the installed 89 | # package version will be considered compatible if it is newer or exactly the 90 | # same as the requested version. This mode should be used for packages which are 91 | # fully backward compatible, also across major versions. 92 | # If ``SameMajorVersion`` is used instead, then the behaviour differs from 93 | # ``AnyNewerVersion`` in that the major version number must be the same as 94 | # requested, e.g. version 2.0 will not be considered compatible if 1.0 is 95 | # requested. This mode should be used for packages which guarantee backward 96 | # compatibility within the same major version. If ``ExactVersion`` is used, then 97 | # the package is only considered compatible if the requested version matches 98 | # exactly its own version number (not considering the tweak version). For 99 | # example, version 1.2.3 of a package is only considered compatible to requested 100 | # version 1.2.3. This mode is for packages without compatibility guarantees. If 101 | # your project has more elaborated version matching rules, you will need to 102 | # write your own custom ConfigVersion.cmake file instead of using this macro. 103 | # 104 | # By default ``install_basic_package_files`` also generates the two helper 105 | # macros ``set_and_check()`` and ``check_required_components()`` into the 106 | # ``Config.cmake`` file. ``set_and_check()`` should be used instead of the 107 | # normal set() command for setting directories and file locations. Additionally 108 | # to setting the variable it also checks that the referenced file or directory 109 | # actually exists and fails with a ``FATAL_ERROR`` otherwise. This makes sure 110 | # that the created ``Config.cmake`` file does not contain wrong 111 | # references. When using the ``NO_SET_AND_CHECK_MACRO, this macro is not 112 | # generated into the ``Config.cmake`` file. 113 | # 114 | # By default, ``install_basic_package_files`` append a call to 115 | # ``check_required_components()`` in Config.cmake file if the 116 | # package supports components. This macro checks whether all requested, 117 | # non-optional components have been found, and if this is not the case, sets the 118 | # ``_FOUND`` variable to ``FALSE``, so that the package is considered to 119 | # be not found. It does that by testing the ``__FOUND`` 120 | # variables for all requested required components. When using the 121 | # ``NO_CHECK_REQUIRED_COMPONENTS_MACRO`` option, this macro is not generated 122 | # into the Config.cmake file. 123 | # 124 | # Finally, the files in the build and install directory are exactly the same. 125 | # 126 | # See the documentation of :module:`CMakePackageConfigHelpers` module for 127 | # further information and references therein. 128 | # 129 | # 130 | # The ``Config.cmake`` is generated using 131 | # ``configure_package_config_file``. See the documentation for the 132 | # :module:`CMakePackageConfigHelpers` module for further information. 133 | # If the ``CONFIG_TEMPLATE`` argument is passed, the specified file 134 | # is used as template for generating the configuration file, otherwise 135 | # this module expects to find a ``Config.cmake.in`` or 136 | # ``-config.cmake.in`` file either in the root directory of the 137 | # project or in current source directory. 138 | # If the file does not exist, a very basic file is created. 139 | # 140 | # A set of variables are checked and passed to 141 | # ``configure_package_config_file`` as ``PATH_VARS``. For each of the 142 | # ``SUFFIX`` considered, if one of the variables:: 143 | # 144 | # _(BUILD|INSTALL)_ 145 | # (BUILD|INSTALL)__ 146 | # 147 | # is defined, the ``_`` variable will be defined 148 | # before configuring the package. In order to use that variable in the 149 | # config file, you have to add a line:: 150 | # 151 | # set_and_check(_ \"@PACKAGE__@\") 152 | # 153 | # if the path must exist or just:: 154 | # 155 | # set(_ \"@PACKAGE__@\") 156 | # 157 | # if the path could be missing. 158 | # 159 | # These variable will have different values whether you are using the 160 | # package from the build tree or from the install directory. Also these 161 | # files will contain only relative paths, meaning that you can move the 162 | # whole installation and the CMake files will still work. 163 | # 164 | # Default ``PATH_VARS`` suffixes are:: 165 | # 166 | # BINDIR BIN_DIR 167 | # SBINDIR SBIN_DIR 168 | # LIBEXECDIR LIBEXEC_DIR 169 | # SYSCONFDIR SYSCONF_DIR 170 | # SHAREDSTATEDIR SHAREDSTATE_DIR 171 | # LOCALSTATEDIR LOCALSTATE_DIR 172 | # LIBDIR LIB_DIR 173 | # INCLUDEDIR INCLUDE_DIR 174 | # OLDINCLUDEDIR OLDINCLUDE_DIR 175 | # DATAROOTDIR DATAROOT_DIR 176 | # DATADIR DATA_DIR 177 | # INFODIR INFO_DIR 178 | # LOCALEDIR LOCALE_DIR 179 | # MANDIR MAN_DIR 180 | # DOCDIR DOC_DIR 181 | # 182 | # more suffixes can be added using the ``EXTRA_PATH_VARS_SUFFIX`` 183 | # argument. 184 | # 185 | # 186 | # The ``Targets.cmake`` is generated using 187 | # :command:`export(TARGETS)` (if ``EXPORT`` or no options are used) or 188 | # :command:`export(TARGETS)` (if `EXPORT` is not used and one between 189 | # ``TARGETS``, ``TARGETS_PROPERTY``, or ``TARGETS_PROPERTIES`` is used) in the 190 | # build tree and :command:`install(EXPORT)` in the installation directory. 191 | # The targets are exported using the value for the ``NAMESPACE`` 192 | # argument as namespace. 193 | # The export can be passed using the `EXPORT` argument. 194 | # The targets can be passed using the `TARGETS` argument or using one or more 195 | # global properties, that can be passed to the function using the 196 | # ``TARGETS_PROPERTY`` or ``TARGET_PROPERTIES`` arguments. 197 | # 198 | # If the ``NO_COMPATIBILITY_VARS`` argument is not set, the compatibility 199 | # variables ``_LIBRARIES`` and ``_INCLUDE_DIRS`` 200 | # are set, trying to guess their correct values from the variables set or 201 | # from the arguments passed to this command. This argument is ignored if 202 | # the template file is not generated by this command. 203 | # 204 | # If the ``INCLUDE_FILE`` argument is passed, the content of the specified file 205 | # (which might be templated) is appended to the ``Config.cmake``. 206 | # This allows to inject custom code to this file, useful e.g. to set additional 207 | # variables which are loaded by downstream projects. 208 | # 209 | # If the ``COMPONENT`` argument is passed, it is forwarded to the 210 | # :command:`install` commands, otherwise is used. 211 | 212 | #============================================================================= 213 | # Copyright 2013 Istituto Italiano di Tecnologia (IIT) 214 | # Authors: Daniele E. Domenichelli 215 | # 216 | # Distributed under the OSI-approved BSD License (the "License"); 217 | # see accompanying file Copyright.txt for details. 218 | # 219 | # This software is distributed WITHOUT ANY WARRANTY; without even the 220 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 221 | # See the License for more information. 222 | #============================================================================= 223 | # (To distribute this file outside of CMake, substitute the full 224 | # License text for the above reference.) 225 | 226 | 227 | if(COMMAND install_basic_package_files) 228 | return() 229 | endif() 230 | 231 | 232 | include(GNUInstallDirs) 233 | include(CMakePackageConfigHelpers) 234 | include(CMakeParseArguments) 235 | 236 | 237 | function(INSTALL_BASIC_PACKAGE_FILES _Name) 238 | 239 | # TODO check that _Name does not contain "-" characters 240 | 241 | set(_options NO_SET_AND_CHECK_MACRO 242 | NO_CHECK_REQUIRED_COMPONENTS_MACRO 243 | UPPERCASE_FILENAMES 244 | LOWERCASE_FILENAMES 245 | NO_COMPATIBILITY_VARS) 246 | set(_oneValueArgs VERSION 247 | COMPATIBILITY 248 | EXPORT 249 | FIRST_TARGET 250 | TARGETS_PROPERTY 251 | VARS_PREFIX 252 | EXPORT_DESTINATION 253 | INSTALL_DESTINATION 254 | DESTINATION 255 | NAMESPACE 256 | CONFIG_TEMPLATE 257 | INCLUDE_FILE 258 | COMPONENT) 259 | set(_multiValueArgs EXTRA_PATH_VARS_SUFFIX 260 | TARGETS 261 | TARGETS_PROPERTIES 262 | DEPENDENCIES 263 | PRIVATE_DEPENDENCIES) 264 | cmake_parse_arguments(_IBPF "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" "${ARGN}") 265 | 266 | if(NOT DEFINED _IBPF_VARS_PREFIX) 267 | set(_IBPF_VARS_PREFIX ${_Name}) 268 | endif() 269 | 270 | if(NOT DEFINED _IBPF_VERSION) 271 | message(FATAL_ERROR "VERSION argument is required") 272 | endif() 273 | 274 | if(NOT DEFINED _IBPF_COMPATIBILITY) 275 | message(FATAL_ERROR "COMPATIBILITY argument is required") 276 | endif() 277 | 278 | if(_IBPF_UPPERCASE_FILENAMES AND _IBPF_LOWERCASE_FILENAMES) 279 | message(FATAL_ERROR "UPPERCASE_FILENAMES and LOWERCASE_FILENAMES arguments cannot be used together") 280 | endif() 281 | 282 | # Prepare install and export commands 283 | set(_first_target ${_Name}) 284 | set(_targets ${_Name}) 285 | set(_install_cmd EXPORT ${_Name}) 286 | set(_export_cmd EXPORT ${_Name}) 287 | 288 | if(DEFINED _IBPF_FIRST_TARGET) 289 | if(DEFINED _IBPF_TARGETS OR DEFINED _IBPF_TARGETS_PROPERTIES OR DEFINED _IBPF_TARGETS_PROPERTIES) 290 | message(FATAL_ERROR "EXPORT cannot be used with TARGETS, TARGETS_PROPERTY or TARGETS_PROPERTIES") 291 | endif() 292 | 293 | set(_first_target ${_IBPF_FIRST_TARGET}) 294 | set(_targets ${_IBPF_FIRST_TARGET}) 295 | endif() 296 | 297 | if(DEFINED _IBPF_EXPORT) 298 | if(DEFINED _IBPF_TARGETS OR DEFINED _IBPF_TARGETS_PROPERTIES OR DEFINED _IBPF_TARGETS_PROPERTIES) 299 | message(FATAL_ERROR "EXPORT cannot be used with TARGETS, TARGETS_PROPERTY or TARGETS_PROPERTIES") 300 | endif() 301 | 302 | set(_export_cmd EXPORT ${_IBPF_EXPORT}) 303 | set(_install_cmd EXPORT ${_IBPF_EXPORT}) 304 | 305 | elseif(DEFINED _IBPF_TARGETS) 306 | if(DEFINED _IBPF_TARGETS_PROPERTY OR DEFINED _IBPF_TARGETS_PROPERTIES) 307 | message(FATAL_ERROR "TARGETS cannot be used with TARGETS_PROPERTY or TARGETS_PROPERTIES") 308 | endif() 309 | 310 | set(_targets ${_IBPF_TARGETS}) 311 | set(_export_cmd TARGETS ${_IBPF_TARGETS}) 312 | list(GET _targets 0 _first_target) 313 | 314 | elseif(DEFINED _IBPF_TARGETS_PROPERTY) 315 | if(DEFINED _IBPF_TARGETS_PROPERTIES) 316 | message(FATAL_ERROR "TARGETS_PROPERTIES cannot be used with TARGETS_PROPERTIES") 317 | endif() 318 | 319 | get_property(_targets GLOBAL PROPERTY ${_IBPF_TARGETS_PROPERTY}) 320 | set(_export_cmd TARGETS ${_targets}) 321 | list(GET _targets 0 _first_target) 322 | 323 | elseif(DEFINED _IBPF_TARGETS_PROPERTIES) 324 | 325 | unset(_targets) 326 | foreach(_prop ${_IBPF_TARGETS_PROPERTIES}) 327 | get_property(_prop_val GLOBAL PROPERTY ${_prop}) 328 | list(APPEND _targets ${_prop_val}) 329 | endforeach() 330 | set(_export_cmd TARGETS ${_targets}) 331 | list(GET _targets 0 _first_target) 332 | 333 | endif() 334 | 335 | # Path for installed cmake files 336 | if(DEFINED _IBPF_DESTINATION) 337 | message(DEPRECATION "DESTINATION is deprecated. Use INSTALL_DESTINATION instead") 338 | if(NOT DEFINED _IBPF_INSTALL_DESTINATION) 339 | set(_IBPF_INSTALL_DESTINATION ${_IBPF_DESTINATION}) 340 | endif() 341 | endif() 342 | 343 | if(NOT DEFINED _IBPF_INSTALL_DESTINATION) 344 | if(WIN32 AND NOT CYGWIN) 345 | set(_IBPF_INSTALL_DESTINATION CMake) 346 | else() 347 | set(_IBPF_INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${_Name}) 348 | endif() 349 | endif() 350 | 351 | if(NOT DEFINED _IBPF_EXPORT_DESTINATION) 352 | set(_IBPF_EXPORT_DESTINATION "${CMAKE_BINARY_DIR}") 353 | elseif(NOT IS_ABSOLUTE _IBPF_EXPORT_DESTINATION) 354 | set(_IBPF_EXPORT_DESTINATION "${CMAKE_BINARY_DIR}/${_IBPF_EXPORT_DESTINATION}") 355 | endif() 356 | 357 | if(NOT DEFINED _IBPF_NAMESPACE) 358 | set(_IBPF_NAMESPACE "${_Name}::") 359 | endif() 360 | 361 | if(NOT DEFINED _IBPF_COMPONENT) 362 | set(_IBPF_COMPONENT "${_Name}") 363 | endif() 364 | 365 | if(_IBPF_NO_SET_AND_CHECK_MACRO) 366 | list(APPEND configure_package_config_file_extra_args NO_SET_AND_CHECK_MACRO) 367 | endif() 368 | 369 | if(_IBPF_NO_CHECK_REQUIRED_COMPONENTS_MACRO) 370 | list(APPEND configure_package_config_file_extra_args NO_CHECK_REQUIRED_COMPONENTS_MACRO) 371 | endif() 372 | 373 | 374 | 375 | # Set input file for config, and ensure that _IBPF_UPPERCASE_FILENAMES 376 | # and _IBPF_LOWERCASE_FILENAMES are set correctly 377 | unset(_config_cmake_in) 378 | set(_generate_file 0) 379 | if(DEFINED _IBPF_CONFIG_TEMPLATE) 380 | if(NOT EXISTS "${_IBPF_CONFIG_TEMPLATE}") 381 | message(FATAL_ERROR "Config template file \"${_IBPF_CONFIG_TEMPLATE}\" not found") 382 | endif() 383 | set(_config_cmake_in "${_IBPF_CONFIG_TEMPLATE}") 384 | if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES) 385 | if("${_IBPF_CONFIG_TEMPLATE}" MATCHES "${_Name}Config.cmake.in") 386 | set(_IBPF_UPPERCASE_FILENAMES 1) 387 | elseif("${_IBPF_CONFIG_TEMPLATE}" MATCHES "${_name}-config.cmake.in") 388 | set(_IBPF_LOWERCASE_FILENAMES 1) 389 | else() 390 | set(_IBPF_UPPERCASE_FILENAMES 1) 391 | endif() 392 | endif() 393 | else() 394 | string(TOLOWER "${_Name}" _name) 395 | if(EXISTS "${CMAKE_SOURCE_DIR}/${_Name}Config.cmake.in") 396 | set(_config_cmake_in "${CMAKE_SOURCE_DIR}/${_Name}Config.cmake.in") 397 | if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES) 398 | set(_IBPF_UPPERCASE_FILENAMES 1) 399 | endif() 400 | elseif(EXISTS "${CMAKE_SOURCE_DIR}/${_name}-config.cmake.in") 401 | set(_config_cmake_in "${CMAKE_SOURCE_DIR}/${_name}-config.cmake.in") 402 | if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES) 403 | set(_IBPF_LOWERCASE_FILENAMES 1) 404 | endif() 405 | elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_Name}Config.cmake.in") 406 | set(_config_cmake_in "${CMAKE_CURRENT_SOURCE_DIR}/${_Name}Config.cmake.in") 407 | if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES) 408 | set(_IBPF_UPPERCASE_FILENAMES 1) 409 | endif() 410 | elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_name}-config.cmake.in") 411 | set(_config_cmake_in "${CMAKE_CURRENT_SOURCE_DIR}/${_name}-config.cmake.in") 412 | if(NOT _IBPF_UPPERCASE_FILENAMES AND NOT _IBPF_LOWERCASE_FILENAMES) 413 | set(_IBPF_LOWERCASE_FILENAMES 1) 414 | endif() 415 | else() 416 | set(_generate_file 1) 417 | if(_IBPF_LOWERCASE_FILENAMES) 418 | set(_config_cmake_in "${CMAKE_CURRENT_BINARY_DIR}/${_name}-config.cmake") 419 | else() 420 | set(_config_cmake_in "${CMAKE_CURRENT_BINARY_DIR}/${_Name}Config.cmake.in") 421 | set(_IBPF_UPPERCASE_FILENAMES 1) 422 | endif() 423 | endif() 424 | endif() 425 | 426 | # Set input file containing user variables 427 | if(DEFINED _IBPF_INCLUDE_FILE) 428 | if(NOT IS_ABSOLUTE "${_IBPF_INCLUDE_FILE}") 429 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_IBPF_INCLUDE_FILE}") 430 | set(_IBPF_INCLUDE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${_IBPF_INCLUDE_FILE}") 431 | endif() 432 | endif() 433 | if(NOT EXISTS "${_IBPF_INCLUDE_FILE}") 434 | message(FATAL_ERROR "File \"${_IBPF_INCLUDE_FILE}\" not found") 435 | endif() 436 | file(READ ${_IBPF_INCLUDE_FILE} _includedfile_user_content_in) 437 | string(CONFIGURE ${_includedfile_user_content_in} _includedfile_user_content) 438 | set(INCLUDED_FILE_CONTENT 439 | "#### Expanded from INCLUDE_FILE by install_basic_package_files() ####") 440 | set(INCLUDED_FILE_CONTENT "${INCLUDED_FILE_CONTENT}\n\n${_includedfile_user_content}") 441 | set(INCLUDED_FILE_CONTENT 442 | "${INCLUDED_FILE_CONTENT} 443 | #####################################################################") 444 | endif() 445 | 446 | # Select output file names 447 | if(_IBPF_UPPERCASE_FILENAMES) 448 | set(_config_filename ${_Name}Config.cmake) 449 | set(_version_filename ${_Name}ConfigVersion.cmake) 450 | set(_targets_filename ${_Name}Targets.cmake) 451 | elseif(_IBPF_LOWERCASE_FILENAMES) 452 | set(_config_filename ${_name}-config.cmake) 453 | set(_version_filename ${_name}-config-version.cmake) 454 | set(_targets_filename ${_name}-targets.cmake) 455 | endif() 456 | 457 | 458 | # If the template config file does not exist, write a basic one 459 | if(_generate_file) 460 | # Generate the compatibility code 461 | unset(_compatibility_vars) 462 | if(NOT _IBPF_NO_COMPATIBILITY_VARS) 463 | unset(_get_include_dir_code) 464 | unset(_set_include_dir_code) 465 | unset(_target_list) 466 | foreach(_target ${_targets}) 467 | list(APPEND _target_list ${_IBPF_NAMESPACE}${_target}) 468 | endforeach() 469 | if(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_INCLUDEDIR OR 470 | DEFINED BUILD_${_IBPF_VARS_PREFIX}_INCLUDEDIR OR 471 | DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_INCLUDEDIR OR 472 | DEFINED INSTALL_${_IBPF_VARS_PREFIX}_INCLUDEDIR) 473 | set(_get_include_dir "set(${_IBPF_VARS_PREFIX}_INCLUDEDIR \"\@PACKAGE_${_IBPF_VARS_PREFIX}_INCLUDEDIR\@\")\n") 474 | set(_set_include_dir "set(${_Name}_INCLUDE_DIRS \"\${${_IBPF_VARS_PREFIX}_INCLUDEDIR}\")") 475 | elseif(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_INCLUDE_DIR OR 476 | DEFINED BUILD_${_IBPF_VARS_PREFIX}_INCLUDE_DIR OR 477 | DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_INCLUDE_DIR OR 478 | DEFINED INSTALL_${_IBPF_VARS_PREFIX}_INCLUDE_DIR) 479 | set(_get_include_dir "set(${_IBPF_VARS_PREFIX}_INCLUDE_DIR \"\@PACKAGE_${_IBPF_VARS_PREFIX}_INCLUDE_DIR\@\")\n") 480 | set(_set_include_dir "set(${_Name}_INCLUDE_DIRS \"\${${_IBPF_VARS_PREFIX}_INCLUDE_DIR}\")") 481 | else() 482 | unset(_include_dir_list) 483 | foreach(_target ${_targets}) 484 | set(_get_include_dir "${_get_include_dir}get_property(${_IBPF_VARS_PREFIX}_${_target}_INCLUDE_DIR TARGET ${_IBPF_NAMESPACE}${_target} PROPERTY INTERFACE_INCLUDE_DIRECTORIES)\n") 485 | list(APPEND _include_dir_list "\"\${${_IBPF_VARS_PREFIX}_${_target}_INCLUDE_DIR}\"") 486 | endforeach() 487 | string(REPLACE ";" " " _include_dir_list "${_include_dir_list}") 488 | string(REPLACE ";" " " _target_list "${_target_list}") 489 | set(_set_include_dir "set(${_Name}_INCLUDE_DIRS ${_include_dir_list})\nlist(REMOVE_DUPLICATES ${_Name}_INCLUDE_DIRS)") 490 | endif() 491 | set(_compatibility_vars "# Compatibility\n${_get_include_dir}\nset(${_Name}_LIBRARIES ${_target_list})\n${_set_include_dir}") 492 | endif() 493 | 494 | # Write the file 495 | file(WRITE "${_config_cmake_in}" 496 | "set(${_IBPF_VARS_PREFIX}_VERSION \@PACKAGE_VERSION\@) 497 | 498 | \@PACKAGE_INIT\@ 499 | 500 | \@PACKAGE_DEPENDENCIES\@ 501 | 502 | if(NOT TARGET ${_IBPF_NAMESPACE}${_first_target}) 503 | include(\"\${CMAKE_CURRENT_LIST_DIR}/${_targets_filename}\") 504 | endif() 505 | 506 | ${_compatibility_vars} 507 | 508 | \@INCLUDED_FILE_CONTENT\@ 509 | ") 510 | endif() 511 | 512 | # Make relative paths absolute (needed later on) and append the 513 | # defined variables to _(build|install)_path_vars_suffix 514 | foreach(p BINDIR BIN_DIR 515 | SBINDIR SBIN_DIR 516 | LIBEXECDIR LIBEXEC_DIR 517 | SYSCONFDIR SYSCONF_DIR 518 | SHAREDSTATEDIR SHAREDSTATE_DIR 519 | LOCALSTATEDIR LOCALSTATE_DIR 520 | LIBDIR LIB_DIR 521 | INCLUDEDIR INCLUDE_DIR 522 | OLDINCLUDEDIR OLDINCLUDE_DIR 523 | DATAROOTDIR DATAROOT_DIR 524 | DATADIR DATA_DIR 525 | INFODIR INFO_DIR 526 | LOCALEDIR LOCALE_DIR 527 | MANDIR MAN_DIR 528 | DOCDIR DOC_DIR 529 | ${_IBPF_EXTRA_PATH_VARS_SUFFIX}) 530 | if(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_${p}) 531 | list(APPEND _build_path_vars_suffix ${p}) 532 | list(APPEND _build_path_vars "${_IBPF_VARS_PREFIX}_${p}") 533 | endif() 534 | if(DEFINED BUILD_${_IBPF_VARS_PREFIX}_${p}) 535 | list(APPEND _build_path_vars_suffix ${p}) 536 | list(APPEND _build_path_vars "${_IBPF_VARS_PREFIX}_${p}") 537 | endif() 538 | if(DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_${p}) 539 | list(APPEND _install_path_vars_suffix ${p}) 540 | list(APPEND _install_path_vars "${_IBPF_VARS_PREFIX}_${p}") 541 | endif() 542 | if(DEFINED INSTALL_${_IBPF_VARS_PREFIX}_${p}) 543 | list(APPEND _install_path_vars_suffix ${p}) 544 | list(APPEND _install_path_vars "${_IBPF_VARS_PREFIX}_${p}") 545 | endif() 546 | endforeach() 547 | 548 | 549 | # ConfigVersion.cmake file (same for build tree and intall) 550 | write_basic_package_version_file("${_IBPF_EXPORT_DESTINATION}/${_version_filename}" 551 | VERSION ${_IBPF_VERSION} 552 | COMPATIBILITY ${_IBPF_COMPATIBILITY}) 553 | install(FILES "${_IBPF_EXPORT_DESTINATION}/${_version_filename}" 554 | DESTINATION ${_IBPF_INSTALL_DESTINATION} 555 | COMPONENT ${_IBPF_COMPONENT}) 556 | 557 | 558 | # Prepare PACKAGE_DEPENDENCIES variable 559 | set(_need_private_deps 0) 560 | if(NOT BUILD_SHARED_LIBS) 561 | set(_need_private_deps 1) 562 | else() 563 | foreach(_target ${_targets}) 564 | get_property(_type TARGET ${_target} PROPERTY TYPE) 565 | if("${_type}" STREQUAL "STATIC_LIBRARY") 566 | set(_need_private_deps 1) 567 | break() 568 | endif() 569 | endforeach() 570 | endif() 571 | 572 | unset(PACKAGE_DEPENDENCIES) 573 | if(DEFINED _IBPF_DEPENDENCIES) 574 | set(PACKAGE_DEPENDENCIES "#### Expanded from @PACKAGE_DEPENDENCIES@ by install_basic_package_files() ####\n\ninclude(CMakeFindDependencyMacro)\n") 575 | 576 | # FIXME When CMake 3.9 or greater is required, remove this madness and just 577 | # use find_dependency 578 | if (CMAKE_VERSION VERSION_LESS 3.9) 579 | string(APPEND PACKAGE_DEPENDENCIES " 580 | set(_${_Name}_FIND_PARTS_REQUIRED) 581 | if (${_Name}_FIND_REQUIRED) 582 | set(_${_Name}_FIND_PARTS_REQUIRED REQUIRED) 583 | endif() 584 | set(_${_Name}_FIND_PARTS_QUIET) 585 | if (${_Name}_FIND_QUIETLY) 586 | set(_${_Name}_FIND_PARTS_QUIET QUIET) 587 | endif() 588 | ") 589 | 590 | foreach(_dep ${_IBPF_DEPENDENCIES}) 591 | if("${_dep}" MATCHES ".+ .+") 592 | string(REPLACE " " ";" _dep_list "${_dep}") 593 | list(INSERT _dep_list 1 \${_${_Name}_FIND_PARTS_QUIET} \${_${_Name}_FIND_PARTS_REQUIRED}) 594 | string(REPLACE ";" " " _depx "${_dep_list}") 595 | string(APPEND PACKAGE_DEPENDENCIES "find_package(${_depx})\n") 596 | else() 597 | string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${_dep})\n") 598 | endif() 599 | endforeach() 600 | if(_need_private_deps) 601 | foreach(_dep ${_IBPF_PRIVATE_DEPENDENCIES}) 602 | if("${_dep}" MATCHES ".+ .+") 603 | string(REPLACE " " ";" _dep_list "${_dep}") 604 | list(INSERT _dep_list 1 \${_${_Name}_FIND_PARTS_QUIET} \${_${_Name}_FIND_PARTS_REQUIRED}) 605 | string(REPLACE ";" "\n " _depx "${_dep_list}") 606 | string(APPEND PACKAGE_DEPENDENCIES "find_package(${_depx})\n") 607 | else() 608 | string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${_dep})\n") 609 | endif() 610 | endforeach() 611 | endif() 612 | 613 | else() 614 | 615 | foreach(_dep ${_IBPF_DEPENDENCIES}) 616 | string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${_dep})\n") 617 | endforeach() 618 | if(_need_private_deps) 619 | foreach(_dep ${_IBPF_PRIVATE_DEPENDENCIES}) 620 | string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${_dep})\n") 621 | endforeach() 622 | endif() 623 | 624 | endif() 625 | 626 | set(PACKAGE_DEPENDENCIES "${PACKAGE_DEPENDENCIES}\n###############################################################################\n") 627 | endif() 628 | 629 | # Prepare PACKAGE_VERSION variable 630 | set(PACKAGE_VERSION ${_IBPF_VERSION}) 631 | 632 | # Config.cmake (build tree) 633 | foreach(p ${_build_path_vars_suffix}) 634 | if(DEFINED ${_IBPF_VARS_PREFIX}_BUILD_${p}) 635 | set(${_IBPF_VARS_PREFIX}_${p} "${${_IBPF_VARS_PREFIX}_BUILD_${p}}") 636 | elseif(DEFINED BUILD_${_IBPF_VARS_PREFIX}_${p}) 637 | set(${_IBPF_VARS_PREFIX}_${p} "${BUILD_${_IBPF_VARS_PREFIX}_${p}}") 638 | endif() 639 | endforeach() 640 | configure_package_config_file("${_config_cmake_in}" 641 | "${_IBPF_EXPORT_DESTINATION}/${_config_filename}" 642 | INSTALL_DESTINATION ${_IBPF_EXPORT_DESTINATION} 643 | PATH_VARS ${_build_path_vars} 644 | ${configure_package_config_file_extra_args} 645 | INSTALL_PREFIX ${CMAKE_BINARY_DIR}) 646 | 647 | # Config.cmake (installed) 648 | foreach(p ${_install_path_vars_suffix}) 649 | if(DEFINED ${_IBPF_VARS_PREFIX}_INSTALL_${p}) 650 | set(${_IBPF_VARS_PREFIX}_${p} "${${_IBPF_VARS_PREFIX}_INSTALL_${p}}") 651 | elseif(DEFINED INSTALL_${_IBPF_VARS_PREFIX}_${p}) 652 | set(${_IBPF_VARS_PREFIX}_${p} "${INSTALL_${_IBPF_VARS_PREFIX}_${p}}") 653 | endif() 654 | endforeach() 655 | configure_package_config_file("${_config_cmake_in}" 656 | "${CMAKE_CURRENT_BINARY_DIR}/${_config_filename}.install" 657 | INSTALL_DESTINATION ${_IBPF_INSTALL_DESTINATION} 658 | PATH_VARS ${_install_path_vars} 659 | ${configure_package_config_file_extra_args}) 660 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${_config_filename}.install" 661 | DESTINATION ${_IBPF_INSTALL_DESTINATION} 662 | RENAME ${_config_filename} 663 | COMPONENT ${_IBPF_COMPONENT}) 664 | 665 | 666 | # Targets.cmake (build tree) 667 | export(${_export_cmd} 668 | NAMESPACE ${_IBPF_NAMESPACE} 669 | FILE "${_IBPF_EXPORT_DESTINATION}/${_targets_filename}") 670 | 671 | # Targets.cmake (installed) 672 | install(${_install_cmd} 673 | NAMESPACE ${_IBPF_NAMESPACE} 674 | DESTINATION ${_IBPF_INSTALL_DESTINATION} 675 | FILE "${_targets_filename}" 676 | COMPONENT ${_IBPF_COMPONENT}) 677 | endfunction() 678 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 2 | # All rights reserved. 3 | # 4 | # This software may be modified and distributed under the terms of the 5 | # BSD-3-Clause license. See the accompanying LICENSE file for details. 6 | 7 | add_library(mymath MODULE MyMath.cpp MyMath.h) 8 | target_include_directories(mymath PRIVATE $) 9 | 10 | add_executable(math_test math_test.cpp) 11 | target_link_libraries(math_test PRIVATE sharedlibpp::sharedlibpp) 12 | 13 | add_library(mymathcustom MODULE MyMathCustom.cpp MyMathCustom.h) 14 | target_include_directories(mymathcustom PRIVATE $) 15 | 16 | add_executable(math_test_custom math_test_custom.cpp) 17 | target_link_libraries(math_test_custom PRIVATE sharedlibpp::sharedlibpp) 18 | -------------------------------------------------------------------------------- /examples/MyMath.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include "MyMath.h" 10 | #include 11 | 12 | SHLIBPP_DEFINE_SHARED_SUBCLASS(my_math, MyMathImpl, MyMath); 13 | 14 | int MyMathImpl::add(int a, int b) 15 | { 16 | return (a+b); 17 | } 18 | 19 | int MyMathImpl::sub(int a, int b) 20 | { 21 | return (a-b); 22 | } 23 | -------------------------------------------------------------------------------- /examples/MyMath.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef MYMATH_H 10 | #define MYMATH_H 11 | 12 | class MyMath 13 | { 14 | public: 15 | virtual int add(int a, int b) = 0; 16 | virtual int sub(int a, int b) = 0; 17 | }; 18 | 19 | class MyMathImpl : public MyMath 20 | { 21 | public: 22 | int add(int a, int b); 23 | int sub(int a, int b); 24 | }; 25 | 26 | #endif //_MYMATH_H_ 27 | -------------------------------------------------------------------------------- /examples/MyMathCustom.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include "MyMathCustom.h" 10 | #include 11 | 12 | SHLIBPP_DEFINE_SHARED_SUBCLASS_CUSTOM(CUSTOM_START_CHECK, CUSTOM_END_CHECK, CUSTOM_SYSTEM_VERSION, my_math_custom, MyMathCustomImpl, MyMathCustom); 13 | 14 | int MyMathCustomImpl::add(int a, int b) 15 | { 16 | return (a+b); 17 | } 18 | 19 | int MyMathCustomImpl::sub(int a, int b) 20 | { 21 | return (a-b); 22 | } 23 | -------------------------------------------------------------------------------- /examples/MyMathCustom.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef MYMATHCUSTOM_H 10 | #define MYMATHCUSTOM_H 11 | 12 | #include 13 | 14 | constexpr int32_t CUSTOM_START_CHECK = 15 | static_cast('T') + 16 | (static_cast('E') << 8) + 17 | (static_cast('S') << 16) + 18 | (static_cast('T') << 24); 19 | constexpr int32_t CUSTOM_END_CHECK = 20 | static_cast('T') + 21 | (static_cast('S') << 8) + 22 | (static_cast('E') << 16) + 23 | (static_cast('T') << 24); 24 | constexpr int32_t CUSTOM_SYSTEM_VERSION = 42; 25 | 26 | class MyMathCustom 27 | { 28 | public: 29 | virtual int add(int a, int b) = 0; 30 | virtual int sub(int a, int b) = 0; 31 | }; 32 | 33 | class MyMathCustomImpl : public MyMathCustom 34 | { 35 | public: 36 | int add(int a, int b); 37 | int sub(int a, int b); 38 | }; 39 | 40 | #endif //_MYMATH_H_ 41 | -------------------------------------------------------------------------------- /examples/math_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include 10 | #include "MyMath.h" 11 | 12 | #include 13 | #include 14 | 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | 19 | if(argc < 2) { 20 | printf("Usage: %s \n", argv[0]); 21 | printf("for example: %s mymath\n", argv[0]); 22 | return 0; 23 | } 24 | 25 | // create an instance of shared library class factory to load the library 26 | printf("Loading the shared library... \n"); 27 | sharedlibpp::SharedLibraryClassFactory myMathFactory(argv[1], "my_math"); 28 | if (!myMathFactory.isValid()) { 29 | printf("error (%d) : %s\n", static_cast(myMathFactory.getStatus()), 30 | myMathFactory.getError().c_str()); 31 | return 1; 32 | } 33 | 34 | // create an instance of the class and call its functions 35 | sharedlibpp::SharedLibraryClass myMath(myMathFactory); 36 | printf("Calling some of its functions... \n"); 37 | printf("15 + 12 = %d\n", myMath->add(15, 12)); 38 | printf("15 - 12 = %d\n", myMath->sub(15, 12)); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/math_test_custom.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include 10 | #include "MyMathCustom.h" 11 | 12 | #include 13 | #include 14 | 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | 19 | if(argc < 2) { 20 | printf("Usage: %s \n", argv[0]); 21 | printf("for example: %s mymath\n", argv[0]); 22 | return 0; 23 | } 24 | 25 | // create an instance of shared library class factory to load the library 26 | printf("Loading the shared library... \n"); 27 | sharedlibpp::SharedLibraryClassFactory myMathFactory(argv[1], 28 | CUSTOM_START_CHECK, 29 | CUSTOM_END_CHECK, 30 | CUSTOM_SYSTEM_VERSION, 31 | "my_math_custom"); 32 | if (!myMathFactory.isValid()) { 33 | printf("error (%d) : %s\n", static_cast(myMathFactory.getStatus()), 34 | myMathFactory.getError().c_str()); 35 | return 1; 36 | } 37 | 38 | // create an instance of the class and call its functions 39 | sharedlibpp::SharedLibraryClass myMath(myMathFactory); 40 | printf("Calling some of its functions... \n"); 41 | printf("15 + 12 = %d\n", myMath->add(15, 12)); 42 | printf("15 - 12 = %d\n", myMath->sub(15, 12)); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /pixi.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "sharedlibpp" 3 | # As this version is currently ignored, we do not 4 | # waste effort in mantain it in synch with the value 5 | # specified in CMakeLists.txt 6 | version = "0.0.0" 7 | description = "iDynTree" 8 | authors = ["Silvio Traversaro "] 9 | channels = ["conda-forge"] 10 | platforms = ["linux-64", "linux-aarch64", "win-64", "osx-64", "osx-arm64"] 11 | 12 | [target.win.activation.env] 13 | CMAKE_INSTALL_PREFIX = "%CONDA_PREFIX%\\Library" 14 | 15 | [target.unix.activation.env] 16 | CMAKE_INSTALL_PREFIX = "$CONDA_PREFIX" 17 | 18 | [tasks] 19 | configure = { cmd = [ 20 | "cmake", 21 | "-DCMAKE_BUILD_TYPE=Release", 22 | "-DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX", 23 | "-DBUILD_TESTING:BOOL=ON", 24 | # Use the cross-platform Ninja generator 25 | "-G", 26 | "Ninja", 27 | # The source is in the root directory 28 | "-S", 29 | ".", 30 | # We wanna build in the .build directory 31 | "-B", 32 | ".build", 33 | ]} 34 | 35 | build = { cmd = "cmake --build .build --config Release", depends_on = ["configure"] } 36 | test = { cmd = "ctest --test-dir .build --build-config Release", depends_on = ["build"] } 37 | install = { cmd = ["cmake", "--install", ".build", "--config", "Release"], depends_on = ["build"] } 38 | uninstall = { cmd = ["cmake", "--build", ".build", "--target", "uninstall"]} 39 | 40 | 41 | [dependencies] 42 | cmake = "*" 43 | c-compiler = "*" 44 | cxx-compiler = "*" 45 | ninja = "*" 46 | pkg-config = "*" 47 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 2 | # All rights reserved. 3 | # 4 | # This software may be modified and distributed under the terms of the 5 | # BSD-3-Clause license. See the accompanying LICENSE file for details. 6 | 7 | include (GNUInstallDirs) 8 | 9 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sharedlibpp/config.h.in" 10 | "${CMAKE_CURRENT_BINARY_DIR}/sharedlibpp/config.h" 11 | @ONLY) 12 | 13 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sharedlibpp/version.h.in" 14 | "${CMAKE_CURRENT_BINARY_DIR}/sharedlibpp/version.h" 15 | @ONLY) 16 | 17 | set(sharedlibpp_HDRS "${CMAKE_CURRENT_BINARY_DIR}/sharedlibpp/config.h" 18 | "${CMAKE_CURRENT_BINARY_DIR}/sharedlibpp/version.h" 19 | sharedlibpp/api.h 20 | sharedlibpp/SharedLibraryClassApi.h 21 | sharedlibpp/SharedLibraryClassFactory.h 22 | sharedlibpp/SharedLibraryClassFactory-inl.h 23 | sharedlibpp/SharedLibraryClass.h 24 | sharedlibpp/SharedLibraryClass-inl.h 25 | sharedlibpp/SharedLibraryFactory.h 26 | sharedlibpp/SharedLibrary.h) 27 | 28 | set(sharedlibpp_SRCS version.cpp 29 | SharedLibrary.cpp 30 | SharedLibraryFactory.cpp) 31 | 32 | add_library(sharedlibpp ${sharedlibpp_SRCS} ${sharedlibpp_HDRS}) 33 | add_library(sharedlibpp::sharedlibpp ALIAS sharedlibpp) 34 | 35 | # Add build definitions 36 | if(NOT BUILD_SHARED_LIBS) 37 | target_compile_definitions(shlibpp PRIVATE SHLIBPP_STATIC) 38 | endif() 39 | set_target_properties(sharedlibpp PROPERTIES DEFINE_SYMBOL BUILDING_SHLIBPP) 40 | 41 | target_include_directories(sharedlibpp PUBLIC $ 42 | $ 43 | $) 44 | 45 | if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.8) 46 | message(AUTHOR_WARNING "CMAKE_MINIMUM_REQUIRED_VERSION is now ${CMAKE_MINIMUM_REQUIRED_VERSION}. This check can be removed") 47 | endif() 48 | if(CMAKE_VERSION VERSION_LESS 3.8) 49 | # Should be enough to enable c++11 50 | target_compile_features(sharedlibpp PUBLIC cxx_constexpr 51 | cxx_nullptr) 52 | else() 53 | target_compile_features(sharedlibpp PUBLIC cxx_std_11) 54 | endif() 55 | 56 | if(UNIX) 57 | target_link_libraries(sharedlibpp PRIVATE dl) 58 | endif() 59 | 60 | set_property(TARGET sharedlibpp PROPERTY PUBLIC_HEADER ${sharedlibpp_HDRS}) 61 | set_property(TARGET sharedlibpp PROPERTY VERSION ${sharedlibpp_VERSION}) 62 | set_property(TARGET sharedlibpp PROPERTY SOVERSION 1) 63 | 64 | install(TARGETS sharedlibpp 65 | EXPORT sharedlibpp 66 | COMPONENT sharedlibpp 67 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 68 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 69 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 70 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sharedlibpp) 71 | -------------------------------------------------------------------------------- /src/SharedLibrary.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include 10 | 11 | #if defined(_WIN32) 12 | # include 13 | #else 14 | # include 15 | #endif 16 | 17 | #include 18 | 19 | using namespace sharedlibpp; 20 | 21 | 22 | class SharedLibrary::Private 23 | { 24 | public: 25 | Private() : 26 | implementation(nullptr), 27 | err_message() 28 | { 29 | } 30 | 31 | void* implementation; 32 | std::string err_message; 33 | }; 34 | 35 | SharedLibrary::SharedLibrary() : 36 | mPriv(new Private) 37 | { 38 | } 39 | 40 | SharedLibrary::SharedLibrary(const char *filename) : 41 | SharedLibrary() 42 | { 43 | open(filename); 44 | } 45 | 46 | SharedLibrary::~SharedLibrary() 47 | { 48 | close(); 49 | delete mPriv; 50 | } 51 | 52 | bool SharedLibrary::open(const char *filename) 53 | { 54 | mPriv->err_message.clear(); 55 | close(); 56 | #if defined(_WIN32) 57 | mPriv->implementation = (void*)LoadLibrary(filename); 58 | if (!mPriv->implementation) { 59 | LPTSTR msg = nullptr; 60 | FormatMessage( 61 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 62 | nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 63 | (LPTSTR)&msg, 0, nullptr); 64 | 65 | if (msg != nullptr) { 66 | mPriv->err_message = std::string(msg); 67 | // release memory allocated by FormatMessage() 68 | LocalFree(msg); msg = nullptr; 69 | } 70 | } 71 | return (mPriv->implementation != nullptr); 72 | #else 73 | mPriv->implementation = dlopen(filename, RTLD_LAZY); 74 | if (!mPriv->implementation) { 75 | char* msg = dlerror(); 76 | if (msg) 77 | mPriv->err_message = msg; 78 | } 79 | return mPriv->implementation != nullptr; 80 | #endif 81 | } 82 | 83 | bool SharedLibrary::close() { 84 | bool error = false; 85 | if (mPriv->implementation != nullptr) { 86 | #if defined(WIN32) 87 | auto result = FreeLibrary((HINSTANCE)mPriv->implementation); 88 | if (!result) { 89 | error = true; 90 | LPTSTR msg = nullptr; 91 | FormatMessage( 92 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 93 | nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 94 | (LPTSTR)&msg, 0, nullptr); 95 | 96 | if (msg != nullptr) { 97 | mPriv->err_message = std::string(msg); 98 | // release memory allocated by FormatMessage() 99 | LocalFree(msg); msg = nullptr; 100 | } 101 | } 102 | #else 103 | auto result = dlclose(mPriv->implementation); 104 | if (result != 0) { 105 | error = true; 106 | char* msg = dlerror(); 107 | if(msg) 108 | mPriv->err_message = msg; 109 | } 110 | #endif 111 | mPriv->implementation = nullptr; 112 | 113 | } 114 | return error; 115 | } 116 | 117 | std::string SharedLibrary::error() 118 | { 119 | return mPriv->err_message; 120 | } 121 | 122 | void *SharedLibrary::getSymbol(const char *symbolName) { 123 | mPriv->err_message.clear(); 124 | if (mPriv->implementation==nullptr) return nullptr; 125 | #if defined(_WIN32) 126 | FARPROC proc = GetProcAddress((HINSTANCE)mPriv->implementation, symbolName); 127 | LPTSTR msg = nullptr; 128 | FormatMessage( 129 | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 130 | nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 131 | (LPTSTR)&msg, 0, nullptr); 132 | 133 | if(msg != nullptr) { 134 | mPriv->err_message = std::string(msg); 135 | // release memory allocated by FormatMessage() 136 | LocalFree(msg); msg = nullptr; 137 | } 138 | return (void*)proc; 139 | #else 140 | dlerror(); 141 | void* func = dlsym(mPriv->implementation,symbolName); 142 | char* msg = dlerror(); 143 | if(msg) 144 | mPriv->err_message = msg; 145 | return func; 146 | #endif 147 | } 148 | 149 | bool SharedLibrary::isValid() const { 150 | return mPriv->implementation != nullptr; 151 | } 152 | -------------------------------------------------------------------------------- /src/SharedLibraryFactory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #if defined(_WIN32) 21 | # define shlibpp_struct_stat struct _stat 22 | # define shlibpp_stat ::_stat 23 | #else 24 | # define shlibpp_struct_stat struct ::stat 25 | # define shlibpp_stat ::stat 26 | #endif 27 | 28 | #if defined(WIN32) || defined(_WIN32) 29 | #define PATH_SEPARATOR "\\" 30 | #else 31 | #define PATH_SEPARATOR "/" 32 | #endif 33 | 34 | class sharedlibpp::SharedLibraryFactory::Private 35 | { 36 | public: 37 | Private(int32_t startCheck, 38 | int32_t endCheck, 39 | int32_t systemVersion, 40 | const char* factoryName); 41 | 42 | bool open(const char* dll_name); 43 | bool isValid() const; 44 | bool useFactoryFunction(void *factory); 45 | 46 | void extendSearchPath(const std::string& path); 47 | void readExtendedPathFromEnvironment(); 48 | std::string findLibraryInExtendedPath(const std::string& libraryName); 49 | static std::vector platformSpecificLibName(const std::string& library); 50 | 51 | SharedLibrary lib; 52 | SharedLibraryFactory::Status status; 53 | SharedLibraryClassApi api; 54 | int returnValue; 55 | int rct; // FIXME Remove this reference counter and use a shared_ptr instead. 56 | std::string name; 57 | std::string className; 58 | std::string baseClassName; 59 | std::string error; 60 | 61 | int32_t startCheck; 62 | int32_t endCheck; 63 | int32_t systemVersion; 64 | const char* factoryName; 65 | 66 | std::vector extendedPath; 67 | std::string pluginPathEnvVar = "SHLIBPP_PLUGIN_PATH"; 68 | }; 69 | 70 | 71 | 72 | sharedlibpp::SharedLibraryFactory::Private::Private(int32_t startCheck, 73 | int32_t endCheck, 74 | int32_t systemVersion, 75 | const char* factoryName) : 76 | status(Status::None), 77 | returnValue(0), 78 | rct(1), 79 | startCheck(startCheck), 80 | endCheck(endCheck), 81 | systemVersion(systemVersion), 82 | factoryName(factoryName) 83 | { 84 | memset(&api, 0, sizeof(SharedLibraryClassApi)); 85 | } 86 | 87 | std::vector sharedlibpp::SharedLibraryFactory::Private::platformSpecificLibName(const std::string& library) 88 | { 89 | 90 | #if defined(_WIN32) 91 | #if defined(NDEBUG) 92 | return {library + ".dll", library + "d.dll", "lib" + library + ".dll"}; 93 | #else 94 | return {library + "d.dll", library + ".dll", "lib" + library + ".dll"}; 95 | #endif 96 | #elif defined(__linux__) 97 | return {"lib" + library + ".so"}; 98 | #elif defined(__APPLE__) 99 | return {"lib" + library + ".dylib"}; 100 | #else 101 | #error "This platform not supported by this project" 102 | #endif 103 | } 104 | 105 | std::string sharedlibpp::SharedLibraryFactory::Private::findLibraryInExtendedPath(const std::string& libraryName) 106 | { 107 | std::size_t found = libraryName.find_first_of("\\/"); 108 | if (found != std::string::npos) { 109 | return {}; 110 | } 111 | 112 | for (const auto& path: extendedPath) { 113 | for (const auto& osLibName : platformSpecificLibName(libraryName)){ 114 | std::string absolutePath = path + PATH_SEPARATOR + osLibName; 115 | 116 | if (std::ifstream(absolutePath)) { 117 | return absolutePath; 118 | } 119 | } 120 | } 121 | 122 | return {}; 123 | } 124 | 125 | bool sharedlibpp::SharedLibraryFactory::Private::open(const char* dll_name) 126 | { 127 | returnValue = 0; 128 | name = ""; 129 | className = ""; 130 | baseClassName = ""; 131 | status = Status::None; 132 | error = ""; 133 | api.startCheck = 0; 134 | 135 | readExtendedPathFromEnvironment(); 136 | std::string pathToLib = findLibraryInExtendedPath(dll_name); 137 | 138 | if (pathToLib.empty()) { 139 | pathToLib = dll_name; 140 | } 141 | 142 | if (!lib.open(pathToLib.c_str())) { 143 | shlibpp_struct_stat dummy; 144 | if (shlibpp_stat(pathToLib.c_str(), &dummy) != 0) { 145 | status = Status::LibraryNotFound; 146 | } else { 147 | status = Status::LibraryNotLoaded; 148 | } 149 | error = lib.error(); 150 | return false; 151 | } 152 | void *fn = lib.getSymbol((factoryName != nullptr) ? factoryName : SHLIBPP_DEFAULT_FACTORY_NAME_STRING); 153 | if (fn == nullptr) { 154 | status = Status::FactoryNotFound; 155 | error = lib.error(); 156 | lib.close(); 157 | return false; 158 | } 159 | if (!useFactoryFunction(fn)) { 160 | status = Status::FactoryNotFunctional; 161 | error = "Hook in shared library misbehaved"; 162 | return false; 163 | } 164 | status = Status::OK; 165 | name = dll_name; 166 | 167 | char buf[256]; 168 | api.getClassName(buf, 256); 169 | className = buf; 170 | api.getBaseClassName(buf, 256); 171 | baseClassName = buf; 172 | 173 | return true; 174 | } 175 | 176 | bool sharedlibpp::SharedLibraryFactory::Private::isValid() const 177 | { 178 | if (returnValue != startCheck) { 179 | return false; 180 | } 181 | if (api.startCheck != startCheck) { 182 | return false; 183 | } 184 | if (api.structureSize != sizeof(SharedLibraryClassApi)) { 185 | return false; 186 | } 187 | if (api.systemVersion != systemVersion) { 188 | return false; 189 | } 190 | if (api.endCheck != endCheck) { 191 | return false; 192 | } 193 | return true; 194 | } 195 | 196 | bool sharedlibpp::SharedLibraryFactory::Private::useFactoryFunction(void *factory) 197 | { 198 | api.startCheck = 0; 199 | if (factory == nullptr) { 200 | return false; 201 | } 202 | returnValue = 203 | ((int (*)(void *ptr,int len)) factory)(&api,sizeof(SharedLibraryClassApi)); 204 | return isValid(); 205 | } 206 | 207 | void sharedlibpp::SharedLibraryFactory::Private::extendSearchPath(const std::string& path) 208 | { 209 | std::string pathToAdd = path; 210 | 211 | if (pathToAdd.back() == '/' || pathToAdd.back() == '\\') { 212 | pathToAdd.pop_back(); 213 | } 214 | 215 | for (const auto& storedPath : extendedPath) { 216 | if (storedPath == pathToAdd) { 217 | return; 218 | } 219 | } 220 | 221 | extendedPath.push_back(pathToAdd); 222 | } 223 | 224 | void sharedlibpp::SharedLibraryFactory::Private::readExtendedPathFromEnvironment() 225 | { 226 | std::string path; 227 | auto content = std::getenv(pluginPathEnvVar.c_str()); 228 | 229 | if (!content) { 230 | return; 231 | } 232 | 233 | std::stringstream envStream(content); 234 | 235 | #if defined(_WIN32) 236 | char delim = ';'; 237 | #else 238 | char delim = ':'; 239 | #endif 240 | 241 | while (getline(envStream, path, delim)) { 242 | extendSearchPath(path); 243 | } 244 | } 245 | 246 | sharedlibpp::SharedLibraryFactory::SharedLibraryFactory(int32_t startCheck, 247 | int32_t endCheck, 248 | int32_t systemVersion, 249 | const char *factoryName) : 250 | mPriv(new Private(startCheck, endCheck, systemVersion, factoryName)) 251 | { 252 | } 253 | 254 | sharedlibpp::SharedLibraryFactory::SharedLibraryFactory(const char *dll_name, 255 | int32_t startCheck, 256 | int32_t endCheck, 257 | int32_t systemVersion, 258 | const char *factoryName) : 259 | SharedLibraryFactory(startCheck, endCheck, systemVersion, factoryName) 260 | { 261 | mPriv->open(dll_name); 262 | } 263 | 264 | sharedlibpp::SharedLibraryFactory::SharedLibraryFactory(const char* dll_name, 265 | const char* factoryName) : 266 | SharedLibraryFactory(SHLIBPP_DEFAULT_START_CHECK, 267 | SHLIBPP_DEFAULT_END_CHECK, 268 | SHLIBPP_DEFAULT_SYSTEM_VERSION, 269 | factoryName) 270 | { 271 | mPriv->open(dll_name); 272 | } 273 | 274 | sharedlibpp::SharedLibraryFactory::~SharedLibraryFactory() 275 | { 276 | delete mPriv; 277 | } 278 | 279 | bool sharedlibpp::SharedLibraryFactory::open(const char *dll_name, 280 | int32_t startCheck, 281 | int32_t endCheck, 282 | int32_t systemVersion, 283 | const char *factoryName) 284 | { 285 | mPriv->startCheck = startCheck; 286 | mPriv->endCheck = endCheck; 287 | mPriv->systemVersion = systemVersion; 288 | mPriv->factoryName = factoryName; 289 | return mPriv->open(dll_name); 290 | } 291 | 292 | bool sharedlibpp::SharedLibraryFactory::open(const char* dll_name, const char* factoryName) 293 | { 294 | mPriv->startCheck = SHLIBPP_DEFAULT_START_CHECK; 295 | mPriv->endCheck = SHLIBPP_DEFAULT_END_CHECK; 296 | mPriv->systemVersion = SHLIBPP_DEFAULT_SYSTEM_VERSION; 297 | mPriv->factoryName = factoryName; 298 | return mPriv->open(dll_name); 299 | } 300 | 301 | void sharedlibpp::SharedLibraryFactory::setPluginPathEnvVarName(const std::string &env_var) 302 | { 303 | mPriv->pluginPathEnvVar = env_var; 304 | } 305 | 306 | void sharedlibpp::SharedLibraryFactory::extendSearchPath(const std::string& path) 307 | { 308 | mPriv->extendSearchPath(path); 309 | } 310 | 311 | bool sharedlibpp::SharedLibraryFactory::isValid() const 312 | { 313 | return mPriv->isValid(); 314 | } 315 | 316 | sharedlibpp::SharedLibraryFactory::Status sharedlibpp::SharedLibraryFactory::getStatus() const 317 | { 318 | return mPriv->status; 319 | } 320 | 321 | std::string sharedlibpp::SharedLibraryFactory::getError() const 322 | { 323 | return mPriv->error; 324 | } 325 | 326 | const sharedlibpp::SharedLibraryClassApi& sharedlibpp::SharedLibraryFactory::getApi() const 327 | { 328 | return mPriv->api; 329 | } 330 | 331 | int sharedlibpp::SharedLibraryFactory::getReferenceCount() const 332 | { 333 | return mPriv->rct; 334 | } 335 | 336 | int sharedlibpp::SharedLibraryFactory::addRef() 337 | { 338 | mPriv->rct++; 339 | return mPriv->rct; 340 | } 341 | 342 | int sharedlibpp::SharedLibraryFactory::removeRef() 343 | { 344 | mPriv->rct--; 345 | return mPriv->rct; 346 | } 347 | 348 | std::string sharedlibpp::SharedLibraryFactory::getName() const 349 | { 350 | return mPriv->name; 351 | } 352 | 353 | std::string sharedlibpp::SharedLibraryFactory::getClassName() const 354 | { 355 | return mPriv->className; 356 | } 357 | 358 | std::string sharedlibpp::SharedLibraryFactory::getBaseClassName() const 359 | { 360 | return mPriv->baseClassName; 361 | } 362 | 363 | bool sharedlibpp::SharedLibraryFactory::useFactoryFunction(void *factory) 364 | { 365 | return mPriv->useFactoryFunction(factory); 366 | } 367 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibrary.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARY_H 10 | #define SHAREDLIBPP_SHAREDLIBRARY_H 11 | 12 | #include 13 | #include 14 | 15 | namespace sharedlibpp { 16 | 17 | /** 18 | * Low-level wrapper for loading shared libraries (DLLs) and accessing 19 | * symbols within it. 20 | */ 21 | class SHLIBPP_API SharedLibrary 22 | { 23 | public: 24 | /** 25 | * Initialize, without opening a shared library yet. 26 | */ 27 | SharedLibrary(); 28 | 29 | /** 30 | * Load the named shared library / DLL. 31 | * 32 | * @param filename name of file (see open method) 33 | */ 34 | SharedLibrary(const char *filename); 35 | 36 | /** 37 | * Destructor. Will close() if needed. 38 | */ 39 | virtual ~SharedLibrary(); 40 | 41 | SharedLibrary(const SharedLibrary& rhs) = delete; 42 | SharedLibrary(SharedLibrary&& rhs) noexcept = delete; 43 | SharedLibrary& operator=(const SharedLibrary& rhs) = delete; 44 | SharedLibrary& operator=(SharedLibrary&& rhs) noexcept = delete; 45 | 46 | /** 47 | * Load the named shared library / DLL. The library is found 48 | * using the algoithm of ACE::ldfind. Operating-system-specific 49 | * extensions will be tried, and the relevant path for shared 50 | * libraries. 51 | * 52 | * @param filename name of file. 53 | * @return true on success 54 | */ 55 | bool open(const char *filename); 56 | 57 | /** 58 | * Shared library no longer needed, unload if not in use elsewhere. 59 | * @return true on success 60 | */ 61 | bool close(); 62 | 63 | /** 64 | * Returns a human-readable string describing the most recent error that 65 | * occurred from a call to one of its functions. 66 | * 67 | * @return the most recent error 68 | */ 69 | std::string error(); 70 | 71 | /** 72 | * Look up a symbol in the shared library. 73 | */ 74 | void *getSymbol(const char *symbolName); 75 | 76 | /** 77 | * Check if the shared library is valid 78 | * 79 | * @return true iff a valid library has been loaded. 80 | */ 81 | bool isValid() const; 82 | 83 | #ifndef DOXYGEN_SHOULD_SKIP_THIS 84 | private: 85 | class SHLIBPP_HIDDEN Private; 86 | Private* mPriv; 87 | #endif 88 | }; 89 | 90 | } // namespace sharedlibpp 91 | 92 | #endif // SHAREDLIBPP_SHAREDLIBRARY_H 93 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibraryClass-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARYCLASS_INL_H 10 | #define SHAREDLIBPP_SHAREDLIBRARYCLASS_INL_H 11 | 12 | 13 | template 14 | sharedlibpp::SharedLibraryClass::SharedLibraryClass() : 15 | content(nullptr), 16 | pfactory(nullptr) 17 | { 18 | } 19 | 20 | template 21 | sharedlibpp::SharedLibraryClass::SharedLibraryClass(SharedLibraryClassFactory& factory) : 22 | SharedLibraryClass() 23 | { 24 | open(factory); 25 | } 26 | 27 | template 28 | sharedlibpp::SharedLibraryClass::~SharedLibraryClass() 29 | { 30 | close(); 31 | } 32 | 33 | template 34 | bool sharedlibpp::SharedLibraryClass::open(SharedLibraryClassFactory& factory) 35 | { 36 | close(); 37 | content = factory.create(); 38 | pfactory = &factory; 39 | factory.addRef(); 40 | 41 | return content != nullptr; 42 | } 43 | 44 | template 45 | bool sharedlibpp::SharedLibraryClass::close() 46 | { 47 | if (content != nullptr) { 48 | pfactory->destroy(content); 49 | if (pfactory->removeRef() == 0) { 50 | delete pfactory; 51 | } 52 | } 53 | 54 | content = nullptr; 55 | pfactory = nullptr; 56 | 57 | return true; 58 | } 59 | 60 | template 61 | T& sharedlibpp::SharedLibraryClass::getContent() 62 | { 63 | return *content; 64 | } 65 | 66 | template 67 | const T& sharedlibpp::SharedLibraryClass::getContent() const 68 | { 69 | return *content; 70 | } 71 | 72 | template 73 | bool sharedlibpp::SharedLibraryClass::isValid() const 74 | { 75 | return content != nullptr; 76 | } 77 | 78 | 79 | template 80 | T& sharedlibpp::SharedLibraryClass::operator*() 81 | { 82 | return (*content); 83 | } 84 | 85 | 86 | template 87 | const T& sharedlibpp::SharedLibraryClass::operator*() const 88 | { 89 | return (*content); 90 | } 91 | 92 | 93 | template 94 | T* sharedlibpp::SharedLibraryClass::operator->() 95 | { 96 | return (content); 97 | } 98 | 99 | template 100 | const T* sharedlibpp::SharedLibraryClass::operator->() const 101 | { 102 | return (content); 103 | } 104 | 105 | #endif // SHAREDLIBPP_SHAREDLIBRARYCLASS_INL_H 106 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibraryClass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARYCLASS_H 10 | #define SHAREDLIBPP_SHAREDLIBRARYCLASS_H 11 | 12 | #include 13 | 14 | namespace sharedlibpp { 15 | 16 | /** 17 | * Container for an object created using a factory provided by a shared library. 18 | * Used to ensure the object is destroyed by a method also provided by the 19 | * shared library. Mixing creation and destruction methods could be very bad. 20 | */ 21 | template 22 | class SharedLibraryClass 23 | { 24 | public: 25 | 26 | /** 27 | * Constructor for empty instance. 28 | */ 29 | SharedLibraryClass(); 30 | 31 | /** 32 | * Constructor for valid instance of a class from a shared library. 33 | * 34 | * @param factory the factory to use to construct (and eventually 35 | * destroy) the instance. 36 | */ 37 | SharedLibraryClass(SharedLibraryClassFactory& factory); 38 | 39 | /** 40 | * Destructor. 41 | */ 42 | virtual ~SharedLibraryClass(); 43 | 44 | /** 45 | * Construct an instance using the specified factory. If an 46 | * instance has already been made, it is destroyed. 47 | * 48 | * @param factory the factory to use to construct (and eventually 49 | * destroy) the instance. 50 | * @return true on success 51 | */ 52 | bool open(SharedLibraryClassFactory& factory); 53 | 54 | /** 55 | * Destroy an instance if one has been created. 56 | * 57 | * @return true on success 58 | */ 59 | virtual bool close(); 60 | 61 | /** 62 | * Gives access to the created instance. 63 | * 64 | * No check made to ensure an instance is in fact present. 65 | * Call SharedLibraryClass::isValid first if unsure. 66 | * 67 | * @return the created instance 68 | */ 69 | T& getContent(); 70 | 71 | /** 72 | * Gives access to the created instance (const version). 73 | * 74 | * No check made to ensure an instance is in fact present. 75 | * Call SharedLibraryClass::isValid first if unsure. 76 | * 77 | * @return the created instance 78 | */ 79 | const T& getContent() const; 80 | 81 | /** 82 | * Check whether a valid instance has been created. 83 | * 84 | * @return true iff a valid instance has been created 85 | */ 86 | bool isValid() const; 87 | 88 | /** 89 | * Shorthand for SharedLibraryClass::getContent 90 | * 91 | * @return the created instance 92 | */ 93 | T& operator*(); 94 | 95 | /** 96 | * Shorthand for SharedLibraryClass::getContent (const version) 97 | * 98 | * @return the created instance 99 | */ 100 | const T& operator*() const; 101 | 102 | /** 103 | * A pointer version of SharedLibraryClass::getContent 104 | * 105 | * @return a pointer to the created instance, or nullptr if there is none 106 | */ 107 | T* operator->(); 108 | 109 | /** 110 | * A pointer version of SharedLibraryClass::getContent (const version) 111 | * 112 | * @return a pointer to the created instance, or nullptr if there is none 113 | */ 114 | const T* operator->() const; 115 | 116 | #ifndef DOXYGEN_SHOULD_SKIP_THIS 117 | private: 118 | T* content; 119 | SharedLibraryClassFactory *pfactory; 120 | #endif 121 | }; 122 | 123 | } // namespace sharedlibpp 124 | 125 | 126 | #include 127 | 128 | #endif // SHAREDLIBPP_SHAREDLIBRARYCLASS_H 129 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibraryClassApi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARYCLASSAPI_H 10 | #define SHAREDLIBPP_SHAREDLIBRARYCLASSAPI_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace sharedlibpp { 17 | 18 | // Be careful loading C++ classes from DLLs. Generally you 19 | // need an exact or very close match between compilers used 20 | // to compile those DLLs and your own code. 21 | 22 | extern "C" { 23 | 24 | /** 25 | * Collection of hooks for creating/destroying a plugin. 26 | * Be careful to check carefully for compatibility before 27 | * using create() or destroy(). 28 | */ 29 | struct SHLIBPP_API SharedLibraryClassApi { 30 | public: 31 | int32_t startCheck; // A 32-bit integer that is checked when loading 32 | // a plugin. 33 | // Don't touch anything further if it isn't. 34 | int32_t structureSize; // size of the SharedLibraryClassApi. 35 | // If this doesn't match what you expect, 36 | // Don't touch anything further if it isn't. 37 | int32_t systemVersion; // Overall version of plugin system. 38 | // This does *not* cover compiler version etc. 39 | 40 | using createFn_t = void*(*)(); 41 | using destroyFn_t = void(*)(void*); 42 | using getFn_t = int32_t(*)(char*, size_t); 43 | 44 | createFn_t create; // Instantiate a plugin object. 45 | destroyFn_t destroy; // Destroy a plugin object. 46 | getFn_t getVersion; // Plugin-related version. 47 | getFn_t getAbi; // Compiler-related version. 48 | getFn_t getClassName; // Name of plugin (subclass). 49 | getFn_t getBaseClassName; // Name superclass. 50 | 51 | int32_t roomToGrow[SHLIBPP_SHAREDLIBRARYCLASSAPI_PADDING]; // Padding. 52 | int32_t endCheck; // A 32-bit integer that is checked when loading 53 | // a plugin. 54 | }; 55 | 56 | } // extern "C" 57 | 58 | } // namespace sharedlibpp 59 | 60 | 61 | #define SHLIBPP_SHARED_CLASS_FN extern "C" SHLIBPP_EXPORT 62 | 63 | constexpr int32_t SHLIBPP_DEFAULT_START_CHECK = 64 | static_cast('S') + 65 | (static_cast('H') << 8) + 66 | (static_cast('P') << 16) + 67 | (static_cast('P') << 24); 68 | constexpr int32_t SHLIBPP_DEFAULT_END_CHECK = 69 | static_cast('P') + 70 | (static_cast('L') << 8) + 71 | (static_cast('U') << 16) + 72 | (static_cast('G') << 24); 73 | constexpr int32_t SHLIBPP_DEFAULT_SYSTEM_VERSION = 5; 74 | #define SHLIBPP_DEFAULT_FACTORY_NAME shlibpp_default_factory 75 | 76 | #define SHLIBPP_STRINGIFY2(X) #X 77 | #define SHLIBPP_STRINGIFY(X) SHLIBPP_STRINGIFY2(X) 78 | #define SHLIBPP_DEFAULT_FACTORY_NAME_STRING SHLIBPP_STRINGIFY(SHLIBPP_DEFAULT_FACTORY_NAME) 79 | 80 | 81 | /** 82 | * Macro to create a bunch of functions with undecorated names that can 83 | * be found within a plugin library to handle creation/deletion of that 84 | * plugin. Use with care. 85 | * 86 | * @param factoryname the name of the "hook" function to make. 87 | * A collection of other helper functions with names composed of the 88 | * factoryname with _create/_destroy/... appended. 89 | * @param startcheck a 32-bit integer that is checked when loading a plugin. 90 | * @param endcheck a 32-bit integer that is checked when loading a plugin. 91 | * @param systemversiona a 32-bit integer representing the version of the plugin 92 | * api that is checked when loading a plugin. 93 | * @param classname the class that the hook will be able to instantiate. 94 | * @param basename the superclass that the user of the plugin should be 95 | * working with. 96 | */ 97 | #define SHLIBPP_DEFINE_SHARED_SUBCLASS_CUSTOM(startcheck, endcheck, systemversion, factoryname, classname, basename) \ 98 | SHLIBPP_SHARED_CLASS_FN void* factoryname ## _create () \ 99 | { \ 100 | classname* cn = new classname; \ 101 | basename* bn = dynamic_cast(cn); \ 102 | if (!bn) { \ 103 | delete cn; \ 104 | } \ 105 | return static_cast(bn); \ 106 | } \ 107 | \ 108 | SHLIBPP_SHARED_CLASS_FN void factoryname ## _destroy (void* obj) \ 109 | { \ 110 | classname* cn = dynamic_cast(static_cast(obj)); \ 111 | if(cn) { \ 112 | delete cn; \ 113 | } \ 114 | } \ 115 | \ 116 | SHLIBPP_SHARED_CLASS_FN int32_t factoryname ## _getVersion (char* ver, size_t len) \ 117 | { \ 118 | return 0; \ 119 | } \ 120 | \ 121 | SHLIBPP_SHARED_CLASS_FN int32_t factoryname ## _getAbi (char* abi, size_t len) \ 122 | { \ 123 | return 0; \ 124 | } \ 125 | \ 126 | SHLIBPP_SHARED_CLASS_FN int32_t factoryname ## _getClassName (char* name, size_t len) \ 127 | { \ 128 | char cname[] = # classname; \ 129 | strncpy(name, cname, len); \ 130 | return static_cast(strlen(cname) + 1); \ 131 | } \ 132 | \ 133 | SHLIBPP_SHARED_CLASS_FN int32_t factoryname ## _getBaseClassName (char* name, size_t len) \ 134 | { \ 135 | char cname[] = # basename; \ 136 | strncpy(name, cname, len); \ 137 | return static_cast(strlen(cname) + 1); \ 138 | } \ 139 | \ 140 | SHLIBPP_SHARED_CLASS_FN int32_t factoryname(void* api, size_t len) { \ 141 | struct sharedlibpp::SharedLibraryClassApi* sapi = static_cast(api); \ 142 | if (len < sizeof(sharedlibpp::SharedLibraryClassApi)) { \ 143 | return -1; \ 144 | } \ 145 | sapi->startCheck = startcheck; \ 146 | sapi->structureSize = sizeof(sharedlibpp::SharedLibraryClassApi); \ 147 | sapi->systemVersion = systemversion; \ 148 | sapi->create = factoryname ## _create; \ 149 | sapi->destroy = factoryname ## _destroy; \ 150 | sapi->getVersion = factoryname ## _getVersion; \ 151 | sapi->getAbi = factoryname ## _getAbi; \ 152 | sapi->getClassName = factoryname ## _getClassName; \ 153 | sapi->getBaseClassName = factoryname ## _getBaseClassName; \ 154 | for (int i=0; iroomToGrow[i] = 0; \ 156 | } \ 157 | sapi->endCheck = endcheck; \ 158 | return sapi->startCheck; \ 159 | } 160 | // The double cast in the _create() and _destroy() functions are 161 | // required to ensure that everything works when `basename` is not the 162 | // first inherited class: 163 | // _create() will return a valid `basename` or a null pointer if 164 | // `classname` does not inherit from `basename`. 165 | // _destroy() will ensure that we are calling `classname` destructor 166 | // even if `basename` is not the first inherited class. If the 167 | // dynamic_cast fails, it will not delete the object (that is probably 168 | // leaked), but it is less dangerous than executing some other random 169 | // function. 170 | 171 | #define SHLIBPP_DEFINE_SHARED_SUBCLASS(factoryname, classname, basename) \ 172 | SHLIBPP_DEFINE_SHARED_SUBCLASS_CUSTOM(SHLIBPP_DEFAULT_START_CHECK, \ 173 | SHLIBPP_DEFAULT_END_CHECK, \ 174 | SHLIBPP_DEFAULT_SYSTEM_VERSION, \ 175 | factoryname, \ 176 | classname, \ 177 | basename) 178 | 179 | #define SHLIBPP_DEFINE_DEFAULT_SHARED_CLASS(classname) \ 180 | SHLIBPP_DEFINE_SHARED_SUBCLASS_CUSTOM(SHLIBPP_DEFAULT_START_CHECK, \ 181 | SHLIBPP_DEFAULT_END_CHECK, \ 182 | SHLIBPP_DEFAULT_SYSTEM_VERSION, \ 183 | SHLIBPP_DEFAULT_FACTORY_NAME, \ 184 | classname, \ 185 | classname) 186 | 187 | #define SHLIBPP_DEFINE_SHARED_CLASS(factoryname, classname) \ 188 | SHLIBPP_DEFINE_SHARED_SUBCLASS_CUSTOM(SHLIBPP_DEFAULT_START_CHECK, \ 189 | SHLIBPP_DEFAULT_END_CHECK, \ 190 | SHLIBPP_DEFAULT_SYSTEM_VERSION, \ 191 | factoryname, \ 192 | classname, \ 193 | classname) 194 | 195 | #endif // SHAREDLIBPP_SHAREDLIBRARYCLASSAPI_H 196 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibraryClassFactory-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARYCLASSFACTORY_INL_H 10 | #define SHAREDLIBPP_SHAREDLIBRARYCLASSFACTORY_INL_H 11 | 12 | template 13 | sharedlibpp::SharedLibraryClassFactory::SharedLibraryClassFactory(int32_t startCheck, 14 | int32_t endCheck, 15 | int32_t systemVersion, 16 | const char *factoryName) : 17 | SharedLibraryFactory(startCheck, endCheck, systemVersion, factoryName) 18 | { 19 | } 20 | 21 | template 22 | sharedlibpp::SharedLibraryClassFactory::SharedLibraryClassFactory(const char *dll_name, 23 | int32_t startCheck, 24 | int32_t endCheck, 25 | int32_t systemVersion, 26 | const char *factoryName) : 27 | SharedLibraryFactory(dll_name, startCheck, endCheck, systemVersion, factoryName) 28 | { 29 | } 30 | 31 | template 32 | sharedlibpp::SharedLibraryClassFactory::SharedLibraryClassFactory(const char *dll_name, 33 | const char *factoryName) : 34 | SharedLibraryFactory(dll_name, factoryName) 35 | { 36 | } 37 | 38 | template 39 | T* sharedlibpp::SharedLibraryClassFactory::create() const 40 | { 41 | if (!isValid()) { 42 | return nullptr; 43 | } 44 | return static_cast(getApi().create()); 45 | } 46 | 47 | template 48 | void sharedlibpp::SharedLibraryClassFactory::destroy(T *obj) const 49 | { 50 | if (!isValid()) { 51 | return; 52 | } 53 | getApi().destroy(obj); 54 | } 55 | 56 | #endif // SHAREDLIBPP_SHAREDLIBRARYCLASSFACTORY_INL_H 57 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibraryClassFactory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARYCLASSFACTORY_H 10 | #define SHAREDLIBPP_SHAREDLIBRARYCLASSFACTORY_H 11 | 12 | #include 13 | #include 14 | 15 | namespace sharedlibpp { 16 | 17 | /** 18 | * A type-safe wrapper for SharedLibraryFactory, committing to 19 | * creation/destruction of instances of a particular super-class. 20 | * 21 | * Note that we take on faith that the named factory method in the 22 | * named shared library does in fact create the named type. 23 | */ 24 | template 25 | class SharedLibraryClassFactory : public SharedLibraryFactory 26 | { 27 | public: 28 | explicit SharedLibraryClassFactory(int32_t startCheck = SHLIBPP_DEFAULT_START_CHECK, 29 | int32_t endCheck = SHLIBPP_DEFAULT_END_CHECK, 30 | int32_t systemVersion = SHLIBPP_DEFAULT_SYSTEM_VERSION, 31 | const char *factoryName = nullptr); 32 | 33 | explicit SharedLibraryClassFactory(const char *dll_name, 34 | int32_t startCheck = SHLIBPP_DEFAULT_START_CHECK, 35 | int32_t endCheck = SHLIBPP_DEFAULT_END_CHECK, 36 | int32_t systemVersion = SHLIBPP_DEFAULT_SYSTEM_VERSION, 37 | const char *factoryName = nullptr); 38 | 39 | explicit SharedLibraryClassFactory(const char *dll_name, 40 | const char *factoryName = nullptr); 41 | 42 | T *create() const; 43 | 44 | void destroy(T *obj) const; 45 | }; 46 | 47 | } // namespace sharedlibpp 48 | 49 | #include 50 | 51 | #endif // SHAREDLIBPP_SHAREDLIBRARYCLASSFACTORY_H 52 | -------------------------------------------------------------------------------- /src/sharedlibpp/SharedLibraryFactory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_SHAREDLIBRARYFACTORY_H 10 | #define SHAREDLIBPP_SHAREDLIBRARYFACTORY_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace sharedlibpp { 17 | 18 | struct SharedLibraryClassApi; 19 | 20 | /** 21 | * A wrapper for a named factory method in a named shared library. 22 | * This wrapper will do some basic checks that the named method does 23 | * indeed behave like a shlibpp plugin hook before offering access to it. 24 | * This is to avoid accidents, it is not a security mechanism. 25 | */ 26 | class SHLIBPP_API SharedLibraryFactory 27 | { 28 | public: 29 | /** 30 | * The status of a factory can be: 31 | * - None: Not configured yet 32 | * - OK: Present and sane 33 | * - LibraryNotFound: Named shared library was not found 34 | * - LibraryNotLoaded: Named shared library failed to load 35 | * - FactoryNotFound: Named method wasn't present in library 36 | * - FactoryNotFunctional: Named method is not working right 37 | */ 38 | enum class Status : std::uint32_t 39 | { 40 | None = 0, //!< Not configured yet. 41 | OK, //!< Present and sane. 42 | LibraryNotFound, //!< Named shared library was not found. 43 | LibraryNotLoaded, //!< Named shared library failed to load. 44 | FactoryNotFound, //!< Named method wasn't present in library. 45 | FactoryNotFunctional //!< Named method is not working right. 46 | }; 47 | 48 | /** 49 | * Constructor for unconfigured factory with custom start check, end check, 50 | * system version and factory name. 51 | * 52 | * @param startCheck a 32-bit integer that is checked when loading a plugin. 53 | * It must be the same used when creating the plugin 54 | * @param endCheck a 32-bit integer that is checked when loading a plugin. 55 | * It must be the same used when creating the plugin 56 | * @param systemVersion a number representing the version of the plugin api 57 | * that is checked when loading a plugin. 58 | * It must be the same used when creating the plugin. 59 | * @param factoryName name of factory method, a symbol within the shared 60 | * library. 61 | * If set, it must be the same used when creating the 62 | * plugin. 63 | */ 64 | explicit SharedLibraryFactory(int32_t startCheck = -1, 65 | int32_t endCheck = -1, 66 | int32_t systemVersion = -1, 67 | const char *factoryName = nullptr); 68 | 69 | /** 70 | * Constructor with custom start check, end check, system version and 71 | * factoryName 72 | * 73 | * @param dll_name name/path of shared library. 74 | * @param startCheck a 32-bit integer that is checked when loading a plugin. 75 | * It must be the same used when creating the plugin 76 | * @param endCheck a 32-bit integer that is checked when loading a plugin. 77 | * It must be the same used when creating the plugin 78 | * @param systemVersion a number representing the version of the plugin api 79 | * that is checked when loading a plugin. 80 | * It must be the same used when creating the plugin. 81 | * @param factoryName name of factory method, a symbol within the shared 82 | * library. 83 | * If set, it must be the same used when creating the 84 | * plugin. 85 | */ 86 | SharedLibraryFactory(const char *dll_name, 87 | int32_t startCheck = -1, 88 | int32_t endCheck = -1, 89 | int32_t systemVersion = -1, 90 | const char *factoryName = nullptr); 91 | 92 | /** 93 | * Constructor with default start check, end check and system version. 94 | * 95 | * @param dll_name name/path of shared library. 96 | * @param factoryName name of factory method, a symbol within the shared 97 | * library. 98 | * If set, it must be the same used when creating the 99 | * plugin. 100 | */ 101 | SharedLibraryFactory(const char *dll_name, 102 | const char *factoryName = nullptr); 103 | 104 | /** 105 | * Destructor 106 | */ 107 | virtual ~SharedLibraryFactory(); 108 | 109 | /** 110 | * Configure the factory. 111 | * 112 | * @param dll_name name/path of shared library. 113 | * @param startCheck a 32-bit integer that is checked when loading a plugin. 114 | * It must be the same used when creating the plugin 115 | * @param endCheck a 32-bit integer that is checked when loading a plugin. 116 | * It must be the same used when creating the plugin 117 | * @param systemVersion a number representing the version of the plugin api 118 | * that is checked when loading a plugin. 119 | * It must be the same used when creating the plugin. 120 | * @param factoryName name of factory method, a symbol within the shared 121 | * library. 122 | * If set, it must be the same used when creating the 123 | * plugin. 124 | * @return true on success. 125 | */ 126 | bool open(const char *dll_name, 127 | int32_t startCheck = -1, 128 | int32_t endCheck = -1, 129 | int32_t systemVersion = -1, 130 | const char *factoryName = nullptr); 131 | 132 | /** 133 | * Configure the factory. 134 | * 135 | * @param dll_name name/path of shared library. 136 | * @param factoryName name of factory method, a symbol within the shared 137 | * library. 138 | * If set, it must be the same used when creating the 139 | * plugin. 140 | * @return true on success. 141 | */ 142 | bool open(const char *dll_name, 143 | const char *factoryName = nullptr); 144 | 145 | /** 146 | * Set the name of the environment variable that extends the search path 147 | * @param env_var The name of the environment variable 148 | */ 149 | void setPluginPathEnvVarName(const std::string& env_var); 150 | 151 | /** 152 | * Add path to search for plugins 153 | * 154 | * @param path The new path to be added. 155 | */ 156 | void extendSearchPath(const std::string& path); 157 | 158 | /** 159 | * Check if factory is configured and present. 160 | * 161 | * @return true iff factory is good to go. 162 | */ 163 | bool isValid() const; 164 | 165 | /** 166 | * Get the status of the factory. 167 | * 168 | * @return one of the SharedLibraryFactory::STATUS_* codes. 169 | */ 170 | Status getStatus() const; 171 | 172 | /** 173 | * Get the latest error of the factory. 174 | * 175 | * @return the latest error. 176 | */ 177 | std::string getError() const; 178 | 179 | /** 180 | 181 | * Get the factory API, which has creation/deletion methods. 182 | * 183 | * @return the factory API 184 | */ 185 | const SharedLibraryClassApi& getApi() const; 186 | 187 | /** 188 | * Get the current reference count of this factory. 189 | * 190 | * @return the current reference count of this factory. 191 | */ 192 | int getReferenceCount() const; 193 | 194 | /** 195 | * Increment the reference count of this factory. 196 | * 197 | * @return the current reference count of this factory, after increment. 198 | */ 199 | int addRef(); 200 | 201 | /** 202 | * Decrement the reference count of this factory. 203 | * 204 | * @return the current reference count of this factory, after decrement. 205 | */ 206 | int removeRef(); 207 | 208 | /** 209 | * Get the name associated with this factory. 210 | * 211 | * @return the name associated with this factory. 212 | */ 213 | std::string getName() const; 214 | 215 | /** 216 | * Get the type associated with this factory. 217 | * 218 | * @return the type associated with this factory. 219 | */ 220 | std::string getClassName() const; 221 | 222 | /** 223 | * Get the base type associated with this factory. 224 | * 225 | * @return the base type associated with this factory. 226 | */ 227 | std::string getBaseClassName() const; 228 | 229 | /** 230 | * 231 | * Specify function to use as factory. 232 | * 233 | * @param factory function to use as factory. 234 | * 235 | * @result true on success. 236 | * 237 | */ 238 | bool useFactoryFunction(void *factory); 239 | 240 | #ifndef DOXYGEN_SHOULD_SKIP_THIS 241 | private: 242 | class SHLIBPP_HIDDEN Private; 243 | Private* mPriv; 244 | #endif 245 | }; 246 | 247 | } // namespace sharedlibpp 248 | 249 | #endif // SHAREDLIBPP_SHAREDLIBRARYFACTORY_H 250 | -------------------------------------------------------------------------------- /src/sharedlibpp/api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_API_H 10 | #define SHAREDLIBPP_API_H 11 | 12 | #if defined _WIN32 || defined __CYGWIN__ 13 | # define SHLIBPP_HELPER_DLL_EXPORT __declspec(dllexport) 14 | # define SHLIBPP_HELPER_DLL_IMPORT __declspec(dllimport) 15 | # define SHLIBPP_HELPER_DLL_LOCAL 16 | #else 17 | # if __GNUC__ >= 4 18 | # define SHLIBPP_HELPER_DLL_EXPORT __attribute__ ((visibility("default"))) 19 | # define SHLIBPP_HELPER_DLL_IMPORT __attribute__ ((visibility("default"))) 20 | # define SHLIBPP_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden"))) 21 | # else 22 | # define SHLIBPP_HELPER_DLL_EXPORT 23 | # define SHLIBPP_HELPER_DLL_IMPORT 24 | # define SHLIBPP_HELPER_DLL_LOCAL 25 | # endif 26 | #endif 27 | 28 | #define SHLIBPP_EXPORT SHLIBPP_HELPER_DLL_EXPORT 29 | #define SHLIBPP_IMPORT SHLIBPP_HELPER_DLL_IMPORT 30 | #define SHLIBPP_LOCAL SHLIBPP_HELPER_DLL_LOCAL 31 | 32 | #ifdef SHLIBPP_STATIC 33 | # define SHLIBPP_API 34 | # define SHLIBPP_HIDDEN 35 | #else 36 | # ifdef BUILDING_SHLIBPP 37 | # define SHLIBPP_API SHLIBPP_HELPER_DLL_EXPORT 38 | # else 39 | # define SHLIBPP_API SHLIBPP_HELPER_DLL_IMPORT 40 | # endif 41 | # define SHLIBPP_HIDDEN SHLIBPP_HELPER_DLL_LOCAL 42 | #endif 43 | 44 | #endif // SHAREDLIBPP_API_H 45 | -------------------------------------------------------------------------------- /src/sharedlibpp/config.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_CONFIG_H 10 | #define SHAREDLIBPP_CONFIG_H 11 | 12 | #define SHLIBPP_POINTER_SIZE @CMAKE_SIZEOF_VOID_P@ 13 | #define SHLIBPP_SHAREDLIBRARYCLASSAPI_PADDING (30-2*(SHLIBPP_POINTER_SIZE/4)) 14 | 15 | #endif // SHAREDLIBPP_CONFIG_H 16 | -------------------------------------------------------------------------------- /src/sharedlibpp/version.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #ifndef SHAREDLIBPP_VERSION_H 10 | #define SHAREDLIBPP_VERSION_H 11 | 12 | #include 13 | #include 14 | 15 | #define SHLIBPP_VERSION_MAJOR @sharedlibpp_VERSION_MAJOR@ 16 | #define SHLIBPP_VERSION_MINOR @sharedlibpp_VERSION_MINOR@ 17 | #define SHLIBPP_VERSION_PATCH @sharedlibpp_VERSION_PATCH@ 18 | #define SHLIBPP_VERSION "@sharedlibpp_VERSION@" 19 | 20 | namespace sharedlibpp { 21 | 22 | SHLIBPP_API int getVersionMajor(); 23 | SHLIBPP_API int getVersionMinor(); 24 | SHLIBPP_API int getVersionPatch(); 25 | SHLIBPP_API std::string getVersion(); 26 | 27 | } // namespace sharedlibpp 28 | 29 | #endif // SHAREDLIBPP_VERSION_H 30 | -------------------------------------------------------------------------------- /src/version.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT) 3 | * All rights reserved. 4 | * 5 | * This software may be modified and distributed under the terms of the 6 | * BSD-3-Clause license. See the accompanying LICENSE file for details. 7 | */ 8 | 9 | #include 10 | 11 | int sharedlibpp::getVersionMajor() 12 | { 13 | return SHLIBPP_VERSION_MAJOR; 14 | } 15 | 16 | int sharedlibpp::getVersionMinor() 17 | { 18 | return SHLIBPP_VERSION_MINOR; 19 | } 20 | 21 | int sharedlibpp::getVersionPatch() 22 | { 23 | return SHLIBPP_VERSION_PATCH; 24 | } 25 | 26 | std::string sharedlibpp::getVersion() 27 | { 28 | return SHLIBPP_VERSION; 29 | } 30 | --------------------------------------------------------------------------------