blob: 80612f5321b01ec4cd436abf4dd50c61c6def0d1 [file] [log] [blame]
/* 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)
}
}
}