Install .cfh and static lib under $GOPATH/pkg. * Install C static archive into $GOPATH/pkg/$PACKAGE/_lib/ * Install .cfh headers into a main include directory, also under `pkg`.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/063b499e Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/063b499e Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/063b499e Branch: refs/heads/master Commit: 063b499ec701883acffac02f8db9a2b42ae679b3 Parents: cd5158c Author: Marvin Humphrey <[email protected]> Authored: Mon Nov 10 09:11:03 2014 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Sun Mar 15 19:01:11 2015 -0700 ---------------------------------------------------------------------- compiler/go/build.go | 59 ++++++++++++++++++++++++++++++++++---- compiler/go/cfc/cfc.go | 38 +++++++++++++++++++++++++ runtime/go/build.go | 69 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 158 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/063b499e/compiler/go/build.go ---------------------------------------------------------------------- diff --git a/compiler/go/build.go b/compiler/go/build.go index d4a585b..80612f5 100644 --- a/compiler/go/build.go +++ b/compiler/go/build.go @@ -20,11 +20,13 @@ 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" @@ -34,11 +36,24 @@ 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() { @@ -118,23 +133,57 @@ func test() { 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 } - libPath := path.Join(buildDir, "libcfc.a") + installedLibDir := path.Join(installDir, "_lib") content := fmt.Sprintf( - "// Auto-generated by build.go, specifying absolute path to static lib.\n"+ + "// Auto-generated by build.go\n"+ "package cfc\n"+ "// #cgo CFLAGS: -I%s/../include -I%s/../src -I%s\n"+ - "// #cgo LDFLAGS: %s\n"+ - "import \"C\"\n", - buildDir, buildDir, buildDir, libPath) + "// #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) } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/063b499e/compiler/go/cfc/cfc.go ---------------------------------------------------------------------- diff --git a/compiler/go/cfc/cfc.go b/compiler/go/cfc/cfc.go index 6533a0a..fb38bfb 100644 --- a/compiler/go/cfc/cfc.go +++ b/compiler/go/cfc/cfc.go @@ -22,9 +22,46 @@ package cfc // #include <stdlib.h> import "C" +import "os" +import "path" +import "path/filepath" import "runtime" +import "strings" import "unsafe" +// Return the path of the main include directory holding clownfish parcel and +// header files. +func MainIncludeDir() string { + return mainIncDir +} + +type CFCError struct { + mess string +} + +func (e CFCError) Error() string { + return e.mess +} + +// Given a package name for a Clownfish parcel with Go bindings, return the +// install path for its C static archive. +// +// TODO: It would be better if we could embed the C archive contents within +// the installed Go archive. +func InstalledLibPath(packageName string) (string, error) { + goPathDirs := filepath.SplitList(os.Getenv("GOPATH")) + if len(goPathDirs) == 0 { + return "", CFCError{"GOPATH environment variable not set"} + } + packageParts := strings.Split(packageName, "/") + filename := "lib" + packageParts[len(packageParts)-1] + ".a" + parts := []string{goPathDirs[0], "pkg"} + parts = append(parts, runtime.GOOS+"_"+runtime.GOARCH) + parts = append(parts, packageParts...) + parts = append(parts, "_lib", filename) + return path.Join(parts...), nil +} + func DoStuff() { hierarchy := NewHierarchy("autogen") hierarchy.Build() @@ -46,6 +83,7 @@ func NewHierarchy(dest string) Hierarchy { destCString := C.CString(dest) defer C.free(unsafe.Pointer(destCString)) obj := Hierarchy{C.CFCHierarchy_new(destCString)} + obj.AddIncludeDir(mainIncDir) runtime.SetFinalizer(&obj, (*Hierarchy).RunDecRef) return obj } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/063b499e/runtime/go/build.go ---------------------------------------------------------------------- diff --git a/runtime/go/build.go b/runtime/go/build.go index 269290b..8411504 100644 --- a/runtime/go/build.go +++ b/runtime/go/build.go @@ -20,11 +20,14 @@ package main import "flag" import "fmt" +import "io" import "io/ioutil" import "log" import "os" import "os/exec" import "path" +import "path/filepath" +import "strings" import "runtime" import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/compiler/go/cfc" @@ -36,11 +39,17 @@ var charmonyH string = "charmony.h" var buildDir string var buildGO string var configGO string +var installedLibPath string func init() { _, buildGO, _, _ = runtime.Caller(1) buildDir = path.Dir(buildGO) configGO = path.Join(buildDir, "clownfish", "config.go") + var err error + installedLibPath, err = cfc.InstalledLibPath(packageName) + if err != nil { + log.Fatal(err) + } } func main() { @@ -124,6 +133,7 @@ func prep() { runCFC() runCommand("make", "-j", "static") writeConfigGO() + runCommand("go", "build", packageName) } func build() { @@ -136,25 +146,78 @@ func test() { runCommand("go", "test", packageName) } +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 installHeaders() { + coreDir := "../core" + incDir := cfc.MainIncludeDir() + doInstall := func(source string, info os.FileInfo, err error) error { + if strings.HasSuffix(source, ".cfp") || strings.HasSuffix(source, ".cfh") { + dest := path.Join(incDir, strings.TrimPrefix(source, coreDir)) + destDir := path.Dir(dest) + if _, err := os.Stat(destDir); os.IsNotExist(err) { + err = os.MkdirAll(destDir, 0755) + if err != nil { + log.Fatalf("Can't create dir '%s': %s", destDir, err) + } + } + os.Remove(dest) + copyFile(source, dest) + } + return nil + } + filepath.Walk("../core", doInstall) +} + +func installStaticLib() { + tempLibPath := path.Join(buildDir, "libclownfish.a") + destDir := path.Dir(installedLibPath) + if _, err := os.Stat(destDir); os.IsNotExist(err) { + err = os.MkdirAll(destDir, 0755) + if err != nil { + log.Fatalf("Can't create dir '%s': %s", destDir, err) + } + } + os.Remove(installedLibPath) + copyFile(tempLibPath, installedLibPath) +} + func install() { prep() runCommand("go", "install", packageName) + installHeaders() + installStaticLib() } func writeConfigGO() { if current(buildGO, configGO) { return } - libPath := path.Join(buildDir, "libcfish.a") content := fmt.Sprintf( "// Auto-generated by build.go, specifying absolute path to static lib.\n"+ "package clownfish\n"+ "// #cgo CFLAGS: -I%s/../core\n"+ "// #cgo CFLAGS: -I%s\n"+ "// #cgo CFLAGS: -I%s/autogen/include\n"+ - "// #cgo LDFLAGS: %s\n"+ + "// #cgo LDFLAGS: -L%s\n"+ + "// #cgo LDFLAGS: -lclownfish\n"+ "import \"C\"\n", - buildDir, buildDir, buildDir, libPath) + buildDir, buildDir, buildDir, buildDir) ioutil.WriteFile(configGO, []byte(content), 0666) }
