Porting a large C project from Unix to Windows - c

So, I have a large C project that was built entirely on Unix (SPARC Solaris). me and several others have begun to revisit it because their was some interest in a windows build.
none of us have done this with a project of such size, so for starters, has anyone ported something from unix to windows and could maybe give me some pointers or how they did it.
our first step on our plan was to decide on a compiler/dev environment.
it seems that our options are MS Visual Studio, Cygwin, mingw/gcc, and Windows Services for UNIX (SFU).
we are on a fairly short timetable so we want to rewrite as little code as possible.
so, Deciding on a compiler.
Another issue is that the code does use POSIX thread commands (pthread, etc)
we would prefer to compile natively, not using some sort of layer between the executable and the OS. unfortunatly with the pthread calls in our code, this may not be possible.
I believe both Cygwin and SFU do just that. Cygwin has a .dll that must be included in compiled code to work. I am not sure about SFU, any information about that would be greatly appreciated. It seems like it would be a good option but was developed to allow for UNIX compiled software to run on a windows machine with SFU, not any old windows box.
mingw does have the ability to create native exes, but lacks the POSIX support.
So, can anyone give me any more information, suggestions, knowledge on any of these compilers in this context. or any experience they have with this sort of thing, it is greatly appreciated.

Short timetable? CygWin, plain and simple.
Despite your preference to not use a layer, that's going to provide the fastest path and you don't seem to indicate that the timeframe requirement is flexible.
We've ported both command-line and X-based UNIX programs to Windows using CygWin with minimal hassle.

Cygwin is likely the fastest path to a working executable. However it will leave you with some interesting distribution choices. Most obviously, cygwin.dll becomes a dependency. Its licensed GPL, unless you pay money to buy commercial use rights.
Cygwin is not particularly friendly to an ordinary Windows user. Its goal is to provide a full POSIX experience on Windows, supplying a shell, all the familiar *nix utilities, and even a port of X. However, it also remaps the Windows disk drive naming into a POSIX-like file system. I've never attempted to distribute an application built for Cygwin to machines that don't already have a full Cygwin installation. I will note that to my knowledge none of the big well-known open-source applications with Windows ports are based on Cygwin.
If the only hard POSIX dependency you have is pthreads, then that is solvable. There is a pthreads port built on native Windows threads that works well with MinGW. IIRC, it is even distributed along with MinGW, or at least is one of their core supported packages.
If the rest of your handling of file names is largely as opaque strings, you may not even need to care about changing / to \. The Windows API is generally happy to treat either character as a path separator, even mixed in the same name. It is the CMD.EXE and early DOS convention of using / for command line options that prevents the use of / for pathnames at the command prompt, not the underlying Windows API.
For tools that might make porting your build process easier, check out the MSYS component of MinGW. It provides a lightweigh fork from the Cygwin environment in which enough *nix utilities are available to generally run ./configure and similar processes.
In addition, the GnuWin32 project has ports of a large number of utilities and libraries that are all built to run as native Windows applications without unusual dependencies.

If the code is (at least mostly) portable and the only major issue is the use of pthreads, you might want to use the Pthreads Win32 library. While incomplete, it's sufficiently complete and accurate to deal with most pthreads code I've tried it with. While normally built as a DLL, this can also be built as a static library to avoid creating an extra dependencies in your executable.
That, of course, leaves everything else to port -- but you haven't said enough to even guess whether porting the rest within your timeframe is at all reasonable.

Related

Is it fine to use linux code compiled on cygwin for production in windows?

I have a working module on linux and one of the client wants it on windows.
There is very good discussion on similar topic here(https://ask.slashdot.org/story/04/08/12/1932246/cygwin-in-a-production-environment), I guess it leaning towards avoiding cygwin for productions but its about 13 years older discussion,there might have been issues but in about 13 years I hope cygwin might have been improved,matured and good for production use.
The code compiled just fine and seems to work ok under cygwin so its very tempting to take it forward rather than redoing it in windows native code.
But if there are really any unsolvable known issues and people are avoiding it for productions I would like to know.
The code heavily uses pthreads,sockets in no-wait
I've used Cygwin a fair bit, and have found it mostly unproblematic. I am aware of some of the reported problems, but haven't experienced them myself. Some things on Cygwin are much slower than the same code on Linux -- I notice this most with directory scans, but that probably isn't the only thing. People complain about fork() being slow, but that isn't really a surprise, as 'forking' isn't a native concept in Windows. If you're just using fork() to launch subprocesses, then conceivably the whole fork/exec thing could selectively be replaced with calls to native Windows APIs.
A potential limitation of Cygwin is that it requires Cygwin at run-time or, at least, a chunk of Cygwin infrastructure. MinGW might remove this restriction, but at the cost of leaving you to make a larger number of compatibility-related changes in your code (file locations, for example). The last time I looked, MinGW didn't have tooling as extensive as Cygwin, either, but it's probably good enough for many purposes.
I guess another possibility to consider these days is the Windows Subsystem for Linux (WSL) on Windows 10. I've found that code that builds for Cygwin usually builds and runs without changes on WSL, but I haven't really figured out what the relative advantages and disadvantages of Cygwin and WSL are.
I've not noticed problems with pthreads in Cygwin, MinGW, or WSL; although I guess any problems are likely to depend on the exact way you use threads. I can't comment on the no-wait socket issue, because that isn't something I've tried.
Incidentally, both Cygwin and MinGW will allow you to call native Windows API, and other functions in DLLs, if you need to. So the possibility exists to create a sort of "hybrid" application that uses POSIX-type functions and also Win32 APIs. This might be useful if it turns out that some things are much faster with Win32 functionality. I'm not sure this is possible with WSL.
I should say that my comment about time consuming updates refers as much to the need to perform a full Windows update as well as apt-get updates prior to running a wsl
script which will go past midnight. Running a separate memory recovery script every 4 hours or so is a partial solution. I have "only " 6GB RAM.

selecting c compiler and creating development environment

I need to write some C functions that will be called by a java program running on a CenOS Linux server, as part of a web application. The server is a hosted dedicated server sitting in another physical location, far away from me.
Do I need to develop the C stuff on the server directly, that is, doing development tunneling into the server? Or can I develop the C program on a Mac or Windows PC in my office, then once everything is working fine, store the final results on the server for use? If the latter, does it limit the choices for development environment in any way? That is, which compiler I should use, or any settings in the IDE or compiler I need to worry about since the development environment will be different than the production environment?
If I use Xcode version 3 on a Mac, it uses GCC by default, whereas Xcode version 4 uses LLVM-GCC to compile. Does the choice of compiler matter assuming I'm using C99 standard things? I don't want the code to be dependent on the development environment since I can't guarantee it'll stay the same in the future. Can I switch the compiler manually in Xcode somehow to verify the code works in GCC as well as LLVM?
Ignoring windows, things are pretty portable across mac/linux. If you develop it on mac in whatever development environment you want (I personally use TextWrangler and GCC from the command line.
Once you develop your software, it's a simple matter of copying the file to your remote server and compiling it there.
You may or may not need to change a few things. The only portability issue I've run into was mac's socket() using PF_ instead of AF_ (Mac will still accept AF_ but it doesn't advertise it in it's manpage, and other systems will not necessarily accept PF_) and sranddev() not being available on some systems; both of which were very easily resolvable.
If, however, you wanted to write the software directly on the remote box, its definitely not a hard thing to do, I would just ssh there and take your pick of text editors (usually vi or emacs) and compilers (usually gcc).
In general, for programs that are just traditional unix command line things, I tend to avoid Xcode as much as possible because it likes to hide things, and IMO its a good thing to actually understand what is going on behind the scenes. (Especially if you use other *nix systems.)
Whatever you do, it will need to be recompiled on the server.
You can probably create code that's runnable/testable under both environments, although you may have to #ifdef around compatibility issues. How much of that, if any, depends a lot on what you're actually writing.
Does the choice of compiler matter assuming I'm using C99 standard things?
Yes: Microsoft, AFAIK, still doesn't fully support C99 (but maybe that's changed in the latest MSVC). Also, you have to resist the temptation of using non-standard features just because they are there. OTOH, a local build env might force you to write portable programs.
The choice depends on how your program is going to communicate with the larger system, but developing at least parts locally is probably the most convenient option.

Run C program written in Linux on Windows

I have C program which I wrote in Linux that runs very well. Now I want to run it on Windows.
How do I easily run it on Windows?
Elaborating a bit on the answers from caf and jartieda...
Cygwin is an attempt to emulate a (nearly) complete POSIX execution environment in a native Windows process. It is complete enough that a surprising amount of Unix application code simply compiles and runs using the familiar ./configure && make && make install idiom. This trick was done by supplying a DLL that emulates POSIX system calls using the Windows API. Based on that, you get a complete GCC toolchain, bash, and all the usual command line utilities you are used to. One downside is that the compiled program is dependent on the Cygwin DLL, which makes it tricky to deliver the result to a system that does not already have Cygwin installed and whose user doesn't want to use a Unix shell.
MinGW is a port of the GCC toolchain that generates native Windows applications that depend on the well known (and distributed with Windows itself) MSVCRT.DLL C runtime library. It makes no attempt to emulate a POSIX operating system, but applications that are mostly based on the standard C libraries, will often build essentially unchanged.
MSYS is a compile-time environment that provides enough Unix utilities (including bash) to often allow ./configure to run, and if the project supports the results, finish the build with MinGW's GCC. The result is a native Windows executable that does not depend on any DLLs you don't deliberately use aside from MSVCRT.DLL. Although the MSYS environment itself was a fork of an early version of the Cygwin project, it is primarily intended to be used to provide a unix-like place to compile native Windows applications: one would generally not build new applications based on its runtime environment.
Another approach to compiling for Windows is to use the MinGW cross compiler on linux. A number of MinGW's core developers work that way, testing they product either under Wine, or under Windows running in a VM or a separate PC.
If the program has a GUI component, then you may have additional difficulties. Some GUI frameworks are available for both Linux and Windows. Qt, wxWidgets, and IUP all leap to mind, but there are others out there.
Edit: I've improved the paragraph above about MSYS to emphasize that it is intended to be a compile-time environment for building programs that run as native Windows applications, and not a full POSIX environment like Cygwin.
Note, also, that there is always the option of porting the project to one of the more traditional compilers for Windows development. Open Watcom, the Borland compilers, and Microsoft all have free or inexpensive versions, although often enough not under licenses that make the opens source community entirely happy.
This approach probably requires more effort because the differences between a Linux environment and the Windows environment become more visible when you also switch from one toolchain to another. This is especially true of the Microsoft compilers which are historically not as fully standards compliant as GCC.
The easiest way is to install the Cygwin environment, and compile it under that.
best way recompile it all using mingw compiler.
easy way recompile it under cygwin environment.
The answers you got so far, focus on installing the GNU operating system on the Windows kernel; but you could also use freeware tools from Microsoft. This solution is probably most attractive if you want to continue to develop on Linux, and only do a little work for porting on Windows:
Microsoft offers a simplified version of their development environment as freeware: Visual Studio Express (download). If your program does only file IO it will probably compile unmodified, because Microsoft supplies the C standard library too.
For GUI I also wholeheartedly recommend the Qt framework. It is very well written and documented; it is now licensed under the LGPL, so you can link it to proprietary applications without any cost. However it is written in C++ so you would need to change the programing language. For integration of QT with Visual Studio Express: I believe it works, but you need to try it out. About five years ago I tested the integration of (proprietary) QT and (professional) Visual Studio for my employer, and it worked perfectly.

make---linux and windows formats

I am in a big problem ..i have compiled my c files using linux make file in Linux OS.
I want to compile the same files in Windows using the same make file by command prompt. For that i have nmake utility and Cygwin utility too.
I have done that successfully with simple programs with simple make file ..
But it is not possible to compile when i was using the complex C files with complex make file.
I have changed the '/' in linux make file to '\' in windows? Anyother changes?
I want to know 'Is there any special make file formats in windows?'
also the difference between them..
I am really in need of that...
Unfortunately, nmake was only loosly inspired by make, and they didn't get many important things right. By far the easiest thing to do is to start by having the same flavor of make on both platforms.
On linux, Gnu make is the default and best option.
On Windows, there are several sources for Gnu make, with some quirks to choose among. Personally, I mostly use the native win32 build of Gnu make from the GnuWin32 project. You might want to poke around at the rest of the project's packages because some of the others will be useful to have as well.
Alternative sources are Cygwin and MinGW32/MSYS.
Cygwin is a credible attempt at providing a *nix compatibility environment on top of the Windows kernel. It consists of a DLL that exports a huge percentage of *nix (especially POSIX) system calls implemented via the Windows API. That DLL also has its own idea about disk mounts and prefers *nix-style path names. The DLL itself is licensed GPL (although a commercial-use license is available for a fee), and programs built in the Cygwin environment require it by default, so that can be a factor to consider. Another factor is that Cygwin is not friendly to normal Windows users, so development projects based on it usually end up difficult for non-unix users to deal with. For a cross-platform developer, however, Cygwin can be really useful as it gets you all of the usual suspect utility programs required by your Makefile, and it includes the MinGW32 native Windows targeted GCC as well as a GCC targeting the Cygwin environment.
MinGW32 is a porting project that did a really good job of porting the GCC compilers to run as native Windows executables. If used along with the header files they supply, it is possible to use nearly all of the Windows API via a C runtime DLL that ships with modern Windows installations.
MSYS is a lightweight fork of Cygwin that contains a minimal set of utilities (starting with a *nix shell) that are usually assumed to exist by a typical *nix Makefile. Unlike Cygwin, MSYS is configured such that the default target is the native Windows API.
What I'm trying to hint at here, and probably should just state flat out, is that your compatibility issues don't end with the dialect of make you use.
The Makefile language itself is highly dependent on the command shell available, and most serious project Makefiles end up using many of the *nix the core utilities such as cp and rm.
I would strongly recommend starting with the GnuWin32 build of make, and also installing MinGW32 and MSYS. It is then relatively easy to write a Makefile that works under both MSYS and linux, and needs only a small amount of platform-specific logic.
You should consider CMake for cross-platform make but your real problem is you shouldn't have to change the '/' to '\'. If you run under cygwin or msys (recommended) this should be handled for you.
NMake is a windows tool and will parse only windows-style paths, i.e. paths with drive letters and backslashes. Therefore you should use GNU Make installed with cygwin.
nmake should read your makefiles okay, the differences are generally between versions of make rather than OSs.
The big question is what your target platform actually is, are you trying to make this code operate in Windows natively or are you looking to run it under Cygwin?
Use gnumake on both platforms. I do. I haven't touched Visual C in years.
nmake got it's own format rather than windows itself, so makefile format is related to make tool rather than os. For simple things format is similar for g(nu)make and nmake, as people suggested before consider using gmake only.

Writing cross-platform apps in C

What things should be kept most in mind when writing cross-platform applications in C? Targeted platforms: 32-bit Intel based PC, Mac, and Linux. I'm especially looking for the type of versatility that Jungle Disk has in their USB desktop edition ( http://www.jungledisk.com/desktop/download.aspx )
What are tips and "gotchas" for this type of development?
I maintained for a number of years an ANSI C networking library that was ported to close to 30 different OS's and compilers. The library didn't have any GUI components, which made it easier. We ended up abstracting out into dedicated source files any routine that was not consistent across platforms, and used #defines where appropriate in those source files. This kept the code that was adjusted per platform isolated away from the main business logic of the library. We also made extensive use of typedefs and our own dedicated types so that we could easily change them per platform if needed. This made the port to 64-bit platforms fairly easy.
If you are looking to have GUI components, I would suggest looking at GUI toolkits such as WxWindows or Qt (which are both C++ libraries).
Try to avoid platform-dependent #ifdefs, as they tend to grow exponentially when you add new platforms. Instead, try to organize your source files as a tree with platform-independent code at the root, and platform-dependent code on the "leaves". There is a nice book on the subject, Multi-Platform Code Management. Sample code in it may look obsolete, but ideas described in the book are still brilliantly vital.
Further to Kyle's answer, I would strongly recommend against trying to use the Posix subsystem in Windows. It's implemented to an absolute bare minimum level such that Microsoft can claim "Posix support" on a feature sheet tick box. Perhaps somebody out there actually uses it, but I've never encountered it in real life.
One can certainly write cross-platform C code, you just have to be aware of the differences between platforms, and test, test, test. Unit tests and a CI (continuous integration) solution will go a long way toward making sure your program works across all your target platforms.
A good approach is to isolate the system-dependent stuff in one or a few modules at most. Provide a system-independent interface from that module. Then build everything else on top of that module, so it doesn't depend on the system you're compiling for.
XVT have a cross platform GUI C API which is mature 15+ years and sits on top of the native windowing toollkits. See WWW.XVT.COM.
They support at least LINUX, Windows, and MAC.
Try to write as much as you can with POSIX. Mac and Linux support POSIX natively and Windows has a system that can run it (as far as I know - I've never actually used it). If your app is graphical, both Mac and Linux support X11 libraries (Linux natively, Mac through X11.app) and there are numerous ways of getting X11 apps to run on Windows.
However, if you're looking for true multi-platform deployment, you should probably switch to a language like Java or Python that's capable of running the same program on multiple systems with little or no change.
Edit: I just downloaded the application and looked at the files. It does appear to have binaries for all 3 platforms in one directory. If your concern is in how to write apps that can be moved from machine to machine without losing settings, you should probably write all your configuration to a file in the same directory as the executable and not touch the Windows registry or create any dot directories in the home folder of the user that's running the program on Linux or Mac. And as far as creating a cross-distribution Linux binary, 32-bit POSIX/X11 would probably be the safest bet. I'm not sure what JungleDisk uses as I'm currently on a Mac.
There do exist quite few portable libraries just examples I've worked within the past
1) glib and gtk+
2) libcurl
3) libapr
Those cover nearly every platform and so they are extremly useful tool.
Posix is fine on Unices but well I doubt it's that great on windows, besides we do not have any stuff for portable GUIs there.
I also second the recommendation to separate code for different platforms into different modules/trees instead of ifdefs.
Also I recommend to check beforehand what are the differences in you platforms and how you could abstract them. E.g. this is some OS related stuff (e.g. the annoying CR,CRLF,LF in text files), or hardware stuff. E.g. the previous mentioned posix compability doesnt stop you from
int c;
fread(&c, sizeof(int), 1, file);
But on different hardware platforms the internal memory layout can be complete different (endianess), forcing you to use conversion functions on some of the target platforms.
You can use NAppGUI for both console and desktop apps. The SDK uses ANSI-C and your code will work on Windows/macOS/Linux.
https://www.nappgui.com
It's free and OpenSource.

Resources