Skip to content

Commit

Permalink
Add optional binary relocatability
Browse files Browse the repository at this point in the history
Signed-off-by: Silvio Traversaro <[email protected]>
  • Loading branch information
traversaro committed May 13, 2024
1 parent 6f1c365 commit 5d511ae
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 8 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ if (BUILD_SDF)
# Find tinyxml2.
gz_find_package(TINYXML2 REQUIRED)

#################################################
# Find DL if doing relocatable installation
if (GZ_ENABLE_RELOCATABLE_INSTALL)
gz_find_package(DL REQUIRED)
endif()


################################################
# Find urdfdom parser. Logic:
#
Expand Down
40 changes: 40 additions & 0 deletions include/sdf/InstallationDirectories.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2024 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef SDF_INSTALLATION_DIRECTORIES_HH_
#define SDF_INSTALLATION_DIRECTORIES_HH_

#include <string>

#include <sdf/sdf_config.h>
#include <sdf/system_util.hh>

namespace sdf
{
inline namespace SDF_VERSION_NAMESPACE {

/// \brief getInstallPrefix return the install prefix of the library
/// i.e. CMAKE_INSTALL_PREFIX unless the library has been moved
SDFORMAT_VISIBLE std::string getInstallPrefix();

/// \brief getSharePath return the share directory used by sdformat
SDFORMAT_VISIBLE std::string getSharePath();

}
}

#endif
4 changes: 2 additions & 2 deletions include/sdf/config.hh.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@
#cmakedefine SDFORMAT_DISABLE_CONSOLE_LOGFILE 1

#ifndef SDF_SHARE_PATH
#define SDF_SHARE_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/"
#define SDF_SHARE_PATH _Pragma ("GCC warning \"'SDF_SHARE_PATH' macro is deprecated, use sdf::getSharePath() function instead. \"") "${CMAKE_INSTALL_FULL_DATAROOTDIR}/"
#endif

#ifndef SDF_VERSION_PATH
#define SDF_VERSION_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/sdformat${PROJECT_VERSION_MAJOR}/${PROJECT_VERSION}"
#define SDF_VERSION_PATH _Pragma ("GCC warning \"'SDF_VERSION_PATH' macro is deprecated and should not be used. \"") "${CMAKE_INSTALL_FULL_DATAROOTDIR}/sdformat${PROJECT_VERSION_MAJOR}/${PROJECT_VERSION}"
#endif

#endif // #ifndef SDF_CONFIG_HH_
25 changes: 25 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ gz_create_core_library(SOURCES ${sources}
CXX_STANDARD 17
LEGACY_PROJECT_PREFIX SDFormat
)
gz_add_get_install_prefix_impl(GET_INSTALL_PREFIX_FUNCTION sdf::getInstallPrefix
GET_INSTALL_PREFIX_HEADER sdf/InstallationDirectories.hh
OVERRIDE_INSTALL_PREFIX_ENV_VARIABLE SDF_INSTALL_PREFIX)

# CMAKE_INSTALL_DATAROOTDIR may be an absolute path, let's make sure to use the
# relative version
if(IS_ABSOLUTE "${CMAKE_INSTALL_DATAROOTDIR}")
file(RELATIVE_PATH CMAKE_INSTALL_RELATIVE_DATAROOTDIR "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_DATAROOTDIR}")
else()
set(CMAKE_INSTALL_RELATIVE_DATAROOTDIR "${CMAKE_INSTALL_DATAROOTDIR}")
endif()

set_property(
SOURCE InstallationDirectories.cc
PROPERTY COMPILE_DEFINITIONS
CMAKE_INSTALL_RELATIVE_DATAROOTDIR="${CMAKE_INSTALL_RELATIVE_DATAROOTDIR}"
)


target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME}
PUBLIC
Expand Down Expand Up @@ -91,6 +109,11 @@ if (BUILD_TESTING)
-DGZ_SDFORMAT_STATIC_DEFINE
)

if(WIN32)
target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME}
PRIVATE shlwapi)
endif()

gz_build_tests(
TYPE UNIT
SOURCES ${gtest_sources}
Expand All @@ -99,6 +122,8 @@ if (BUILD_TESTING)
${PROJECT_SOURCE_DIR}/test
LIB_DEPS
library_for_tests
ENVIRONMENT
SDF_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)

if (TARGET UNIT_gz_TEST)
Expand Down
151 changes: 151 additions & 0 deletions src/InstallationDirectories.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* Copyright (C) 2024 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include <regex>

#include <sdf/config.h>
#include <sdf/InstallationDirectories.hh>

#ifdef _WIN32
#include <shlwapi.h>
#endif

namespace sdf
{
inline namespace SDF_VERSION_NAMESPACE {

// We locally import the gz::common::joinPaths function
// See https://github.com/gazebosim/gz-physics/pull/507#discussion_r1186919267
// for more details

// Function imported from
// https://github.com/gazebosim/gz-common/blob/ignition-common4_4.6.2/src/FilesystemBoost.cc#L507
#ifndef WIN32
static const char preferred_separator = '/';
#else // Windows
static const char preferred_separator = '\\';
#endif
const std::string separator(const std::string &_p)
{
return _p + preferred_separator;
}

// Function imported from
// https://github.com/gazebosim/gz-common/blob/ignition-common4_4.6.2/src/Filesystem.cc#L227
std::string checkWindowsPath(const std::string _path)
{
if (_path.empty())
return _path;

// Check if this is a http or https, if so change backslashes generated by
// jointPaths to '/'
if ((_path.size() > 7 && 0 == _path.compare(0, 7, "http://")) ||
(_path.size() > 8 && 0 == _path.compare(0, 8, "https://")))
{
return std::regex_replace(_path, std::regex(R"(\\)"), "/");
}

// This is a Windows path, convert all '/' into backslashes
std::string result = std::regex_replace(_path, std::regex(R"(/)"), "\\");
std::string drive_letters;

// only Windows contains absolute paths starting with drive letters
if (result.length() > 3 && 0 == result.compare(1, 2, ":\\"))
{
drive_letters = result.substr(0, 3);
result = result.substr(3);
}
result = drive_letters + std::regex_replace(
result, std::regex("[<>:\"|?*]"), "");
return result;
}

// Function imported from
// https://github.com/gazebosim/gz-common/blob/ignition-common4_4.6.2/src/Filesystem.cc#L256
std::string joinPaths(const std::string &_path1,
const std::string &_path2)
{

/// This function is used to avoid duplicated path separators at the
/// beginning/end of the string, and between the two paths being joined.
/// \param[in] _path This is the string to sanitize.
/// \param[in] _stripLeading True if the leading separator should be
/// removed.
auto sanitizeSlashes = [](const std::string &_path,
bool _stripLeading = false)
{
// Shortcut
if (_path.empty())
return _path;

std::string result = _path;

// Use the appropriate character for each platform.
#ifndef _WIN32
char replacement = '/';
#else
char replacement = '\\';
#endif

// Sanitize the start of the path.
size_t index = 0;
size_t leadingIndex = _stripLeading ? 0 : 1;
for (; index < result.length() && result[index] == replacement; ++index)
{
}
if (index > leadingIndex)
result.erase(leadingIndex, index-leadingIndex);

// Sanitize the end of the path.
index = result.length()-1;
for (; index < result.length() && result[index] == replacement; --index)
{
}
index += 1;
if (index < result.length()-1)
result.erase(index+1);
return result;
};

std::string path;
#ifndef _WIN32
path = sanitizeSlashes(sanitizeSlashes(separator(_path1)) +
sanitizeSlashes(_path2, true));
#else // _WIN32
std::string path1 = sanitizeSlashes(checkWindowsPath(_path1));
std::string path2 = sanitizeSlashes(checkWindowsPath(_path2), true);
std::vector<char> combined(path1.length() + path2.length() + 2);
if (::PathCombineA(combined.data(), path1.c_str(), path2.c_str()) != NULL)
{
path = sanitizeSlashes(checkWindowsPath(std::string(combined.data())));
}
else
{
path = sanitizeSlashes(checkWindowsPath(separator(path1) + path2));
}
#endif // _WIN32
return path;
}

std::string getSharePath()
{
return sdf::joinPaths(
getInstallPrefix(), CMAKE_INSTALL_RELATIVE_DATAROOTDIR);
}

}
}
15 changes: 10 additions & 5 deletions src/SDF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "sdf/Assert.hh"
#include "sdf/Console.hh"
#include "sdf/Filesystem.hh"
#include "sdf/InstallationDirectories.hh"
#include "sdf/SDFImpl.hh"
#include "SDFImplPrivate.hh"
#include "sdf/sdf_config.h"
Expand All @@ -45,11 +46,15 @@ std::string SDF::version = SDF_VERSION; // NOLINT(runtime/string)

std::string sdfSharePath()
{
#ifdef SDF_SHARE_PATH
if (std::string(SDF_SHARE_PATH) != "/")
return SDF_SHARE_PATH;
#endif
return "";
std::string sharePath = sdf::getSharePath();
if (sharePath != "/")
{
return sharePath;
}
else
{
return "";
}
}

/////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions test/integration/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ endif()
gz_build_tests(TYPE ${TEST_TYPE}
SOURCES ${tests}
INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test
ENVIRONMENT SDF_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)


Expand Down
5 changes: 4 additions & 1 deletion test/performance/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ set(tests
parser_urdf.cc
)

gz_build_tests(TYPE ${TEST_TYPE} SOURCES ${tests} INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test)
gz_build_tests(TYPE ${TEST_TYPE}
SOURCES ${tests}
INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/test
ENVIRONMENT SDF_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX})

0 comments on commit 5d511ae

Please sign in to comment.