Easiest way to support Windows coming from Linux/Mac?

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

mvk
Posts: 589
Joined: Tue Jun 04, 2013 10:15 pm

Easiest way to support Windows coming from Linux/Mac?

Post by mvk »

I have always done all my chess programming on Mac/Linux/FreeBSD. Now I want to support windows, and from the current code base this might be a rather big project. So I want to start practicing with something small and simple to get the hang of it.

I don't have a windows development system at the moment, and zero experience in that area. Last time I used a compiler there was in DOS land.

What is the easiest route? Specifically: starting from nothing, how make an .exe given a bunch of .c and .h files in the same directory? Preferably on Mac, but Linux is ok. I don't care if it is 32 bit or 64 bit. Or is the simplest way to buy a win pc? Would be fine with me. What environment to install with it, or does it come with a compiler nowadays? If the .exe works under 'wine' that is already a major step for me.

Any caveats related to computer chess, specifically handling of the UCI event loop, hash table allocation, threading, and sigint handling (or ignoring) in xboard mode, etc?

(Mingw from macports doesn't install btw.)

Just a few pointers into the right directlion would be tremendously helpful.
[Account deleted]
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Boost

Post by sje »

First, the easiest and more sure way of building and testing a Windows executable is to obtain an inexpensive Windows machine and the appropriate native tool chain. To assist with migration, I'd strongly suggest moving C++11 compliant source only and use the third party Boost frameworks as needed on both the source platform and the destination (Windows) platform. The main caveat is that you might want to skip Boost if you are not comfortable with its licensing terms, and instead use C++11 exclusively.

http://www.boost.org/doc/libs/1_35_0/mo ... ndows.html

The idea is to let others do the dirty work of presenting platform dependent operations in a portable fashion. Example: on OpenBSD/Linux/etc., the pthread framework is used for threads, mutexes, and spinlocks; on Windows the typical Windows junk gets used. The answer is to use the C++11 thread library instead which is the same everywhere.

The other area of concern is the user interface, If your program needs a point-and-click graphical interface, the only truly authentic solution which will be pleasing to all users regardless of platform is to use native tools to develop the interface and then integrate it with the portable part of the application. The freely available, one size fits all toolkits might work to some extent, but their one size doesn't really fit anyone very well.
mar
Posts: 2554
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Easiest way to support Windows coming from Linux/Mac?

Post by mar »

I think you should be able to use a VM for this, should be fine if VirtualBox works.
As for compilers, there should be a plenty of options (MinGW, clang and msc)
There's VisualStudio community edition (2013 or later) that's for free and includes ms compiler.

I never used signals but my guess it'll either work a bit different or not at all.
Threading might be a problem, I assume you are used to pthreads. IIRC there should be pthreads ports for Windows, you can also go for a custom wrapper using WinAPI/CRT
(beginthreadex - ms way to create threads because ms CRT allocates some extra thread-local stuff, which is probably not required for a chess program)

So once you wrap what's incompatible it should be no problem to support all OSes.
EDIT: I think you should be able to cross-compile for Windows using MinGW, at least on Linux. IIRC that's what Lucas did with DiscoCheck
User avatar
Werner Taelemans
Posts: 119
Joined: Mon Feb 03, 2014 11:57 am
Location: Belgium
Full name: Werner Taelemans

Re: Easiest way to support Windows coming from Linux/Mac?

Post by Werner Taelemans »

mvk wrote: If the .exe works under 'wine' that is already a major step for me.
TDM-gcc http://tdm-gcc.tdragon.net/ works fine under wine.
mar
Posts: 2554
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Boost

Post by mar »

sje wrote:To assist with migration, I'd strongly suggest moving C++11 compliant source only and use the third party Boost frameworks as needed on both the source platform and the destination (Windows) platform. The main caveat is that you might want to skip Boost if you are not comfortable with its licensing terms, and instead use C++11 exclusively.
You're joking, right?
Rookie is written in C as is apparent from Marcel's post.
Boost license is very liberal, in fact it's only one step above unlicense/public domain, you don't have to give credit/include copy of the license with your binaries.
syzygy
Posts: 5557
Joined: Tue Feb 28, 2012 11:56 pm

Re: Easiest way to support Windows coming from Linux/Mac?

Post by syzygy »

mvk wrote:What is the easiest route? Specifically: starting from nothing, how make an .exe given a bunch of .c and .h files in the same directory? Preferably on Mac, but Linux is ok. I don't care if it is 32 bit or 64 bit. Or is the simplest way to buy a win pc? Would be fine with me. What environment to install with it, or does it come with a compiler nowadays? If the .exe works under 'wine' that is already a major step for me.
Install a mingw cross-compiler on Linux or, if available, on Mac. Test with wine.
Any caveats related to computer chess, specifically handling of the UCI event loop, hash table allocation, threading, and sigint handling (or ignoring) in xboard mode, etc?
A few things will have to be done using the Windows API.
mvk
Posts: 589
Joined: Tue Jun 04, 2013 10:15 pm

Re: Boost

Post by mvk »

mar wrote:
sje wrote:To assist with migration, I'd strongly suggest moving C++11 compliant source only and use the third party Boost frameworks as needed on both the source platform and the destination (Windows) platform. The main caveat is that you might want to skip Boost if you are not comfortable with its licensing terms, and instead use C++11 exclusively.
You're joking, right?
Rookie is written in C as is apparent from Marcel's post.
Boost license is very liberal, in fact it's only one step above unlicense/public domain, you don't have to give credit/include copy of the license with your binaries.
Eventually I will have to rewrite large parts of Rookie for this anyway, so it is not a big issue from my point of view. Getting C code to be accepted by a C++ compiler doesn't sound like too much of a hassle. I'm fairly open to a lot of options and I appreciate all suggestions made so far by all posters.

The engine I will try this with first is floyd. This is a weak mini-engine (think MSCP grade) I have created for some personal study projects and is relatively clean. Rookie is not clean at all.

This thing might then morph into a windows version of Rookie if I graft Rookie's eval and move generator into this project, or it might evolve into a separate full program. I don't expect I can do a direct port of Rookie v3 to windows without losing my sanity.

I don't mind a few #ifdefs if they can be localised. The trial project is single core, but uses a search thread for UCI. I tried C11 threads (not C11++), but the C11 standard declares them optional and they are not supported on the Mac when I tried. I haven't checked on Linux, but fell back to pthreads instead. If it stays C, I don't want to go back to older standards than C99 though. I know this was a problem for a long time with MS compilers, and I don't know if they have caught up.

The Unixy things that Floyd now uses I'm aware of:

1. phtread_create() and pthread_join() for every `go' / `stop'. If the counterpart on Windows is fast that would be nice. I would hate to make a thread pool. But if that is needed, c'est la vie.
2. signal(SIGALRM) and alarm(). These must be replaced anyway due to the granularity problem, and I want to use a timer thread instead of a signal.
3. #define _XOPEN_SOURCE to get M_LN10 out of math.h on FreeBSD. Not a big deal at all. I can easily do this in a different way.

I would prefer no library dependencies or configuration files for the user. Best is if everything will be self-contained in one .exe
[Account deleted]
mar
Posts: 2554
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Boost

Post by mar »

mvk wrote:1. phtread_create() and pthread_join() for every `go' / `stop'. If the counterpart on Windows is fast that would be nice. I would hate to make a thread pool. But if that is needed, c'est la vie.
WinAPI equivalents would be CreateThread (or the recommended _beginthreadex [CRT] that basically does the same)
and WaitForSingleObject on thread handle.
After the wait you should also call CloseHandle.
EDIT: Wait + Close = pthread_join
mvk
Posts: 589
Joined: Tue Jun 04, 2013 10:15 pm

Re: Boost

Post by mvk »

mar wrote:
mvk wrote:1. phtread_create() and pthread_join() for every `go' / `stop'. If the counterpart on Windows is fast that would be nice. I would hate to make a thread pool. But if that is needed, c'est la vie.
WinAPI equivalents would be CreateThread (or the recommended _beginthreadex [CRT] that basically does the same)
and WaitForSingleObject on thread handle.
After the wait you should also call CloseHandle.
EDIT: Wait + Close = pthread_join
I have the MingGW+wine route now more or less working, in the sense that it doesn't crash immediately and almost all warnings are eliminated. More testing is needed and one more warning to go, but I have crossed the big hurdle. All thanks a lot. Most win32/posix changes are isolated around thread and alarm handling.
[Account deleted]
mar
Posts: 2554
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Boost

Post by mar »

Congratulations.
I see one potential problem though. I would stay away from using TerminateThread as it's considered unsafe (last resort).

I think pthread_join also waits for the thread to terminate the natural way (i.e. exiting threadproc)

So I'd either remove TerminateThread completely or,
if you need to terminate before the sleep is over, I suggest to encapsulate WinAPI Event (=pthread mutex + condition variable) in alarm struct.
CreateEvent returns handle (that needs to be Close()d later), so manual reset, initially non-signalled

Then instead of using Sleep(msec) you would use WaitForSingleObject(StopEvent, msec)
and SetEvent(StopEvent) instead of TerminateThread