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

Adjusted link flags for Mac OS X #41

Merged
merged 1 commit into from
Aug 5, 2013
Merged

Adjusted link flags for Mac OS X #41

merged 1 commit into from
Aug 5, 2013

Conversation

lloeki
Copy link
Contributor

@lloeki lloeki commented Aug 2, 2013

First, glfw3 builds as libglfw3 by default, so we link against that.
Then, we have to link a few frameworks, to get rid of missing symbols.

glfw3 homebrew PR pending: Homebrew/legacy-homebrew#21620

FWIW, the glfw -> glfw3 move is probably valid for Linux too, but I can't test that right now, so not included.

First, glfw3 builds as libglfw3 by default, so we link against that.
Then, we have to link a few frameworks, to get rid of missing symbols.
@dmitshur
Copy link
Member

dmitshur commented Aug 3, 2013

How has it worked fine before?

@tapir
Copy link
Member

tapir commented Aug 3, 2013

By default GLFW does not build the dynamic libraries. And confusingly enough the library names are "libglfw.so" and "libglfw3.a".

I don't have experience with Mac but right now we're only supporting the dynamic library. Can you check if it's the case with your patch?

Also see #39 for a similar discussion for Linux.

@lloeki
Copy link
Contributor Author

lloeki commented Aug 3, 2013

I tested it by linking against the static lib (this is IMHO more in the spirit of go).
No issues encountered building and running the trivial example in go-gl/glfw3 README.md. I even copied the resulting binary to another Mac with no trace of go nor glfw, and it Just Worked.
It seems there's no facility to build both static and dylib in glfw's cmake build system (it's currently an either/or) so I favored static in the homebrew formula for now. Also I strived to allow both glfw 2.x and glfw3 to be installed side by side (really useful, and the point of both the different static naming and the dylib version symlinks)
Will try to link dynamically later, especially using flags like -l:libssl.so.1.0.0
On 3 Aug 2013 11:59, "Coşku Baş" <notifications@github.com (mailto:notifications@github.com)> wrote:

By default GLFW does not build the dynamic libraries. And confusingly enough the library names are "libglfw.so" and "libglfw3.a".
I don't have experiance with Mac but right now we're only supporting the dynamic library. Can you check if it's the case with your patch?
Als osee #39 (#39) for a similar discussion for Linux.


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

@tapir
Copy link
Member

tapir commented Aug 3, 2013

Most linux distributions only ship the dynamic library. Windows binaries from glfw.org has both dynamic and static libraries. So in the name of consistency I would like to keep it to dynamic for Mac as well.

Also, if we use static libraries, people who use binaries for glfw will have the burden to install all other needed libraries such as Xorg-devel in linux.

To me it seems easier to link against the dynamic library but I'm willing to hear the arguments for static linking.

@lloeki
Copy link
Contributor Author

lloeki commented Aug 5, 2013

Most linux distributions do ship with the (dynamic only) library as a package, so to distribute an application on Linux for an end user, one would build a package that depends on the given package, and it would be pulled in upon install. Going dynamic is really the most straightforward way under Linux.

The typical approach is different on Mac OS X. As there is no (end-user oriented) package manager, apps are self-contained bundles that include their dependencies. Of course, someone downloading a self-contained app will certainly not want to download an app he expects to be self-contained to require manual installation of glfw. First, just as app bundles are preferred to standalone executable binaries, frameworks are preferred to dylibs. Either way, dylib paths are hardcoded into the binaries. The OSX linker provides a method to encode a relative path to the dylibs and frameworks dyld variable (more like a placeholder) named @executable_path, allowing one to bundle frameworks and dynamic libraries inside the app container, so that wherever the app is placed, the dylib can be found. This feature is obscure enough that it is handled automagically by Xcode, and I can't find a way to use it straight from ld (or cc with -Wl, and contrary to rpath which won't help us there anyway), let alone try this as a cgo flag inside the go-gl/glfw3 package and all its potential implications.

So, AFAIK, the static library is currently the most straightforward way under Mac OS X as soon as you think about distributing the final binary. Anyway bundling the dylib defeats the whole purpose of dynamic libraries so one might as well go static.

I personally see no particular reason to try to maintain a form of symmetry at this level across both platforms, since they have their own idiosyncrasies. Still, suggestions as to how to cleanly bundle a dylib in an app bundle are otherwise welcome.

@tapir
Copy link
Member

tapir commented Aug 5, 2013

There are other purposes of bundling a dynamic library such as end-user being able to replace it _but_ I'm OK with your approach. I've never used a Mac so I'm in no position to disagree with what you're saying.
Thanks.

Edit: Shall we mention brew.sh in the README? Is it easy to get the glfw3 framework with it?

tapir added a commit that referenced this pull request Aug 5, 2013
Adjusted link flags for Mac OS X
@tapir tapir merged commit 23b0c2f into go-gl:master Aug 5, 2013
@evantandersen
Copy link

Static libraries don't work with go on mac, it causes every symbol to be linked to 0x0 without generating any errors. See this bug discussion for more details: https://code.google.com/p/go/issues/detail?id=4868

The only way to run glfw with go is to use dynamic libraries.

@tapir
Copy link
Member

tapir commented Sep 8, 2013

@lloeki can you comment on this and #47
thanks

@lloeki
Copy link
Contributor Author

lloeki commented Sep 8, 2013

An example run:

$ go version
go1.1.2 darwin/amd64
$ brew install https://raw.github.com/lloeki/homebrew/0b6859d34bc7fe6883c4e6770c3f28e73ea8c171/Library/Formula/glfw3.rb
$ go get github.com/go-gl/glfw3
$ curl https://github.com/go-gl/glfw3 \
  | perl -e '$_ = do { local $/; <STDIN> }; /<pre>(.*)<\/pre>/s && (($code = $1) =~ s/<.+?>//sg) && print $code' \
  > example.go
$ go build example.go
$ otool -l example | grep glfw    # returns nothing
$ ./example    # works
$ scp example foo.local:
$ ssh foo.local ./example     # with a remote session open
SIGILL: illegal instruction
PC=0x4071607
signal arrived during cgo execution

github.com/go-gl/glfw3._Cfunc_glfwInit(0xc20003d150)
    github.com/go-gl/glfw3/_obj/_cgo_defun.c:401 +0x2f
github.com/go-gl/glfw3.Init(0x40d8d88)
    github.com/go-gl/glfw3/_obj/_cgo_gotypes.go:568 +0x1c
main.main()
    /Users/lloeki/Workspace/projects/go-opengl/example.go:15 +0x2a

goroutine 2 [syscall]:

goroutine 3 [runnable]:
rax     0x1
rbx     0x151003f0
rcx     0x7fff8547d782
rdx     0x151002a8
rdi     0x7fff5fbff4f0
rsi     0x200001d80
rbp     0x7fff5fbff500
rsp     0x7fff5fbff4f0
r8      0x15100260
r9      0x4035b44f
r10     0x7fff71ae7f01
r11     0x206
r12     0xcd4ec081c82d
r13     0xcd4e89660df0
r14     0x151002a0
r15     0xffffffffffffffff
rip     0x4071607
rflags  0x10206
cs      0x2b
fs      0x0
gs      0x0

Which I think is not the same issue, since it's a SIGILL, not a SIGSEGV the symbols are there with a non-0x0 address. Case in point: nm -a example | grep -i glfw (which lists all symbols) returns the following

Note: foo.local has no trace whatsoever of any glfw.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 8, 2013

I swear I made it work previously, but I was building on another machine: I very recently migrated from a '09 MacBook Pro to a brand new Retina 13". So instead of trying on another machine, I tried on the same one, but:

$ rm -Rf pkg/ src/ bin/
$ brew remove glfw3
$ ./example

and voilà, it works.

To wit: foo.local above is a '10 iMac, which has a Core 2 Duo, just like my old '09 MBP, whereas my new machine has a Core i5. SIGILL makes sense if Go decided to emit i5 optimized code that could not run on the C2D.

Of note: static linking requires Go 1.1.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 8, 2013

if Go decided

Go, or the compiler used to build libglfw3 (which might just be more likely).

@lloeki
Copy link
Contributor Author

lloeki commented Sep 8, 2013

Confirmed: I built libglfw3 on a C2D, copied it to my i5, rebuilt go-go/glfw3 and example.go, copied it to the clean iMac, and ran it with no issues.

TL;DR: static linking works.

BTW, the code.google.com issue mentioned above refers to someone trying to build go code against the static lib way before go 1.1, hence with no static library support.

@evantandersen
Copy link

I know the google code issue is old, but it still seems to be affecting me. Here is my run:

$ go version
go version go1.1.2 darwin/amd64
$ go get github.com/go-gl/glfw3
$ go build TDPro
$ ./TDPro 
SIGSEGV: segmentation violation
PC=0x0
signal arrived during cgo execution

github.com/go-gl/glfw3._Cfunc_glfwInit(0x1)
    github.com/go-gl/glfw3/_obj/_cgo_defun.c:401 +0x2f
github.com/go-gl/glfw3.Init(0xdb180)
    github.com/go-gl/glfw3/_obj/_cgo_gotypes.go:568 +0x1c
main.main()
    /Users/evantandersen/Documents/golang/src/TDPro/TDPro.go:68 +0x27

goroutine 2 [syscall]:

goroutine 3 [runnable]:
rax     0x8a3af
rbx     0x587e50
rcx     0x587e50
rdx     0x587de8
rdi     0x587e50
rsi     0x1b4520
rbp     0x7fff5fbffaa0
rsp     0x7fff5fbffa88
r8      0x1
r9      0xf8c30
r10     0x3
r11     0xf3f80
r12     0x14cb49fb5c7f7
r13     0x1809030099920
r14     0x1321e8bacfcd9400
r15     0x0
rip     0x0
rflags  0x10206
cs      0x2b
fs      0x0
gs      0x0

I'm building go-gl/glfw against libglfw3.a. This seems to be identical to the issue in the google bug report.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 9, 2013

Let's look at this deeper then.

How did you install/build go, and libglfw3? Is the issue reproducible with the go-gl/glfw3 example?

Which OS, Xcode version and C compiler are you using? Did you install Apple's gcc-42 (which doesn't work anymore with recent Xcode)

@evantandersen
Copy link

Installed go with installer package from google code.
Downloaded libglfw3 source from website, make && make install
The issue is reproducible with the example.
10.8.4 & Xcode 4.6.3

I have not installed any different versions of gcc. The current version on my system is 4.2.1.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 9, 2013

I replicated the bug: it is caused by the official golang installer release. There is no such problem with homebrew's built from source version (which I would recommend anyway).

@lloeki
Copy link
Contributor Author

lloeki commented Sep 9, 2013

glfw3 is getting some love from homebrew in the homebrew-versions tap, which should be merged shortly.

I updated the formula to build dynamically as glfw3, which will definitely solve the schizophrenic link flag problem on that front.

Following the merge, installing glfw3 will be like:

brew tap homebrew/versions
brew install homebrew/versions/glfw3 --static

Skip the --static flag if you want the dylib instead.

@dmitshur
Copy link
Member

Ok, that explains everything (what I wrote above and #47).

When doing cmake . -DBUILD_SHARED_LIBS=ON, you end up getting libglfw.dylib, so -lglfw is needed. But when doing cmake ., it generates libglfw3.a so -lglfw3 is correct in that case.

I've always used shared libraries on OS X, but I would prefer to use static if it works. I'll try that now.

@dmitshur
Copy link
Member

Ok, I'm having the same issue as @charliehorse55 when trying the static linking approach. go-gl/glfw3 builds successfully (an only 4 KB increase in size over the shared library version; 465 KB vs. 461 KB). But running at trivial go glfw3 program gives:

Desktop $ go run simple.go 
SIGSEGV: segmentation violation
PC=0x0
signal arrived during cgo execution

github.com/go-gl/glfw3._Cfunc_glfwInit(0xc20003e150)
    github.com/go-gl/glfw3/_obj/_cgo_defun.c:401 +0x2f
github.com/go-gl/glfw3.Init(0x64)
    github.com/go-gl/glfw3/_obj/_cgo_gotypes.go:569 +0x1c
main.main()
    /Users/Dmitri/Desktop/simple.go:15 +0x1c

goroutine 2 [syscall]:

goroutine 3 [runnable]:
rax     0x6c1ed
rbx     0x560f28
rcx     0x560f28
rdx     0x560ec0
rdi     0x560f28
rsi     0x1275a0
rbp     0x7fff5fbff9c0
rsp     0x7fff5fbff9a8
r8      0xc200061158
r9      0x46
r10     0x355e2f28
r11     0x6ae8e396
r12     0x11983287bdcc3
r13     0x1431028c3d0d0
r14     0x13270dfed7757600
r15     0x0
rip     0x0
rflags  0x10202
cs      0x2b
fs      0x0
gs      0x0
exit status 2

I'm on go version go1.1.2 darwin/amd64, OS X 10.8.5.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 25, 2013

Yeah, upstream made naming decisions that end up being confusing as hell. I made the glfw3 homebrew formula always build as libglfw3, so that it can be installed alongside glfw2 (which builds as libglfw). In any case, glfw3 names everything as 'glfw3' in terms of files (and glfw in terms of code), except the dylib.

See the homebrew-versions tap (specifically this PR)

@dmitshur
Copy link
Member

@lloeki How are you able to build and run statically built glfw3 go programs?

@lloeki
Copy link
Contributor Author

lloeki commented Sep 25, 2013

@shurcooL did you use the official golang package (from code.google.com)? if so, it's broken, and you should give homebrew a shot.

@dmitshur
Copy link
Member

Edit: Never mind, I misread what you said.

Yes, I used the official golang package. I'll try building Go from source then.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 25, 2013

To sum up:

$ brew install go
$ brew tap homebrew/versions
$ brew install --static glfw3
$ go get github.com/go-gl/glfw3

If you want to redistribute the binaries, be sure to use:

$ brew install --build-bottle --static glfw3

Else it'll build with something like --march=native and it won't run on lower end CPUs.

@tapir
Copy link
Member

tapir commented Sep 25, 2013

Is there a golang issue opened for their installer bug?
Shall we include this small homebrew tutorial in the readme?

@lloeki
Copy link
Contributor Author

lloeki commented Sep 25, 2013

There's the aforementioned issue, but its current status 'retracted' might make it invisible. I'll create a new one.

Since I see this as the mist straightforward way to install go, glfw3 and g-gl/glfw3, I'd say yes, it should be in the README.

@dmitshur
Copy link
Member

Ok, I can finally confirm what @lloeki has been saying. I tried to install go1.1.2 from source, but because I already have Xcode 5 which breaks it, I couldn't. Instead I installed go1.2rc1 from source and I was able to successfully statically link with libglfw3.a and run a program. :D So both shared and static libraries are supported on OS X, at the very least.

However, the build + run times seem to be significantly worse than when doing shared library. If this is confirmed to be true, then we should probably try to offer the option for both types of linking so the user can decide what's better for them. For instance, I would take faster build time of shared library, but stick with static for creating release binaries. But this needs to be verified first.

Edit: Yeah, I think my build+run time calculation was faulty, thankfully.

@lloeki
Copy link
Contributor Author

lloeki commented Sep 25, 2013

However, the build + run times seem to be significantly worse than when doing shared library

I did not notice anything particular on that front:

Static:

$ time (go build test_glfw3.go)
real    0m0.286s
user    0m0.221s
sys 0m0.064s

Dynamic:

$ time (go build test_glfw3.go)
real    0m0.274s
user    0m0.214s
sys 0m0.058s

For instance, I would take faster build time of shared library, but stick with static for creating release binaries.

Anyway, no problem, with the consistent naming scheme we don't have to touch go-gl/glfw source code:

$ brew install glfw3   # installs dylib
$ go get github.com/go-gl/glfw3
$ go build whatever
... release time!
$ rm -rf pkg src
$ brew remove glfw3
$ brew install --build-bottle --static glfw3   # installs static lib, compiled for penryn
$ go get github.com/go-gl/glfw3
$ go build whatever

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants