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:
Martin Lopatář 2026-01-10 08:01:57 +01:00 committed by Martin Lopatář
parent 53509f09ba
commit 6ef7947c93
16 changed files with 179 additions and 23 deletions

View file

@ -316,6 +316,19 @@ wl_connection_set_max_buffer_size(struct wl_connection *connection,
ring_buffer_ensure_space(&connection->out, 0);
}
#ifdef __APPLE__
static int fd_setfl_nonblock(int fd)
{
int flags;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
return flags;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
struct wl_connection *
wl_connection_create(int fd, size_t max_buffer_size)
{
@ -329,6 +342,10 @@ wl_connection_create(int fd, size_t max_buffer_size)
connection->fd = fd;
#ifdef __APPLE__
fd_setfl_nonblock(fd);
#endif
return connection;
}

View file

@ -23,6 +23,8 @@
* SOFTWARE.
*/
#include "../config.h"
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
@ -45,6 +47,13 @@
#include "wayland-server-private.h"
#include "wayland-os.h"
#ifndef HAVE_ITIMERSPEC
struct itimerspec {
struct timespec it_interval;
struct timespec it_value;
};
#endif
/** \cond INTERNAL */
#define TIMER_REMOVED -2

View file

@ -34,6 +34,7 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <ctype.h>

View file

@ -75,17 +75,19 @@ wl_os_socket_cloexec(int domain, int type, int protocol)
{
int fd;
#ifdef SOCK_CLOEXEC
fd = wl_socket(domain, type | SOCK_CLOEXEC, protocol);
if (fd >= 0)
return fd;
if (errno != EINVAL)
return -1;
#endif
fd = wl_socket(domain, type, protocol);
return set_cloexec_or_close(fd);
}
#if defined(__FreeBSD__)
#if defined(LOCAL_PEERCRED)
int
wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
{
@ -101,11 +103,15 @@ wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
#if HAVE_XUCRED_CR_PID
/* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */
*pid = ucred.cr_pid;
#elif defined(LOCAL_PEERPID)
if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERPID, pid, &len) < 0)
*pid = 0;
#else
*pid = 0;
#endif
return 0;
}
#elif defined(SO_PEERCRED)
int
wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
@ -125,6 +131,7 @@ wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
*pid = ucred.pid;
return 0;
}
#else
#error "Don't know how to read ucred on this platform"
#endif
@ -186,7 +193,7 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
* fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
*/
#pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.")
#else
#elif defined(MSG_CMSG_CLOEXEC)
ssize_t len;
len = wl_recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
@ -220,7 +227,8 @@ wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
int fd;
#ifdef HAVE_ACCEPT4
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
if (fd >= 0)
return fd;