glfw: Use os.UserConfigDir for GLFW DLL instead of temporary directories

As of this change, Ebiten requries Go 1.13 due to os.UserConfigDir.

Fixes #1393
This commit is contained in:
Hajime Hoshi 2020-11-01 16:54:58 +09:00
parent 335c11960a
commit 5b8370298a
8 changed files with 71 additions and 36 deletions

View File

@ -7,7 +7,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
go: ['1.12.17', '1.13.15', '1.14.10', '1.15.3'] go: ['1.13.15', '1.14.10', '1.15.3']
name: Test with Go ${{ matrix.go }} on ${{ matrix.os }} name: Test with Go ${{ matrix.go }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:

2
go.mod
View File

@ -1,6 +1,6 @@
module github.com/hajimehoshi/ebiten/v2 module github.com/hajimehoshi/ebiten/v2
go 1.12 go 1.13
require ( require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200707082815-5321531c36a2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200707082815-5321531c36a2

View File

@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build go1.12 // +build go1.13
package ebiten package ebiten
// Ebiten forces to use Go 1.12 or later, since // Ebiten forces to use Go 1.13 or later, since
// 1) Between Go 1.10 and Go 1.11, ioutil.TempFile's behavior is different. Ebiten forces the Go version in order to avoid confusion. (#777) // 1) Between Go 1.10 and Go 1.11, ioutil.TempFile's behavior is different. Ebiten forces the Go version in order to avoid confusion. (#777)
// 2) FuncOf in syscall/js is defined as of Go 1.12. // 2) FuncOf in syscall/js is defined as of Go 1.12.
// 3) os.UserConfigDir is defined as of Go 1.13.
const __EBITEN_REQUIRES_GO_VERSION_1_12_OR_LATER__ = true const __EBITEN_REQUIRES_GO_VERSION_1_13_OR_LATER__ = true

View File

@ -18,7 +18,7 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
) )
var _ = __EBITEN_REQUIRES_GO_VERSION_1_12_OR_LATER__ var _ = __EBITEN_REQUIRES_GO_VERSION_1_13_OR_LATER__
func init() { func init() {
graphicscommand.SetGraphicsDriver(uiDriver().Graphics()) graphicscommand.SetGraphicsDriver(uiDriver().Graphics())

View File

@ -17,7 +17,11 @@
package main package main
import ( import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -107,11 +111,10 @@ func run() error {
return err return err
} }
in, err := os.Open(dll) in, err := ioutil.ReadFile(dll)
if err != nil { if err != nil {
return err return err
} }
defer in.Close()
out, err := os.Create(fmt.Sprintf("glfwdll_windows_%s.go", arch)) out, err := os.Create(fmt.Sprintf("glfwdll_windows_%s.go", arch))
if err != nil { if err != nil {
@ -120,10 +123,27 @@ func run() error {
defer out.Close() defer out.Close()
// As the file name already specified the build environment, buildtags are not requried. // As the file name already specified the build environment, buildtags are not requried.
if err := file2byteslice.Write(out, in, true, "", "glfw", "glfwDLLCompressed"); err != nil { if err := file2byteslice.Write(out, bytes.NewReader(in), true, "", "glfw", "glfwDLLCompressed"); err != nil {
return err return err
} }
// Dump the hash
hashout, err := os.Create(fmt.Sprintf("glfwdllhash_windows_%s.go", arch))
if err != nil {
return err
}
defer hashout.Close()
hash := sha256.Sum256(in)
if _, err := fmt.Fprintf(hashout, `// Code generated by gen.go. DO NOT EDIT.
package glfw
const glfwDLLHash = "%s"
`, hex.EncodeToString(hash[:])); err != nil {
return err
}
// Clean up the files.
for _, o := range objs { for _, o := range objs {
if err := os.Remove(o); err != nil { if err := os.Remove(o); err != nil {
return err return err

View File

@ -0,0 +1,5 @@
// Code generated by gen.go. DO NOT EDIT.
package glfw
const glfwDLLHash = "93ce68219cb0e920a0b9f04a38bbeff104f530a643fd0a792215572525869f90"

View File

@ -0,0 +1,5 @@
// Code generated by gen.go. DO NOT EDIT.
package glfw
const glfwDLLHash = "9297f0b5337eb17f170398f4e027f59a8daf502cb45cff9b74b615d70d8369c2"

View File

@ -19,8 +19,8 @@ import (
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"path/filepath"
"unsafe" "unsafe"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@ -28,7 +28,6 @@ import (
type dll struct { type dll struct {
d *windows.LazyDLL d *windows.LazyDLL
path string
procs map[string]*windows.LazyProc procs map[string]*windows.LazyProc
} }
@ -47,37 +46,45 @@ func (d *dll) call(name string, args ...uintptr) uintptr {
return r return r
} }
func createTempDLL(content io.Reader) (string, error) {
f, err := ioutil.TempFile("", "glfw.*.dll")
if err != nil {
return "", err
}
defer f.Close()
fn := f.Name()
if _, err := io.Copy(f, content); err != nil {
return "", err
}
return fn, nil
}
func loadDLL() (*dll, error) { func loadDLL() (*dll, error) {
f, err := gzip.NewReader(bytes.NewReader(glfwDLLCompressed)) cachedir, err := os.UserCacheDir()
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer f.Close()
fn, err := createTempDLL(f) dir := filepath.Join(cachedir, "ebiten")
if err != nil { if err := os.MkdirAll(dir, 0755); err != nil {
return nil, err return nil, err
} }
fn := filepath.Join(dir, glfwDLLHash+".dll")
if _, err := os.Stat(fn); err != nil {
if !os.IsNotExist(err) {
return nil, err
}
f, err := gzip.NewReader(bytes.NewReader(glfwDLLCompressed))
if err != nil {
return nil, err
}
defer f.Close()
out, err := os.Create(fn)
if err != nil {
return nil, err
}
defer out.Close()
if _, err := io.Copy(out, f); err != nil {
return nil, err
}
if err := out.Sync(); err != nil {
return nil, err
}
}
return &dll{ return &dll{
d: windows.NewLazyDLL(fn), d: windows.NewLazyDLL(fn),
path: fn,
}, nil }, nil
} }
@ -85,9 +92,6 @@ func (d *dll) unload() error {
if err := windows.FreeLibrary(windows.Handle(d.d.Handle())); err != nil { if err := windows.FreeLibrary(windows.Handle(d.d.Handle())); err != nil {
return err return err
} }
if err := os.Remove(d.path); err != nil {
return err
}
return nil return nil
} }