mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2026-03-21 05:34:00 -04:00
build: Fix build and tests on macOS
This commit addresses several compatibility issues that prevented Wayland from building and passing its test suite on macOS Core and Compatibility changes: - Emulate Linux behavior by explicitly setting O_NONBLOCK on connections (fixes blocking sendmsg issues on macOS). - Fix compilation on platforms missing SOCK_CLOEXEC and MSG_CMSG_CLOEXEC. - Implement wl_os_socket_peercred() using LOCAL_PEERPID for macOS. - Ensure availability of struct itimerspec (required for POSIX Timers API). Test suite fixes: - Add socketpair_cloexec() wrapper to handle platforms without atomic SOCK_CLOEXEC support. - Add implementation of memrchr() for platforms that do not provide it. - Implement is_debugger_attached() for macOS to handle test timeouts. - Fix tests to handle Mach-O binary format (instead of ELF). - Update egl-symbols-check to support macOS *.dylib Mach-O libraries. Build system: - Add meson option 'xml_catalog' to allow specifying custom catalog paths. Signed-off-by: Martin Lopatář <lopin@dataplex.cz>
This commit is contained in:
parent
5a45a89a83
commit
0f7f06bd4c
16 changed files with 180 additions and 23 deletions
|
|
@ -97,7 +97,7 @@ TEST(client_destroy_listener)
|
|||
bool user_data_destroyed = false;
|
||||
int s[2];
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
@ -184,7 +184,7 @@ TEST(client_destroy_removes_link)
|
|||
struct client_destroy_listener destroy_listener;
|
||||
int s[2];
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ setup(int *s)
|
|||
{
|
||||
struct wl_connection *connection;
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
|
||||
connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(connection);
|
||||
|
|
@ -181,8 +181,7 @@ struct marshal_data {
|
|||
static void
|
||||
setup_marshal_data(struct marshal_data *data)
|
||||
{
|
||||
assert(socketpair(AF_UNIX,
|
||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, data->s) == 0);
|
||||
data->read_connection = wl_connection_create(data->s[0],
|
||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->read_connection);
|
||||
|
|
@ -885,7 +884,7 @@ TEST(request_bogus_size)
|
|||
for (bogus_size = 11; bogus_size >= 0; bogus_size--) {
|
||||
fprintf(stderr, "* bogus size %d\n", bogus_size);
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
|
|||
|
|
@ -61,10 +61,12 @@ socket_wrapper(int domain, int type, int protocol)
|
|||
{
|
||||
wrapped_calls_socket++;
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if (fall_back && (type & SOCK_CLOEXEC)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return socket(domain, type, protocol);
|
||||
}
|
||||
|
|
@ -110,10 +112,12 @@ recvmsg_wrapper(int sockfd, struct msghdr *msg, int flags)
|
|||
{
|
||||
wrapped_calls_recvmsg++;
|
||||
|
||||
#ifdef MSG_CMSG_CLOEXEC
|
||||
if (fall_back && (flags & MSG_CMSG_CLOEXEC)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return recvmsg(sockfd, msg, flags);
|
||||
}
|
||||
|
|
@ -170,12 +174,14 @@ TEST(os_wrappers_socket_cloexec)
|
|||
do_os_wrappers_socket_cloexec(0);
|
||||
}
|
||||
|
||||
#ifdef MSG_CMSG_CLOEXEC
|
||||
TEST(os_wrappers_socket_cloexec_fallback)
|
||||
{
|
||||
/* forced fallback */
|
||||
init_fallbacks(1);
|
||||
do_os_wrappers_socket_cloexec(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_os_wrappers_dupfd_cloexec(int n)
|
||||
|
|
@ -232,8 +238,7 @@ struct marshal_data {
|
|||
static void
|
||||
setup_marshal_data(struct marshal_data *data)
|
||||
{
|
||||
assert(socketpair(AF_UNIX,
|
||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, data->s) == 0);
|
||||
|
||||
data->read_connection = wl_connection_create(data->s[0],
|
||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
|
|
@ -350,11 +355,13 @@ TEST(os_wrappers_recvmsg_cloexec)
|
|||
do_os_wrappers_recvmsg_cloexec(0);
|
||||
}
|
||||
|
||||
#ifdef MSG_CMSG_CLOEXEC
|
||||
TEST(os_wrappers_recvmsg_cloexec_fallback)
|
||||
{
|
||||
init_fallbacks(1);
|
||||
do_os_wrappers_recvmsg_cloexec(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_os_wrappers_epoll_create_cloexec(int n)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,17 @@
|
|||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
#ifdef __APPLE__
|
||||
static void *memrchr(const void *s, int c, size_t n) {
|
||||
const unsigned char *p = (const unsigned char *)s;
|
||||
while (n--) {
|
||||
if (p[n] == (unsigned char)c)
|
||||
return (void *)(p + n);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
registry_handle_global(void *data, struct wl_registry *registry,
|
||||
uint32_t id, const char *interface, uint32_t version)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ TEST(create_resource_tst)
|
|||
int s[2];
|
||||
uint32_t id;
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
@ -111,7 +111,7 @@ TEST(destroy_res_tst)
|
|||
.notify = &destroy_notify
|
||||
};
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
@ -159,7 +159,7 @@ TEST(create_resource_with_same_id)
|
|||
int s[2];
|
||||
uint32_t id;
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
@ -243,7 +243,7 @@ TEST(resource_destroy_iteration)
|
|||
.notify = &resource_destroy_notify
|
||||
};
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
assert(socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
|
|
|
|||
|
|
@ -36,9 +36,11 @@
|
|||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef HAVE_SYS_PROCCTL_H
|
||||
#include <sys/procctl.h>
|
||||
#elif defined(HAVE_SYS_PRCTL_H)
|
||||
|
|
@ -46,6 +48,8 @@
|
|||
#ifndef PR_SET_PTRACER
|
||||
# define PR_SET_PTRACER 0x59616d61
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include "test-runner.h"
|
||||
|
|
@ -63,7 +67,12 @@ static int timeouts_enabled = 1;
|
|||
/* set to one if the output goes to the terminal */
|
||||
static int is_atty = 0;
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern const struct test __start_test_section __asm("section$start$__DATA$test_section");
|
||||
extern const struct test __stop_test_section __asm("section$end$__DATA$test_section");
|
||||
#else
|
||||
extern const struct test __start_test_section, __stop_test_section;
|
||||
#endif
|
||||
|
||||
static const struct test *
|
||||
find_test(const char *name)
|
||||
|
|
@ -308,6 +317,22 @@ is_debugger_attached(void)
|
|||
|
||||
return rc;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
static int
|
||||
is_debugger_attached(void)
|
||||
{
|
||||
int ret;
|
||||
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
|
||||
struct kinfo_proc info;
|
||||
size_t size;
|
||||
|
||||
info.kp_proc.p_flag = 0;
|
||||
ret = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
|
||||
assert(ret == 0);
|
||||
|
||||
return (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static int
|
||||
is_debugger_attached(void)
|
||||
|
|
@ -317,6 +342,43 @@ is_debugger_attached(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
socketpair_cloexec(int domain, int type, int protocol, int sv[2])
|
||||
{
|
||||
int flags;
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if (socketpair(domain, type | SOCK_CLOEXEC, protocol, sv) == 0)
|
||||
return 0;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (socketpair(domain, type, protocol, sv) < 0)
|
||||
return -1;
|
||||
|
||||
flags = fcntl(sv[0], F_GETFD);
|
||||
if (flags < 0)
|
||||
goto err;
|
||||
|
||||
if (fcntl(sv[0], F_SETFD, flags | FD_CLOEXEC) < 0)
|
||||
goto err;
|
||||
|
||||
flags = fcntl(sv[1], F_GETFD);
|
||||
if (flags < 0)
|
||||
goto err;
|
||||
|
||||
if (fcntl(sv[1], F_SETFD, flags | FD_CLOEXEC) < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
close(sv[0]);
|
||||
close(sv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const struct test *t;
|
||||
|
|
|
|||
|
|
@ -37,11 +37,17 @@ struct test {
|
|||
int must_fail;
|
||||
} __attribute__ ((aligned (16)));
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define TEST_SECTION "__DATA,test_section"
|
||||
#else
|
||||
#define TEST_SECTION "test_section"
|
||||
#endif
|
||||
|
||||
#define TEST(name) \
|
||||
static void name(void); \
|
||||
\
|
||||
const struct test test##name \
|
||||
__attribute__ ((used, section ("test_section"))) = { \
|
||||
__attribute__ ((used, section (TEST_SECTION))) = { \
|
||||
#name, name, 0 \
|
||||
}; \
|
||||
\
|
||||
|
|
@ -51,7 +57,7 @@ struct test {
|
|||
static void name(void); \
|
||||
\
|
||||
const struct test test##name \
|
||||
__attribute__ ((used, section ("test_section"))) = { \
|
||||
__attribute__ ((used, section (TEST_SECTION))) = { \
|
||||
#name, name, 1 \
|
||||
}; \
|
||||
\
|
||||
|
|
@ -86,6 +92,9 @@ test_sleep(unsigned int);
|
|||
void
|
||||
test_disable_coredumps(void);
|
||||
|
||||
int
|
||||
socketpair_cloexec(int domain, int type, int protocol, int sv[2]);
|
||||
|
||||
#define DISABLE_LEAK_CHECKS \
|
||||
do { \
|
||||
extern int fd_leak_check_enabled; \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue