Skip to content
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

x/mobile/app: support all-Go app development on windows #9306

Open
crawshaw opened this issue Dec 13, 2014 · 25 comments

Comments

@crawshaw
Copy link
Contributor

commented Dec 13, 2014

The http://golang.org/x/mobile/app package lets you run all-Go apps on desktop darwin and linux with nothing more than the stock Go build. Just go get and you're programming. This is done via cgo: we ask for a window, get an OpenGL context, and map mouse events to touch events.

We should do the same for Windows. There are a few complications.

The first is by default there is C compiler for cgo on windows. On both linux and OS X we can rely on the user to install gcc/xcode because the platform makes it easy. By comparison MinGW is an extra, non-obvious step for windows users and VC++ isn't supported (and not necessarily any more obvious).

The second is there is no OpenGL. Well, there is kinda, as provided by graphics card makers, but support in particular for OpenGL ES 2 and EGL is spotty. Luckily, Chrome has this problem too and maintain an open source project implementing ES 2 and EGL for Windows on top of DirectX: https://code.google.com/p/angleproject/

I want to avoid importing angleproject directly into the mobile repository as it has several licenses and I want to keep the notices story for the Go repository simple. So we will need another repository that contains a package that links against angleproject and creates the window.

Is there any way about needing windows users to install a C compiler? Can we ship a binary .dll in a repository that is downloaded with go get? If we do, what about the cgo parts of mobile/app and mobile/gl? Can they be provided by the .dll even if we fetch it as part of a different repository? For mobile/app probably, but mobile/gl is harder.

@minux

This comment has been minimized.

Copy link
Member

commented Dec 13, 2014

you can use the syscall package to access dll exported functions without
cgo. But be aware that floating point arguments and return are not
supported.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Dec 13, 2014

Like @minux said. And yes you can download any .DLL as part of go get, but you would have to put it somewhere in your PATH to be able to use it.

@crawshaw

This comment has been minimized.

Copy link
Contributor Author

commented Dec 13, 2014

syscall.LoadLibrary looks like it would work, but it would mean generating a lot of code for the mobile/gl package. That is, something like https://github.com/golang/mobile/blob/master/gl/gldebug.go that replaces all the cgo calls with syscall.GetProcAddress+syscall.Syscall in a gl_windows.go file.

That's probably the way to go.

@minux

This comment has been minimized.

Copy link
Member

commented Dec 13, 2014

If you really want to avoid cgo on windows, that is probably the way to go. The generator
need to take care of floating point arguments and returns and probably you also need
to generate the corresponding C wrapper for functions taking floating point arguments
and returning floating point result.

That said, there does exist an easier way to avoid gcc, which I'd call frozen cgo. The idea
is that we preprocess all the cgo files, and compile the cgo.o and include it as cgo.syso
in the package directory.

This approach should work well for cases where we know the interface won't change
(for example, all the C code is statically linked in the syso file). And it also relies on the
fact windows does not support external linking. However, not supporting external linking
also means the syso can't use much C++.

The frozen cgo approach does work. As an example, given this simple cgo program:
package main
/*
int f() { return 42; }
*/
import "C"
func main() {
println(C.f())
}

First go build -work cgo.go, record the $WORK it showed.

And then create a new directory, and copy these four files into it:
cp $WORK/command-line-arguments/obj/all.o cgo$GOOS$GOARCH.syso
cp $WORK/command-line-arguments/obj/cgo_gotypes.o z_cgo_gotypes$GOOS$GOARCH.go
cp $WORK/command-line-arguments/obj/cgo_imports.go z_cgo_imports$GOOS$GOARCH.go
cp $WORK/command-line-arguments/obj/cgo.cgo1.go z_cgo$GOOS_$GOARCH.go

And go build -x inside that directory. You will see that cgo and gcc are not invoked.

This generalizes all cgo programs, just copy all.o to cgo$GOOS_$GOARCH.syso,
and all the Go files inside work directory, replace their leading underscore (go build won't build
any files with underscore as prefix) and append $GOOS$GOARCH to their base name
(we must treat all these as platform dependent).

Although this means that you need to separate windows support to separate package and
precompile for both 386 and amd64, this should be much easier than to use the syscall package
and create wrappers because all this can be automated.

This is the first time I publicly discuss this concept, hopefully it has not been proposed before. :-)

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Dec 16, 2014

@minux, I tried following your instructions, but it fails.

C:\go\path\mine\src\foo>dir
Volume in drive C has no label.
Volume Serial Number is XXXX-YYYY

Directory of C:\go\path\mine\src\foo

16/12/2014 10:36 AM

.
16/12/2014 10:36 AM ..
16/12/2014 10:12 AM 87 cgo.go
1 File(s) 87 bytes
2 Dir(s) 112,487,620,608 bytes free

C:\go\path\mine\src\foo>type cgo.go
package main

/*
int f() { return 42; }
*/
import "C"

func main() {
println(C.f())
}

C:\go\path\mine\src\foo>go build -work cgo.go
WORK=C:\DOCUME1\brainman\LOCALS1\Temp\go-build029113339

C:\go\path\mine\src\foo>set WORK=C:\DOCUME1\brainman\LOCALS1\Temp\go-build029113339

C:\go\path\mine\src\foo>copy %WORK%\command-line-arguments_obj_all.o cgo_windows_386.syso
1 file(s) copied.

C:\go\path\mine\src\foo>copy %WORK%\command-line-arguments_obj_cgo_gotypes.o z_cgo_gotypes_windows_386.go
The system cannot find the file specified.

C:\go\path\mine\src\foo>

I am also not convinced that general C code can be packaged into executable on Windows. Some C libs might be configured to be built as DLLs. Then you have to ship these DLLs as part of your app. Some C libs might rely on external libs (DLLs) (for example Microsoft C runtime or similar). Then again you have to distribute these along with your app.

Mind you, you could, probably, create DLL file in /tmp on the fly and load it on your app startup. I have never tried that, but I don't see why it won't work. Maybe anti-virus might complain ...

I am also not sure why you want to run mobile app natively on Windows desktop. I think it would be nuch more useful to be able to launch mobile app inside of some emulator that runs on Windows desktop. The emulator that creates environment that looks as close as possible to real device. Or just launch mobile app on real device.

Alex

@crawshaw

This comment has been minimized.

Copy link
Contributor Author

commented Dec 16, 2014

Configuring build environments for mobile devices is hard. For iOS, you just cannot do it on windows. For android, you need to install the SDK+NDK+Go cross compiler.

What we have right now for Mac and Linux lets you download the stock Go build, write a 15-line app and type go build. Compile+test cycles are dramatically faster than working on the real device, and the whole experience is a lot more fun. I'd like to bring that to windows users. I'm sure we can, there's just work to do.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Dec 16, 2014

Sure, lets try.

@minux

This comment has been minimized.

Copy link
Member

commented Dec 16, 2014

@alexbrainman,
the essence is that you copy all generated source files in $WORK to the new
directory.
My procedure is for tip. If you're using 1.4, then you need to adjust it
accordingly (1.4
still generates C files to be compiled by the Plan 9 C compiler.)

If you're using tip, copy all Go files in $WORK, but rename them so that
they don't have
a underscore as prefix as the go tool will ignore filenames starting with
underscore.

@minux

This comment has been minimized.

Copy link
Member

commented Dec 16, 2014

I think doing iOS development on Linux is possible, if we tried hard
enough, we might be
able to get it work on windows.

clang is definitely buildable on windows, as and ld64 are harder. The code
signing tools
are even harder. But at least it's possible to build everything on Linux.

I doubt any iOS app developer want to develop on Windows, though.

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Dec 16, 2014

@minux I am using

C:\go\path\mine\src\foo>go version
go version devel +ab96371 Mon Dec 15 01:55:29 2014 +0000 windows/386

@dmitshur

This comment has been minimized.

Copy link
Member

commented Mar 31, 2015

What we have right now for Mac and Linux lets you download the stock Go build, write a 15-line app and type go build. Compile+test cycles are dramatically faster than working on the real device, and the whole experience is a lot more fun. I'd like to bring that to windows users. I'm sure we can, there's just work to do.


Does x/mobile/gl support windows yet? (I can't remember if either Hana or I added it.) I hope it's not to hard to add, but I wouldn't want to break any gxui users on windows.

So AFAICT, no it doesn't. It doesn't seem trivial to add either. The problem is windows doesn't really have an OpenGL header that's worth using (the system one is OpenGL 1.1, which is pretty worthless). Typically, the drivers support more up to date versions of GL - GXUI has shown that most windows users have a driver that supports at least OpenGL 2.1, but the function pointers need to be obtained using something like wglGetProcAddress.

I'm not sure what the best course of action is for adding Windows support into x/mobile/gl. Really all you're going to end up with is something using GLEW or something that looks very similar to GLOW.

/cc @crawshaw @ben-clayton

It seems the end goal is to make it work very seamless on Windows, but it sounds hard to do right away.

What do you think about taking a smaller step first, getting it to work at least as well as github.com/go-gl/gl/v2.1/gl works on Windows, and then creating a new issue to improve the experience?

Doing that can be done very quickly and allow google/gxui#86 to proceed.

There are a few ways to make it happen:

  • Import and use github.com/go-gl/gl/v2.1/gl to implement the GL interface using windows build constraint.
  • Use glow (the GL bindings generator that is used to generate all go-gl/gl/... packages) to generate the implementation of GL needed for windows build constraint.
  • Similar to above, but outright copy the code of github.com/go-gl/gl/v2.1/gl to implement the GL interface using windows build constraint.
  • Other ways?
@ben-clayton

This comment has been minimized.

Copy link

commented Apr 1, 2015

I like the idea of using GLOW - I didn't realise that it was usable outside of the go-gl library.
I'm wondering if we could use GLOW to generate the GLES 2 bindings for all platforms, then wrap these with x/mobile/gl's types.
It seems like GLOW might need to add an Android branch to the procaddr.go generated code. This however is certainly doable.

@rsc rsc added this to the Unplanned milestone Apr 10, 2015

@rsc rsc removed the release-none label Apr 10, 2015

@rsc rsc changed the title mobile/app: support all-Go app development on windows x/mobile/app: support all-Go app development on windows Apr 14, 2015

@rsc rsc modified the milestones: Unreleased, Unplanned Apr 14, 2015

@rsc rsc removed repo-mobile labels Apr 14, 2015

@crawshaw crawshaw self-assigned this Aug 19, 2015

@gopherbot

This comment has been minimized.

Copy link

commented Aug 21, 2015

CL https://golang.org/cl/13745 mentions this issue.

@ip

This comment has been minimized.

Copy link

commented Aug 24, 2015

What's the problem to install GCC on Windows for end user? Can't find the link now, but official Go recommended TDM-GCC for building Go from source. It's one-click GUI installer, no configuration. Are workarounds worth the effort?

@ip

This comment has been minimized.

Copy link

commented Aug 24, 2015

@crawshaw GetProcAddress gets a string as argument, you don't need to generate 300 GetProcAddress() calls, just store function names in array and loop through it, writing addresses to another array.
I saw it's done in such way in SDL for example.
Also, you don't of course need to put DLL into PATH, because LoadLibrary recognizes full paths.

hyangah added a commit to golang/mobile that referenced this issue Aug 24, 2015
all: support go get golang.org/x/mobile/... on Windows
Fixes golang/go#12212
Workaround for golang/go#12261 until golang/go#9306 is fixed.

Change-Id: I51c1bcfc92c1553fe2132586a0234b1c1af6aeb1
Reviewed-on: https://go-review.googlesource.com/13745
Reviewed-by: David Crawshaw <crawshaw@golang.org>
@gopherbot

This comment has been minimized.

Copy link

commented Dec 9, 2015

CL https://golang.org/cl/17678 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 9, 2015

CL https://golang.org/cl/17677 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 9, 2015

CL https://golang.org/cl/17676 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 9, 2015

CL https://golang.org/cl/17675 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 9, 2015

CL https://golang.org/cl/17674 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 10, 2015

CL https://golang.org/cl/17722 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 10, 2015

CL https://golang.org/cl/17721 mentions this issue.

crawshaw added a commit to golang/exp that referenced this issue Dec 11, 2015
shiny/driver/windriver: factor out a win32 package
A Windows version of the gldriver shares a lot of common code with
the existing windriver. This CL factors it out into a new internal
pacakge, win32.

For golang/go#9306

Change-Id: If602bb42946f1df662b2529d5b277257ae7706d3
Reviewed-on: https://go-review.googlesource.com/17676
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
crawshaw added a commit to golang/exp that referenced this issue Dec 11, 2015
win32: mouse drag and wheel support
For golang/go#9306

Change-Id: Ib6a7b23288bebebb5e111221338323a2692187b0
Reviewed-on: https://go-review.googlesource.com/17721
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
crawshaw added a commit to golang/exp that referenced this issue Dec 11, 2015
win32: keyboard support
For golang/go#9306

Change-Id: I2e4029e261307e08748b7088c495512247f10d21
Reviewed-on: https://go-review.googlesource.com/17722
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
crawshaw added a commit to golang/mobile that referenced this issue Dec 14, 2015
gl: factor cgo types out of gl.go
This allows a subsequent CL to introduce windows support by directly
calling an ANGLE dll.

For golang/go#9306

Change-Id: I7dbe8f2b77b9e2c744f0d848f716ee4448916fe7
Reviewed-on: https://go-review.googlesource.com/17674
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
crawshaw added a commit to golang/mobile that referenced this issue Dec 14, 2015
gl: add windows implementation based on ANGLE
ANGLE is an open source project that implements OpenGL ES on top of
DirectX. It is used by Chrome to implement WebGL:

	https://github.com/google/angle

It can be compiled into libGLESv2.dll/libEGL.dll and used directly
from Go. This CL includes the changes necessary to the gl package
to use ANGLE.

For the EGL changes, I intend to get x/exp/shiny/driver/gldriver
working, and then make x/mobile/app use it when compiling for
GOOS=windows. (The dependency on shiny's screen package will only
hold when building for desktop OSs.)

For golang/go#9306

Change-Id: I01cb39bc8b56547584b7992eab437bd7ed0312b5
Reviewed-on: https://go-review.googlesource.com/17675
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
crawshaw added a commit to golang/mobile that referenced this issue Dec 14, 2015
gl: remove data race on cStrings
Each GL context is used serially, so make the map context-specific.

For golang/go#9306

Change-Id: Ic8261795312bf404f765a9ae8969468f4d170dae
Reviewed-on: https://go-review.googlesource.com/17772
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
crawshaw added a commit to golang/mobile that referenced this issue Dec 14, 2015
all: windows build tags
For golang/go#9306

Change-Id: Ia8778f5b371371d103c55c12606257ee7ca45fd4
Reviewed-on: https://go-review.googlesource.com/17778
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
@gopherbot

This comment has been minimized.

Copy link

commented Dec 14, 2015

CL https://golang.org/cl/17777 mentions this issue.

@gopherbot

This comment has been minimized.

Copy link

commented Dec 14, 2015

CL https://golang.org/cl/17810 mentions this issue.

crawshaw added a commit to golang/mobile that referenced this issue Dec 15, 2015
gl: download ANGLE if necessary
For golang/go#9306

Change-Id: Ibb469d843d2bddeaa3690c59bc9ad532ea3473f7
Reviewed-on: https://go-review.googlesource.com/17810
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
crawshaw added a commit to golang/mobile that referenced this issue Dec 15, 2015
app: add shiny backend
Combined with the outstanding shiny CLs and prebuilt ANGLE dlls in the
right place, this makes it possible to run example/basic on a windows
machine.

Eventually this shiny backend will also replace the app package's
custom darwin_amd64 and linux_x11 backends.

For golang/go#9306

Change-Id: Ia4bf9a85b9d903d79cee36abb470a0ad57f09f36
Reviewed-on: https://go-review.googlesource.com/17777
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
gopherbot pushed a commit to golang/exp that referenced this issue Jan 12, 2016
shiny/driver/gldriver: windows support
For golang/go#9306

Change-Id: Ib6a7b23288bebebb5e1d53917d67af72692187b0
Reviewed-on: https://go-review.googlesource.com/17677
Reviewed-by: Nigel Tao <nigeltao@golang.org>
@gonutz

This comment has been minimized.

Copy link

commented Apr 30, 2016

Although this is an old issue I still want to point you to my Direct3D9 wrapper.
It still needs a C compiler (it was tested with MinGW 32 and 64) but you do not have to install any extra libraries or drivers for it to work.
I am also thinking about providing a version of the wrapper that does not use CGo, similar to what w32 does but I have yet to find out how to do that. Until then, only installing MinGW seems OK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
10 participants
You can’t perform that action at this time.