facebook / flow

Adds static typing to JavaScript to improve developer productivity and code quality.
https://flow.org/
MIT License
22.09k stars 1.85k forks source link

Please provide Windows binaries #6

Closed StoneCypher closed 7 years ago

StoneCypher commented 9 years ago

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

prabirshrestha commented 9 years ago

+1

m90 commented 9 years ago

+1

Bartvds commented 9 years ago

+1

insin commented 9 years ago

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.

StoneCypher commented 9 years ago

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

henriknorberg commented 9 years ago

+1

stephen-gobin commented 9 years ago

+1

totty90 commented 9 years ago

+1

lefessan commented 9 years ago

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
lefessan commented 9 years ago

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

gabelevi commented 9 years ago

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 :)

totty90 commented 9 years ago

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 (:

lefessan commented 9 years ago

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 !

gabelevi commented 9 years ago

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.

cecilemuller commented 9 years ago

+1

pingec commented 9 years ago

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

koistya commented 9 years ago

+1

lefessan commented 9 years ago

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

j201 commented 9 years ago

+1

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

gabelevi commented 9 years ago

@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.

lefessan commented 9 years ago

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...

koistya commented 9 years ago

@lefessan cool! Thanks, much appreciated.

wchaowu commented 9 years ago

@lefessan cool +1

lefessan commented 9 years ago

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 !

jquense commented 9 years ago

+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

lefessan commented 9 years ago

@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 !).

pradeeproark commented 9 years ago

@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.

jquense commented 9 years ago

@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

Davidhanson90 commented 9 years ago

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.

lefessan commented 9 years ago

@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 9 years ago

@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.

Davidhanson90 commented 9 years ago

@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

woopsie commented 9 years ago

@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?

lefessan commented 9 years ago

@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.

StoneCypher commented 9 years ago

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

Daniel15 commented 9 years ago

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.

pradeeproark commented 9 years ago

@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.

Daniel15 commented 9 years ago

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

nemoo commented 9 years ago

+1

Erid commented 9 years ago

+1

wajfaj commented 9 years ago

what?

lefessan commented 9 years ago

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 ?

lefessan commented 9 years ago

@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 ':' ?

woopsie commented 9 years ago

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

lefessan commented 9 years ago

@woopsie : thanks ! It's fixed now.

futurechan commented 9 years ago

:+1:

MetaMemoryT commented 9 years ago

:+1:

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

dougwilson commented 9 years ago

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

martindanielson commented 9 years ago

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

bitplanets commented 9 years ago

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.