Commit 81666349 authored by Kitware Robot's avatar Kitware Robot Committed by Brad King

KWSys 2019-03-28 (e92bdbe8)

Code extracted from:

    https://gitlab.kitware.com/utils/kwsys.git

at commit e92bdbe8e6eca2a8b6dcf14920e5e25308504206 (master).

Upstream Shortlog
-----------------

Ben Boeckel (7):
      30198dbc DynamicLoader: fix error reporting on Windows
      cf6b5f69 DynamicLoader: use Encoding::ToWindowsExtendedPath for the libname
      d17291ad DynamicLoader: support loading libraries using flags
      40d9e482 DynamicLoader: support loading sibling libraries on Windows
      971809c5 DynamicLoader: test the SearchBesideLibrary flag
      efb006b9 DynamicLoader: include stdio.h for _snprintf
      9e8e9ba0 DynamicLoader: avoid the min/max macros from windows.h

Brad King (1):
      92334e76 SystemTools: CopyFileAlways: avoid copying file over self
parent 868dc1a1
......@@ -172,6 +172,9 @@ ENDIF()
IF(KWSYS_USE_Directory)
SET(KWSYS_USE_Encoding 1)
ENDIF()
IF(KWSYS_USE_DynamicLoader)
SET(KWSYS_USE_Encoding 1)
ENDIF()
IF(KWSYS_USE_FStream)
SET(KWSYS_USE_Encoding 1)
ENDIF()
......@@ -1096,6 +1099,20 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
ADD_LIBRARY(${KWSYS_NAMESPACE}TestDynload MODULE testDynload.c)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestDynload PROPERTY LABELS ${KWSYS_LABELS_LIB})
ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestDynload ${KWSYS_TARGET_INTERFACE})
if (WIN32)
# Windows tests supported flags.
add_library(${KWSYS_NAMESPACE}TestDynloadImpl SHARED testDynloadImpl.c)
set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY LABELS ${KWSYS_LABELS_LIB})
set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY DEFINE_SYMBOL BUILDING_TestDynloadImpl)
set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dynloaddir")
add_dependencies(${KWSYS_NAMESPACE}TestDynloadImpl ${KWSYS_TARGET_INTERFACE})
add_library(${KWSYS_NAMESPACE}TestDynloadUse MODULE testDynloadUse.c)
set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadUse PROPERTY LABELS ${KWSYS_LABELS_LIB})
set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadUse PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dynloaddir")
add_dependencies(${KWSYS_NAMESPACE}TestDynloadUse ${KWSYS_TARGET_INTERFACE})
target_link_libraries(${KWSYS_NAMESPACE}TestDynloadUse PRIVATE ${KWSYS_NAMESPACE}TestDynloadImpl)
endif ()
ENDIF()
CREATE_TEST_SOURCELIST(
KWSYS_CXX_TEST_SRCS ${KWSYS_NAMESPACE}TestsCxx.cxx
......
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#if defined(_WIN32)
# define NOMINMAX // hide min,max to not conflict with <limits>
#endif
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)
#include KWSYS_HEADER(Configure.hxx)
#include KWSYS_HEADER(Encoding.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
......@@ -25,6 +30,28 @@
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.
#define CHECK_OPEN_FLAGS(var, supported, ret) \
do { \
/* Check for unknown flags. */ \
if ((var & AllOpenFlags) != var) { \
return ret; \
} \
\
/* Check for unsupported flags. */ \
if ((var & (supported)) != var) { \
return ret; \
} \
} while (0)
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
{
return DynamicLoader::OpenLibrary(libname, 0);
}
}
#if !KWSYS_SUPPORTS_SHARED_LIBS
// Implementation for environments without dynamic libs
# include <string.h> // for strerror()
......@@ -32,7 +59,7 @@
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
return 0;
}
......@@ -67,8 +94,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
CHECK_OPEN_FLAGS(flags, 0, 0);
return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
}
......@@ -130,8 +159,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
CHECK_OPEN_FLAGS(flags, 0, 0);
NSObjectFileImageReturnCode rc;
NSObjectFileImage image = 0;
......@@ -185,19 +216,22 @@ const char* DynamicLoader::LastError()
// Implementation for Windows win32 code but not cygwin
# include <windows.h>
# include <stdio.h>
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
DynamicLoader::LibraryHandle lh;
int length = MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, NULL, 0);
wchar_t* wchars = new wchar_t[length + 1];
wchars[0] = '\0';
MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, wchars, length);
lh = LoadLibraryW(wchars);
delete[] wchars;
return lh;
CHECK_OPEN_FLAGS(flags, SearchBesideLibrary, NULL);
DWORD llFlags = 0;
if (flags & SearchBesideLibrary) {
llFlags |= LOAD_WITH_ALTERED_SEARCH_PATH;
}
return LoadLibraryExW(Encoding::ToWindowsExtendedPath(libname).c_str(), NULL,
llFlags);
}
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
......@@ -247,24 +281,38 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
# endif
}
# define DYNLOAD_ERROR_BUFFER_SIZE 1024
const char* DynamicLoader::LastError()
{
LPVOID lpMsgBuf = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, 0, NULL);
wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1];
DWORD error = GetLastError();
DWORD length = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
lpMsgBuf, DYNLOAD_ERROR_BUFFER_SIZE, NULL);
static char str[DYNLOAD_ERROR_BUFFER_SIZE + 1];
if (length < 1) {
/* FormatMessage failed. Use a default message. */
_snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
"DynamicLoader encountered error 0x%X. "
"FormatMessage failed with error 0x%X",
error, GetLastError());
return str;
}
if (!lpMsgBuf) {
return NULL;
if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str,
DYNLOAD_ERROR_BUFFER_SIZE, NULL, NULL)) {
/* WideCharToMultiByte failed. Use a default message. */
_snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
"DynamicLoader encountered error 0x%X. "
"WideCharToMultiByte failed with error 0x%X",
error, GetLastError());
}
static char* str = 0;
delete[] str;
str = strcpy(new char[strlen((char*)lpMsgBuf) + 1], (char*)lpMsgBuf);
// Free the buffer.
LocalFree(lpMsgBuf);
return str;
}
......@@ -282,8 +330,10 @@ namespace KWSYS_NAMESPACE {
static image_id last_dynamic_err = B_OK;
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
CHECK_OPEN_FLAGS(flags, 0, 0);
// image_id's are integers, errors are negative. Add one just in case we
// get a valid image_id of zero (is that even possible?).
image_id rc = load_add_on(libname.c_str());
......@@ -360,8 +410,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
CHECK_OPEN_FLAGS(flags, 0, NULL);
char* name = (char*)calloc(1, libname.size() + 1);
dld_init(program_invocation_name);
strncpy(name, libname.c_str(), libname.size());
......@@ -404,8 +456,10 @@ const char* DynamicLoader::LastError()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname)
const std::string& libname, int flags)
{
CHECK_OPEN_FLAGS(flags, 0, NULL);
return dlopen(libname.c_str(), RTLD_LAZY);
}
......
......@@ -66,10 +66,23 @@ public:
// Return type from DynamicLoader::GetSymbolAddress.
typedef void (*SymbolPointer)();
enum OpenFlags
{
// Search for dependent libraries beside the library being loaded.
//
// This is currently only supported on Windows.
SearchBesideLibrary = 0x00000001,
AllOpenFlags = SearchBesideLibrary
};
/** Load a dynamic library into the current process.
* The returned LibraryHandle can be used to access the symbols in the
* library. */
* library. The optional second argument is a set of flags to use when
* opening the library. If unrecognized or unsupported flags are specified,
* the library is not opened. */
static LibraryHandle OpenLibrary(const std::string&);
static LibraryHandle OpenLibrary(const std::string&, int);
/** Attempt to detach a dynamic library from the
* process. A value of true is returned if it is successful. */
......
......@@ -2436,10 +2436,6 @@ static bool CloneFileContent(const std::string& source,
bool SystemTools::CopyFileAlways(const std::string& source,
const std::string& destination)
{
// If files are the same do not copy
if (SystemTools::SameFile(source, destination)) {
return true;
}
mode_t perm = 0;
bool perms = SystemTools::GetPermissions(source, perm);
std::string real_destination = destination;
......@@ -2460,6 +2456,10 @@ bool SystemTools::CopyFileAlways(const std::string& source,
} else {
destination_dir = SystemTools::GetFilenamePath(destination);
}
// If files are the same do not copy
if (SystemTools::SameFile(source, real_destination)) {
return true;
}
// Create destination directory
......
......@@ -21,11 +21,15 @@
// left on disk.
#include <testSystemTools.h>
static std::string GetLibName(const char* lname)
static std::string GetLibName(const char* lname, const char* subdir = NULL)
{
// Construct proper name of lib
std::string slname;
slname = EXECUTABLE_OUTPUT_PATH;
if (subdir) {
slname += "/";
slname += subdir;
}
#ifdef CMAKE_INTDIR
slname += "/";
slname += CMAKE_INTDIR;
......@@ -45,26 +49,29 @@ static std::string GetLibName(const char* lname)
* r3: should CloseLibrary succeed ?
*/
static int TestDynamicLoader(const char* libname, const char* symbol, int r1,
int r2, int r3)
int r2, int r3, int flags = 0)
{
std::cerr << "Testing: " << libname << std::endl;
kwsys::DynamicLoader::LibraryHandle l =
kwsys::DynamicLoader::OpenLibrary(libname);
kwsys::DynamicLoader::OpenLibrary(libname, flags);
// If result is incompatible with expectation just fails (xor):
if ((r1 && !l) || (!r1 && l)) {
std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
std::cerr << "OpenLibrary: " << kwsys::DynamicLoader::LastError()
<< std::endl;
return 1;
}
kwsys::DynamicLoader::SymbolPointer f =
kwsys::DynamicLoader::GetSymbolAddress(l, symbol);
if ((r2 && !f) || (!r2 && f)) {
std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
std::cerr << "GetSymbolAddress: " << kwsys::DynamicLoader::LastError()
<< std::endl;
return 1;
}
#ifndef __APPLE__
int s = kwsys::DynamicLoader::CloseLibrary(l);
if ((r3 && !s) || (!r3 && s)) {
std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
std::cerr << "CloseLibrary: " << kwsys::DynamicLoader::LastError()
<< std::endl;
return 1;
}
#else
......@@ -113,5 +120,14 @@ int testDynamicLoader(int argc, char* argv[])
res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderData", 1, 1, 1);
res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderData", 1, 0, 1);
#ifdef _WIN32
libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynloadUse", "dynloaddir");
res += TestDynamicLoader(libname.c_str(), "dummy", 0, 0, 0);
res += TestDynamicLoader(libname.c_str(), "TestLoad", 1, 1, 1,
kwsys::DynamicLoader::SearchBesideLibrary);
res += TestDynamicLoader(libname.c_str(), "_TestLoad", 1, 0, 1,
kwsys::DynamicLoader::SearchBesideLibrary);
#endif
return res;
}
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#include "testDynloadImpl.h"
int TestDynamicLoaderImplData = 0;
void TestDynamicLoaderImplSymbolPointer()
{
}
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef _WIN32
# ifdef BUILDING_TestDynloadImpl
# define DLIMPL_EXPORT __declspec(dllexport)
# else
# define DLIMPL_EXPORT __declspec(dllimport)
# endif
#else
# define DLIMPL_EXPORT
#endif
DLIMPL_EXPORT int TestDynamicLoaderImplData;
DLIMPL_EXPORT void TestDynamicLoaderImplSymbolPointer();
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#include "testDynloadImpl.h"
#ifdef _WIN32
# define DL_EXPORT __declspec(dllexport)
#else
# define DL_EXPORT
#endif
DL_EXPORT int TestLoad()
{
TestDynamicLoaderImplSymbolPointer();
return TestDynamicLoaderImplData;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment