facebook/flow

Please provide Windows binaries

StoneCypher opened this issue · 253 comments

There's a whole lot of Windows developers out there who would love to use this too, and who will contribute based on it.

+1

m90 commented

+1

+1

Has anyone tried building on Cygwin in the meantime? Looks like OCaml supports it:

https://ocaml.org/docs/install.html#Windows

Edit:

hack/heap/hh_shared.c:96:25: fatal error: sys/syscall.h: No such file or directory

If I delete the include and the syscall, I'm stumped because I'm on 32-bit Windows and integers overflow all over the place.

Looks like OCPWin might be the way to go. Looking into it.

+1

+1

+1

There is actually no issue at all with compiling the OCaml part of "flow" on Windows. The following file (copied in build.ocp at the root of the project) will work ASAP on Windows using OcpWin (after ocp-build init and ocp-build build):

begin program "flow"
    cclib = [ "-lelf" ] (* comment this line under Windows *)
    requires = [ "unix" "str" ]
  files = [
(* comment these C files under Windows to compile only the OCaml part *)
    "src/embedded/flowlib_elf.c"
      "hack/heap/hh_shared.c"
      "hack/utils/realpath.c"
      "hack/inotify/inotify_stubs.c"
      "hack/utils/nproc.c"
      "hack/hhi/hhi_elf.c"
      "hack/utils/get_build_id.gen.c" (* This file should have been generated first, for example under Linux *)
      "hack/utils/get_build_id.c"

      "hack/avl/monoidAvl.ml" "hack/client/clientExceptions.ml"
      "hack/utils/path.ml" "hack/client/clientLogCommand.ml"
      "src/server/sysConfig.ml" "hack/utils/tmp.ml"
      "hack/socket/socket.ml" "hack/utils/ident.ml"
      "hack/utils/sys_utils.ml" "hack/utils/utils.ml"
      "hack/utils/lock.ml" "hack/client/clientUtils.ml"
      "hack/utils/pidLog.ml" "hack/client/clientStop.ml"
      "hack/utils/build_id.ml" "hack/utils/hh_json.ml"
      "hack/utils/relative_path.ml" "hack/utils/pos.ml"
      "hack/utils/errors.ml" "hack/server/serverMsg.ml"
      "hack/client/hackClientStop.ml" "hack/utils/shell.ml"
      "hack/client/clientStart.ml" "hack/stubs/eventLogger.ml"
      "hack/utils/tty.ml" "hack/client/clientBuild.ml"
      "hack/client/clientEnv.ml" "hack/client/clientProlog.ml"
      "hack/client/clientStatus.ml" "hack/client/clientCommand.ml"
      "hack/utils/config_file.ml" "hack/utils/wwwroot.ml"
      "hack/client/clientArgs.ml" "hack/deps/fileInfo.ml"
      "hack/deps/typing_graph.ml" "hack/deps/typing_deps.ml"
      "hack/heap/prefix.ml" "hack/heap/value.ml"
      "hack/heap/sharedMem.ml" "hack/naming/naming_special_names.ml"
      "hack/parsing/namespace_env.ml" "hack/parsing/ast.ml"
      "hack/naming/nast.ml" "hack/typing/typing_reason.ml"
      "hack/typing/typing_defs.ml" "hack/typing/typing_env.ml"
      "hack/typing/typing_hooks.ml" "hack/typing/typing_print.ml"
      "hack/server/argumentInfoService.ml"
      "hack/client/clientArgumentInfo.ml"
      "hack/globals/autocomplete.ml" "hack/globals/find_refs.ml"
      "hack/globals/ide.ml" "hack/naming/naming_ast_helpers.ml"
      "hack/naming/naming_hooks.ml" "hack/parsing/namespaces.ml"
      "hack/naming/naming.ml" "hack/naming/naming_heap.ml"
      "hack/naming/nastVisitor.ml" "hack/typing/typeVisitor.ml"
      "hack/typing/typing_exts.ml" "hack/typing/typing_hint.ml"
      "hack/typing/typing_utils.ml"
      "hack/typing/typing_instantiate.ml" "hack/typing/typing_tdef.ml"
      "hack/typing/nastCheck.ml" "hack/typing/nast_terminality.ml"
      "hack/typing/typing_expand.ml"
      "hack/typing/typing_unification_env.ml"
      "hack/typing/typing_unify.ml" "hack/typing/typing_subtype.ml"
      "hack/typing/typing_ops.ml" "hack/typing/typing_suggest.ml"
      "hack/typing/nastInitCheck.ml"
      "hack/typing/typingEqualityCheck.ml"
      "hack/typing/typing_alias.ml" "hack/typing/typing_async.ml"
      "hack/typing/typing_dynamic_yield.ml"
      "hack/typing/typing_enum.ml" "hack/typing/typing_extends.ml"
      "hack/typing/typing_generic.ml" "hack/typing/typing_lenv.ml"
      "hack/typing/typing_variance.ml" "hack/typing/typing.ml"
      "hack/server/autocompleteService.ml"
      "hack/client/clientAutocomplete.ml" "hack/server/serverError.ml"
      "hack/client/clientCheckStatus.ml" "hack/client/colorFile.ml"
      "hack/parsing/parser_heap.ml" "hack/typing/coverage_level.ml"
      "hack/client/clientColorFile.ml" "hack/globals/serverConfig.ml"
      "hack/heap/globalStorage.ml" "hack/parsing/lexer_hack.mll"
      "hack/parsing/parser_hack.ml" "hack/procs/bucket.ml"
      "hack/utils/fork.ml" "hack/utils/printSignal.ml"
      "hack/procs/worker.ml" "hack/procs/multiWorker.ml"
      "hack/server/find.ml" "hack/server/serverArgs.ml"
      "hack/server/serverEnv.ml" "hack/typing/typing_inherit.ml"
      "hack/typing/typing_decl.ml"
      "hack/typing/typing_decl_service.ml"
      "hack/typing/typing_check_service.ml"
      "hack/server/serverIdeUtils.ml"
      "hack/server/serverCoverageMetric.ml"
      "hack/client/clientCoverageMetric.ml"
      "hack/typing/typing_compare.ml" "hack/server/findRefsService.ml"
      "hack/server/serverFindRefs.ml" "hack/client/clientFindRefs.ml"
      "hack/server/methodJumps.ml" "hack/client/clientMethodJumps.ml"
      "hack/client/clientOutline.ml" "hack/server/serverRefactor.ml"
      "hack/client/clientRefactor.ml" "hack/parsing/parsing_hooks.ml"
      "hack/search/searchUtils.ml" "hack/search/fuzzySearchService.ml"
      "hack/utils/trie.ml" "hack/search/trieSearchService.ml"
      "hack/search/searchService.ml"
      "hack/search/hackSearchService.ml" "hack/client/clientSearch.ml"
      "hack/client/clientTypeAtPos.ml" "hack/server/fileOutline.ml"
      "hack/server/serverArgumentInfo.ml"
      "hack/server/serverColorFile.ml"
      "hack/server/serverFileOutline.ml"
      "hack/server/serverInferType.ml" "hack/server/serverSearch.ml"
      "hack/client/clientCheck.ml" "hack/inotify/inotify.ml"
      "hack/fsnotify_linux/fsnotify.ml" "hack/dfind/dfindEnv.ml"
      "hack/dfind/dfindMaybe.ml" "hack/dfind/dfindAddFile.ml"
      "hack/dfind/dfindServer.ml" "hack/dfind/dfindLib.ml"
      "hack/hhi/hhi.ml" "hack/parsing/parsing_service.ml"
      "hack/server/serverDfind.ml" "hack/server/serverEnvBuild.ml"
      "hack/server/serverHealth.ml" "hack/server/serverPeriodical.ml"
      "hack/server/serverFunctors.ml" "src/common/flowConfig.ml"
      "src/embedded/flowlib.ml" "src/common/files_js.ml"
      "src/commands/commandUtils.ml" "src/parser/spider_monkey_ast.ml"
      "src/common/reason_js.ml" "src/parser/parse_error.ml"
      "src/common/errors_js.ml" "src/common/modes_js.ml"
      "src/typing/constraint_js.ml" "src/typing/flow_js.ml"
      "src/typing/env_js.ml" "src/typing/type_inference_hooks_js.ml"
      "src/typing/autocomplete_js.ml"
      "src/server/autocompleteService_js.ml"
      "src/server/serverProt.ml" "src/commands/autocompleteCommand.ml"
      "src/commands/configCommands.ml" "src/dts/dts_ast.ml"
      "src/dts/lexer_dts.mll" "src/dts/parser_dts.ml"
      "src/dts/printer_dts.ml" "src/commands/convertCommand.ml"
      "src/commands/findModuleCommand.ml"
      "src/commands/getDefCommand.ml"
      "src/commands/getImportersCommand.ml"
      "src/commands/getImportsCommand.ml"
      "src/commands/portCommand.ml" "src/parser/lexer_flow.mll"
      "src/parser/parser_flow.ml" "src/parsing/parsing_service_js.ml"
      "src/typing/module_js.ml" "src/typing/type_inference_js.ml"
      "src/typing/comments_js.ml" "src/typing/getDef_js.ml"
      "src/typing/init_js.ml" "src/typing/sort_js.ml"
      "src/typing/types_js.ml" "src/server/server.ml"
      "src/commands/serverCommands.ml" "src/commands/singleCommand.ml"
      "src/commands/statusCommands.ml" "src/commands/stopCommand.ml"
      "src/commands/suggestCommand.ml"
      "src/commands/typeAtPosCommand.ml"
      "src/stubs/flowEventLogger.ml" "src/flow.ml"

  ]
end

So, porting "flow" is only a matter of porting the 7 files in C...

There really are 3 main pieces of Flow and Hack that are platform specific

  1. File system watching. This is inotify on Linux and fsevents on Darwin (MacOS)
  2. Embedding libraries in the binary (libraries are gzip'd and stuck in the text section of the flow binary...then extracted at runtime). This uses libelf on Linux and mach-o/getsect.h on Darwin.
  3. Shared memory stuff. I hear the mmap stuff we do wouldn't port well.

This is something we'd like to do sometime in the next year, but if someone wants to take a stab at it we'd be more than happy to take the PR :)

File system watching. This is inotify on Linux and fsevents on Darwin (MacOS)

Maybe we can postpone that for now. We can build manually for now. But at least should do the work (:

From what I saw, there is no need to port part 2. (libelf/mach-o), as "flow" will also look up for "flowlib.tar.gz" in its environment (in the parent dir of its executable...). So, inotify and mmap... already quite some work !

Yeah, if you don't run the server as daemon, you don't need the file watching. And you can probably just stick the gzip'd libraries next to the binary and with a little hacking you don't need the embedded libraries stuff.

The shared memory part is a little trickier, but we've had success working around it for simple in-browser playground sorts of things. For example, the Hack tutorial runs the Hack typechecker in the browser without the shared memory stuff.

+1

Flow looks like an improvement over TypesScript, would be great if it would run on Windows!
(+1)

+1

@gabelevi: any hint on the trick to get rid of the shared memory stuff ?

j201 commented

+1

It would be great to see this as a competitor to TypeScript, but Windows support is necessary for that.

@lefessan So the way Hack compiles to JS is that it replaces a few things with simplified versions. So normally Hack uses sharedMem.ml which calls to external C functions. However, when we compile it to JS, it instead uses a different sharedMem.ml which is greatly simplified and doesn't call into C.

I used ocpwin to compile a very simplified version for Windows.
http://www.ocamlpro.com/pub/ocpwin/flow-builds/

Still a lot of work to do to get a fully working version !

How to use it :
unzip the file, there are 2 files flow32.exe and flow64.exe to use depending on your system.
You must set a variable FLOWLIB to point at the lib/ directory of flow:

On Cygwin (you must use it for now)

export FLOWLIB=c:/cygwin/home/user/flow-simple-windows/lib

The server has been removed, so it probably only works with:

flow64 single DIRECTORY

I hope it is enough to play with Flow on Windows, while waiting for an official Windows version...

@lefessan cool! Thanks, much appreciated.

@lefessan cool +1

I uploaded a new version:
http://www.ocamlpro.com/pub/ocpwin/flow-builds/

Now, it should behave as the linux/macosx client, but without any multicore support. Works without Cygwin.

Feedback welcome !

+1. I was disappointed I couldn't try out flow. Is there word of an official stance or timeline? is win support a priority? it salads strikes me as odd when any new large web oss project is not cross platform. Why wasn't a tool choosen from the beginning (cough node) that handled what's seems to be fairly simple platform deps?

also for a lot Windows devs something a cygwin dep is a complete non-standard.

looking forward to trying this out eventually! it would be helpful to know when that might be :P

@jquense: portability is an issue, but writing a type-checker is a much harder issue (don't even think about doing it in Javascript...). So, they chose the best tool (OCaml) for the hardest problem, and they left porting as an easy problem... and indeed, it took us only two days to have a working Windows version (ok, no multicore and persistent state, the code is uggly, and it's not official, but it works !).

@jquense linux or osx share a common root and it is pretty easy to port between them. Windows is always a different beast, same happened with git, node etc. It will take a while, of course you can jump in and try to submit patches to get windows upto speed.

@lefessan @pradeepcodes perhaps i came off as overly whiny, I didn't mean to pout. I mostly just wondering what the official stance is on win support. I realize the nix/osx are an easy port, and that windows if a different animal, i wasn't trying to say that it is easy to build something that meets the needs and is cross platform. My concern is more that when projects don't have cross-platform support as a priority from the beginning, the porting story is usually pretty bad for a long while (node is a good example). I am just wondering what the flow team's position on this is, and whether getting windows support first class is even something they care about. It helps me and my team when we know that flow will eventually be first class on windows, or its always going to be a "if ppl send the prs we'll merge them" sort of a support

Dog food comes to mind. Typescript compiler is written in Typescript. Not sure why OCaml was chosen but its good practice to build your compiler in the language your compiling, 😉 Anyways +1 for windows support.

@Davidhanson90 : Scilab/Matlab compiler in Scilab, R compiler in R, is it really a good practice ? Writing a compiler is mostly manipulating huge trees (AST) in a recursive way, OCaml is a typed functional programming language with a feature called "pattern-matching" (check the manual, it's worth it !) that makes these kinds of manipulations much easier than in other languages... OCaml was also used for other languages, such as the first Rust compiler by Mozilla, Facebook Hack compiler, the Haxe compiler, etc...

alt- commented

@lefessan Thank you for the port!

Minor issue: I get an error when it tries to find the .flowconfig when run in a very specific path:

Fatal error: exception Sys_error("C:/Users/Owner/Downloads/flow-simple-windows-20141120/flow-simple-windows/./..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//

Changing the path slightly or doing a flow init makes it work fine.

@lefessan I'm not saying OCaml isn't a good language for it but I feel that it would be good to dogfood the language you're building. Maybe good practice is the wrong words. Anyways maybe the compiler will be written in flow when its done. 👍

Other languages with self hosting compilers.

◾Ada
◾BASIC
◾Burroughs Algol
◾C
◾C++ (compilers: Visual C++, clang, probably others)
◾C# and Visual Basic .NET via Microsoft Roslyn
◾CoffeeScript
◾Common Lisp
◾Crystal
◾Curry
◾Delphi
◾Eiffel
◾F#
◾FASM
◾Factor
◾Fancy
◾Free Pascal
◾Haskell
◾Java
◾Mercury
◾Modula-2
◾Nimrod
◾Oberon
◾OCaml
◾Pascal
◾Perl 6 (compilers: Rakudo Perl & Niecza Perl 6 are both self-hosting)
◾PL/I
◾Python
◾Rust
◾Scheme
◾Scala
◾Smalltalk
◾SML
◾TypeScript
◾XPL

@lefessan just tried the 32 bit version. flow32 check runs fine. Starting the server with flow32 start doesn't return. (Win7)

I've just re-read you earlier comment wrt "the server has been removed". Did that still apply to the later version?

@woopsie: indeed, I should have written it in the doc, that the server will not detach itself, it will keep running in the terminal (thus, not returning)... unless it is started in the background by another subcommand. I will try to find some time next week to understand how to detach the server.

@woopsie @lefessan The windows equivalent of foo & is START "" foo

File system watching. This is inotify on Linux and fsevents on Darwin (MacOS)

@gabelevi For what it's worth, file system watching on Windows is pretty straightfoward via the .NET FileSystemWatcher class which can be used in C++ via C++/CLI.

@Daniel15 would't that involve now instantiating the .NET runtime .. wouldn't http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx be more suitable.

@pradeepcodes Yeah, that should work too. I wasn't sure if there was a nice interface to it outside of .NET.

+1

Erid commented

+1

what?

I have uploaded a new version on http://www.ocamlpro.com/pub/ocpwin/flow-builds/. Everything works on my computer, so I am looking for feedback from other Windows users...

@gabelevi: would it make sense to put a link to my page from http://flowtype.org/docs/getting-started.html, for Windows users, with a warning that it is a "third party" contribution, .i.e external to Facebook ?

@gabelevi : would it be possible to change the syntax of flow suggest FILE:line,pos-line,pos to avoid the use of ':' ? Since files on Windows can start with "C:", the heuristics using ':' to find the region is broken. Maybe use '@' instead of ':' ?

@lefessan looks like href for flow-simple-windows-20141127 is pointing to flow-simple-windows-20141120

@woopsie : thanks ! It's fixed now.

👍

👍

Could the windows flow builds at http://www.ocamlpro.com/pub/ocpwin/flow-builds/ be set up with http://www.appveyor.com/ continuous integration?

Hm, yea, it would be neat to have "official" Windows support :)

Another developer here, mostly on Windows.

I swear that soon "nerds" and "hackers" will all be Windows users due to the amount of hacks we need to get all the libs working properly. Tide turning!

+1

Works with files in the same dir. But it will not look into sub dirs into my specific project. On an empty project work fine.

I think there is an error in a file that breaks the flow script silently because always shows "0 errors".

If I put the flowconfig in the current dir I have 3 errors. If I put a dir above I have 2 errors. In the exact same file! Fragile alarm here!

File

/* @flow */
define(function(require, exports, module){

    var _ = require('underscore');
    var utils = require('../utils');
    var fnFactory = utils.fnFactory;

    // Data:
    //  - player: Player game
    var ZI = function(data){
        _.extend(this, data);
        this.checkWaveStatus()

    }

    ZI.getPlayerZIScore = function(player){
        var XP             = player.XP;
        var totalGoldMined = player.totalGoldMined;
        var secondsPlayed  = player.stats.secondsPlayed;
        var planetsOwnedN  = player.stats.planetsOwnedN;
        var score = XP             * 3 +
                    totalGoldMined * 1 +
                    planetsOwnedN  * 10 +
                    secondsPlayed  * 1;
        return score;
    }

    ZI.canSendNextWave = function(player){
        var currentScore = ZI.getPlayerZIScore(player);
        var prevScore    = player.ZI.lastScore;
        var percentIncrease = (currentScore - prevScore) / prevScore * 100;
        if(percentIncrease > 30){
            return {
                yes: true
            }
        }else{
            return {
                retryInMs: (30 - percentIncrease) * 1000 * 10 * 1
            }
        }
    }

    _.extend(ZI.prototype, {
        checkWaveStatus: function(){
            var res = ZI.canSendNextWave(this.player);
            if(res.yes){
                this.sendNextWave();
            }
        },

        sendNextWave: function(){
            throw new Error('finish this')
            // this.API('sendNextWave');
        }
    })

    return ZI;
});

Output with flowconfig in the same folder:

E:\bp\Web\game07\src\client\ZI>flow64 check

E:/bp/Web/game07/src/client/ZI/ZI.js:2:1,6: identifier define
Unknown global name

E:/bp/Web/game07/src/client/ZI/ZI.js:4:13,33: underscore
Required module not found

E:/bp/Web/game07/src/client/ZI/ZI.js:5:17,35: utils.js
Required module not found

Found 3 errors

Now I move the flowconfig in the E:/bp/Web/game07/src/client folder:

E:/bp/Web/game07/src/client/ZI/ZI.js:2:1,6: identifier define
Unknown global name

E:/bp/Web/game07/src/client/ZI/ZI.js:4:13,33: underscore
Required module not found

Found 2 errors

Interesting.

+1

+1

+1

+1

+1

kolo commented

+1

+1

I need this! +1

+1

@lefessan any chance of an updated build? really need to grab this commit
if appveyor support is a possibility - that'd be ace!

It would be great for an official build, because people like sindresorhus don't want to merge third party binaries (with good cause,) and are maintaining the binary packages that actually get invoked by the various toolchains out there.

An official build is meaningfully different than an identical third party build.

👍 +1

+1

+1

+1

So that's (counting +1 and 👍) 32 so far.

Guess I'm gonna plus my own thing because I want to start a running tally by example.

+1 = 33.

+1 (34)

+1 (35)
ps if any of the flow folks fancy giving an update here, or a preference on people registering their interest (watch this PR, uservoice, etc) that'd be great..
unfortunately no experience at all in ocaml, so cant really offer up any help on a PR with code (rather than +1s) , but be more than happy to jump in and help where we can (testing, appveyor CI setup, etc)

+1 because our teams are working on mixed environments and we cannot afford to use unsupported tools.

+1 (37)

+1 (38)

+1 (39)

+1 (40)

Could this be fixed by using js_of_ocaml to port it to Node?

+1 (41)

As though the developers don't already know how much interest there is in Windows support:
+1 (Meaning of life, the universe, and everything)

Just had to do it.

@Flaise - amazingly, they don't.

Um... They realize. It's just there are specific things extremely difficult
to port IIRC, and it's not quite as high priority as fully addressing ES6
support, given projects like Cygwin.
On Mar 23, 2015 2:42 PM, "John Haugeland" notifications@github.com wrote:

@Flaise https://github.com/Flaise - amazingly, they don't.


Reply to this email directly or view it on GitHub
#6 (comment).

xvik commented

+1 (43)

@IMPinball - a port is already present in this thread. All it needs is to be adopted.

@spicyj You asked which thread. This one

+1 (44)

+1 (45)

+1 (46)

+1 (47)

db commented

+1 (48)

+1

+1

@lefessan would it be possible to share the work you've done to port flow back in November ? The version you made does work, but it is getting old now and it would be nice if others could contribute to the port.

Is a WIndows binary available ? We have a big AngularJS application and developers are adding code too fast. My office machine is WIndows 7.

@mohanr - not currently. That's why we're making a tally of how many people need it.

@mohanr there was a port done back in November 2014.
You can find it here http://www.ocamlpro.com/pub/ocpwin/flow-builds/
However, in my case, this is not an option because it's lacking features that were implemented in the master branch a few weeks after that.

+1 (51)

+1 (52)

+1 (53)

+1 (54)

@lefessan, I'm also interested if it is possible to share the work you've done to port flow back in November? If community will get the idea where to start we can try to update flow ourselves. Thank you. cc @Cellule