| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /* Build "script" for cfc (Apache Clownfish compiler). |
| */ |
| package main |
| |
| import "flag" |
| import "fmt" |
| import "io" |
| import "io/ioutil" |
| import "log" |
| import "os" |
| import "os/exec" |
| import "path" |
| import "path/filepath" |
| import "runtime" |
| |
| var packageName string = "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/compiler/go/cfc" |
| var charmonizerC string = "../common/charmonizer.c" |
| var charmonizerEXE string = "charmonizer" |
| var charmonyH string = "charmony.h" |
| var buildDir string |
| var buildGO string |
| var configGO string |
| var installDir string |
| var cfIncludeDir string |
| |
| func init() { |
| _, buildGO, _, _ = runtime.Caller(1) |
| buildDir = path.Dir(buildGO) |
| configGO = path.Join(buildDir, "cfc", "config.go") |
| |
| // Compute include dir for clownfish headers. |
| goPathDirs := filepath.SplitList(os.Getenv("GOPATH")) |
| if len(goPathDirs) == 0 { |
| log.Fatal("GOPATH environment variable not set") |
| } |
| commonDir := path.Join(goPathDirs[0], "pkg", |
| runtime.GOOS+"_"+runtime.GOARCH, "git-wip-us.apache.org", "repos", |
| "asf", "lucy-clownfish.git") |
| cfIncludeDir = path.Join(commonDir, "_include") |
| installDir = path.Join(commonDir, "compiler", "go", "cfc") |
| } |
| |
| func main() { |
| os.Chdir(buildDir) |
| flag.Parse() |
| action := "build" |
| args := flag.Args() |
| if len(args) > 0 { |
| action = args[0] |
| } |
| switch action { |
| case "build": |
| build() |
| case "clean": |
| clean() |
| case "test": |
| test() |
| case "install": |
| install() |
| default: |
| log.Fatalf("Unrecognized action specified: %s", action) |
| } |
| } |
| |
| func current(orig, dest string) bool { |
| destInfo, err := os.Stat(dest) |
| if err != nil { |
| if os.IsNotExist(err) { |
| // If dest doesn't exist, we're not current. |
| return false |
| } else { |
| log.Fatalf("Unexpected stat err: %s", err) |
| } |
| } |
| |
| // If source is newer than dest, we're not current. |
| origInfo, err := os.Stat(orig) |
| if err != nil { |
| log.Fatalf("Unexpected: %s", err) |
| } |
| return destInfo.ModTime().Before(origInfo.ModTime()) |
| } |
| |
| func runCommand(name string, args ...string) { |
| command := exec.Command(name, args...) |
| command.Stdout = os.Stdout |
| command.Stderr = os.Stderr |
| err := command.Run() |
| if err != nil { |
| log.Fatal(err) |
| } |
| } |
| |
| func configure() { |
| if !current(charmonizerC, charmonizerEXE) { |
| runCommand("cc", "-o", charmonizerEXE, charmonizerC) |
| } |
| if !current(charmonizerEXE, charmonyH) { |
| runCommand("./charmonizer", "--cc=cc", "--enable-c", "--host=go", |
| "--enable-makefile", "--", "-std=gnu99", "-O2") |
| } |
| } |
| |
| func prep() { |
| configure() |
| runCommand("make", "-j", "static") |
| writeConfigGO() |
| } |
| |
| func build() { |
| prep() |
| runCommand("go", "build", packageName) |
| } |
| |
| func test() { |
| prep() |
| runCommand("go", "test", packageName) |
| } |
| |
| func makePath(dir string) { |
| if _, err := os.Stat(dir); os.IsNotExist(err) { |
| err = os.MkdirAll(dir, 0755) |
| if err != nil { |
| log.Fatalf("Can't create dir '%s': %s", dir, err) |
| } |
| } |
| } |
| |
| func copyFile(source, dest string) { |
| sourceFH, err := os.Open(source) |
| if err != nil { |
| log.Fatal(err) |
| } |
| defer sourceFH.Close() |
| destFH, err := os.Create(dest) |
| if err != nil { |
| log.Fatal(err) |
| } |
| defer destFH.Close() |
| _, err = io.Copy(destFH, sourceFH) |
| if err != nil { |
| log.Fatalf("io.Copy from %s to %s failed: %s", source, dest, err) |
| } |
| } |
| |
| func install() { |
| prep() |
| runCommand("go", "install", packageName) |
| makePath(cfIncludeDir) |
| installedLibDir := path.Join(installDir, "_lib") |
| makePath(installedLibDir) |
| installedLibPath := path.Join(installedLibDir, "libcfc.a") |
| copyFile("libcfc.a", installedLibPath) |
| } |
| |
| func writeConfigGO() { |
| if current(buildGO, configGO) { |
| return |
| } |
| installedLibDir := path.Join(installDir, "_lib") |
| content := fmt.Sprintf( |
| "// Auto-generated by build.go\n"+ |
| "package cfc\n"+ |
| "// #cgo CFLAGS: -I%s/../include -I%s/../src -I%s\n"+ |
| "// #cgo LDFLAGS: -L%s\n"+ |
| "// #cgo LDFLAGS: -L%s\n"+ |
| "// #cgo LDFLAGS: -lcfc\n"+ |
| "import \"C\"\n"+ |
| "var mainIncDir string = \"%s\"\n", |
| buildDir, buildDir, buildDir, buildDir, installedLibDir, cfIncludeDir) |
| ioutil.WriteFile(configGO, []byte(content), 0666) |
| } |
| |
| func clean() { |
| if _, err := os.Stat(charmonizerEXE); os.IsNotExist(err) { |
| return |
| } |
| fmt.Println("Cleaning") |
| if _, err := os.Stat("Makefile"); !os.IsNotExist(err) { |
| runCommand("make", "clean") |
| } |
| cleanables := []string{charmonizerEXE, charmonyH, "Makefile", configGO} |
| for _, file := range cleanables { |
| err := os.Remove(file) |
| if err == nil { |
| fmt.Println("Removing", file) |
| } else if !os.IsNotExist(err) { |
| log.Fatal(err) |
| } |
| } |
| } |