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.
Easiest way to support Windows coming from Linux/Mac?
Moderators: hgm, Rebel, chrisw
-
- Posts: 589
- Joined: Tue Jun 04, 2013 10:15 pm
Easiest way to support Windows coming from Linux/Mac?
[Account deleted]
-
- Posts: 4675
- Joined: Mon Mar 13, 2006 7:43 pm
Boost
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.
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.
-
- 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?
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
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
-
- 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?
TDM-gcc http://tdm-gcc.tdragon.net/ works fine under wine.mvk wrote: If the .exe works under 'wine' that is already a major step for me.
-
- Posts: 2554
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: Boost
You're joking, right?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.
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.
-
- Posts: 5557
- Joined: Tue Feb 28, 2012 11:56 pm
Re: Easiest way to support Windows coming from Linux/Mac?
Install a mingw cross-compiler on Linux or, if available, on Mac. Test with wine.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.
A few things will have to be done using the Windows API.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?
-
- Posts: 589
- Joined: Tue Jun 04, 2013 10:15 pm
Re: Boost
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.mar wrote:You're joking, right?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.
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.
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]
-
- Posts: 2554
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: Boost
WinAPI equivalents would be CreateThread (or the recommended _beginthreadex [CRT] that basically does the same)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.
and WaitForSingleObject on thread handle.
After the wait you should also call CloseHandle.
EDIT: Wait + Close = pthread_join
-
- Posts: 589
- Joined: Tue Jun 04, 2013 10:15 pm
Re: Boost
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.mar wrote:WinAPI equivalents would be CreateThread (or the recommended _beginthreadex [CRT] that basically does the same)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.
and WaitForSingleObject on thread handle.
After the wait you should also call CloseHandle.
EDIT: Wait + Close = pthread_join
[Account deleted]
-
- Posts: 2554
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: Boost
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
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