ebiten/internal/glfw/gen.go
Hajime Hoshi 8b775cf0dd internal/glfw: Add a new build tag ebitenexternaldll to requrie external DLLs
Embedding a DLL file and extrating it on the fly can be problematic.
The application might be unexpectedly recognized as a virus by some
virus checkers.

To mitigate this issue, Ebiten adds a new build mode `ebitenexternaldll`
which prevents Ebiten from embedding DLL files. Instead, the application
will require DLL files for GLFW.

Closes #1832
2021-10-14 02:44:25 +09:00

173 lines
3.4 KiB
Go

// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build ignore
// +build ignore
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"github.com/hajimehoshi/file2byteslice"
"golang.org/x/sync/errgroup"
)
type arch string
const (
archAmd64 arch = "amd64"
arch386 arch = "386"
)
func (a arch) gcc() string {
switch a {
case archAmd64:
return "x86_64-w64-mingw32-gcc"
case arch386:
return "i686-w64-mingw32-gcc"
default:
panic("not reached")
}
}
func c2o(str string) string {
return strings.TrimSuffix(filepath.Base(str), ".c") + ".o"
}
func execCommand(name string, args ...string) error {
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
func run() error {
srcs, err := filepath.Glob(filepath.Join("glfw", "src", "*.c"))
if err != nil {
return err
}
sort.Strings(srcs)
for _, arch := range []arch{archAmd64, arch386} {
g := errgroup.Group{}
for _, s := range srcs {
s := s
g.Go(func() error {
args := []string{
"-c",
"-o",
c2o(s),
"-D_GLFW_WIN32",
"-D_GLFW_BUILD_DLL",
"-Iglfw/deps/mingw",
"-g",
"-Os",
s,
}
if err := execCommand(arch.gcc(), args...); err != nil {
return err
}
return nil
})
}
if err := g.Wait(); err != nil {
return err
}
objs := []string{}
for _, s := range srcs {
objs = append(objs, c2o(s))
}
dll := fmt.Sprintf("glfw_windows_%s.dll", arch)
args := []string{
"-shared",
"-o",
dll,
"-Wl,--no-insert-timestamp",
}
args = append(args, objs...)
args = append(args, "-lopengl32", "-lgdi32")
if err := execCommand(arch.gcc(), args...); err != nil {
return err
}
dllf, err := os.Open(dll)
if err != nil {
return err
}
defer dllf.Close()
hash := sha256.New()
in := io.TeeReader(dllf, hash)
out, err := os.Create(fmt.Sprintf("glfwdll_windows_%s.go", arch))
if err != nil {
return err
}
defer out.Close()
// As the file name already specified the build environment, buildtags are not requried.
if err := file2byteslice.Write(out, in, true, "!ebitenexternaldll", "glfw", "glfwDLLCompressed"); err != nil {
return err
}
// Dump the hash
hashout, err := os.Create(fmt.Sprintf("glfwdllhash_windows_%s.go", arch))
if err != nil {
return err
}
defer hashout.Close()
hashsum := hash.Sum(nil)
if _, err := fmt.Fprintf(hashout, `// Code generated by gen.go. DO NOT EDIT.
//go:build !ebitenexternaldll
// +build !ebitenexternaldll
package glfw
const glfwDLLHash = "%s"
`, hex.EncodeToString(hashsum[:])); err != nil {
return err
}
// Clean up the files.
for _, o := range objs {
if err := os.Remove(o); err != nil {
return err
}
}
}
if err := execCommand("gofmt", "-s", "-w", "."); err != nil {
return err
}
return nil
}
func main() {
if err := run(); err != nil {
panic(err)
}
}