Archive

Archive for the ‘Windows’ Category

Building OpenJDK 8 for Windows using MSYS

August 3, 2015 Leave a comment

This article will describe how to build OpenJDK 8 on Windows using MSYS. Since the building itself is performed by build scripts, we will focus on two things: installation of necessary libraries and compilers, and fixing build scripts, since they don’t work out of the box. As most of my articles, this one is written for my future self, because I’m sure I’ll get back to this task in future, and I don’t like solving problems I know I’ve solved before and I don’t remember how. Also this article is not a simple list of steps, I’ve tried to explain the reasons behind the actions. Readme file of OpenJDK says that “building the source code for the OpenJDK requires a certain degree of technical expertise”, so let’s make ourselves this expertise by learning while doing.

Getting the source.

The first step is to get the source. OpenJDK developers use Mercurial version control system as a code storage. You can open this URL: http://hg.openjdk.java.net/ in browser to see a list of projects hosted by OpenJDK. The project you need is jdk8. If you click on jdk8, you’ll see a list of repositories which jdk8 consists of. The top one is called jdk8, which makes a full URL: http://hg.openjdk.java.net/jdk8/jdk8/. You may wonder why there are two jdk8 directories in the URL? This remained from some old times when there were so called “gate” repositories to which changes were pushed for integration, and once those changes were verified, they were merged into read-only main repositories. So, jdk8/jdk8 is a read-only repository. Gate repositories approach was abandoned, but for OpenJDK 8 the path to read-only repository remains the same. If you are curious, you can read more about OpenJDK Mercurial repositories here.

So, let’s get ourselves this respository. You will need Mercurial tools for this. I like GUI tools, so I’ve downloaded SmartGit/Hg. It took me a while to figure out why there are no Mercurial option when you try to clone a remote repository. To make this work, you need to download and install official Mercurial command-line tools, and then go to settings of SmartGit and point it to hg.exe tool. This will make Mercurial to appear in a list of VCSes. Thus, GUI tools are not a full replacement for command-line tools, they just make life a little easier. If you don’t like GUIs, you can skip them and use command-line Mercurial tools, that’s quite easy. So go ahead and clone a repository http://hg.openjdk.java.net/jdk8/jdk8/ to some local directory.

Structure of OpenJDK build

The top repository jdk8/jdk8 contains only build infrastructure, it doesn’t contain any real source code, which is sorted into several additional other repositories. So, from this point we can either download those repositories, or we can do that later, when we will prepare everything. Let’s take a second approach, and start with preparing for a build. Take a look at a repository we just cloned. There are two readme files: a short text file and a bigger HTML file. Both are worth reading. Also there are two directories: common and make, and three scripts. The script named get_source.sh will download all remaining sources using Mercurial command-line tools, and we will postpone this until later. Two remaining scripts are the core of build process.

C is not a Java, there are many aspects of the language which are not defined and compiler-specific, like, for example, size of int value. So C programmers achieve portability by having special cases for compiler-dependent things. This is usually done “on source level”: a compiler-specific information is moved to dedicated header file. So to port a C program to another compiler requires changing compiler-dependent info and recompilation. To simplify this task programs used scripts which probe the compiler they are running on and generate a compiler-dependent header files. By convention these scripts are called configure. And OpenJDK has this script. We need to run it at least once. After that we have to use make tool to build everything, becase we have a script for it, called Makefile. Such two-stage comfigure/make approach is standard in Unix world for open-source software.

Let’s take a look at configure file. It is a unix shell script which prepares a build. It is very small, all it does is executing another configure script, located in common/autoconf. This second configure does a little more, like parsing command-line parameters, of which you can read more in readme.html. The main job is done by big script called generated-configure.sh. So, in order to run these scripts we need some Unix-like environment on Windows. There are two options: Cygwin and MSYS. Both environments are quite similar: each provides a shared library (dll) which implements some set of POSIX functions on Windows, and a set of Unix tools compiled as Windows executables, which rely on that dll. Cygwin is bigger, provides a larger set of POSIX calls and includes more Unix tools, so it’s like a complete unix-like environment. MSYS (which means “minimal system”) supports a smaller set of POSIX calls and provides a set of Unix tools just enough to be able to run typical configure scripts. I like everything minimal, so I prefer MSYS.

Installing MSYS and dealing with configure.

MSYS itself is not an independent project, it is a part of another project called MinGW (Minimalist Gnu for Windows), which is a quite interesting story worth telling. Most of the application programs written in C use standard library, and there are many reasons for that. On Unix systems it’s a convenient and portable way to do system calls. Standard library also includes lots of useful functions, like string manipulation. Since standard library relies on OS services, the OS kernel itself cannot use standard library. Windows provides it’s own set of services for applications, called Win32 API, but their compiler suite provides a standard library for compatibility and convenience. Some standard libraries are tied to specific compilers, but there are independent libraries: newlib, uClibc, dietlibc, mucl. When choosing a standard library one has to consider its features, performance, size, support of particular OS/CPU, and also the licence. For example, using library released with GPL requires you to release your program under GPL. The licence terms may be different depending on how you link against a library. There are two options: static linking (library will be included into executable) and dynamic linking. Licensing terms for dynamic linking are usually less restrictive then for static linking. However, if you choose dynamic linking you should somehow ensure that library is installed on computers where your program will run. So, knowing all this we can now get to MingGW. It is a version of GCC compiler which produces Windows executables dynamically linked with standard library supplied with Microsoft Visual C v 6.0 (msvcrt.dll). The license allows any code to dynamically link against it, and practically this library is present in all Windows systems (used by Microsoft’s own applications), so you don’t need to distribute it yourself. Thus MinGW produces executables which can be released under any license and distributed in a very simple way. Technically MinGW consists of a set of header files for standard library, an import library for mscvrt.dll and a version of GCC which produces Windows executables linked with import library. Later some additional libraries were ported to MinGW and now are provided as a part of it. Also MinGW was extended with include files and import libraries for Windows API, so now you can use it to write native Windows software. MinGW made it easier to port software written in C from Unix to Windows, but that was not enough. Thus MSYS was born, it is an environment for running configure scripts.

OK, back to building OpenJDK. Go to MinGW site and download installer. Run it. It will show a list of packages you can install. You don’t actually need MinGW compilers, since they are not used by OpenJDK built, but I advice you to install them. You’ll definitely need make and autoconf. Also you’ll need basic MSYS, and several specific MSYS packages: bsd cpio, mktemp, zip, unzip.

Now, as you have installed MSYS, you can start it’s shell (bash). You can use your windows paths in a special way, for example “C:\projects\openjdk” should be used as “/c/projects/openjdk”. You can try to run configure script right away. At the beginning this script will check availability of required tools, so if you forgot to install abovementioned cpio, mktemp, zip and unzip, then configure will complain (that’s how I learned that I need them). So here we will encounter a first problem with OpenJDK build environment which requires manual intervention. The script will fail finding cpio.

Learning autoconf

The script will fail finding cpio, since it is called bsdcpio. If you’ll try to track the problem (either by looking at source code or by reading log file) you’ll get to a script generated-configure.sh. To fix our problem, we need to modify this generated-configure.sh script. However, editing it directly is a wrong way. This script is generated (hence the name) by a tool called autoconf from sources located in OpenJDK folder common/autoconf. So, let’s get there and edit the sources. The actual change should be made in file basics.m4. Replace cpio with bsdcpio.

To generate new generated-configure.sh you should execute autogen.sh. But attempt to do it will fail, autogen.sh will complain that it can’t find autoconf. The reason is simple: autoconf was installed into MinGW location which is not available for MSYS by default. So, you should go to MSYS installation directory and find “etc” directory (on my machine it is located at c:\tools\mingw\msys\1.0\etc). Here you should create a file called fstab which will configure mounting of windows directories to msys filesystem. Take a look at fstab.sample to see how to do it, you may even copy it as fstab and edit it. Your task is to map root MinGW folder as /mingw. To apply changes in fstab you should restart MSYS bash. There is another file in etc called profile, which configures bash. By default this profile will add /mingw/bin into search path. So, if you did everything right, the result of “which autoconf” should be something like “/mingw/bin/autoconf”. Now you can get back and use autogen.sh to generate build script. Do it. Oops, another error.

This time autogen will complain that autoconf 2.69 or higher is required. However, MinGW includes version 2.68. When I encountered this error I’ve decided to try with 2.68, and believe me, it works perfectly fine. So, let’s hack OpenJDK build scripts and fix the required version. It is specified in file configure.ac. Again execute autogen.sh. This time it should work. Ignore output about no custom hook found.

We just fixed our first configure-stage error, and there will be more. To simplify troubleshooting, you should take a look at file called config.log, which contains output produced by conifugure script. If this log is not verbose enough, you can start the configure with command-line argument –debug-configure. It will make the script to produce additional log called debug-configure.log which is very verbose.

Installing bootstrap JDK.

Large part of JDK is written in Java,including the compiler. So building JDK requires you to have some bootstrap JDK. I’ve never got any problems installing it. You can even install it into default directory, and at any path, even the one which includes spaces.

Having fun with Microsoft Windows 7 SDK.

MinGW provides a C and C++ compilers for Windows, but the only officially supported by OpenJDK is Microsoft Visual C++ compiler, and we are going to use it. Otherwise configure will complain that it cannot find Visual Studio and quit. If you own Visual Studio, that’s great, and you can skip this part. However, in this article I’ll describe how to use minimalist development tools. So, we will use Microsoft Windows 7 SDK, which includes command-line C and C++ compilers from Visual Studio 2010. And it is free! You should download it from official site of Microsoft. There are web installer and several ISO images: for 32-bit systems, for Itanium and for 64-bit systems (amd-64). During the installation you can select which components to install, and I suggest to keep default settings, which include all necessary libraries and the compiler. If you will encounter some problems during the installation, check installation logs for exact description of the failure. I’ve got an error saying that SDK can’t install redistributable runtime libraries. Even de-selecting these libraries in a list of installed components doesn’t help. This happens because you already have a more recent version of those libraries installed (I had version 10.0.40219, and SDK will install 10.0.30319). It’s a shame for Microsoft to keep such bugs in installer. The only workaround is to uninstall your current redistributable of Microsoft Visual C runtime libraries, then install Windows SDK, and then download and install latest version of runtime library.

Now let’s check if compilers are working. If you will skip this part, you may get nasty errors much later. So, go to “c:\Program files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64” and launch cvtres.exe. If it has started successfully, that’s good. But on some systems it fails with application error. In fact you can skip this error, since it will not manifest at configure stage, but you’ll get strange error messages later on make stage, so let’s fix it now. Careful investigation with Dependency Walker tool shows that cvtres.exe imports a bunch of functions from msvcr100_clr0400.dll, and this dll doesn’t have any exported functions. Actually a version of this library included in SDK is OK, but some update for Microsoft .Net framework overwrites it with no-export version. Nice. In order to fix this, you need to download a patch from Microsoft called Microsoft Visual C++ 2010 Service Pack 1 Compiler Update for the Windows SDK 7.1. It will fix dependency problem for cvtres.exe, it will use another version of runtime dll. Download the update, install it and check that cvtres.exe works.

No, that’s not all. The update we just applied broke another thing. Unbelievable. I’ve created an empty file called ammintrin.h just to get around this annoying thing.

Patching the build scripts

Having Windows SDK will let you get further with configure, but eventually it will fail. That happens because scripts for building OpenJDK 8 using MSYS have errors. These errors were fixed in scripts for OpenJDK 9. The link to fixes could be found in this mail thread. Initial letter from Volker Simonis contains change request, and in subsequent messages Eric Joelsson extended it. Here is a list of changes:

  1. Fix for bsdcpio in basics.m4, which we have already applied
  2. Change in basics_windows.m4, which fixes AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS] problem with configure cannot find set_env.cmd file of Windows SDK
  3. Two fixes in toolchain_windows.m4: one for architecture type, and another with quotes for grep
  4. Fixes in platform.m4 for correct environment value. It’s a supplementary fix for other fixes to work.
  5. Fixes in NativeCompilation.gmk and specs.gmk.in will help if you’ll have an error during make. Without those fixes you’ll have to clean everything and re-make again from scratch, which takes a lot of time

So we should manually apply those fixes for OpenJDK 8. There are also change in generated_configure.sh, but you don’t need to apply it. Instead, generate it via autogen.

FreeType.

OpenJDK requires FreeType library. You can build it yourself from sources, I’ve downloaded a pre-built version. However, this pre-build version was strange: it included import library freetype.lib with all functions prefixed with underscore (“_”). To fix this, I’ve created an import library manually from dll using lib tool included in Microsoft Visual C command-line compiler suite (lib.exe /def:freetype6.def). This will produce a file freetype6.lib, which you should rename to freetype.lib, overwriting existing file (I’ve made a backup copy of it called _freetype.lib). You also need to copy freetype6.dll from bin directory in to lib directory and rename it to freetype.dll. And, finally, you need to explicitly specify path to the location where you’ve installed FreeType. A corresponding command-line argument for configure script is called –with-freetype.

Completing the configure

If you’ve done everything right, the configure step will successfully finish. The result will be stored in build directory of OpenJDK. The main item here is specs.gmk. Now you should download modules with source code.

Compilation

Launch make all. If make hangs edit specs.gmk and set JOBS=1. As a result you’ll get directory called j2sdk-image, that’s your JDK!

Advertisements
Categories: Java, Windows Tags: , , ,

Your first and second OCaml programs for Win32

July 3, 2007 Leave a comment

Since “C Programming language” by Kernigan and Ritchie most books about C started with “first program in C” to print “Hello, world!” on console. Windows is so much different from Unix so it even has it’s own “main function” named “WinMain” (instead of “main” for Unix). Because of that huge difference books about programming with Win32API usually start with their own “first program in C for Windows”, simple 5-line program for showing same message using MessageBox function. You can find such examples in book by Petzold and tutorials like this. Let’s make exactly the same program in OCaml.

Program will look like:

open Win32

let _ =
  ignore (message_box null_hwnd “Content of MsgBox” “Caption of MsgBox” [MB_OK]);
  exit 0;

Yes, that’s it, simple. There are no WinMain here, because it’s OCaml, not C. OCaml specifies it’s own entry point to program. WinMain has several arguments; they are available as global variables, however they are stored not by implementation of WinMain, but by invoking some Win32 API functions.

After this simple program books go in different directions. Some books go to windows, message reading/dispatching cycle and window procedures. I prefer to go to dialogs, because first program was also about dialogs. Dialogs are convenient because they could be defined in resources. My second OCaml program for Win32 consists of two files. Here is a OCaml file:

open Win32

let dlg_processors = [
    on_wm_initdialog (fun ~wnd ~msg ~focus ->
        message_return true)
    ;
    on_wm_command (fun ~wnd ~msg ~notify_code ~id ~ctrl ->
        if id == control_id_of_standard IDOK && notify_code == bn_clicked then
           end_dialog ~dlg:wnd ~result:0;
   message_handled
 )
]

let _ =
    try
        ignore (
            dialog_box
                ~inst:the_instance
                ~name:(Rn_string “TestDialog”)
                ~parent:null_hwnd
                ~proc:(standard_dialog_proc ~processors:dlg_processors));

        exit 0

    with
        e ->
            let s = Printexc.to_string e in
            ignore (message_box ~wnd:null_hwnd ~text:s ~caption:”Uncaught exception” ~options:[MB_OK]);
            exit 1

And here is test.rc file:

#include <windows.h>
ABOUTDLG DIALOG 20, 20, 199, 99
STYLE DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION
CAPTION “Example caption”
FONT 8, “MS Shell Dlg”
BEGIN
  CONTROL “&OK”,1,”BUTTON”,BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,72,74,40,14
  CONTROL “Hello everybody”,104,”STATIC”,SS_LEFT |WS_CHILD |WS_VISIBLE ,45,14,128,8
  CONTROL “example custom dialog”,105,”STATIC”,SS_LEFT |WS_CHILD |WS_VISIBLE ,45,35,99,8
END

First program used pre-defined generic purpose dialog, second procedure used custom dialog defined in resource file. I hope these two programs will give a good start for everybody who are interested in using OCaml for Win32 programming. Next steps will include making custom resizable Windows with menues, and much more. Unfortunatelly there are not so many information about writing GUI application in OCaml. But maybe with time there will be books even better then one by Petzold!

Categories: OCaml, Windows

Making Win32 GUI programs in OCaml, continued #3. Unsorted thoughts

June 23, 2007 Leave a comment

WordPress shows me report about my blog, and I can see some people come to my blog by making search requests such as “OCaml MFC”. It seems that MFC is most known class library for Windows. Maybe it’s not bad at all. I know it was created at time then C++ was not mature, that’s why MFC contains so many hacks and looks ugly. It also suffers from bad documentation, but it has lots of dedicated books, so it is counted as very well supported. Some people prefer other libraries for C++, such as Qt, wxWidgets, OWL, Ultimate++, SmartWin++. Those libraries are less known and have different focuses, such as open license, productivity, simplicity, cross-platform support. But, as I already stated several times, making OCaml wrapper around some other class library is not an approach I whould take.

One examle of OO widget library for Win32 is a SWT from Eclipse. I now wonder how is it made. I should take my time and investigate.

Thinking about separate compilation. I belive that only reason why this feature is in place is to speed up compilation by compiling only changed files. First users manually specified which files to compile, later tools like make become doing that job.

I’ve also compared Java run-time linking process with loading shared library in C/C++. Java has two ways of loading classes: implicitly, when some class is referenced from another class, and explicitly, by using “Class” class. First approach is simple, second approach gives excellent flexibility such as “plug-ins” and, combined with some ClassLoader magic, allows even using several versions of same library simulteneously. Shared libraries also have these two approaches. Implicit loading of shared library for Windows is very well described here. Dynamic approach for Windows means usage of LoadLibrary()/GetProcAddress()/FreeLibrary() functions.

OCaml has dynamic linking, but only in byte-code mode. It seems that even ocaml-win32 doesn’t support LoadLibrary()/GetProcAddress()

Categories: Java, OCaml, Windows

Making Win32 GUI programs in OCaml, continued #2. Hacking example application and thoughts about separate compilation

June 22, 2007 Leave a comment

Deep in my soul I’m software hacker. Don’t confuse me with crackers: I’m not doing anything which is not legal. When I say hacker I mean a man who likes to play with code for fun. I love to take working program with open code and try to make little changes and see effect. I like to take executable file with closed source and get all available information using tools, for example to see which shared libraries that program uses.

My approach to OCaml is very hackerish. I’ve learned only a small part of language. But I can’t wait, I want to play with language now. I’m playing with ocaml-win32 without solid knowledge of OCaml language itself and I don’t remember much of Win32 programming now. Normal approach whould be to obtain knowledge by reading books and tutorials, then to apply knowledge by development of software. I’m doing those things simultaneously. Probably my way is slower in terms of product. This means that I will produce a working program later then if I whould read first. But my approach is more funny and more enjoyable. That’s why I follow it.

I’m telling that all so everybody could undersand that I’m just a newbie, and they should not trust my opinion in any way. I’m posing this information because I never seen anything else on the topic, and I think that information I’m posting is better than nothing.

After been able to compile ocaml-win32 I was trying to make my own example. I’ve created a separate directory for my own project, copied example file and tried to compile it unchanged. I’ve copied some lines from original Makefile into my own Makefile, and launched it. Imagine my surprise when I’ve got “unbound module Win32” message from compiler! I quickly realised that directory where you try to compile program matters a lot. It took me some time to figure out about .mli files. These files are compiled interface descriptions, and used for separate compilation of modules. In some sense they are similar to .h files of C/C++ language. When I specified path to ocaml-win32 directory using -I option of ocamlc, everything went fine.

This feature led me to thinking about separate compilation in different languages. In Assembler and C/C++ we have “independent compilation”: if you use some function defined in another module you should just declare it in your file, and this function will be marked as “to be resolved” in object file. Linker will search for all such references and bind them to actual implementations. Library authors just make life easier to library users by declaring all their functions in .inc or .h files, and those files are simply concatenated to code of library users. Object code contains unresolved functions in symbolic form, but executable code doesn’t contain it. So, library authors need to write two files each time: library interface and library implementation. Only difference between Assembler and C for me is that in Assembler you don’t need to use .inc file in library implementation, because Assembler procedures don’t need to be declared before they are implemented.

In Java situation is different. Compiler resolves method names at compile time. It uses Java classes compiled into bytecode to check that invokation is syntaxically correct, and includes method’s name in compiled class. Linking in Java happens every time program starts: JVM loads classes, finds names of all classes referenced from just loaded class, loads referenced classes, then binds method invokation to method implementation in memory. Linking at start makes program start a long process, but also allows quick replacement of dependent code as long as method signature remains the same, and also allows some magic like loading code over network on demand. Java linking is similar to dynamic linking in C/Assembler. However, for dynamic linking you still need two files: library implementation and library interface, but in Java you need only compiled class files.

Supporting two files in C is a pain. Also textual representation of interface makes compilation slow: each time interface is used it should be loaded and parsed. Some compilers have a workaround by using pre-compiled headers, but I think that’s overcomplication. In Java you have another pain: code should be compiled in strict order, all code on which your classes depend should be compiled before. That’s possible for C to have a single file, and generate .h files on the fly, making it similar to Java. Also problem of Java approach is that class files are big, because they contain all information nesessary for linking.

OCaml also has separate compilation. Each compilation unit has interface. Interface could be specified explicitly, but if they are not specified then everything is availabe through interface. Interfaces are compiled in exactly the same way as implementations. When some module uses another module it requires only compiled module interface for it’s compilation. So, this approach is something between C and Java: you can have one or two files for source code, two files will be produced as result of compilation. Then some module uses library, it requires only compiled interface for compilation, and compiled implementation will be used when all compiled modules linked together. Compiled interfaces are faster then .h files because they are parsed faster, and they are faster then Java classes because they are smaller. Java approach is little easier because you don’t need to specify both compiled interface and compiled implementation.

Well, that’s all my thoughts about separate compilation for now. Back to my OCaml fun.

Then I was able to compile unchanged example application in separate folder, I’ve started to make small changes to it. By looking at the code I’ve started to remember all messy details about Win32 programming: program’s message loop, Window class, Window procedure, working with program resources, specifying brushes. I was able to edit resource definition file and add new icon. After that I was able to specify to main window to use that icon by editing definition of main window class. I was also able to change background color for main window. Without knowledge of OCaml I can’t go further. However, I’m quite happy with progress I was able to made.

Now I need to learn more about OCaml language itself, about it’s standard library. And I should also refresh all my knowledge about Win32API. For OCaml I have all free books. For Win32 I have books of Petzold and Richter.

After playing with ocaml-win32 I think that using only that library is be too complex way of development. OCaml is OO language, so some library should be build on top of low-level API. I still believe that ocaml-win32+class library written in OCaml is right approach, better then OCaml wrapper over OO widget library written in C++ (like SmartWin++, Tk, wxWidgets, and others). There is a library for OCaml named “osiris”. However, it compiles with error, and I don’t know OCaml good enough to fix it myself now.

Categories: OCaml, Windows

Making Win32 GUI programs in OCaml, continued #1. Native compilation

June 19, 2007 1 comment

I keep playing with OCaml, and it’s very fun.

First funny thing is that OCaml could be used to compile C/C++ files. Of course, it doesn’t contain C compiler inside, it invokes some external compiler. Which compiler to invoke depends on version of OCaml, for Windows it supports Microsoft Visual C++ and MinGW. Thos e compilers should be possible to locate via PATH, because OCaml simply invokes “gcc” or “cl”. Why such feature is implemented – I don’t know, because compiler could always be invoked directly. Probably OCaml adds it’s own include and libary directories for compiler and linker.

OCaml can produce two types of code: byte-code and native code. Byte code available for much wider range of platforms then native code. Byte code files are very similar to object files produced by C compiler: they have extensions .cmo, they could be organized in libraries (they have extensions .cma). Byte code files could be executed by OCaml virtual machine called “ocamlrun”. Compiler is also able to produce stand-alone executables which contain both virtual machine runtime and byte code for your program. Such stand-alone program is usual exe file and could be executed on any Windows machine. In this case linker is invoked (from MinGW or Microsoft Visual C++). Stand-alone programs also able to contain staticaly-linked object code, written in C/C++ or assembly.

Native compiler produces native code. It does that in two-step approach: first, assembly source generated, then external assembler is invoked for compilation. OCaml version for Microsoft Visual C++ invokes Microsoft Assembler (ml.exe), so it is required for native compilation. I didn’t checked that, but I suppose that Ocaml version for MinGW invokes GNU assembler. After compiling all modules are linked using external linker. Native executables are also stand-alone, and they are usually faster then byte-code.

I’ve discovered that by playing with ocaml-win32. By default only byte-code version of library is compiled. To compile native version of library, I’ve invoked “nmake win32.cmxa”, and got “command not found: ml.exe”. So I’ve downloaded Microsoft Assembler and then everything were build succesfully.

I like OCaml more and more. It’s approach to compilation seems very good to me. And ability to interface C makes it very powerful.

Categories: OCaml, Windows

Making Win32 GUI applications in OCaml

June 15, 2007 3 comments

In my recent article I was talking about my attempts to find language other that C/C++ for writing GUI applications. Well, I should admit that last time I did GUI application myself was 5 years ago. It was written in C++ and used MFC. All last time I did only server-side programming. Only now I need to write a new GUI application, and I want this application to be written in programming language other than C/C++, so I could practice that language.  So, I didn’t GUI programing for long time, so my opinion about languages, libraries and graphical toolkits is not very solid. But I’m windows user, and I have my opinion about GUI programs that I use. For me very important things about GUI program is that UI should look native and be fast, and that it should be small and launch quickly. That makes external impression about program.

Nowdays almost everybody use some object-oriented wrapper library around Windows ui.dll, because it simplifies development greatly. I know a good wrapper for C++, called SmartWin++, but I never used it myself seriously. I’ve just downloaded it and tried to build example applications. Executables are small and fast, and UI looks native. Code for applications is small and clean, especially compared to MFC-oriented applications. At last, SmartWin++ could be used with both Microsoft Visual C++ compiler and with MinGW compiler, which is also important for me. Probably soon they will add support for other compilers. All those things make me happy with SmartWin++ library if I choose C/C++ as implementation language.

Making access to Win32 UI library for other languages is more difficult, because there should be a binding to C for each function. Taking into account size of Win32API it’s a huge task. So, people who develop other languages usually do binding to some simplified wrapper around ui.dll. Microsoft did that for Visual Basic. Borland did that for Delphi. Perl, Python and OCaml have bindings to wxWidgets.

Some words about wxWidgets. It’s good library, and could be used for fast application development in C++, because it’s much simpler to use then raw Win32 UI API, and easier than MFC. For me the only problem of wxWidgets is that it’s not just object-oriented wrapper around Win32 UI, but cross-platform library with wrappers around lots of platform-specific toolkits. I don’t like this idea, and prefer SmartWin++.

So, finally, I came to conclusion: when you develop GUI, you don’t choose the language which you like, but choose the language which has best libraries for that GUI.

In abovementioned article I told that OCaml is very Unix-biased. I’m apologising for that, I was wrong. OCaml has good support for windows sockets and threads in standard library, but it also has good binding to Win32API as additional library. This makes it perfectly suitable for development of native Win32 UI applications. However, this path is not easy at the beginning. Here I whould like to share my own experience, hoping it will save somebody’s time.

First, few words about OCaml. For Win32 it’s available in three flavours: CygWin, MinGW and Microsoft Visual C++. Initially I thought that it means that those compilers were used to compile OCaml tools. That’s right, but also that means that those compilers will be used by OCaml tools themselves to compile your source code. If you installing MinGW version, you should have MinGW itself installed. If you installing Visual C++ version, then you should have Visual C++. Fortunatelly, both compilers are available for free. This additional requirement for C compiler was not obvious for me, and I’ve spent some time trying to figure it out.

If you want to use ocam-win32 library, you must have version of OCaml for Visual C++. I hope someday this library could be also built from MinGW.

Library is available in source form from here. Unzip it in any place, and you will have lots of sources in both C and Ocaml, together with several small text files. Those files are not very helpfull, so it’s not easy to figure out what to do. Finally I understood that I should make library myself. The only toolkit I had was MinGW, so I’ve tried to invoke “make”, but received “delimeter absent” error, because Makefile used spaces instead of tabs. After some time I’ve realized that I need Visual C++. I’ve installed free compiler and tried to build it by invoking nmake. No complains about delimeters this time, but OCaml kept invoking gcc, which complained about compiler keys. So I undestood that I need version of OCaml built for Visual C++. That was not obvious.  I’ve re-installed OCaml, and run nmake again. Better this time, now it was complaining about missing headers. It occured that I should have Microsoft Platform SDK installed. It’s big, so I’ve installed only Platform core SDK.  To correctly compile a lots of environment variables should be set correctly. Include directories should contain both Visual C++ runtime headers and Platform SDK headers. The same story for libraries. I was able to do that by first invoking “set environment” script of Protocol SDK, then, from same command prompt, invoking vcvars32.bat. Another attempt to compile, and this time it was complaining about missing “shlwapi.h” file. After some googling I’ve found that I should install not just Platform core SDK, but also IE SDK. I did that, and, finally, got the library!

There is a test application, which starts very fast and looks native. So, now I’m quite optimistic about usage of OCaml for GUI applications for Win32 platform. OCaml seems much easier language than C++.

Many thanks to authors of this library. I had lots of problems during installation because it’s a long time since I’ve last used Visual C++, and because library is  for hackers who know that to do. Library authours should extend their readme files, and they should also redistribute compiled versions of libraries.

Update: this article is a first one dedicated to GUI programming in OCaml. See subsequent posts which will describe by progress on the path. That’s not a tutorial, just information written by newbie, so don’t trust me.

Categories: OCaml, Windows