blob: 64c99caa25b96ef6485de755a29610b285701fd9 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// 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.
package main
import (
"flag"
"fmt"
"net"
"os"
"strings"
"time"
"android.googlesource.com/platform/tools/gpu/cc"
. "android.googlesource.com/platform/tools/gpu/maker"
)
var targetOS = flag.String("targetos", HostOS, "target OS to build")
func main() { Run() }
const (
GPURoot = "android.googlesource.com/platform/tools/gpu"
// Request to send to replayd to have it shutdown. Note we do not use the
// value in replay/protocol/connection_type.go to avoid introducing a
// dependency on the code we are trying to build.
ReplaydShutdownRequest = 2
)
var (
gapirpath = Path(gpusrc, "cc/gapir")
gapiipath = Path(gpusrc, "cc/gapii")
gapiiwinpath = Path(gpusrc, "cc/gapii/windows")
gapiiosxpath = Path(gpusrc, "cc/gapii/osx")
cppcoder = Path(gpusrc, "cc/gapic/coder")
javabase = Path(Paths.Root, "../")
javapaths = []string{
Path(javabase, "base/rpclib/src/main/java/com/android/tools/rpclib"),
Path(javabase, "base/rpclib/src/test/java/com/android/tools/rpclib"),
Path(javabase, "adt/idea/android/src/com/android/tools/idea/editors/gfxtrace"),
}
gpusrc = GoSrcPath(GPURoot)
Tools struct {
Embed Entity
Apic Entity
Codergen Entity
Gapit Entity
}
Apps struct {
Gapis Entity
Gapir Entity
Gapid Entity
}
)
func init() {
Register(func() {
// Install rules for the build tools
Tools.Embed = GoInstall(GPURoot + "/tools/embed")
Tools.Apic = GoInstall(GPURoot + "/api/apic")
Tools.Codergen = GoInstall(GPURoot + "/tools/codergen")
Tools.Gapit = GoInstall(GPURoot + "/tools/gapit")
List("gapit").DependsOn(Tools.Gapit)
List("tools").DependsStruct(Tools)
// All the embed rules
embedCopyright := Embed(Path(gpusrc, "tools/copyright"))
embedCodergen := Embed(Path(gpusrc, "tools/codergen/template"))
Creator(Tools.Apic).DependsOn(embedCopyright)
Creator(Tools.Codergen).DependsOn(embedCopyright, embedCodergen)
// All the apic rules
GfxApi("test", "gfxapi_test.api")
GfxApi("gles", "gles.api")
// The codergen rule
Codergen("codergen", "--go", "--java", javabase, "-cpp", cppcoder, GPURoot+"/...")
//
List("code").DependsOn("embed", "apic", "codergen")
// The native code rules
cctargets := []string{*targetOS}
if os.Getenv("ANDROID_NDK_ROOT") != "" {
cctargets = append(cctargets, []string{"android-arm", "android-arm64"}...)
}
cc.Graph(cctargets)
Apps.Gapir = Virtual("cc:replayd")
Creator(Apps.Gapir).DependsOn(ShutdownReplayd(), "code")
Creator("cc:spy").DependsOn("code")
// The testing rules
gotest := GoTest(GPURoot + "/...")
// Runtime dependencies
Creator(Tools.Gapit).DependsOn("cc:spy")
List("runtime").DependsOn(Apps.Gapir, "cc:spy")
Creator(gotest).DependsOn("code", "runtime")
if *targetOS == HostOS {
List("test").DependsOn("go_test", "cc_test")
} else {
List("test").DependsOn("go_test")
}
// The main binary rules
Apps.Gapis = GoInstall(GPURoot + "/server/gapis")
Creator(Apps.Gapis).DependsOn("code")
Apps.Gapid = GoInstall(GPURoot + "/_experimental/client/gapid")
Creator(Apps.Gapid).DependsOn("code")
List("apps").DependsStruct(Apps)
// Application launchers
Command(Apps.Gapis).Creates(Virtual("gapis")).DependsOn(Apps.Gapir)
Command(Apps.Gapid, "--gxuidebug").Creates(Virtual("gapid")).DependsOn(Apps.Gapis, "runtime")
// Utilties
GoRun(Path(gpusrc, "tools/clean_generated/main.go"), gpusrc).Creates(Virtual("clean_gpu"))
GoRun(Path(gpusrc, "tools/clean_generated/main.go"), javapaths...).Creates(Virtual("clean_java"))
GoRun(Path(gpusrc, "tools/copyright/copyright/main.go"), "-o", gpusrc).Creates(Virtual("copyright")).DependsOn(embedCopyright)
// The default rules
List(Default).DependsOn("apps", "test")
})
}
func Embed(path string) Entity {
out := File(path, "embed.go")
args := []string{"--out", out.Name()}
files := FilesOf(path, func(i os.FileInfo) bool {
return !i.IsDir() && !strings.HasSuffix(i.Name(), ".go") && !strings.HasSuffix(i.Name(), ".md")
})
for _, f := range files {
args = append(args, f.Name())
}
s := Command(Tools.Embed, args...).Creates(out)
for _, f := range files {
s.DependsOn(f)
}
List("embed").DependsOn(out)
return out
}
func Apic(path string, api string, template string) {
dst := Dir(path)
a := File(api)
t := File(template)
_, apiname := PathSplit(api)
_, templatename := PathSplit(template)
deps := File(Paths.Deps, fmt.Sprintf("%v_%v.deps", apiname, templatename))
s := Command(Tools.Apic,
"template",
"--dir", dst.Name(),
"--deps", deps.Name(),
a.Name(), t.Name()).DependsOn(a, t, dst, Dir(Paths.Deps))
s.UseDepsFile(deps)
List("apic").DependsOn(deps)
}
func Codergen(name string, args ...string) {
Command(Tools.Codergen, args...).Creates(Virtual(name)).DependsOn("apic").Access(GoPkgResources)
}
func ShutdownReplayd() Entity {
e := Virtual("shutdownreplayd")
NewStep(func(*Step) error {
for _, endpoint := range []string{"localhost:9283", "localhost:9284"} {
const maxRetries = 10
for i := 0; i < maxRetries; i++ {
conn, err := net.Dial("tcp", endpoint)
if err != nil {
// Assume this means there is no replayd
break
}
defer conn.Close()
msg := []byte{ReplaydShutdownRequest}
n, err := conn.Write(msg)
if err != nil {
return fmt.Errorf("Failed to send shutdown request to Replayd %v", err)
}
if n != len(msg) {
return fmt.Errorf("Failed to send shutdown request to Replayd (only sent %v bytes", n)
}
if i == maxRetries-1 {
return fmt.Errorf("Replayd at %v did not die", endpoint)
}
time.Sleep(100 * time.Millisecond)
}
}
return nil
}).Creates(e)
return e
}
func GfxApi(pkg string, api string) {
out := Path(gpusrc, "gfxapi", pkg)
in := Path(out, api)
templates := Path(gpusrc, "gfxapi", "templates")
istest := strings.HasSuffix(pkg, "test")
// go code
Apic(out, in, Path(templates, "api.go.tmpl"))
Apic(out, in, Path(templates, "replay_writer.go.tmpl"))
Apic(out, in, Path(templates, "schema.go.tmpl"))
Apic(out, in, Path(templates, "state_mutator.go.tmpl"))
if istest {
return
}
// gapir code
Apic(gapirpath, in, Path(templates, "gfx_api.cpp.tmpl"))
Apic(gapirpath, in, Path(templates, "gfx_api.h.tmpl"))
// gapii code
Apic(gapiipath, in, Path(templates, "api_exports.cpp.tmpl"))
Apic(gapiipath, in, Path(templates, "api_imports.cpp.tmpl"))
Apic(gapiipath, in, Path(templates, "api_imports.h.tmpl"))
Apic(gapiipath, in, Path(templates, "api_spy.h.tmpl"))
Apic(gapiipath, in, Path(templates, "api_types.h.tmpl"))
Apic(gapiiwinpath, in, Path(templates, "opengl32_exports.def.tmpl"))
Apic(gapiiwinpath, in, Path(templates, "opengl32_resolve.cpp.tmpl"))
Apic(gapiiwinpath, in, Path(templates, "opengl32_x64.asm.tmpl"))
Apic(gapiiosxpath, in, Path(templates, "opengl_framework_exports.cpp.tmpl"))
}