Fix Windows build

master
Perttu Ahola 2014-10-31 10:53:35 +02:00
parent a1610d5203
commit 3cb57eaee4
14 changed files with 158 additions and 70 deletions

View File

@ -115,7 +115,6 @@ set(SERVER_EXE_NAME buildat_server)
set(BUILDAT_CORE_SRCS
src/core/log.cpp
src/core/json.cpp
src/boot/cmem.c
src/boot/autodetect.cpp
src/impl/fs.cpp
src/impl/event.cpp
@ -134,11 +133,13 @@ set(BUILDAT_CORE_SRCS
src/impl/thread.cpp
)
if(WIN32)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/boot/windows/cmem.c)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/windows/file_watch.cpp)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/windows/process.cpp)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/windows/debug.cpp)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/windows/os.cpp)
else()
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/boot/linux/cmem.c)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/linux/file_watch.cpp)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/linux/process.cpp)
set(BUILDAT_CORE_SRCS ${BUILDAT_CORE_SRCS} src/impl/linux/debug.cpp)
@ -155,6 +156,7 @@ if(WIN32)
target_link_libraries(${BUILDAT_CORE_NAME}
wsock32
ws2_32
psapi # Process stuff
${ABSOLUTE_PATH_LIBS}
${LINK_LIBS_ONLY}
)
@ -252,17 +254,20 @@ if(WIN32)
install(TARGETS ${BUILDAT_CORE_NAME} DESTINATION "${DST_BIN}")
# Always copy these DLLs to the same directory as the executables. On the
# server, they also exist in the compiler's path, but there really is no
# reasonable way of accessing them from there.
# Even Rust does it this way: https://github.com/rust-lang/rust/issues/1011
install(FILES "${COMPILER_USR_PATH}/bin/libwinpthread-1.dll" DESTINATION "${DST_BIN}")
install(FILES "${COMPILER_USR_PATH}/bin/libgcc_s_dw2-1.dll" DESTINATION "${DST_BIN}")
install(FILES "${COMPILER_USR_PATH}/bin/libstdc++-6.dll" DESTINATION "${DST_BIN}")
if(BUILD_CLIENT)
install(TARGETS ${CLIENT_EXE_NAME} DESTINATION "${DST_BIN}")
install(DIRECTORY "${CMAKE_SOURCE_DIR}/client" DESTINATION "${DST_SHARE}")
install(DIRECTORY "${CMAKE_SOURCE_DIR}/extensions" DESTINATION "${DST_SHARE}")
install(FILES "${CMAKE_SOURCE_DIR}/util/windows/launch_client.bat" DESTINATION ".")
install(FILES "${CMAKE_SOURCE_DIR}/util/windows/wine_launch_client.sh" DESTINATION ".")
if(NOT BUILD_SERVER)
install(FILES "${COMPILER_USR_PATH}/bin/libwinpthread-1.dll" DESTINATION "${DST_BIN}")
install(FILES "${COMPILER_USR_PATH}/bin/libgcc_s_dw2-1.dll" DESTINATION "${DST_BIN}")
install(FILES "${COMPILER_USR_PATH}/bin/libstdc++-6.dll" DESTINATION "${DST_BIN}")
endif()
endif()
if(BUILD_SERVER)

View File

@ -12,6 +12,7 @@
#include <cereal/archives/portable_binary.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/tuple.hpp>
#include <deque>
#ifdef _WIN32
#include "ports/windows_sockets.h"
#include "ports/windows_compat.h" // usleep()
@ -19,7 +20,7 @@
#include <sys/socket.h>
#include <unistd.h> // usleep()
#endif
#include <deque>
#include <errno.h>
#define MODULE "network"
using interface::Event;
@ -218,10 +219,12 @@ struct Module: public interface::Module, public network::Interface
char buf[100000];
ssize_t r = recv(fd, buf, 100000, 0);
if(r == -1){
#ifdef ECONNRESET // No idea why this isn't defined on MinGW
if(errno == ECONNRESET){
log_v(MODULE, "Peer %zu: Connection reset by peer", peer.id);
return;
}
#endif
throw Exception(ss_()+"Receive failed: "+strerror(errno));
}
if(r == 0){

View File

@ -199,6 +199,7 @@ static void generate_urho3d_root_alternatives(sv_<ss_> &roots)
generate_buildat_root_alternatives(buildat_roots);
for(const ss_ &buildat_root : buildat_roots){
roots.push_back(buildat_root + "/Urho3D");
roots.push_back(buildat_root + "/../Urho3D");
}
}

57
src/boot/basic_init.h Normal file
View File

@ -0,0 +1,57 @@
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
#pragma once
#include "core/types.h"
#include "boot/cmem.h"
#include "interface/debug.h"
#include "interface/os.h"
#ifdef _WIN32
#include "ports/windows_sockets.h"
#include "ports/windows_compat.h"
#else
#include <unistd.h>
#endif
void signal_handler_init();
namespace boot
{
struct BasicInitScope
{
BasicInitScope(){
boot::buildat_mem_libc_enable();
signal_handler_init();
// Force '.' as decimal point
try {
std::locale::global(std::locale(std::locale(""), "C", std::locale::numeric));
} catch(std::runtime_error &e){
// Can happen on Wine
fprintf(stderr, "Failed to set numeric C++ locale\n");
}
setlocale(LC_NUMERIC, "C");
log_init();
log_set_max_level(CORE_VERBOSE);
interface::debug::SigConfig debug_sig_config;
interface::debug::init_signal_handlers(debug_sig_config);
srand(interface::os::time_us());
#ifdef _WIN32
WORD version_request = MAKEWORD(2, 2);
WSADATA wsa_data;
if(int err = WSAStartup(version_request, &wsa_data))
throw Exception("WSAStartup failed; err="+itos(err));
#endif
}
~BasicInitScope(){
#ifdef _WIN32
WSACleanup();
#endif
}
};
}
// vim: set noet ts=4 sw=4:

View File

@ -1,3 +1,5 @@
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
#define _GNU_SOURCE // RTLD_NEXT
#include <stdint.h>
#include <stdlib.h>

12
src/boot/windows/cmem.c Normal file
View File

@ -0,0 +1,12 @@
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
void buildat_mem_libc_enable()
{
// No-op
}
void buildat_mem_libc_disable()
{
// No-op
}

View File

@ -2,8 +2,8 @@
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
#include "core/types.h"
#include "core/log.h"
#include "boot/basic_init.h"
#include "boot/autodetect.h"
#include "boot/cmem.h"
#include "client/config.h"
#include "client/state.h"
#include "client/app.h"
@ -35,30 +35,9 @@ void signal_handler_init()
(void)signal(SIGINT, sigint_handler);
}
void basic_init()
{
boot::buildat_mem_libc_enable();
signal_handler_init();
// Force '.' as decimal point
try {
std::locale::global(std::locale(std::locale(""), "C", std::locale::numeric));
} catch(std::runtime_error &e){
// Can happen on Wine
fprintf(stderr, "Failed to set numeric C++ locale\n");
}
setlocale(LC_NUMERIC, "C");
log_init();
log_set_max_level(CORE_VERBOSE);
srand(interface::os::time_us());
}
int main(int argc, char *argv[])
{
basic_init();
boot::BasicInitScope basic_init_scope;
client::Config &config = g_client_config;

View File

@ -164,4 +164,20 @@ static inline const T* check(const T *v){
return v;
}
#ifdef __MINGW32__
// MinGW doesn't have std::to_string (as of mingw-w64 4.9.1); define something to replace it
// This include is going to fuck things up for Linux users that use modules developed on Windows
#include <sstream>
namespace std {
template<typename T>
ss_ to_string(const T &v){
std::ostringstream os;
os<<v;
return os.str();
}
}
// Also this doesn't exist on MinGW (as of mingw-w64 4.9.1)
typedef int ssize_t;
#endif
// vim: set noet ts=4 sw=4:

View File

@ -71,6 +71,7 @@ struct CThread: public Thread
}
log_d(MODULE, "Thread started: %p (%s)", thread, cs(thread_name));
#ifndef _WIN32
// Set thread name
if(!thread_name.empty()){
ss_ limited_name = thread_name.size() <= 15 ?
@ -81,7 +82,6 @@ struct CThread: public Thread
}
}
#ifndef _WIN32
// Disable all signals
sigset_t sigset;
sigemptyset(&sigset);

View File

@ -48,11 +48,11 @@ struct CThreadPool: public ThreadPool
{
Thread *thread = (Thread*)arg;
log_d(MODULE, "Worker thread %p start", arg);
#ifndef _WIN32
// Set name
if(pthread_setname_np(thread->thread, "buildat:worker")){
log_w(MODULE, "Failed to set worker thread %p name", thread);
}
#ifndef _WIN32
// Disable all signals
sigset_t sigset;
sigemptyset(&sigset);

View File

@ -1,9 +1,12 @@
// http://www.apache.org/licenses/LICENSE-2.0
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
#include "interface/os.h"
#include "core/log.h"
#include <sys/time.h>
#include "ports/windows_minimal.h"
#include "ports/windows_compat.h"
#include <psapi.h>
#define MODULE "os"
namespace interface {
namespace os {
@ -20,14 +23,38 @@ void sleep_us(int us)
usleep(us);
}
struct HandleScope {
HANDLE h;
HandleScope(HANDLE h): h(h){}
~HandleScope(){CloseHandle(h);}
};
ss_ get_current_exe_path()
{
const DWORD buflen = 1000;
char buf[buflen];
DWORD len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen);
if(len < buflen)
throw Exception("len < buflen");
return buf;
DWORD process_id = GetCurrentProcessId();
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_id);
if(process == nullptr)
throw Exception("get_current_exe_path(): process == nullptr");
HandleScope hs(process);
HMODULE modules[1000];
DWORD num_module_bytes;
if(!EnumProcessModules(process, modules, sizeof modules, &num_module_bytes))
throw Exception("get_current_exe_path(): EnumProcessModules failed");
for(size_t i = 0; i < num_module_bytes / sizeof(HMODULE); i++){
TCHAR module_name[MAX_PATH];
if(GetModuleFileNameEx(process, modules[i], module_name,
sizeof(module_name) / sizeof(char))){
//log_w(MODULE, "module_name=%s", module_name);
// We want a module that ends in ".exe"
ss_ ns(module_name);
if(ns.substr(ns.size()-4, 4) == ".exe"){
return ns;
}
}
}
throw Exception("get_current_exe_path(): .exe module not found");
}
}

View File

@ -10,6 +10,7 @@
#include <unistd.h> // usleep()
#endif
#include <cstring> // strerror()
#include <cstdlib> // rand()
namespace interface
{
@ -26,6 +27,14 @@ namespace interface
bool check(int timeout_us, const sv_<int> &sockets,
sv_<int> &active_sockets)
{
#ifdef _WIN32
// On Windows select() returns an error if no sockets are supplied
if(sockets.empty()){
usleep(timeout_us);
return true;
}
#endif
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = timeout_us;

View File

@ -3,8 +3,8 @@
#include "core/types.h"
#include "core/log.h"
#include "core/config.h"
#include "boot/basic_init.h"
#include "boot/autodetect.h"
#include "boot/cmem.h"
#include "server/config.h"
#include "server/state.h"
#include "interface/server.h"
@ -13,12 +13,6 @@
#include "interface/os.h"
#include <c55/getopt.h>
#include <c55/os.h>
#ifdef _WIN32
#include "ports/windows_sockets.h"
#include "ports/windows_compat.h"
#else
#include <unistd.h>
#endif
#include <iostream>
#include <climits>
#include <cstdlib> // srand()
@ -52,33 +46,9 @@ void signal_handler_init()
#endif
}
void basic_init()
{
boot::buildat_mem_libc_enable();
signal_handler_init();
// Force '.' as decimal point
try {
std::locale::global(std::locale(std::locale(""), "C", std::locale::numeric));
} catch(std::runtime_error &e){
// Can happen on Wine
fprintf(stderr, "Failed to set numeric C++ locale\n");
}
setlocale(LC_NUMERIC, "C");
log_init();
log_set_max_level(CORE_VERBOSE);
interface::debug::SigConfig debug_sig_config;
interface::debug::init_signal_handlers(debug_sig_config);
srand(interface::os::time_us());
}
int main(int argc, char *argv[])
{
basic_init();
boot::BasicInitScope basic_init_scope;
server::Config &config = g_server_config;

View File

@ -18,6 +18,7 @@
#include "interface/semaphore.h"
#include "interface/debug.h"
#include "interface/select_handler.h"
#include "interface/os.h"
#include <iostream>
#include <algorithm>
#include <fstream>
@ -624,6 +625,12 @@ struct CState: public State, public interface::Server
extra_ldflags += " -lbuildat_core";
// Always include these to make life easier
extra_ldflags += " -lwsock32 -lws2_32";
// Add the path of the current executable to the library search path
{
ss_ exe_path = interface::os::get_current_exe_path();
ss_ exe_dir = interface::fs::strip_file_name(exe_path);
extra_ldflags += " -L\""+exe_dir+"\"";
}
#else
extra_cxxflags += " "+info.meta.cxxflags_linux;
extra_ldflags += " "+info.meta.ldflags_linux;