mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
feat: add MinGW cross-compilation support for Windows builds on Linux (#2108)
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -10,4 +10,9 @@
|
||||
*.so
|
||||
*.dSYM
|
||||
.DS_Store
|
||||
.vscode
|
||||
.vscode
|
||||
3rd/lua/lua.exe
|
||||
3rd/lua/luac.exe
|
||||
3rd/lua/lua54.dll
|
||||
skynet.exe
|
||||
*.dll
|
||||
|
||||
1
3rd/compat-mingw/arpa/inet.h
Normal file
1
3rd/compat-mingw/arpa/inet.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
5
3rd/compat-mingw/compat.c
Normal file
5
3rd/compat-mingw/compat.c
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "compat.h"
|
||||
|
||||
#include "dlfcn.c"
|
||||
#include "unistd.c"
|
||||
#include "wepoll.c"
|
||||
4
3rd/compat-mingw/compat.h
Normal file
4
3rd/compat-mingw/compat.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "unistd.h"
|
||||
#include "dlfcn.h"
|
||||
20
3rd/compat-mingw/dlfcn.c
Normal file
20
3rd/compat-mingw/dlfcn.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "dlfcn.h"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
void *dlopen(const char *path, int flag) {
|
||||
return LoadLibraryA(path);
|
||||
}
|
||||
|
||||
const char *dlerror() {
|
||||
DWORD err = GetLastError();
|
||||
HLOCAL LocalAddress = NULL;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, 0, (PTSTR)&LocalAddress, 0, NULL);
|
||||
return (LPSTR)LocalAddress;
|
||||
}
|
||||
|
||||
void *dlsym(void *dl, const char *sym) {
|
||||
return GetProcAddress(dl, sym);
|
||||
}
|
||||
|
||||
7
3rd/compat-mingw/dlfcn.h
Normal file
7
3rd/compat-mingw/dlfcn.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum { RTLD_NOW, RTLD_GLOBAL };
|
||||
|
||||
void *dlopen(const char *path, int flag);
|
||||
const char *dlerror();
|
||||
void *dlsym(void *dl, const char *sym);
|
||||
3
3rd/compat-mingw/netdb.h
Normal file
3
3rd/compat-mingw/netdb.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
1
3rd/compat-mingw/netinet/in.h
Normal file
1
3rd/compat-mingw/netinet/in.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
1
3rd/compat-mingw/netinet/tcp.h
Normal file
1
3rd/compat-mingw/netinet/tcp.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
3
3rd/compat-mingw/sys/epoll.h
Normal file
3
3rd/compat-mingw/sys/epoll.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "wepoll.h"
|
||||
1
3rd/compat-mingw/sys/file.h
Normal file
1
3rd/compat-mingw/sys/file.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
17
3rd/compat-mingw/sys/socket.h
Normal file
17
3rd/compat-mingw/sys/socket.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#undef FD_SETSIZE
|
||||
#define FD_SETSIZE 1024
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include <ws2ipdef.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include "socket_poll.h"
|
||||
#include "socket_epoll.h"
|
||||
381
3rd/compat-mingw/unistd.c
Normal file
381
3rd/compat-mingw/unistd.c
Normal file
@@ -0,0 +1,381 @@
|
||||
#include "unistd.h"
|
||||
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
#include <errno.h>
|
||||
|
||||
// WSA error to errno mapping function
|
||||
static void set_errno_from_wsa_error(int wsa_error) {
|
||||
switch (wsa_error) {
|
||||
case WSAECONNRESET:
|
||||
errno = ECONNRESET;
|
||||
break;
|
||||
case WSAECONNABORTED:
|
||||
errno = ECONNABORTED;
|
||||
break;
|
||||
case WSAECONNREFUSED:
|
||||
errno = ECONNREFUSED;
|
||||
break;
|
||||
case WSAENETDOWN:
|
||||
errno = ENETDOWN;
|
||||
break;
|
||||
case WSAENETUNREACH:
|
||||
errno = ENETUNREACH;
|
||||
break;
|
||||
case WSAEHOSTDOWN:
|
||||
errno = EHOSTDOWN;
|
||||
break;
|
||||
case WSAEHOSTUNREACH:
|
||||
errno = EHOSTUNREACH;
|
||||
break;
|
||||
case WSAETIMEDOUT:
|
||||
errno = ETIMEDOUT;
|
||||
break;
|
||||
case WSAENOTCONN:
|
||||
errno = ENOTCONN;
|
||||
break;
|
||||
case WSAEWOULDBLOCK:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case WSAEINTR:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case WSAEINVAL:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case WSAEACCES:
|
||||
errno = EACCES;
|
||||
break;
|
||||
case WSAEADDRINUSE:
|
||||
errno = EADDRINUSE;
|
||||
break;
|
||||
case WSAEADDRNOTAVAIL:
|
||||
errno = EADDRNOTAVAIL;
|
||||
break;
|
||||
default:
|
||||
errno = EIO; // Generic I/O error for unknown cases
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Windows Socket initialization
|
||||
static int winsock_initialized = 0;
|
||||
|
||||
static int init_winsock(void) {
|
||||
if (!winsock_initialized) {
|
||||
WSADATA wsaData;
|
||||
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
winsock_initialized = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cleanup_winsock(void) {
|
||||
if (winsock_initialized) {
|
||||
WSACleanup();
|
||||
winsock_initialized = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-initialize Winsock when the library is loaded
|
||||
__attribute__((constructor))
|
||||
static void auto_init_winsock(void) {
|
||||
init_winsock();
|
||||
}
|
||||
|
||||
// Auto-cleanup Winsock when the library is unloaded
|
||||
__attribute__((destructor))
|
||||
static void auto_cleanup_winsock(void) {
|
||||
cleanup_winsock();
|
||||
}
|
||||
|
||||
static LONGLONG get_cpu_freq() {
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return freq.QuadPart;
|
||||
}
|
||||
|
||||
int kill(pid_t pid, int exit_code) {
|
||||
return TerminateProcess((HANDLE)(uintptr_t)pid, exit_code);
|
||||
}
|
||||
|
||||
#define NANOSEC 1000000000
|
||||
#define MICROSEC 1000000
|
||||
|
||||
void usleep(size_t us) {
|
||||
if (us > 1000) {
|
||||
Sleep(us / 1000);
|
||||
return;
|
||||
}
|
||||
LONGLONG delta = get_cpu_freq() / MICROSEC * us;
|
||||
LARGE_INTEGER counter;
|
||||
QueryPerformanceCounter(&counter);
|
||||
LONGLONG start = counter.QuadPart;
|
||||
for (;;) {
|
||||
QueryPerformanceCounter(&counter);
|
||||
if (counter.QuadPart - start >= delta)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void sleep(size_t ms) {
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
int clock_gettime(int what, struct timespec* ti) {
|
||||
switch (what) {
|
||||
case CLOCK_MONOTONIC:
|
||||
static __int64 Freq = 0;
|
||||
static __int64 Start = 0;
|
||||
static __int64 StartTime = 0;
|
||||
if (Freq == 0) {
|
||||
StartTime = time(NULL);
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&Freq);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&Start);
|
||||
}
|
||||
__int64 Count = 0;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&Count);
|
||||
|
||||
// 乘以1000,把秒化为毫秒
|
||||
__int64 now = (__int64)((double)(Count - Start) / (double)Freq * 1000.0) + StartTime * 1000;
|
||||
ti->tv_sec = now / 1000;
|
||||
ti->tv_nsec = (now - now / 1000 * 1000) * 1000 * 1000;
|
||||
return 0;
|
||||
case CLOCK_REALTIME:
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st); // 获取 UTC 时间
|
||||
|
||||
// 将 SYSTEMTIME 转换为 UNIX 时间戳
|
||||
FILETIME ft;
|
||||
SystemTimeToFileTime(&st, &ft);
|
||||
ULARGE_INTEGER u64;
|
||||
u64.LowPart = ft.dwLowDateTime;
|
||||
u64.HighPart = ft.dwHighDateTime;
|
||||
|
||||
ti->tv_sec = (uint32_t)((u64.QuadPart - 116444736000000000ULL) / 10000000); // 转换为秒
|
||||
ti->tv_nsec = (uint32_t)((u64.QuadPart % 10000000) * 100); // 获取纳秒部分
|
||||
return 0; // 响应成功
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
// 获取当前线程的 CPU 时间
|
||||
FILETIME creation_time, exit_time, kernel_time, user_time;
|
||||
if (GetThreadTimes(GetCurrentThread(), &creation_time, &exit_time, &kernel_time, &user_time)) {
|
||||
ULARGE_INTEGER u64;
|
||||
u64.LowPart = user_time.dwLowDateTime;
|
||||
u64.HighPart = user_time.dwHighDateTime;
|
||||
|
||||
ti->tv_sec = (uint32_t)((u64.QuadPart - 116444736000000000ULL) / 10000000); // 转换为秒
|
||||
ti->tv_nsec = (uint32_t)((u64.QuadPart % 10000000) * 100); // 获取纳秒部分
|
||||
return 0;
|
||||
} else {
|
||||
return -1; // 获取失败
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int flock(int fd, int flag) {
|
||||
// Not implemented
|
||||
return 3;
|
||||
}
|
||||
|
||||
int fcntl(int fd, int cmd, long arg) {
|
||||
if (cmd == F_GETFL)
|
||||
return 0;
|
||||
|
||||
if (cmd == F_SETFL && arg == O_NONBLOCK) {
|
||||
u_long ulOption = 1;
|
||||
ioctlsocket(fd, FIONBIO, &ulOption);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sigfillset(int* flag) {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
int sigemptyset(int* set) {
|
||||
/*Not implemented*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sigaction(int flag, struct sigaction* action, void* param) {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
static void socket_keepalive(int fd) {
|
||||
int keepalive = 1;
|
||||
int ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepalive,
|
||||
sizeof(keepalive));
|
||||
|
||||
assert(ret != SOCKET_ERROR);
|
||||
}
|
||||
|
||||
int pipe(int fd[2]) {
|
||||
int listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listen_fd == INVALID_SOCKET) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
|
||||
|
||||
srand(time(NULL));
|
||||
// use random port(range from 60000 to 60999) to simulate pipe()
|
||||
int port;
|
||||
for (;;) {
|
||||
port = 60000 + rand() % 1000;
|
||||
sin.sin_port = htons(port);
|
||||
if (!bind(listen_fd, (struct sockaddr*)&sin, sizeof(sin)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (listen(listen_fd, 5) == SOCKET_ERROR) {
|
||||
closesocket(listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_keepalive(listen_fd);
|
||||
|
||||
int client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (client_fd == INVALID_SOCKET) {
|
||||
closesocket(listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(client_fd, (struct sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) {
|
||||
closesocket(listen_fd);
|
||||
closesocket(client_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in client_addr;
|
||||
size_t name_len = sizeof(client_addr);
|
||||
int client_sock = accept(listen_fd, (struct sockaddr*)&client_addr, &name_len);
|
||||
if (client_sock == INVALID_SOCKET) {
|
||||
closesocket(listen_fd);
|
||||
closesocket(client_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
closesocket(listen_fd); // Close listen socket as it's no longer needed
|
||||
|
||||
fd[0] = client_sock;
|
||||
fd[1] = client_fd;
|
||||
|
||||
socket_keepalive(client_sock);
|
||||
socket_keepalive(client_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write(int fd, const void* ptr, unsigned int sz) {
|
||||
WSABUF vecs[1];
|
||||
vecs[0].buf = (char*)ptr;
|
||||
vecs[0].len = sz;
|
||||
|
||||
DWORD bytesSent;
|
||||
if (WSASend(fd, vecs, 1, &bytesSent, 0, NULL, NULL)) {
|
||||
int wsa_error = WSAGetLastError();
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1;
|
||||
} else {
|
||||
return bytesSent;
|
||||
}
|
||||
}
|
||||
|
||||
int read(int fd, void* buffer, unsigned int sz) {
|
||||
|
||||
WSABUF vecs[1];
|
||||
vecs[0].buf = buffer;
|
||||
vecs[0].len = sz;
|
||||
|
||||
DWORD bytesRecv = 0;
|
||||
DWORD flags = 0;
|
||||
if (WSARecv(fd, vecs, 1, &bytesRecv, &flags, NULL, NULL)) {
|
||||
int wsa_error = WSAGetLastError();
|
||||
|
||||
if (wsa_error == WSAECONNRESET) {
|
||||
return 0; // Connection closed by peer
|
||||
}
|
||||
|
||||
// Map WSA error to errno for better error reporting
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1;
|
||||
} else {
|
||||
return bytesRecv;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for recv function with better error handling
|
||||
int compat_recv(SOCKET s, char *buf, int len, int flags) {
|
||||
WSABUF vecs[1];
|
||||
vecs[0].buf = buf;
|
||||
vecs[0].len = len;
|
||||
|
||||
DWORD bytesRecv = 0;
|
||||
DWORD wsaFlags = 0;
|
||||
if (WSARecv(s, vecs, 1, &bytesRecv, &wsaFlags, NULL, NULL)) {
|
||||
int wsa_error = WSAGetLastError();
|
||||
|
||||
// Handle non-blocking operations - these are not real errors
|
||||
if (wsa_error == WSAEWOULDBLOCK || wsa_error == WSAEINTR) {
|
||||
// For non-blocking sockets, this is normal - no data available right now
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1; // Caller should check errno == EAGAIN
|
||||
}
|
||||
|
||||
if (wsa_error == WSAECONNRESET) {
|
||||
return 0; // Connection closed by peer
|
||||
}
|
||||
|
||||
// Map WSA error to errno for better error reporting
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1;
|
||||
} else {
|
||||
return bytesRecv;
|
||||
}
|
||||
}
|
||||
|
||||
int close(int fd) {
|
||||
shutdown(fd, SD_BOTH);
|
||||
return closesocket(fd);
|
||||
}
|
||||
|
||||
int daemon(int a, int b) {
|
||||
// Not implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* strsep(char** stringp, const char* delim) {
|
||||
char* s;
|
||||
const char* spanp;
|
||||
int c, sc;
|
||||
char* tok;
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
117
3rd/compat-mingw/unistd.h
Normal file
117
3rd/compat-mingw/unistd.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include <io.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Define missing errno values for network errors
|
||||
#ifndef ECONNRESET
|
||||
#define ECONNRESET 104
|
||||
#endif
|
||||
#ifndef ECONNABORTED
|
||||
#define ECONNABORTED 103
|
||||
#endif
|
||||
#ifndef ECONNREFUSED
|
||||
#define ECONNREFUSED 111
|
||||
#endif
|
||||
#ifndef ENETDOWN
|
||||
#define ENETDOWN 100
|
||||
#endif
|
||||
#ifndef ENETUNREACH
|
||||
#define ENETUNREACH 101
|
||||
#endif
|
||||
#ifndef EHOSTDOWN
|
||||
#define EHOSTDOWN 112
|
||||
#endif
|
||||
#ifndef EHOSTUNREACH
|
||||
#define EHOSTUNREACH 113
|
||||
#endif
|
||||
#ifndef ETIMEDOUT
|
||||
#define ETIMEDOUT 110
|
||||
#endif
|
||||
#ifndef ENOTCONN
|
||||
#define ENOTCONN 107
|
||||
#endif
|
||||
#ifndef EADDRINUSE
|
||||
#define EADDRINUSE 98
|
||||
#endif
|
||||
#ifndef EADDRNOTAVAIL
|
||||
#define EADDRNOTAVAIL 99
|
||||
#endif
|
||||
|
||||
// Include winsock2.h for gethostname and other network functions
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
// Undefine Windows legacy keywords that conflict with variable names
|
||||
#ifdef near
|
||||
#undef near
|
||||
#endif
|
||||
#ifdef far
|
||||
#undef far
|
||||
#endif
|
||||
|
||||
// Socket compatibility macros
|
||||
#define SHUT_RD SD_RECEIVE
|
||||
#define SHUT_WR SD_SEND
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
|
||||
#define ssize_t size_t
|
||||
|
||||
#define random rand
|
||||
#define srandom srand
|
||||
#define snprintf _snprintf
|
||||
#define localtime_r _localtime64_s
|
||||
|
||||
#define pid_t int
|
||||
|
||||
int kill(pid_t pid, int exit_code);
|
||||
|
||||
void usleep(size_t us);
|
||||
void sleep(size_t ms);
|
||||
|
||||
int clock_gettime(int what, struct timespec *ti);
|
||||
|
||||
enum { LOCK_EX, LOCK_NB };
|
||||
int flock(int fd, int flag);
|
||||
|
||||
struct sigaction {
|
||||
void (*sa_handler)(int);
|
||||
int sa_flags;
|
||||
int sa_mask;
|
||||
};
|
||||
enum { SIGPIPE, SIGHUP, SA_RESTART };
|
||||
void sigfillset(int *flag);
|
||||
int sigemptyset(int* set);
|
||||
void sigaction(int flag, struct sigaction *action, void* param);
|
||||
|
||||
int pipe(int fd[2]);
|
||||
int daemon(int a, int b);
|
||||
|
||||
#define O_NONBLOCK 1
|
||||
#define F_SETFL 0
|
||||
#define F_GETFL 1
|
||||
|
||||
int fcntl(int fd, int cmd, long arg);
|
||||
|
||||
char *strsep(char **stringp, const char *delim);
|
||||
|
||||
int write(int fd, const void* ptr, unsigned int sz);
|
||||
int read(int fd, void* buffer, unsigned int sz);
|
||||
// Wrapper function for recv with better error handling
|
||||
int compat_recv(SOCKET s, char *buf, int len, int flags);
|
||||
|
||||
// Macro to redirect recv calls to our wrapper
|
||||
#define recv compat_recv
|
||||
int close(int fd);
|
||||
|
||||
#define getpid _getpid
|
||||
#define open _open
|
||||
#define dup2 _dup2
|
||||
2253
3rd/compat-mingw/wepoll.c
Normal file
2253
3rd/compat-mingw/wepoll.c
Normal file
File diff suppressed because it is too large
Load Diff
113
3rd/compat-mingw/wepoll.h
Normal file
113
3rd/compat-mingw/wepoll.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* wepoll - epoll for Windows
|
||||
* https://github.com/piscisaureus/wepoll
|
||||
*
|
||||
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WEPOLL_H_
|
||||
#define WEPOLL_H_
|
||||
|
||||
#ifndef WEPOLL_EXPORT
|
||||
#define WEPOLL_EXPORT
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum EPOLL_EVENTS {
|
||||
EPOLLIN = (int) (1U << 0),
|
||||
EPOLLPRI = (int) (1U << 1),
|
||||
EPOLLOUT = (int) (1U << 2),
|
||||
EPOLLERR = (int) (1U << 3),
|
||||
EPOLLHUP = (int) (1U << 4),
|
||||
EPOLLRDNORM = (int) (1U << 6),
|
||||
EPOLLRDBAND = (int) (1U << 7),
|
||||
EPOLLWRNORM = (int) (1U << 8),
|
||||
EPOLLWRBAND = (int) (1U << 9),
|
||||
EPOLLMSG = (int) (1U << 10), /* Never reported. */
|
||||
EPOLLRDHUP = (int) (1U << 13),
|
||||
EPOLLONESHOT = (int) (1U << 31)
|
||||
};
|
||||
|
||||
#define EPOLLIN (1U << 0)
|
||||
#define EPOLLPRI (1U << 1)
|
||||
#define EPOLLOUT (1U << 2)
|
||||
#define EPOLLERR (1U << 3)
|
||||
#define EPOLLHUP (1U << 4)
|
||||
#define EPOLLRDNORM (1U << 6)
|
||||
#define EPOLLRDBAND (1U << 7)
|
||||
#define EPOLLWRNORM (1U << 8)
|
||||
#define EPOLLWRBAND (1U << 9)
|
||||
#define EPOLLMSG (1U << 10)
|
||||
#define EPOLLRDHUP (1U << 13)
|
||||
#define EPOLLONESHOT (1U << 31)
|
||||
|
||||
#define EPOLL_CTL_ADD 1
|
||||
#define EPOLL_CTL_MOD 2
|
||||
#define EPOLL_CTL_DEL 3
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef uintptr_t SOCKET;
|
||||
|
||||
typedef union epoll_data {
|
||||
void* ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
SOCKET sock; /* Windows specific */
|
||||
HANDLE hnd; /* Windows specific */
|
||||
} epoll_data_t;
|
||||
|
||||
struct epoll_event {
|
||||
uint32_t events; /* Epoll events and flags */
|
||||
epoll_data_t data; /* User data variable */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WEPOLL_EXPORT HANDLE epoll_create(int size);
|
||||
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
|
||||
|
||||
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
|
||||
|
||||
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* event);
|
||||
|
||||
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WEPOLL_H_ */
|
||||
2
Makefile
2
Makefile
@@ -121,6 +121,7 @@ $(LUA_CLIB_PATH)/lpeg.so : 3rd/lpeg/lpcap.c 3rd/lpeg/lpcode.c 3rd/lpeg/lpprint.c
|
||||
clean :
|
||||
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so && \
|
||||
rm -rf $(SKYNET_BUILD_PATH)/*.dSYM $(CSERVICE_PATH)/*.dSYM $(LUA_CLIB_PATH)/*.dSYM
|
||||
$(MAKE) clean -f mingw.mk
|
||||
|
||||
cleanall: clean
|
||||
ifneq (,$(wildcard 3rd/jemalloc/Makefile))
|
||||
@@ -128,3 +129,4 @@ ifneq (,$(wildcard 3rd/jemalloc/Makefile))
|
||||
endif
|
||||
cd 3rd/lua && $(MAKE) clean
|
||||
rm -f $(LUA_STATICLIB)
|
||||
$(MAKE) cleanall -f mingw.mk
|
||||
161
mingw.mk
Normal file
161
mingw.mk
Normal file
@@ -0,0 +1,161 @@
|
||||
# Cross-compilation toolchain
|
||||
CC = x86_64-w64-mingw32-gcc
|
||||
AR = x86_64-w64-mingw32-ar
|
||||
RANLIB = x86_64-w64-mingw32-ranlib
|
||||
|
||||
LUA_CLIB_PATH ?= luaclib
|
||||
CSERVICE_PATH ?= cservice
|
||||
SKYNET_BUILD_PATH ?= .
|
||||
COMPAT_MINGW_DIR = 3rd/compat-mingw
|
||||
|
||||
LUA_DIR = 3rd/lua
|
||||
LUA_CFLAGS = -g -O2 -Wall -I. -std=gnu99 -I../../skynet-src
|
||||
LUA_STATICLIB := 3rd/lua/liblua.a
|
||||
LUA_DLL ?= 3rd/lua/lua54.dll
|
||||
SKYNET_DLL ?= $(SKYNET_BUILD_PATH)/skynet.dll
|
||||
LUA_INC ?= $(LUA_DIR)
|
||||
|
||||
# Lua linking options
|
||||
LUA_LIBS = -L$(LUA_DIR) -llua54
|
||||
LUA_STATIC_LIBS = $(LUA_STATICLIB)
|
||||
|
||||
# Skynet linking and include options
|
||||
SKYNET_LINK_LIBS = -L$(SKYNET_BUILD_PATH) -lskynet
|
||||
SKYNET_INCLUDES = -Iskynet-src -I$(COMPAT_MINGW_DIR) -I$(LUA_INC)
|
||||
SHARED_BUILD = $(CC) $(CFLAGS) $(SHARED)
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS = -g -O2 -Wall -std=gnu99 -I$(LUA_INC) $(MYCFLAGS)
|
||||
CFLAGS += -I3rd/lua -Iskynet-src -I$(COMPAT_MINGW_DIR)
|
||||
CFLAGS += -include $(COMPAT_MINGW_DIR)/compat.h
|
||||
CFLAGS += -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-pointer-sign -Wno-unused-function
|
||||
|
||||
LDFLAGS = -Wl,--export-all-symbols,--out-implib,libskynet.a
|
||||
SHARED = -fPIC --shared -Wl,--export-all-symbols,--enable-auto-import,--allow-shlib-undefined,--unresolved-symbols=ignore-all
|
||||
|
||||
SKYNET_LIBS = -static-libgcc -Wl,-Bstatic -lpthread -Wl,-Bdynamic -lm -lws2_32 -lgdi32
|
||||
|
||||
SKYNET_DEFINES = -DNOUSE_JEMALLOC
|
||||
|
||||
COMPAT_LIB = $(COMPAT_MINGW_DIR)/libcompat.a
|
||||
|
||||
CSERVICE = snlua logger gate harbor
|
||||
|
||||
LUA_CLIB = skynet client bson md5 sproto lpeg
|
||||
|
||||
LUA_CLIB_SKYNET = \
|
||||
lua-skynet.c lua-seri.c \
|
||||
lua-socket.c \
|
||||
lua-mongo.c \
|
||||
lua-netpack.c \
|
||||
lua-memory.c \
|
||||
lua-multicast.c \
|
||||
lua-cluster.c \
|
||||
lua-crypt.c lsha1.c \
|
||||
lua-sharedata.c \
|
||||
lua-stm.c \
|
||||
lua-debugchannel.c \
|
||||
lua-datasheet.c \
|
||||
lua-sharetable.c \
|
||||
\
|
||||
|
||||
SKYNET_SRC = skynet_main.c skynet_handle.c skynet_module.c skynet_mq.c \
|
||||
skynet_server.c skynet_start.c skynet_timer.c skynet_error.c \
|
||||
skynet_harbor.c skynet_env.c skynet_monitor.c skynet_socket.c socket_server.c \
|
||||
mem_info.c malloc_hook.c skynet_daemon.c skynet_log.c
|
||||
|
||||
$(LUA_STATICLIB):
|
||||
@echo "Building Lua static library..."
|
||||
cd $(LUA_DIR) && $(CC) $(LUA_CFLAGS) -DMAKE_LIB -c onelua.c -o onelua.o
|
||||
cd $(LUA_DIR) && $(AR) rcs liblua.a onelua.o
|
||||
|
||||
$(LUA_DLL) : $(LUA_STATICLIB)
|
||||
@echo "Building Lua DLL..."
|
||||
cd $(LUA_DIR) && $(CC) -shared -o lua54.dll onelua.o -Wl,--export-all-symbols,--out-implib,liblua54.a $(SKYNET_LIBS)
|
||||
@echo "Lua DLL and import library created successfully"
|
||||
|
||||
$(LUA_DIR)/lua.exe : $(LUA_DLL) $(LUA_STATICLIB)
|
||||
@echo "Building Lua interpreter..."
|
||||
cd $(LUA_DIR) && $(CC) $(LUA_CFLAGS) -c lua.c -o lua.o
|
||||
cd $(LUA_DIR) && $(CC) $(LUA_CFLAGS) -o lua.exe lua.o -L. -llua54 $(SKYNET_LIBS)
|
||||
cp $(LUA_DLL) $(SKYNET_BUILD_PATH)/
|
||||
|
||||
$(LUA_DIR)/luac.exe : $(LUA_DLL) $(LUA_STATICLIB)
|
||||
@echo "Building Lua compiler..."
|
||||
cd $(LUA_DIR) && $(CC) $(LUA_CFLAGS) -DMAKE_LUAC -c onelua.c -o luac.o
|
||||
cd $(LUA_DIR) && $(CC) $(LUA_CFLAGS) -o luac.exe luac.o liblua.a $(SKYNET_LIBS)
|
||||
|
||||
$(COMPAT_LIB): $(COMPAT_MINGW_DIR)/compat.c
|
||||
@echo "Building compatibility library..."
|
||||
$(CC) $(CFLAGS) -c $(COMPAT_MINGW_DIR)/compat.c -o $(COMPAT_MINGW_DIR)/compat.o
|
||||
cd $(COMPAT_MINGW_DIR) && $(AR) rcs libcompat.a compat.o
|
||||
cd $(COMPAT_MINGW_DIR) && $(RANLIB) libcompat.a
|
||||
|
||||
# Build order: first build core libraries, then dependent modules
|
||||
all : core_libs modules tools
|
||||
|
||||
.PHONY: core_libs modules tools
|
||||
|
||||
core_libs: $(LUA_STATICLIB) $(LUA_DLL) $(SKYNET_DLL)
|
||||
|
||||
modules: core_libs $(foreach v, $(CSERVICE), $(CSERVICE_PATH)/$(v).so) $(foreach v, $(LUA_CLIB), $(LUA_CLIB_PATH)/$(v).so)
|
||||
|
||||
tools: core_libs $(LUA_DIR)/lua.exe $(LUA_DIR)/luac.exe $(SKYNET_BUILD_PATH)/skynet.exe
|
||||
|
||||
|
||||
SKYNET_LIB_SRC = $(filter-out skynet_main.c, $(SKYNET_SRC))
|
||||
|
||||
|
||||
$(SKYNET_DLL) : $(foreach v, $(SKYNET_LIB_SRC), skynet-src/$(v)) $(COMPAT_LIB) $(LUA_DLL)
|
||||
@echo "Building skynet.dll..."
|
||||
$(CC) $(CFLAGS) -shared -o $@ $(foreach v, $(SKYNET_LIB_SRC), skynet-src/$(v)) $(COMPAT_LIB) $(LUA_LIBS) $(SKYNET_INCLUDES) $(SKYNET_LIBS) $(SKYNET_DEFINES) $(LDFLAGS)
|
||||
|
||||
|
||||
$(SKYNET_BUILD_PATH)/skynet.exe : skynet-src/skynet_main.c $(SKYNET_DLL) $(COMPAT_LIB) $(LUA_DLL)
|
||||
@echo "Building skynet.exe..."
|
||||
$(CC) $(CFLAGS) -o $@ skynet-src/skynet_main.c $(COMPAT_LIB) $(SKYNET_LINK_LIBS) $(LUA_LIBS) $(SKYNET_INCLUDES) $(SKYNET_LIBS) $(SKYNET_DEFINES)
|
||||
cp $(LUA_DLL) $(SKYNET_BUILD_PATH)/
|
||||
|
||||
$(LUA_CLIB_PATH) :
|
||||
mkdir $(LUA_CLIB_PATH)
|
||||
|
||||
$(CSERVICE_PATH) :
|
||||
mkdir $(CSERVICE_PATH)
|
||||
|
||||
define CSERVICE_TEMP
|
||||
$$(CSERVICE_PATH)/$(1).so : service-src/service_$(1).c $$(LUA_DLL) $$(SKYNET_DLL) | $$(CSERVICE_PATH)
|
||||
$$(CC) $$(CFLAGS) $$(SHARED) $$< -o $$@ $$(SKYNET_INCLUDES) $$(LUA_LIBS) $$(SKYNET_LINK_LIBS)
|
||||
endef
|
||||
|
||||
$(foreach v, $(CSERVICE), $(eval $(call CSERVICE_TEMP,$(v))))
|
||||
|
||||
|
||||
$(LUA_CLIB_PATH)/skynet.so : $(addprefix lualib-src/,$(LUA_CLIB_SKYNET)) $(SKYNET_DLL) $(LUA_DLL) | $(LUA_CLIB_PATH)
|
||||
$(SHARED_BUILD) $(addprefix lualib-src/,$(LUA_CLIB_SKYNET)) -o $@ $(SKYNET_INCLUDES) -Iservice-src -Ilualib-src $(SKYNET_LINK_LIBS) $(LUA_LIBS) $(SKYNET_LIBS)
|
||||
|
||||
$(LUA_CLIB_PATH)/bson.so : lualib-src/lua-bson.c $(LUA_DLL) | $(LUA_CLIB_PATH)
|
||||
$(SHARED_BUILD) $^ -o $@ $(SKYNET_INCLUDES) $(LUA_LIBS) $(SKYNET_LIBS)
|
||||
|
||||
$(LUA_CLIB_PATH)/md5.so : 3rd/lua-md5/md5.c 3rd/lua-md5/md5lib.c 3rd/lua-md5/compat-5.2.c $(LUA_DLL) | $(LUA_CLIB_PATH)
|
||||
$(SHARED_BUILD) -I3rd/lua-md5 -Wno-attributes $^ -o $@ $(LUA_LIBS) $(SKYNET_LIBS)
|
||||
|
||||
$(LUA_CLIB_PATH)/client.so : lualib-src/lua-clientsocket.c lualib-src/lua-crypt.c lualib-src/lsha1.c $(COMPAT_LIB) $(LUA_DLL) | $(LUA_CLIB_PATH)
|
||||
$(SHARED_BUILD) $^ -o $@ $(LUA_LIBS) $(SKYNET_LIBS)
|
||||
|
||||
$(LUA_CLIB_PATH)/sproto.so : lualib-src/sproto/sproto.c lualib-src/sproto/lsproto.c $(LUA_DLL) | $(LUA_CLIB_PATH)
|
||||
$(SHARED_BUILD) -Ilualib-src/sproto $^ -o $@ $(LUA_LIBS) $(SKYNET_LIBS)
|
||||
|
||||
$(LUA_CLIB_PATH)/lpeg.so : 3rd/lpeg/lpcap.c 3rd/lpeg/lpcode.c 3rd/lpeg/lpprint.c 3rd/lpeg/lptree.c 3rd/lpeg/lpvm.c 3rd/lpeg/lpcset.c $(LUA_DLL) | $(LUA_CLIB_PATH)
|
||||
$(SHARED_BUILD) -I3rd/lpeg $^ -o $@ $(LUA_LIBS) $(SKYNET_LIBS)
|
||||
|
||||
.PHONY: clean cleanall core_libs modules tools
|
||||
|
||||
clean :
|
||||
rm -f $(SKYNET_BUILD_PATH)/*.exe $(SKYNET_BUILD_PATH)/*.dll $(SKYNET_BUILD_PATH)/*.a
|
||||
rm -f $(COMPAT_LIB) $(COMPAT_MINGW_DIR)/*.o
|
||||
rm -f $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
|
||||
rm -f $(LUA_DIR)/*.a
|
||||
|
||||
cleanall: clean
|
||||
rm -f $(LUA_STATICLIB)
|
||||
rm -f $(LUA_DIR)/*.exe $(LUA_DIR)/*.dll $(LUA_DIR)/*.a $(LUA_DIR)/*.o
|
||||
@@ -1,5 +1,5 @@
|
||||
PLAT ?= none
|
||||
PLATS = linux freebsd macosx
|
||||
PLATS = linux freebsd macosx mingw
|
||||
|
||||
CC ?= gcc
|
||||
|
||||
@@ -25,6 +25,7 @@ EXPORT := -Wl,-E
|
||||
linux : PLAT = linux
|
||||
macosx : PLAT = macosx
|
||||
freebsd : PLAT = freebsd
|
||||
mingw : PLAT = mingw
|
||||
|
||||
macosx : SHARED := -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup
|
||||
macosx : EXPORT :=
|
||||
@@ -38,3 +39,6 @@ macosx : SKYNET_DEFINES :=-DNOUSE_JEMALLOC
|
||||
|
||||
linux macosx freebsd :
|
||||
$(MAKE) all PLAT=$@ SKYNET_LIBS="$(SKYNET_LIBS)" SHARED="$(SHARED)" EXPORT="$(EXPORT)" MALLOC_STATICLIB="$(MALLOC_STATICLIB)" SKYNET_DEFINES="$(SKYNET_DEFINES)"
|
||||
|
||||
mingw :
|
||||
$(MAKE) -f mingw.mk all PLAT=$@
|
||||
|
||||
Reference in New Issue
Block a user