On 26/03/2012, at 12:40 AM, Shayne Fletcher wrote: CC'd to lists because lots of info here.
Also CC'd to Erick, because if fbuild doesn't work right, he may be interested in upgrading it. The bottom lines are: * this is going to be very hard * it cannot be done by one or even two people: we need some more developers because quite a bit of difficult DESIGN work is required here. It isn't just a matter of a few patches. * it cannot be done by one person working on Windows and another separate person working on Posix. Otherwise the turnaround time for checking changes work on BOTH platforms will be huge. We will end up with code that doesn't build on either platform. Dual booting isn't enough. Someone needs BOTH platforms running simultaneously with high speed access to the repository .. ideally on a shared local disk. This might be done with a hypervisor like Xen or something that can run both OS together and even share desktop space. Otherwise another good way is to use Windows with a X Window as a console to a Linux server. I used to own two identical desktop machines and ran Linux on one and Windows on the other. Even that was hard to manage, even with Samba to share disk: that's probably the only effective way to do it. Cygwin can be useful. However a Cygwin build is very tricky. It is good I think to use Cygwin to run the build process but still *target* pure Win32/MSCV++. You can run MSVC++ (and any other windows programs) from inside Cygwin. This gives you bash and all the other build tools. You can also try a mingw build inside Cygwin to get Felix running on Windows, but that is only a transient solution because it is using gcc (mingw port), not MSVC++. We definitely want MSVC++ builds in the long run. > What was it you suggested earlier? Run up ``make build`` from a MinGW`` bash > shell and see where it goes? Yes. To build Felix to a useful state you need flx_pkgconfig. This tool is an essential part of the compilation process. It gathers information from a database in response to the *.resh file generated by flxg and generates a #include file which the C++ code generated by flxg #includes. flx_pkgconfig itself is written in Felix, and the #include file required is "pre-calculated" and part of the repository. All other builds, including the "flx" tool, require flx_pkgconfig. See src/flx_pkgconfig/flx_pkgconfig.includes: which says: #include <iostream> #include "flx_ioutil.hpp" #include "flx_strutil.hpp" #include "flx_rtl.hpp" #include "flx_gc.hpp" Even if you cannot build flx_pkgconfig under MSVC++ it may help if you have an executable that works. That way, if you finally get "flx" to compile and generated buildable code you have the tool to complete the compilation process. Secondly, you need to get "flx" to work. In the old days there was a bash script that did the job, and also a flx.bat file for windows. Then that got replaced by a Python script. Finally that got replaced by a program written in Felix itself. So the second challenge is to get "flx" to build. You do NOT need "flx" to make Felix programs. You can manually run "flxg" and then compile the resulting C++ code "by hand" with MSVC++. It's a pain, but a *.BAT script or Python script that can build flx_pkgconfig and flx itself under Windows would be very useful. Flxg itself is written in Ocaml and should compile on Windows. At least the 32 bit version should compile. [Last I looked 64 bit Ocaml on Windows had a number of bugs in the bignum library due to bad coding by Xavier Leroy: he assumed "long" was 64 bits. On Windows it is only 32 bits. I put in a ticket but AFAIK it never got fixed. INRIA doesn't care about Windows :] The biggest problem you'll have initially is filenames. Flxg tries to ensure it will work with the native file system, but without testing it is hard to be sure I didn't use "/" as a separator in some places instead of Filename.sep. The filename problem will occur in fbuild flxg flx_pkgconfig flx as well as a lot of the library code. The "general" rule for filenames is this: conceptually all filenames consist of two parts: (a) a native prefix (b) a relative file The (a) part is * platform dependent * always provided by the environment eg command line * never manipulated by any code For example on Posix: /usr/local/lib/felix and on Windows: C:\program files (x86)\felix The second part of the filename is ALWAYS IN UNIX FORMAT. All literals in code use Unix relative filenames. To make a native filename, the UNix part is converted to native format and prefixed by the native prefix with a separator possibly stuck in between. You should find some Ocaml code that does this. However it may not be rigorously applied! The point here is that any literal filenames in flxg (and possibly in Felix code as well) if given in Unix format: std/list.flx are correct as written. They should NOT be converted to Windows filenames as literals. The conversion SHOULD be done by the code that adds that file to a prefix. But I may have neglected to do this in all cases in flxg (Ocaml) and I can *promise* I have not done it in all the Felix code floating around. We need to actually review and design a proper filename handling library. The existing code is minimal (it provides only Filename::sep and a join function or so, which is NOT enough: I dont remember but we'll have to sit down and make the rules. In theory, strings should NOT be allowed for filenames, it should be Relative_Filename "...." (Unix format) and Native_Filename ... (Windows or Posix depending). Windows_Filename... Posix_Filename ... and all the functions accepting filenames should require values of filename type (NOT strings). IMNSHO (in my not so humble opinion) the correct layout for a filename is: file:///...... i.e. we should use a URI. Of course that would mean open("http://....:") would eventually have to work :) You may also have problems with Async I/O (sockets, event manager using IO completion ports: this USED to work. A long time ago). Async I/O is NOT required for flx or flx_pkgconfig, only things that use sockets of timers need it. But it has to work eventually. A lot of code uses Posix. For example the file copy program flx_cp and the listing flx_ls both rely on Posix. The BIG challenge to get everything working is getting rid of all the Posix dependencies. There are three ways to do this. All are required. The first way is to provide an emulation in C++. This is already done for semaphores, for example, which Windows doesn't provide: it provides WaitForSingleObject, and there is code that uses that to emulate Posix semaphores. Where possible, emulations of Posix are the easiest way to solve problems, because the Felix code is left unchanged. The only problem is with the build system, making the emulation libraries, and ensuring that they get linked in: flx_pkgconfig should handle this if set up correctly. In many cases, Felix uses a C++ abstraction, for example threads are implemented in C++ in such a way the interface is the same for Posix or Windows. This is not quite as nice as a Posix emulation, because an abstraction has to be designed which supports all the required functionality, and then it has to be implemented for both Posix and Windows. A really NASTY example of this is flx_dynload, which provides dynamic loading abstraction that works on both Posix with dlopen and Windows with LoadLibrary. Its nasty because the implementations on Unix also differ a bit (cg Cygwin, OSX). AND because we have to statically link much code as an alternative .. with the same interface to the code (it's done with some tricky macros .. :) The third technique is to use Felix. There are two techniques: (a) conditional compilation. This SUCKS and should be avoided. The Faio interface uses this at the moment. Even some parts of the webserver uses it (and the Windows code isn't written). Generally, conditional compilation of bits and pieces should be avoided. (b) Abstraction. I think this is the right way. The idea here -- and there's no implementation using this idea yet -- is to provide a Felix type class with virtual functions, and provide two instances: one for Windows and one for Posix. Code (such as webservers) can then just use the abstraction presented by the class, and we can somehow use a SMALL bit of conditional compilation to select the appropriate instance. YOU NEED TO KNOW ABOUT lpsrc/flx_maker.pak This file is the "remnant" of the old interscript based build system. It is used to generate platform dependent code. You will find code it generates like: build/release/lib/plat/config.flx all such files say //GENERATED during config at the top. Ahem actually the most IMPORTANT one doesn't: build/release/plat/flx.flxh which says, on my box: macro val PLAT_WIN32 = false; macro val PLAT_POSIX = true; macro val PLAT_LINUX = false; macro val PLAT_MACOSX = true; macro val PLAT_CYGWIN = false; macro val PLAT_SOLARIS = false; macro val PLAT_BSD = true; you can see my platform is POSIX and OSX and BSD -- its a Mac ;( For windows PLAT_WIN32 should come out true. Conditional compilation in Felix is done with ORDINARY conditionals: if PLAT_WIN32 do fun basename (x:string) => split (x, "\\"); else fun basename (x:string) => split(x,"/"; done The rule is that if the condition of a conditional is a "compile time constant" then the code which is not selected is *deleted*. In other words, it doesn't have to be type correct. It has to parse, that's all. Sometimes this is a pain: you can write: fun basename(x:string) => split(x, if PLAT_WIN32 then "\\" else "/" endif); for example, but you cannot write typedef socket = if PLAT_WIN32 then HANDLE else int endif; because there only statements and expression have conditionals. Not patterns, attributes, header or body insertions, etc etc. Actually types DO have conditionals but I don't think the constant folder respects them; you can write typedef socket = typematch OS_TYPE with | WIN_TYPE => HANDLE | POSIX_TYPE => int endmatch ; and this is a perfectly valid type expression, but it isn't a type until it is reduced: the constant folder doesn't do type reductions at the moment. The reduction may be done too late for overloading, etc, to actually work. I could fix this, but it only improves things a bit, maybe perhaps .. :) You can always just conditionally compile one of two typedefs so it isn't clear this upgrade is worthwhile. Note I am looking for a way to make this stuff work WITHOUT coarse conditional compilation. That is, something like: typedef socket = int when POSIX; typedef socket = HANLE when WIN32; This is still conditional compilation, but it is not as crude a gross if/do/else/done construction: it's more like "guarded code" and similar to the requires tag clauses, only instead of yanking in dependencies based on use, it selects code based on environment. I've been looking for a way to do this nicely for some time! The hard bit here is that it isn't just POSIX vs WINDOWS. The environment is factored in a complex way (see above, I run POSIX OSX BSD. And also POSIX has option XSI (X/Open extensions, mainly from BSD). YMMV :) -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ This SF email is sponsosred by: Try Windows Azure free for 90 days Click Here http://p.sf.net/sfu/sfd2d-msazure _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language