diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ab4fe860..0b3fa91f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,6 +3,10 @@ name: CI
on: [push, pull_request]
+defaults:
+ run:
+ shell: bash
+
jobs:
build-linux:
runs-on: ubuntu-latest
@@ -10,6 +14,9 @@ jobs:
image: centos/devtoolset-7-toolchain-centos7
options: --user 0
steps:
+ - name: Install Git
+ run: yum install -y git
+
- name: Install CMake
env:
version: 3.17.3
@@ -25,29 +32,21 @@ jobs:
- name: Get sources
uses: actions/checkout@v2
- - name: Cache FBS-C-Bridge build dir
- id: fbs-bridge-cache
+ - name: Cache Deps
uses: actions/cache@v2
- env:
- cache-name: cache-fbs-c-bridge-build
with:
- path: ./third_party/flatbuffers-c-bridge/cmake-build/*.a
- key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('./third_party/flatbuffers-c-bridge/*') }}
+ path: ./third_party/*
+ key: ${{ runner.os }}-deps-${{ hashFiles('./third_party/*') }}
- - name: Build FBS-C-Bridge
- if: steps.fbs-bridge-cache.outputs.cache-hit != 'true'
- run: ./third_party/flatbuffers-c-bridge/build.sh
-
- - name: Build
- run: |
- cd cmd/objectbox-generator
- go build
+ - run: make
+ - run: make test-depend
+ - run: make test
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: objectbox-generator-${{ runner.os }}
- path: cmd/objectbox-generator/objectbox-generator
+ path: objectbox-generator
build:
strategy:
@@ -57,30 +56,23 @@ jobs:
- macos-10.15
runs-on: ${{ matrix.os }}
steps:
+ - run: git config --global core.autocrlf false
+
- name: Get sources
uses: actions/checkout@v2
- - name: Cache FBS-C-Bridge build dir
- id: fbs-bridge-cache
+ - name: Cache Deps
uses: actions/cache@v2
- env:
- cache-name: cache-fbs-c-bridge-build
with:
- path: ./third_party/flatbuffers-c-bridge/cmake-build/*.a
- key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('./third_party/flatbuffers-c-bridge/*') }}
+ path: ./third_party/*
+ key: ${{ runner.os }}-deps-${{ hashFiles('./third_party/*') }}
- - name: Build FBS-C-Bridge
- if: steps.fbs-bridge-cache.outputs.cache-hit != 'true'
- shell: bash
- run: ./third_party/flatbuffers-c-bridge/build.sh
-
- - name: Build
- run: |
- cd cmd/objectbox-generator
- go build
+ - run: make
+ - run: make test-depend
+ - run: make test
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: objectbox-generator-${{ runner.os }}
- path: cmd/objectbox-generator/objectbox-generator*
+ path: objectbox-generator*
diff --git a/Makefile b/Makefile
index 154164a4..4ee3d369 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,11 @@
# Default target executed when no arguments are given to make.
default_target: all
-.PHONY: default_target help clean depend build test
+.PHONY: default_target help clean depend build test test-depend
help: ## Show this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
-
-
#==============================================================================
all: depend build
@@ -23,6 +21,13 @@ clean: ## Clean previous builds
rm -f objectbox-generator
rm -f objectbox-generator.exe
rm -rf third_party/flatbuffers-c-bridge/cmake-build
+ ./third_party/flatcc/clean.sh
+ ./third_party/objectbox-c/clean.sh
depend: ## Build dependencies
./third_party/flatbuffers-c-bridge/build.sh
+
+test-depend: depend ## Build test dependencies
+ ./third_party/flatcc/build.sh
+ ./third_party/objectbox-c/get-objectbox-c.sh
+
diff --git a/internal/generator/flatbuffersc/fbsc_test.go b/internal/generator/flatbuffersc/fbsc_test.go
index 31f10a65..1d3b724d 100644
--- a/internal/generator/flatbuffersc/fbsc_test.go
+++ b/internal/generator/flatbuffersc/fbsc_test.go
@@ -65,6 +65,7 @@ func TestFbsSchemaParser(t *testing.T) {
_, err = file.WriteString(testSchema)
assert.NoErr(t, err)
+ assert.NoErr(t, file.Close())
schema, err = ParseSchemaFile(file.Name())
assert.NoErr(t, err)
@@ -123,6 +124,7 @@ func TestFbsFlatc(t *testing.T) {
_, err = file.WriteString(testSchema)
assert.NoErr(t, err)
+ assert.NoErr(t, file.Close())
code, err = ExecuteFlatc([]string{"--go", "-o", outDir, file.Name()})
assert.NoErr(t, err)
diff --git a/test/build/c-compiler.go b/test/build/c-compiler.go
new file mode 100644
index 00000000..89706c90
--- /dev/null
+++ b/test/build/c-compiler.go
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 ObjectBox Ltd. All rights reserved.
+ * https://objectbox.io
+ *
+ * This file is part of ObjectBox Generator.
+ *
+ * ObjectBox Generator is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * ObjectBox Generator is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ObjectBox Generator. If not, see .
+ */
+
+package build
+
+import (
+ "testing"
+
+ "github.com/objectbox/objectbox-generator/test/assert"
+ "github.com/objectbox/objectbox-generator/test/cmake"
+)
+
+// Check verifies the C/C++ objectbox test code can be compiled - whether the required libraries are available.
+func CanCompileObjectBoxCCpp(t *testing.T, repoRoot string, cpp, required bool) bool {
+ var err error
+
+ var includeDirs = IncludeDirs(repoRoot)
+ var libDirs = LibDirs(repoRoot)
+
+ // check objectbox lib
+ if cpp {
+ err = cmake.LibraryExists("objectbox", []string{"objectbox-cpp.h"}, includeDirs, libDirs)
+ } else {
+ err = cmake.LibraryExists("objectbox", []string{"objectbox.h"}, includeDirs, libDirs)
+ }
+ assert.NoErr(t, err)
+
+ // check flatbuffers library availability
+ if cpp {
+ // Note: we don't need flatbuffers library explicitly, it's part of objectbox at the moment.
+ err = cmake.LibraryExists("", []string{"flatbuffers/flatbuffers.h"}, includeDirs, libDirs)
+ } else {
+ err = cmake.LibraryExists("flatccrt", []string{"stddef.h", "flatcc/flatcc.h", "flatcc/flatcc_builder.h"}, includeDirs, libDirs)
+ }
+
+ if required {
+ assert.NoErr(t, err)
+ } else if err != nil {
+ t.Logf("C/C++ compilation not available because %s", err)
+ return false
+ }
+ return true
+}
diff --git a/test/build/conf.go b/test/build/conf.go
new file mode 100644
index 00000000..8b627126
--- /dev/null
+++ b/test/build/conf.go
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 ObjectBox Ltd. All rights reserved.
+ * https://objectbox.io
+ *
+ * This file is part of ObjectBox Generator.
+ *
+ * ObjectBox Generator is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * ObjectBox Generator is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ObjectBox Generator. If not, see .
+ */
+
+package build
+
+import "path"
+
+const flatbuffersDir = "third_party/flatbuffers-c-bridge/third_party/flatbuffers"
+const flatccDir = "third_party/flatcc"
+const objectBoxCDir = "third_party/objectbox-c"
+
+func IncludeDirs(repoRoot string) []string {
+ var result []string
+ result = append(result, path.Join(repoRoot, flatbuffersDir, "include"))
+ result = append(result, path.Join(repoRoot, flatccDir, "include"))
+ result = append(result, path.Join(repoRoot, objectBoxCDir, "include"))
+ return result
+}
+
+func LibDirs(repoRoot string) []string {
+ var result []string
+ result = append(result, path.Join(repoRoot, objectBoxCDir, "lib"))
+ result = append(result, path.Join(repoRoot, flatccDir, "lib"))
+ return result
+}
diff --git a/test/cmake/cmake.go b/test/cmake/cmake.go
new file mode 100644
index 00000000..1770b244
--- /dev/null
+++ b/test/cmake/cmake.go
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 ObjectBox Ltd. All rights reserved.
+ * https://objectbox.io
+ *
+ * This file is part of ObjectBox Generator.
+ *
+ * ObjectBox Generator is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * ObjectBox Generator is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ObjectBox Generator. If not, see .
+ */
+
+// package cmake provides tools to create, configure and build C & C++ projects using CMake
+package cmake
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "text/template"
+)
+
+// Cmake contains all configuration necessary to configure and build a CMake project
+type Cmake struct {
+ // Configs required for CMakeLists.txt
+ Name string // Executable name
+ IsCpp bool
+ Standard int // CMAKE_C/CXX_STANDARD
+ Files []string
+ IncludeDirs []string
+ LinkLibs []string // Library names or full paths
+ LinkDirs []string // Where should the linker look for libraries
+ Generator string
+
+ // Build configuration
+ SourceDir string
+ ConfDir string
+ BuildDir string
+
+ tempRoot string
+}
+
+// CreateTempDirs creates temporary directories for conf and build dir
+func (cmake *Cmake) CreateTempDirs() error {
+ if len(cmake.tempRoot) != 0 {
+ return errors.New("temp root is already set")
+ }
+
+ tempRoot, err := ioutil.TempDir("", cmake.Name+"cmake")
+ if err != nil {
+ return err
+ }
+
+ buildDir, err := createTempDir(tempRoot, "build")
+ confDir, err2 := createTempDir(tempRoot, "conf")
+
+ if err != nil || err2 != nil {
+ os.RemoveAll(cmake.tempRoot)
+ if err != nil {
+ return err
+ }
+ return err2
+ }
+
+ cmake.tempRoot = tempRoot
+ cmake.BuildDir = buildDir
+ cmake.ConfDir = confDir
+
+ if len(cmake.SourceDir) == 0 {
+ cmake.SourceDir = cmake.ConfDir
+ }
+ return nil
+}
+
+func createTempDir(parent, name string) (string, error) {
+ var path = filepath.Join(parent, name)
+ if err := os.Mkdir(path, 0700); err != nil {
+ return "", err
+ }
+ return path, nil
+}
+
+func (cmake *Cmake) RemoveTempDirs() error {
+ if len(cmake.SourceDir) == 0 {
+ cmake.SourceDir = cmake.ConfDir
+ }
+ return os.RemoveAll(cmake.tempRoot)
+}
+
+// WriteCMakeListsTxt writes cmake specification to file and returns the file name.
+func (cmake *Cmake) WriteCMakeListsTxt() error {
+ // open the file, overwrite if it exists
+ file, err := os.OpenFile(filepath.Join(cmake.ConfDir, "CMakeLists.txt"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ writer := bufio.NewWriter(file)
+ if err := cmakeListsTpl.Execute(writer, cmake); err != nil {
+ return err
+ }
+
+ return writer.Flush()
+}
+
+func (cmake *Cmake) GetCMakeListsTxt() (string, error) {
+ var b bytes.Buffer
+ writer := bufio.NewWriter(&b)
+ if err := cmakeListsTpl.Execute(writer, cmake); err != nil {
+ return "", err
+ } else if err = writer.Flush(); err != nil {
+ return "", err
+ }
+ return string(b.Bytes()), nil
+}
+
+var cmakeListsTpl = template.Must(template.New("CMakeLists.txt").
+ Funcs(template.FuncMap{
+ "Join": func(ss []string) string {
+ switch len(ss) {
+ case 0:
+ return ""
+ case 1:
+ return filepath.ToSlash(ss[0])
+ default:
+ var result string
+ for _, s := range ss {
+ result = result + "\n\t" + filepath.ToSlash(s)
+ }
+ return result
+ }
+ },
+ }).
+ Parse(`
+cmake_minimum_required(VERSION 3.0)
+{{if .Standard}}set(CMAKE_C{{if .IsCpp}}XX{{end}}_STANDARD {{.Standard}}){{end}}
+project({{.Name}} C{{if .IsCpp}}XX{{end}})
+
+add_executable(${PROJECT_NAME} {{Join .Files}})
+{{if .IncludeDirs}}target_include_directories(${PROJECT_NAME} PRIVATE {{Join .IncludeDirs}}){{end}}
+{{if .LinkLibs}}target_link_libraries(${PROJECT_NAME} PRIVATE {{Join .LinkLibs}}){{end}}
+{{if .LinkDirs}}target_link_directories(${PROJECT_NAME} PRIVATE {{Join .LinkDirs}}){{end}}
+`))
+
+// Configure runs cmake configuration step.
+func (cmake *Cmake) Configure() ([]byte, []byte, error) {
+ if len(cmake.Generator) == 0 && runtime.GOOS == "windows" {
+ // Using MinGW because MSVC doesn't support linking to .dll - app is supposed to load them on runtime
+ cmake.Generator = "MinGW Makefiles"
+ }
+
+ if len(cmake.Generator) > 0 {
+ return cmakeExec(cmake.BuildDir, cmake.ConfDir, "-G", cmake.Generator)
+ } else {
+ return cmakeExec(cmake.BuildDir, cmake.ConfDir)
+ }
+}
+
+// Configure runs cmake build step.
+func (cmake *Cmake) Build() ([]byte, []byte, error) {
+ return cmakeExec(cmake.SourceDir, "--build", cmake.BuildDir)
+}
+
+func cmakeExec(cwd string, args ...string) (stdOut []byte, stdErr []byte, err error) {
+ var cmd = exec.Command("cmake", args...)
+ cmd.Dir = cwd
+ stdOut, err = cmd.Output()
+ if ee, ok := err.(*exec.ExitError); ok {
+ stdErr = ee.Stderr
+ }
+ return
+}
diff --git a/test/cmake/libcheck.go b/test/cmake/libcheck.go
new file mode 100644
index 00000000..1c3b6231
--- /dev/null
+++ b/test/cmake/libcheck.go
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 ObjectBox Ltd. All rights reserved.
+ * https://objectbox.io
+ *
+ * This file is part of ObjectBox Generator.
+ *
+ * ObjectBox Generator is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * ObjectBox Generator is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ObjectBox Generator. If not, see .
+ */
+
+package cmake
+
+import (
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+)
+
+// LibraryExists tries to compile a simple program linking to the given library
+func LibraryExists(name string, includeFiles, includeDirs, linkDirs []string) error {
+ build := Cmake{
+ Name: "check-" + name,
+ IsCpp: true,
+ Standard: 11,
+ Files: []string{"main.cpp"},
+ IncludeDirs: includeDirs,
+ LinkDirs: linkDirs,
+ }
+ if err := build.CreateTempDirs(); err != nil {
+ return err
+ }
+ defer build.RemoveTempDirs()
+
+ if len(name) > 0 {
+ build.LinkLibs = []string{name}
+ }
+
+ if err := build.WriteCMakeListsTxt(); err != nil {
+ return err
+ }
+
+ { // write main.cpp
+ mainPath := filepath.Join(build.SourceDir, build.Files[0])
+ var mainSrc string
+ if len(includeFiles) > 0 {
+ for _, inc := range includeFiles {
+ mainSrc = mainSrc + "#include <" + inc + ">\n"
+ }
+ }
+ mainSrc = mainSrc + "\nint main(){ return 0; }\n\n"
+ if err := ioutil.WriteFile(mainPath, []byte(mainSrc), 0600); err != nil {
+ return err
+ }
+ }
+
+ if stdOut, stdErr, err := build.Configure(); err != nil {
+ return fmt.Errorf("cmake configuration failed: \n%s\n%s\n%s", stdOut, stdErr, err)
+ }
+
+ if stdOut, stdErr, err := build.Build(); err != nil {
+ return fmt.Errorf("cmake build failed: \n%s\n%s\n%s", stdOut, stdErr, err)
+ }
+
+ return nil
+}
diff --git a/test/cmake/libcheck_test.go b/test/cmake/libcheck_test.go
new file mode 100644
index 00000000..f9402609
--- /dev/null
+++ b/test/cmake/libcheck_test.go
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 ObjectBox Ltd. All rights reserved.
+ * https://objectbox.io
+ *
+ * This file is part of ObjectBox Generator.
+ *
+ * ObjectBox Generator is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * ObjectBox Generator is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ObjectBox Generator. If not, see .
+ */
+
+package cmake_test
+
+import (
+ "runtime"
+ "testing"
+
+ "github.com/objectbox/objectbox-generator/test/assert"
+ "github.com/objectbox/objectbox-generator/test/cmake"
+)
+
+func TestLibExists(t *testing.T) {
+ if testing.Short() {
+ t.SkipNow()
+ }
+
+ err := cmake.LibraryExists("nonsense", nil, nil, nil)
+ assert.Err(t, err)
+
+ err = cmake.LibraryExists("", []string{"non-existent-lib/include.h"}, nil, nil)
+ assert.Err(t, err)
+
+ if runtime.GOOS == "windows" {
+ err = cmake.LibraryExists("", []string{"array"}, nil, nil)
+ } else {
+ err = cmake.LibraryExists("stdc++", []string{"array"}, nil, nil)
+ }
+ assert.NoErr(t, err)
+}
diff --git a/test/comparison/c-helper.go b/test/comparison/c-helper.go
index efeb87d7..6404ea11 100644
--- a/test/comparison/c-helper.go
+++ b/test/comparison/c-helper.go
@@ -20,37 +20,34 @@
package comparison
import (
- "bufio"
- "bytes"
"io/ioutil"
"os"
- "os/exec"
"path"
"path/filepath"
"testing"
- "text/template"
"github.com/objectbox/objectbox-generator/internal/generator"
- cgenerator "github.com/objectbox/objectbox-generator/internal/generator/c"
+ "github.com/objectbox/objectbox-generator/internal/generator/c"
"github.com/objectbox/objectbox-generator/test/assert"
+ "github.com/objectbox/objectbox-generator/test/build"
+ "github.com/objectbox/objectbox-generator/test/cmake"
)
-var cmakeListsTpl = template.Must(template.New("cmake").Parse(`
-cmake_minimum_required(VERSION 3.0)
-{{if .Cpp}}
-set(CMAKE_CXX_STANDARD 11)
-{{else}}
-set(CMAKE_C_STANDARD 99)
-{{end}}
-project(compilation-test {{if not .Cpp}}C{{end}})
+type cTestHelper struct {
+ cpp bool
+ canCompile bool
+}
-add_executable(${PROJECT_NAME} {{.Main}})
-target_include_directories(${PROJECT_NAME} PRIVATE {{.Include}})
-target_link_libraries(${PROJECT_NAME} objectbox)
-`))
+func (h *cTestHelper) init(t *testing.T, conf testSpec) {
+ if !testing.Short() {
+ var mandatory = h.cpp // we require cpp compilation to be available at the moment
+ if _, isCI := os.LookupEnv("CI"); isCI {
+ t.Log("CI environment variable defined. Compilation support is mandatory.")
+ mandatory = true
+ }
-type cTestHelper struct {
- cpp bool
+ h.canCompile = build.CanCompileObjectBoxCCpp(t, repoRoot(t), h.cpp, mandatory)
+ }
}
func (h cTestHelper) generatorFor(t *testing.T, conf testSpec, sourceFile string, genDir string) generator.CodeGenerator {
@@ -65,40 +62,49 @@ func (cTestHelper) prepareTempDir(t *testing.T, conf testSpec, srcDir, tempDir,
}
func (h cTestHelper) build(t *testing.T, conf testSpec, dir string, expectedError error, errorTransformer func(err error) error) {
- includeDir, err := filepath.Abs(dir) // main.c/cpp will include generated headers from here
- assert.NoErr(t, err)
+ if !h.canCompile {
+ t.Skip("Compilation not available")
+ }
- tempRoot, err := ioutil.TempDir("", "objectbox-generator-test-build")
+ includeDir, err := filepath.Abs(dir) // main.c/cpp will include generated headers from here
assert.NoErr(t, err)
- defer os.RemoveAll(tempRoot)
- buildDir := path.Join(tempRoot, "build")
- cmakeConfDir := path.Join(tempRoot, "conf") // using "conf" dir to write CMakeLists.txt and main.c/cpp
- assert.NoErr(t, os.Mkdir(buildDir, 0700))
- assert.NoErr(t, os.Mkdir(cmakeConfDir, 0700))
-
- mainFile := path.Join(cmakeConfDir, "main.c")
- if h.cpp {
- mainFile = path.Join(cmakeConfDir, "main.cpp")
+ cmak := cmake.Cmake{
+ Name: "compilation-test",
+ IsCpp: h.cpp,
+ IncludeDirs: append(build.IncludeDirs(repoRoot(t)), includeDir),
+ LinkDirs: build.LibDirs(repoRoot(t)),
+ LinkLibs: []string{"objectbox"},
+ }
+ assert.NoErr(t, cmak.CreateTempDirs())
+ defer cmak.RemoveTempDirs()
+
+ var mainFile string
+ if cmak.IsCpp {
+ cmak.Standard = 11
+ mainFile = path.Join(cmak.ConfDir, "main.cpp")
+ } else {
+ cmak.Standard = 99
+ mainFile = path.Join(cmak.ConfDir, "main.c")
+ cmak.LinkLibs = append(cmak.LinkLibs, "flatccrt")
}
- { // write CMakeLists.txt to the conf dir
- var tplArguments = struct {
- Cpp bool
- Ext string
- Include string
- Main string
- }{h.cpp, conf.generatedExt, includeDir, mainFile}
-
- var b bytes.Buffer
- writer := bufio.NewWriter(&b)
- assert.NoErr(t, cmakeListsTpl.Execute(writer, tplArguments))
- assert.NoErr(t, writer.Flush())
- assert.NoErr(t, ioutil.WriteFile(path.Join(cmakeConfDir, "CMakeLists.txt"), b.Bytes(), 0600))
+ cmak.Files = append(cmak.Files, mainFile)
+
+ assert.NoErr(t, cmak.WriteCMakeListsTxt())
+ if testing.Verbose() {
+ cml, err := cmak.GetCMakeListsTxt()
+ assert.NoErr(t, err)
+ t.Logf("Using CMakeLists.txt: %s", cml)
}
{ // write main.c/cpp to the conf dir - a simple one, just include all sources
var mainSrc = ""
+ if cmak.IsCpp {
+ mainSrc = mainSrc + "#include \"objectbox-cpp.h\"\n"
+ } else {
+ mainSrc = mainSrc + "#include \"objectbox.h\"\n"
+ }
files, err := ioutil.ReadDir(includeDir)
assert.NoErr(t, err)
@@ -107,35 +113,22 @@ func (h cTestHelper) build(t *testing.T, conf testSpec, dir string, expectedErro
mainSrc = mainSrc + "#include \"" + file.Name() + "\"\n"
}
}
+
mainSrc = mainSrc + "int main(){ return 0; }\n\n"
+ t.Logf("main.c/cpp file contents \n%s", mainSrc)
assert.NoErr(t, ioutil.WriteFile(mainFile, []byte(mainSrc), 0600))
}
- // configure the cmake project
- stdOut, stdErr, err := cmake(buildDir, cmakeConfDir)
- if err != nil {
- assert.Failf(t, "cmake build configuration failed: \n%s\n%s\n%s", stdOut, stdErr, err)
- }
- if testing.Verbose() {
+ if stdOut, stdErr, err := cmak.Configure(); err != nil {
+ assert.Failf(t, "cmake configuration failed: \n%s\n%s\n%s", stdOut, stdErr, err)
+ } else {
t.Logf("configuration output:\n%s", string(stdOut))
}
- // build the code
- stdOut, stdErr, err = cmake(includeDir, "--build", buildDir)
-
- checkBuildError(t, errorTransformer, stdOut, stdErr, err, expectedError)
-
- if testing.Verbose() {
+ if stdOut, stdErr, err := cmak.Build(); err != nil {
+ checkBuildError(t, errorTransformer, stdOut, stdErr, err, expectedError)
+ assert.Failf(t, "cmake build failed: \n%s\n%s\n%s", stdOut, stdErr, err)
+ } else {
t.Logf("build output:\n%s", string(stdOut))
}
}
-
-func cmake(cwd string, args ...string) (stdOut []byte, stdErr []byte, err error) {
- var cmd = exec.Command("cmake", args...)
- cmd.Dir = cwd
- stdOut, err = cmd.Output()
- if ee, ok := err.(*exec.ExitError); ok {
- stdErr = ee.Stderr
- }
- return
-}
diff --git a/test/comparison/conf.go b/test/comparison/conf.go
index b0e73612..7ac142da 100644
--- a/test/comparison/conf.go
+++ b/test/comparison/conf.go
@@ -27,6 +27,9 @@ import (
)
type testHelper interface {
+ // init sets up the helper before the very first execution
+ init(t *testing.T, conf testSpec)
+
// generatorFor constructs and configures a code generator for the given source file
generatorFor(t *testing.T, conf testSpec, sourceFile string, genDir string) generator.CodeGenerator
@@ -48,7 +51,7 @@ type testSpec struct {
}
var confs = map[string]testSpec{
- "fbs-c": {"c", ".fbs", ".obx.h", &cgenerator.CGenerator{PlainC: true}, cTestHelper{cpp: false}},
- "fbs-cpp": {"cpp", ".fbs", "-cpp.obx.h", &cgenerator.CGenerator{PlainC: false}, cTestHelper{cpp: true}},
+ "fbs-c": {"c", ".fbs", ".obx.h", &cgenerator.CGenerator{PlainC: true}, &cTestHelper{cpp: false}},
+ "fbs-cpp": {"cpp", ".fbs", "-cpp.obx.h", &cgenerator.CGenerator{PlainC: false}, &cTestHelper{cpp: true}},
// TODO "go": {"go", ".go", ".obx.go", &gogenerator.GoGenerator{}, goTestHelper{}},
}
diff --git a/test/comparison/generator_test.go b/test/comparison/generator_test.go
index db5742e8..3cb3c9b5 100644
--- a/test/comparison/generator_test.go
+++ b/test/comparison/generator_test.go
@@ -46,6 +46,7 @@ func TestCompare(t *testing.T) {
srcType, genType := typesFromConfKey(parts[0])
conf, ok := confs[parts[0]]
assert.True(t, ok)
+ conf.helper.init(t, conf)
generateOneDir(t, *overwriteExpected, conf, srcType, genType, parts[1])
} else {
t.Fatal("invalid target specification, expected 1 or two parts separated by '/'")
diff --git a/test/comparison/go-helper.go b/test/comparison/go-helper.go
index 56c8c44c..7e97d7ce 100644
--- a/test/comparison/go-helper.go
+++ b/test/comparison/go-helper.go
@@ -42,6 +42,8 @@ var goGeneratorArgsRegexp = regexp.MustCompile("//go:generate go run github.com/
type goTestHelper struct{}
+func (h *goTestHelper) init(t *testing.T, conf testSpec) {}
+
func (h goTestHelper) generatorFor(t *testing.T, conf testSpec, sourceFile string, genDir string) generator.CodeGenerator {
source, err := ioutil.ReadFile(sourceFile)
assert.NoErr(t, err)
diff --git a/test/comparison/test-all.go b/test/comparison/test-all.go
index 238d60d2..562e6c44 100644
--- a/test/comparison/test-all.go
+++ b/test/comparison/test-all.go
@@ -53,6 +53,7 @@ func generateAllDirs(t *testing.T, overwriteExpected bool, confKey string) {
conf, ok := confs[confKey]
assert.True(t, ok)
+ conf.helper.init(t, conf)
for _, testCase := range testCases {
if !testCase.IsDir() {
diff --git a/test/comparison/util.go b/test/comparison/util.go
index 613910f4..eedda5f7 100644
--- a/test/comparison/util.go
+++ b/test/comparison/util.go
@@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"os"
+ "path/filepath"
"strings"
"testing"
@@ -40,7 +41,7 @@ func checkBuildError(t *testing.T, errorTransformer func(err error) error, stdOu
var receivedError = errorTransformer(fmt.Errorf("%s\n%s\n%s", stdOut, stdErr, err))
// Fix paths in the error output on Windows so that it matches the expected error (which always uses '/').
- if os.PathSeparator != '/' {
+ if os.PathSeparator != '/' && expectedError != nil {
// Make sure the expected error doesn't contain the path separator already - to make it easier to debug.
if strings.Contains(expectedError.Error(), string(os.PathSeparator)) {
assert.Failf(t, "compile-error.expected contains this OS path separator '%v' so paths can't be normalized to '/'", string(os.PathSeparator))
@@ -50,3 +51,9 @@ func checkBuildError(t *testing.T, errorTransformer func(err error) error, stdOu
assert.Eq(t, expectedError, receivedError)
}
+
+func repoRoot(t *testing.T) string {
+ cwd, err := os.Getwd()
+ assert.NoErr(t, err)
+ return filepath.ToSlash(filepath.Join(cwd, "..", ".."))
+}
diff --git a/third_party/flatbuffers-c-bridge/build.sh b/third_party/flatbuffers-c-bridge/build.sh
index 5c3196e3..3cc5843b 100755
--- a/third_party/flatbuffers-c-bridge/build.sh
+++ b/third_party/flatbuffers-c-bridge/build.sh
@@ -31,7 +31,15 @@ fi
function build() {
echo "******** Configuring & building ********"
- srcDirAbsolute="$(pwd)/$srcDir"
+ # Note: we need an absolute path...
+ # realpath isn't available on macOS and the "else" variant didn't work well on windows because the path was already absolute...
+ srcDirAbsolute=
+ if [[ -x $(command -v realpath) ]]; then
+ srcDirAbsolute=$(realpath "$srcDir")
+ else
+ srcDirAbsolute="$(pwd)/$srcDir"
+ fi
+
pwd=$(pwd)
mkdir -p "$buildDir"
diff --git a/third_party/flatcc/.gitignore b/third_party/flatcc/.gitignore
new file mode 100644
index 00000000..0e1dfdcc
--- /dev/null
+++ b/third_party/flatcc/.gitignore
@@ -0,0 +1,4 @@
+build
+src
+lib
+include
\ No newline at end of file
diff --git a/third_party/flatcc/build.sh b/third_party/flatcc/build.sh
new file mode 100755
index 00000000..fe96056a
--- /dev/null
+++ b/third_party/flatcc/build.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+fccVersion=v0.6.0
+fccRepo=github.com/dvidelabs/flatcc
+
+scriptDir=$(dirname "${BASH_SOURCE[0]}")
+srcDir=${scriptDir}/src
+buildDir=${scriptDir}/build
+installDir=${scriptDir}
+
+buildType=Release
+configArgs="-DCMAKE_BUILD_TYPE=${buildType}"
+
+if [[ "$(uname)" == MINGW* ]] || [[ "$(uname)" == CYGWIN* ]]; then
+ configArgs+=' -G "MinGW Makefiles"'
+ # aligned_alloc() would be missing on MinGW, see https://github.com/dvidelabs/flatcc/issues/155
+ # It's fixed now on master, the following line can be removed after upgrading to a new release
+ export CFLAGS="-DFLATCC_USE_GENERIC_ALIGNED_ALLOC=1"
+fi
+
+function prepare() {
+ echo "******** Getting Flatcc sources ********"
+ if [[ ! -d ${srcDir} ]]; then
+ echo "Cloning ${fccRepo} into Into: ${srcDir}"
+ git clone https://${fccRepo}.git "${srcDir}"
+ fi
+
+ echo "Checking out ${fccVersion}"
+ (cd "${srcDir}"; git fetch)
+ (cd "${srcDir}"; git checkout ${fccVersion})
+}
+
+function build() {
+ echo "******** Configuring & building ********"
+
+ # Note: we need an absolute path...
+ # realpath isn't available on macOS and the "else" variant didn't work well on windows because the path was already absolute...
+ srcDirAbsolute=
+ if [[ -x $(command -v realpath) ]]; then
+ srcDirAbsolute=$(realpath "$srcDir")
+ else
+ srcDirAbsolute="$(pwd)/$srcDir"
+ fi
+
+ pwd=$(pwd)
+ mkdir -p "$buildDir"
+
+ set -x
+
+ # need to use eval because of quotes in configArgs... bash is just wonderful...
+ cd "$buildDir"
+ eval "cmake \"$srcDirAbsolute\" $configArgs"
+ cd "$pwd"
+
+ cmake --build "$buildDir" --config ${buildType} --target flatccrt
+ set +x
+}
+
+function install() {
+ echo "******** Collecting artifacts ********"
+ echo "Copying from ${srcDir} to ${installDir}:"
+ cp -rv "${srcDir}/include" "${installDir}"
+ if [[ -d "${srcDir}/lib/${buildType}" ]]; then
+ cp -rv "${srcDir}/lib/${buildType}" "${installDir}/lib"
+ else
+ cp -rv "${srcDir}/lib" "${installDir}"
+ fi
+}
+
+prepare
+build
+install
diff --git a/third_party/flatcc/clean.sh b/third_party/flatcc/clean.sh
new file mode 100755
index 00000000..e97f6047
--- /dev/null
+++ b/third_party/flatcc/clean.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+scriptDir=$(dirname "${BASH_SOURCE[0]}")
+set +x
+rm -rf "${scriptDir}/build"
+rm -rf "${scriptDir}/include"
+rm -rf "${scriptDir}/lib"
+rm -rf "${scriptDir}/src"
\ No newline at end of file
diff --git a/third_party/objectbox-c/.gitignore b/third_party/objectbox-c/.gitignore
new file mode 100644
index 00000000..5c15c317
--- /dev/null
+++ b/third_party/objectbox-c/.gitignore
@@ -0,0 +1,3 @@
+download
+include
+lib
\ No newline at end of file
diff --git a/third_party/objectbox-c/clean.sh b/third_party/objectbox-c/clean.sh
new file mode 100755
index 00000000..66aa5de5
--- /dev/null
+++ b/third_party/objectbox-c/clean.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+scriptDir=$(dirname "${BASH_SOURCE[0]}")
+set +x
+rm -rf "${scriptDir}/download"
+rm -rf "${scriptDir}/include"
+rm -rf "${scriptDir}/lib"
\ No newline at end of file
diff --git a/third_party/objectbox-c/get-objectbox-c.sh b/third_party/objectbox-c/get-objectbox-c.sh
new file mode 100755
index 00000000..b11922c4
--- /dev/null
+++ b/third_party/objectbox-c/get-objectbox-c.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+cVersion=0.9.0
+
+scriptDir=$(dirname "${BASH_SOURCE[0]}")
+
+
+echo "******** Downloading ObjectBox-C library ********"
+echo "Into: ${scriptDir}"
+cd "${scriptDir}"
+
+# don't install the library system-wide, just download it
+export installLibrary=false
+bash <(curl -s https://raw.githubusercontent.com/objectbox/objectbox-c/master/download.sh) --quiet ${cVersion}
+
+echo "******** Collecting artifacts ********"
+cp -rfv download/testing/*objectbox*/include ./
+cp -rfv download/testing/*objectbox*/lib ./
+rm -rfv download
+
+echo "Downloaded ObjectBox-C headers and library:"
+echo "Current directory: ${scriptDir}"
+ls -lh include lib
\ No newline at end of file