mirror of
https://github.com/openharmony/third_party_vulkan-loader.git
synced 2026-07-19 17:13:36 -04:00
test: Fix framework to work on MacOS
Main issue was getting function redireciton to work, dyld-interposer accomplishes that. It required making the shim-library a dylib, but otherwise only required minor changes. Change-Id: I7b7e2c86cc0c0b082f58241a7e146b74af72e792
This commit is contained in:
committed by
Charles Giessen
parent
1ff4c76125
commit
820fc25d1d
@@ -17,7 +17,7 @@
|
||||
|
||||
add_library(testing_framework_util STATIC test_util.cpp test_util.h)
|
||||
target_link_libraries(testing_framework_util PUBLIC Vulkan::Headers)
|
||||
if(UNIX)
|
||||
if(UNIX OR APPLE)
|
||||
target_link_libraries(testing_framework_util PUBLIC ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
@@ -30,7 +30,7 @@ target_compile_options(testing_framework_util INTERFACE
|
||||
$<$<BUILD_WSI_XLIB_SUPPORT>:-DVK_USE_PLATFORM_XLIB_KHR>
|
||||
$<$<BUILD_WSI_WAYLAND_SUPPORT>:-DVK_USE_PLATFORM_WAYLAND_KHR>>
|
||||
)
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(UNIX)
|
||||
target_compile_options(testing_framework_util PUBLIC -fPIC)
|
||||
endif()
|
||||
target_include_directories(testing_framework_util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
@@ -21,10 +21,11 @@ if (WIN32)
|
||||
target_include_directories(shim-library PUBLIC ${CMAKE_SOURCE_DIR}/loader ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
elseif(UNIX)
|
||||
add_library(shim-library STATIC shim.h linux_shim.cpp)
|
||||
if(APPLE)
|
||||
add_library(shim-library SHARED shim.h unix_shim.cpp)
|
||||
else()
|
||||
add_library(shim-library STATIC shim.h unix_shim.cpp)
|
||||
endif()
|
||||
target_link_libraries(shim-library PRIVATE testing_framework_util)
|
||||
target_include_directories(shim-library PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
elseif(APPLE)
|
||||
|
||||
endif()
|
||||
@@ -148,17 +148,17 @@ struct PlatformShim {
|
||||
};
|
||||
|
||||
std::vector<std::string> parse_env_var_list(std::string const& var);
|
||||
|
||||
// dynamically link on windows
|
||||
#if defined(WIN32)
|
||||
extern "C" {
|
||||
// dynamically link on windows and macos
|
||||
#if defined(WIN32) || defined(__APPLE__)
|
||||
using PFN_get_platform_shim = PlatformShim& (*)();
|
||||
#define GET_PLATFORM_SHIM_STR "get_platform_shim"
|
||||
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
#elif defined(__linux__)
|
||||
// statically link on linux
|
||||
PlatformShim& get_platform_shim();
|
||||
#endif
|
||||
|
||||
}
|
||||
// Functions which are called by the Test Framework need a definition, but since the shim is a DLL, this
|
||||
// would require loading the functions before using. To get around this, most PlatformShim functions are member
|
||||
// functions, so only the `get_platform_shim()` is needed to be loaded. As a consequence, all the member functions
|
||||
|
||||
@@ -28,37 +28,53 @@
|
||||
#include "shim.h"
|
||||
|
||||
static PlatformShim platform_shim;
|
||||
|
||||
extern "C" {
|
||||
#if defined(__linux__)
|
||||
PlatformShim& get_platform_shim() {
|
||||
platform_shim = PlatformShim();
|
||||
return platform_shim;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
FRAMEWORK_EXPORT PlatformShim &get_platform_shim() {
|
||||
platform_shim = PlatformShim();
|
||||
return platform_shim;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
// Necessary for MacOS function himming
|
||||
#if defined(__linux__)
|
||||
#define OPENDIR_FUNC_NAME opendir
|
||||
#define ACCESS_FUNC_NAME access
|
||||
#define FOPEN_FUNC_NAME fopen
|
||||
#elif defined(__APPLE__)
|
||||
#define OPENDIR_FUNC_NAME my_opendir
|
||||
#define ACCESS_FUNC_NAME my_access
|
||||
#define FOPEN_FUNC_NAME my_fopen
|
||||
#endif
|
||||
|
||||
using PFN_OPENDIR = DIR* (*)(const char* path_name);
|
||||
using PFN_ACCESS = int (*)(const char* pathname, int mode);
|
||||
using PFN_FOPEN = FILE* (*)(const char* filename, const char* mode);
|
||||
|
||||
FRAMEWORK_EXPORT DIR* opendir(const char* path_name) {
|
||||
static PFN_OPENDIR real_opendir = nullptr;
|
||||
static PFN_OPENDIR real_opendir = nullptr;
|
||||
static PFN_ACCESS real_access = nullptr;
|
||||
static PFN_FOPEN real_fopen = nullptr;
|
||||
|
||||
FRAMEWORK_EXPORT DIR* OPENDIR_FUNC_NAME(const char* path_name) {
|
||||
if (!real_opendir) real_opendir = (PFN_OPENDIR)dlsym(RTLD_NEXT, "opendir");
|
||||
|
||||
DIR* dir;
|
||||
if (platform_shim.is_fake_path(path_name)) {
|
||||
auto fake_path_name = platform_shim.get_fake_path(fs::path(path_name));
|
||||
//printf("Open Dir %s as %s\n", path_name, fake_path_name.c_str());
|
||||
dir = real_opendir(fake_path_name.c_str());
|
||||
} else {
|
||||
// printf("Open Dir %s\n", path_name);
|
||||
dir = real_opendir(path_name);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
using PFN_ACCESS = int (*)(const char* pathname, int mode);
|
||||
|
||||
FRAMEWORK_EXPORT int access(const char* in_pathname, int mode) {
|
||||
static PFN_ACCESS real_access = nullptr;
|
||||
FRAMEWORK_EXPORT int ACCESS_FUNC_NAME(const char* in_pathname, int mode) {
|
||||
if (!real_access) real_access = (PFN_ACCESS)dlsym(RTLD_NEXT, "access");
|
||||
|
||||
fs::path path{in_pathname};
|
||||
@@ -69,36 +85,45 @@ FRAMEWORK_EXPORT int access(const char* in_pathname, int mode) {
|
||||
if (platform_shim.is_fake_path(path.parent_path())) {
|
||||
fs::path fake_path = platform_shim.get_fake_path(path.parent_path());
|
||||
fake_path /= path.filename();
|
||||
// printf("ACCESS: in_pathname %s as %s\n", split.path.c_str(), fake_path.c_str());
|
||||
return real_access(fake_path.c_str(), mode);
|
||||
}
|
||||
return real_access(in_pathname, mode);
|
||||
}
|
||||
|
||||
using PFN_FOPEN = FILE* (*)(const char* filename, const char* mode);
|
||||
|
||||
FRAMEWORK_EXPORT FILE* fopen(const char* in_filename, const char* mode) {
|
||||
static PFN_FOPEN real_fopen = nullptr;
|
||||
FRAMEWORK_EXPORT FILE* FOPEN_FUNC_NAME(const char* in_filename, const char* mode) {
|
||||
if (!real_fopen) real_fopen = (PFN_FOPEN)dlsym(RTLD_NEXT, "fopen");
|
||||
//printf("fopen file %s\n", in_filename);
|
||||
|
||||
fs::path path{in_filename};
|
||||
if (!path.has_parent_path()) {
|
||||
return real_fopen(in_filename, mode);
|
||||
}
|
||||
|
||||
// printf("path %s as %s\n", split.path.c_str(), split.name.c_str());
|
||||
|
||||
FILE* f_ptr;
|
||||
if (platform_shim.is_fake_path(path.parent_path())) {
|
||||
auto fake_path = platform_shim.get_fake_path(path.parent_path()) / path.filename();
|
||||
// printf("fopen %s as %s\n", in_filename, fake_path.c_str());
|
||||
f_ptr = real_fopen(fake_path.c_str(), mode);
|
||||
} else {
|
||||
// printf("fopen %s\n", filename);
|
||||
f_ptr = real_fopen(in_filename, mode);
|
||||
}
|
||||
|
||||
return f_ptr;
|
||||
}
|
||||
|
||||
/* Shiming functions on apple is limited by the linker prefering to not use functions in the
|
||||
* executable in loaded dylibs. By adding an interposer, we redirect the linker to use our
|
||||
* version of the function over the real one, thus shimming the system function.
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
#define MACOS_ATTRIB __attribute__((section("__DATA,__interpose")))
|
||||
#define VOIDP_CAST(_func) reinterpret_cast<const void*>(&_func)
|
||||
|
||||
struct Interposer {
|
||||
const void* shim_function;
|
||||
const void* underlying_function;
|
||||
};
|
||||
|
||||
__attribute__((used)) static Interposer _interpose_opendir MACOS_ATTRIB = {VOIDP_CAST(my_opendir), VOIDP_CAST(opendir)};
|
||||
__attribute__((used)) static Interposer _interpose_access MACOS_ATTRIB = {VOIDP_CAST(my_access), VOIDP_CAST(access)};
|
||||
__attribute__((used)) static Interposer _interpose_fopen MACOS_ATTRIB = {VOIDP_CAST(my_fopen), VOIDP_CAST(fopen)};
|
||||
#endif
|
||||
} // extern "C"
|
||||
@@ -29,12 +29,12 @@
|
||||
|
||||
namespace detail {
|
||||
PlatformShimWrapper::PlatformShimWrapper(DebugMode debug_mode) : debug_mode(debug_mode) {
|
||||
#if defined(WIN32)
|
||||
#if defined(WIN32) || defined(__APPLE__)
|
||||
shim_library = LibraryWrapper(SHIM_LIBRARY_NAME);
|
||||
auto get_platform_shim_func = shim_library.get_symbol<PFN_get_platform_shim>(GET_PLATFORM_SHIM_STR);
|
||||
assert(get_platform_shim_func != NULL && "Must be able to get \"platform_shim\"");
|
||||
platform_shim = &get_platform_shim_func();
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
#elif defined(__linux__)
|
||||
platform_shim = &get_platform_shim();
|
||||
#endif
|
||||
platform_shim->setup_override(debug_mode);
|
||||
|
||||
@@ -222,7 +222,7 @@ std::string make_native(std::string const& in_path) {
|
||||
else
|
||||
out += c;
|
||||
}
|
||||
#elif defined(__linux__) || defined(APPLE)
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
for (size_t i = 0; i < in_path.size(); i++) {
|
||||
if (i + 1 < in_path.size() && in_path[i] == '\\' && in_path[i + 1] == '\\') {
|
||||
out += '/';
|
||||
|
||||
Reference in New Issue
Block a user