mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
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
This commit is contained in:

committed by
Brad King

parent
868dc1a121
commit
8166634958
@@ -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
|
||||
|
@@ -1,9 +1,14 @@
|
||||
/* 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;
|
||||
wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1];
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
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);
|
||||
|
||||
if (!lpMsgBuf) {
|
||||
return 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 (!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;
|
||||
}
|
||||
|
10
testDynloadImpl.c
Normal file
10
testDynloadImpl.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/* 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()
|
||||
{
|
||||
}
|
15
testDynloadImpl.h
Normal file
15
testDynloadImpl.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* 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();
|
15
testDynloadUse.c
Normal file
15
testDynloadUse.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* 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;
|
||||
}
|
Reference in New Issue
Block a user