Skip to content

Commit

Permalink
find_library: Centralize functionality here
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Cousineau <eric.cousineau@tri.global>
  • Loading branch information
EricCousineau-TRI committed Mar 25, 2019
1 parent 3dcb27f commit 2087cfd
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 0 deletions.
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ include_directories(include)

ament_export_include_directories(include)

add_library(${PROJECT_NAME} SHARED
src/find_library.cpp)
target_include_directories(${PROJECT_NAME}
PUBLIC
include
)
ament_export_libraries(${PROJECT_NAME})

if(BUILD_TESTING)
find_package(ament_cmake_gtest REQUIRED)
find_package(ament_lint_auto REQUIRED)
Expand All @@ -32,10 +40,22 @@ if(BUILD_TESTING)
ament_lint_auto_find_test_dependencies()

ament_add_gtest(test_basic test/test_basic.cpp)

add_library(toy_test_library SHARED test/toy_test_library.cpp)
ament_add_gtest(test_find_library test/test_find_library.cpp)
target_link_libraries(test_find_library ${PROJECT_NAME} toy_test_library)
set_tests_properties(test_find_library PROPERTIES
ENVIRONMENT
"_TOY_TEST_LIBRARY_DIR=$<TARGET_FILE_DIR:toy_test_library>;_TOY_TEST_LIBRARY=$<TARGET_FILE:toy_test_library>")
endif()

ament_package()

install(
DIRECTORY include/
DESTINATION include)
install(
TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
32 changes: 32 additions & 0 deletions include/rcpputils/find_library.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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 RCPPUTILS__FIND_LIBRARY_H_
#define RCPPUTILS__FIND_LIBRARY_H_

#include <string>

namespace rcpputils {

/// Finds a library (using the appropriate shared-library environment variable,
/// e.g. `LD_LIBRARY_PATH` on Linux), and returns the absolute filesystem path
/// (including the appropriate prefix and suffix).
/**
* \param[in] library_name Name of the library to find.
*/
std::string find_library_path(const std::string & library_name);

} // namespace rcpputils

#endif // RCPPUTILS__FIND_LIBRARY_H_
106 changes: 106 additions & 0 deletions src/find_library.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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 "rcpputils/find_library.hpp"

#include <cstddef>

#include <list>
#include <fstream>
#include <sstream>

namespace rcpputils {

namespace {

std::string get_env_var(const char * env_var)
{
char * value = nullptr;
#ifndef _WIN32
value = getenv(env_var);
#else
size_t value_size;
_dupenv_s(&value, &value_size, env_var);
#endif
std::string value_str = "";
if (value) {
value_str = value;
#ifdef _WIN32
free(value);
#endif
}
// printf("get_env_var(%s) = %s\n", env_var, value_str.c_str());
return value_str;
}

std::list<std::string> split(const std::string & value, const char delimiter)
{
std::list<std::string> list;
std::istringstream ss(value);
std::string s;
while (std::getline(ss, s, delimiter)) {
list.push_back(s);
}
// printf("split(%s) = %zu\n", value.c_str(), list.size());
return list;
}

bool is_file_exist(const char * filename)
{
std::ifstream h(filename);
// printf("is_file_exist(%s) = %s\n", filename, h.good() ? "true" : "false");
return h.good();
}

} // namespace

std::string find_library_path(const std::string & library_name)
{
// TODO(eric.cousineau): Does Poco provide this functionality?
const char * env_var;
char separator;
const char * filename_prefix;
const char * filename_extension;
#ifdef _WIN32
env_var = "PATH";
separator = ';';
filename_prefix = "";
filename_extension = ".dll";
#elif __APPLE__
env_var = "DYLD_LIBRARY_PATH";
separator = ':';
filename_prefix = "lib";
filename_extension = ".dylib";
#else
env_var = "LD_LIBRARY_PATH";
separator = ':';
filename_prefix = "lib";
filename_extension = ".so";
#endif
std::string search_path = get_env_var(env_var);
std::list<std::string> search_paths = split(search_path, separator);

std::string filename = filename_prefix;
filename += library_name + filename_extension;

for (auto it : search_paths) {
std::string path = it + "/" + filename;
if (is_file_exist(path.c_str())) {
return path;
}
}
return "";
}

} // namespace rcpputils
53 changes: 53 additions & 0 deletions test/test_find_library.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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 "gtest/gtest.h"

#include "rcpputils/find_library.hpp"

namespace rcpputils {
namespace {

TEST(test_find_library, find_library) {
// Get ground-truth values from CTest properties.
const char * toy_lib_expected = getenv("_TOY_TEST_LIBRARY");
EXPECT_NE(toy_lib_expected, nullptr);
const char * toy_lib_dir = getenv("_TOY_TEST_LIBRARY_DIR");
EXPECT_NE(toy_lib_dir, nullptr);

// Set our relevant path variable.
const char * env_var{};
#ifdef _WIN32
env_var = "PATH";
#elif __APPLE__
env_var = "DYLD_LIBRARY_PATH";
#else
env_var = "LD_LIBRARY_PATH";
#endif
const int override = 1;
setenv(env_var, toy_lib_dir, override);

// Positive test.
const std::string toy_lib_actual = find_library_path("toy_test_library");
EXPECT_EQ(toy_lib_actual, toy_lib_expected);

// (Hopefully) Negative test.
const std::string bad_path = find_library_path(
"this_is_a_junk_libray_name_please_dont_define_this_if_you_do_then_"
"you_are_really_naughty");
EXPECT_EQ(bad_path, "");
}

} // namespace
} // namespace rcpputils
22 changes: 22 additions & 0 deletions test/toy_test_library.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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.

/// @file
/// Trivial library to ensure we have some linking present.

namespace toy_test_library {

int add_one(int x) { return x + 1; }

} // namespace toy_test_library

0 comments on commit 2087cfd

Please sign in to comment.