Skip to content

Commit

Permalink
Allow kdlpp to be built as shared library (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjol authored Sep 1, 2023
2 parents 65fae00 + bbd8d7f commit e8bceb7
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 14 deletions.
10 changes: 9 additions & 1 deletion bindings/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,19 @@ if(BUILD_KDLPP)
src/kdlpp.cpp
)

add_library(kdlpp STATIC ${KDLPP_CXX_SOURCES})
add_library(kdlpp ${KDLPP_CXX_SOURCES})

target_compile_options(kdlpp PRIVATE ${KDL_COMPILE_OPTIONS})
target_compile_definitions(kdlpp PRIVATE BUILDING_KDLPP=1)

target_include_directories(kdlpp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(kdlpp PUBLIC kdl)
target_compile_features(kdlpp PUBLIC cxx_std_20)

if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(kdlpp PUBLIC KDLPP_STATIC_LIB=1)
endif()

install(TARGETS kdlpp COMPONENT libkdlpp)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/kdlpp.h TYPE INCLUDE COMPONENT libkdlpp)

Expand Down
24 changes: 19 additions & 5 deletions bindings/cpp/include/kdlpp.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#ifndef KDLPP_H_
#define KDLPP_H_

#if defined(_WIN32)
# if defined(KDLPP_STATIC_LIB)
# define KDLPP_EXPORT
# elif defined(BUILDING_KDLPP)
# define KDLPP_EXPORT __declspec(dllexport)
# else
# define KDLPP_EXPORT __declspec(dllimport)
# endif
#elif defined(__GNUC__) && __GNUC__ >= 4
# define KDLPP_EXPORT __attribute__((visibility("default")))
#else
# define KDLPP_EXPORT
#endif

#include <functional>
#include <map>
#include <optional>
Expand Down Expand Up @@ -30,7 +44,7 @@ class TypeError : public std::exception {
};

// Exception thrown on regular KDL parsing errors
class ParseError : public std::exception {
class KDLPP_EXPORT ParseError : public std::exception {
std::string m_msg;
public:
ParseError(kdl_str const& msg);
Expand All @@ -57,7 +71,7 @@ enum NumberRepresentation {

// A KDL number: could be a long long, a double, or a string
// Analogous to kdl_number
class Number {
class KDLPP_EXPORT Number {
std::variant<long long, double, std::u8string> m_value;

public:
Expand Down Expand Up @@ -138,7 +152,7 @@ enum class Type {

// A KDL value, possibly including a type annotation
// Analogous to kdl_value
class Value : public HasTypeAnnotation {
class KDLPP_EXPORT Value : public HasTypeAnnotation {
std::variant<std::monostate, bool, Number, std::u8string> m_value;

public:
Expand Down Expand Up @@ -311,7 +325,7 @@ class Node : public HasTypeAnnotation {
};

// A KDL document - consisting of several nodes.
class Document {
class KDLPP_EXPORT Document {
std::vector<Node> m_nodes;

public:
Expand All @@ -338,7 +352,7 @@ class Document {
};

// Load a KDL document from string
Document parse(std::u8string_view kdl_text);
KDLPP_EXPORT Document parse(std::u8string_view kdl_text);

} // namespace kdl

Expand Down
4 changes: 2 additions & 2 deletions bindings/cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ target_link_libraries(kdlpp_test kdlpp test_util)
add_test(kdlpp_test kdlpp_test)

if (WIN32 AND BUILD_SHARED_LIBS)
# Copy kdl.dll to the test folder so that the tests work
# Copy kdl.dll and kdlpp.dll to the test folder so that the tests work
add_custom_command(TARGET kdlpp_test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:kdl> $<TARGET_FILE_DIR:kdlpp_test>)
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:kdl> $<TARGET_FILE:kdlpp> $<TARGET_FILE_DIR:kdlpp_test>)
endif()
13 changes: 7 additions & 6 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,17 @@ of the ``DESTDIR`` environment variable).
Dynamic vs static library
^^^^^^^^^^^^^^^^^^^^^^^^^

The ckdl C library ``libkdl`` supports both dynamic linking and static linking. Which option
you want to choose depends on your situation: When using C, C++, or a similar language, static
libraries can be easier to work with, while when using a dynamic runtime a dynamic library
may be your best bet (Python's ctypes and .NET's P/Invoke are examples of technologies that
as good as require the use of a dynamic library).
The ckdl C library ``libkdl`` and the C++ bindings ``libkdlpp`` support both dynamic linking
and static linking. Which option you want to choose depends on your situation: When using C,
C++, or a similar language, static libraries can be easier to work with, while when using a
dynamic runtime a dynamic library may be your best bet (Python's ctypes and .NET's P/Invoke
are examples of technologies that as good as require the use of a dynamic library).

.. attention::

On **Windows**, if you're using the static library, and not the DLL, you must define the
macro ``KDL_STATIC_LIB`` before including the ckdl headers, or you'll get linking errors.
macro ``KDL_STATIC_LIB`` before including the ckdl headers, and ``KDLPP_STATIC_LIB``
before including the kdlpp header, or you'll get linking errors.

On UNIX, this is not required, but it can't hurt in portable applications and libraries.

Expand Down

0 comments on commit e8bceb7

Please sign in to comment.