-
Notifications
You must be signed in to change notification settings - Fork 570
proposal: Limit support to one GOOS value (primarily for stdlib). #693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This came up when I investigated what it'd take to fix #688. I seriously considered 3 alternative fixed GOOS values to use:
Using Using Using Using Consider the following Go code in gopherjs/compiler/natives/src/syscall/syscall_unix.go Lines 57 to 74 in f7c5653
Here's the equivalent code if we targeted func naclWrite(fd int, b []byte) int {
switch fd {
case 1, 2:
printToConsole(b)
return len(b)
default:
printWarning()
return -1
}
} See how much cleaner that is? Of course, I haven't implemented everything for |
To conclude, my recommendation if this proposal is accepted is to target @neelance What do you think? |
The main reason for supporting multiple GOOS is so that Could you please list some examples of support for multiple GOOS causing overhead? Is it mainly about windows? |
I don't understand why |
Ok, I see now. It's about the syscall module, which is used to implement Normally, JavaScript is portable and can be run on any OS with I'm going to put this proposal on hold and think more about this, given the new information (well, old, but remembered now). |
In playing around with #688 it seemed life would be simpler the goroot surrogate was (nacl) libgo, which might be a good idea anyway for wasm-related reasons. It also occurs to me the syscall issue could be addressed by giving the node addon moderately more love and mandating it if you want to gohperjs test. |
Changes in this commit ensure that we can at least build supported standard library packages with GOOS=darwin. In theory, GOOS shouldn't even matter, since we always target the same platform (nodejs or browser), but for historical reasons, it does matter and we need to take extra steps to make it work. See gopherjs#693 for more details.
So long as we rely on OS-specific syscalls, we must build the package with OS-appropriate GOOS/GOARCH (see also gopherjs#693). Using runtime.GOOS here is not ideal, since it ignores environment variables, making "cross-compiling" impossible. This is not a big deal in most cases, but makes reproducing errors like in gopherjs#1027 more difficult.
I would like to revive discussion of this proposal. Now that the upstream support To be coherent with the upstream I would propose using As a proof of concept for code reuse, I hacked gopherjs build system to use |
In the Go project, an area we wanted to explore is improving experience for out-of-tree ports to reduce the need for having all ports be added in-tree. GopherJS is a compiler for an out-of-tree port. If there’s a small and reasonable change in the main repo that can help here significantly, I think it would be worth proposing and considering. However, I don’t quite understand why a change would need to happen in the Go tree. You said:
Can you elaborate on this? |
Sorry, I realize now that my original comment had a few logical leaps that are likely confusing to anyone who can't read my mind 😅 Here's my chain of reasoning:
|
I'm going to give this a go, since I suspect this will have several simplification benefits for our users, as well as for maintenance. Roughly my plan is:
At the moment I'm conducting early experiments in my own fork: https://github.com/nevkontakte/gopherjs/tree/syscall2. I'm keeping my experiment notes in https://github.com/nevkontakte/gopherjs/wiki/The-Syscall-Experiment for the time being. Suggestions/comments are welcome! |
@nevkontakte Looks good, thanks, will try to test it. following your branch. |
GopherJS will use this target going forward. The values where chosen by the following logic: - GOOS describes the targeted API environment, which is generally the same as when building wasm: both execute under a browser or nodejs. Build tag `js` is shared by GopherJS and wasm and can be used to target the general environment. - GOARCH describes the low-level emitted code, which is currently EcmaScript 5. Using `ecmascript` here differentiates from `wasm`, while not referencing GopherJS explicitly. It also leaves us a different paths for future upgrades to ES6+ by either changing GOARCH or keeping it and making this change implicit. At the same time, we use fixed js/wasm target when building standard library packages, which resolves a lot of concerns discussed in gopherjs#693. Using js/ecmascript is not feasible because it'll require us to maintain a lot more overlays and/or rewrite build tags, which leads to the exactly same outcome. This change is potentially breaking for users that may have relied on GOOS=linux in their sources. To make transition easier for them, we support using GOOS/GOARCH from environment. However, they will be only applied to the user code. Standard library will still be built with js/wasm.
GopherJS will use this target going forward. The values where chosen by the following logic: - GOOS describes the targeted API environment, which is generally the same as when building wasm: both execute under a browser or nodejs. Build tag `js` is shared by GopherJS and wasm and can be used to target the general environment. - GOARCH describes the low-level emitted code, which is currently EcmaScript 5. Using `ecmascript` here differentiates from `wasm`, while not referencing GopherJS explicitly. It also leaves us a different paths for future upgrades to ES6+ by either changing GOARCH or keeping it and making this change implicit. At the same time, we use fixed js/wasm target when building standard library packages, which resolves a lot of concerns discussed in gopherjs#693. Using js/ecmascript is not feasible because it'll require us to maintain a lot more overlays and/or rewrite build tags, which leads to the exactly same outcome. This change is potentially breaking for users that may have relied on GOOS=linux in their sources. To make transition easier for them, we support using GOOS/GOARCH from environment. However, they will be only applied to the user code. Standard library will still be built with js/wasm.
GopherJS will use this target going forward. The values where chosen by the following logic: - GOOS describes the targeted API environment, which is generally the same as when building wasm: both execute under a browser or nodejs. Build tag `js` is shared by GopherJS and wasm and can be used to target the general environment. - GOARCH describes the low-level emitted code, which is currently EcmaScript 5. Using `ecmascript` here differentiates from `wasm`, while not referencing GopherJS explicitly. It also leaves us a different paths for future upgrades to ES6+ by either changing GOARCH or keeping it and making this change implicit. At the same time, we use fixed js/wasm target when building standard library packages, which resolves a lot of concerns discussed in gopherjs#693. Using js/ecmascript is not feasible because it'll require us to maintain a lot more overlays and/or rewrite build tags, which leads to the exactly same outcome. In addition, we always set `gopherjs` build tag to make it easy to guard sources using GopherJS-specific features. This is similar to `gc` and `gccgo` build tags respective compilers set. This change is potentially breaking for users that may have relied on GOOS=linux in their sources. To make transition easier for them, we support using GOOS/GOARCH from environment. However, they will be only applied to the user code. Standard library will still be built with js/wasm.
GopherJS will use this target going forward. The values where chosen by the following logic: - GOOS describes the targeted API environment, which is generally the same as when building wasm: both execute under a browser or nodejs. Build tag `js` is shared by GopherJS and wasm and can be used to target the general environment. - GOARCH describes the low-level emitted code, which is currently EcmaScript 5. Using `ecmascript` here differentiates from `wasm`, while not referencing GopherJS explicitly. It also leaves us a different paths for future upgrades to ES6+ by either changing GOARCH or keeping it and making this change implicit. At the same time, we use fixed js/wasm target when building standard library packages, which resolves a lot of concerns discussed in gopherjs#693. Using js/ecmascript is not feasible because it'll require us to maintain a lot more overlays and/or rewrite build tags, which leads to the exactly same outcome. In addition, we always set `gopherjs` build tag to make it easy to guard sources using GopherJS-specific features. This is similar to `gc` and `gccgo` build tags respective compilers set. This change is potentially breaking for users that may have relied on GOOS=linux in their sources. To make transition easier for them, we support using GOOS/GOARCH from environment. However, they will be only applied to the user code. Standard library will still be built with js/wasm.
Hi all, it took me longer than I wished, but I think I have a pretty usable implementation in https://github.com/nevkontakte/gopherjs/tree/syscall2 I'd like to merge into the master (before I start working on Go 1.18 support). I have a couple of minor items on the TODO list, but the hard part of the work is done. Here are some of the notable changes:
While I'm polishing things up, I would like to ask everyone to try checking out my branch (https://github.com/nevkontakte/gopherjs/tree/syscall2) and trying to use that version of GopherJS with your projects. If you find any problems, please report them here. |
@nevkontakte I'm happy to report that I've switched to your syscall2 branch on a fairly large project and everything seems to work fine! |
@nevkontakte I tested out your syscall2 branch and was able to get everything running, though I did run into a roadbump. Our bindings would not load in our dev build. We serve our application in the browser with Dart Dev Compiler, which generates AMD modules and uses requirejs to load modules. Since this snippet sees that Our production build does not use requirejs and did not run into any problems loading our js. Other than that, looks great! We were able to remove |
There are environments like AMD, which expose `require()` function, but do not provide `fs` module. In such cases we should fall back to our stub (see gopherjs#693 (comment)).
@regenvanwalbeek-wf thanks for the report, it's a good catch. I've pushed a fix (note that it was a force push), could you try it again? |
@nevkontakte This fix works for us, thank you! 🚀 |
I've found a problem with one of my test suites. It's an OSS package, if you care to do your own testing/debugging: https://github.com/go-kivik/kivik With
When I switch to your
|
That's probably a package that isn't designed to build on js. You'll need to figure out which package is importing syscall and referencing those undefined types on js. I can take a look today maybe |
@flimzy this is an interesting example. The error (obviously) comes from the
Looking at the source code,
So I think Christian is correct here, this package was never designed to work with |
GopherJS will use this target going forward. The values where chosen by the following logic: - GOOS describes the targeted API environment, which is generally the same as when building wasm: both execute under a browser or nodejs. Build tag `js` is shared by GopherJS and wasm and can be used to target the general environment. - GOARCH describes the low-level emitted code, which is currently EcmaScript 5. Using `ecmascript` here differentiates from `wasm`, while not referencing GopherJS explicitly. It also leaves us a different paths for future upgrades to ES6+ by either changing GOARCH or keeping it and making this change implicit. At the same time, we use fixed js/wasm target when building standard library packages, which resolves a lot of concerns discussed in gopherjs#693. Using js/ecmascript is not feasible because it'll require us to maintain a lot more overlays and/or rewrite build tags, which leads to the exactly same outcome. In addition, we always set `gopherjs` build tag to make it easy to guard sources using GopherJS-specific features. This is similar to `gc` and `gccgo` build tags respective compilers set. This change is potentially breaking for users that may have relied on GOOS=linux in their sources. To make transition easier for them, we support using GOOS/GOARCH from environment. However, they will be only applied to the user code. Standard library will still be built with js/wasm.
There are environments like AMD, which expose `require()` function, but do not provide `fs` module. In such cases we should fall back to our stub (see gopherjs#693 (comment)).
Upstream patch submitted: otiai10/copy#75 |
@flimzy do you want to wait for otiai10/copy#75 to get merged before we merge #1111? |
No, that's not necessary. I have no idea how long that will take, and I can always use a fork of that repo in the meantime. |
In that case, I'm happy to merge as soon as I have your approval :) |
GopherJS will use this target going forward. The values where chosen by the following logic: - GOOS describes the targeted API environment, which is generally the same as when building wasm: both execute under a browser or nodejs. Build tag `js` is shared by GopherJS and wasm and can be used to target the general environment. - GOARCH describes the low-level emitted code, which is currently EcmaScript 5. Using `ecmascript` here differentiates from `wasm`, while not referencing GopherJS explicitly. It also leaves us a different paths for future upgrades to ES6+ by either changing GOARCH or keeping it and making this change implicit. At the same time, we use fixed js/wasm target when building standard library packages, which resolves a lot of concerns discussed in gopherjs#693. Using js/ecmascript is not feasible because it'll require us to maintain a lot more overlays and/or rewrite build tags, which leads to the exactly same outcome. In addition, we always set `gopherjs` build tag to make it easy to guard sources using GopherJS-specific features. This is similar to `gc` and `gccgo` build tags respective compilers set. This change is potentially breaking for users that may have relied on GOOS=linux in their sources. To make transition easier for them, we support using GOOS/GOARCH from environment. However, they will be only applied to the user code. Standard library will still be built with js/wasm.
There are environments like AMD, which expose `require()` function, but do not provide `fs` module. In such cases we should fall back to our stub (see gopherjs#693 (comment)).
The GopherJS compiler supports building output only for GOARCH=js value, and any GOOS value.
That means it will produce valid and different output for this Go package, depending on which GOOS value is used:
Of course, it also supports cross-compiling, so one can produce different outputs by doing:
I propose we limit support to just a single fixed GOOS value.
This is primarily meant to apply to the Go standard library, which we must manually apply overrides for in order to get it to build and work correctly for GOARCH=js. See https://github.com/gopherjs/gopherjs/commits/master/compiler/natives/src. However, I think we should apply for all packages for simplicity/consistency. Applying the limit to just Go stdlib but not 3rd party packages would be weird and unnecessary.
The motivation is simple. It costs a lot of developer time to support Go standard library for GopherJS. Right now, I don't think this project can afford to continue to support all GOOS values. It's an open source project, with no funding, and most of the progress is made by volunteers contributing in their spare time in after work hours.
The value gained from supporting multiple GOOS values is small. The cost is prohibitively high.
The compiler will continue to be able to (theoretically) compile for many GOOS values, we're just not going to support GOOS values other than a single one that we pick.
The text was updated successfully, but these errors were encountered: