├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── args.go ├── artifactcache.go ├── build.sh ├── cmd.go ├── example ├── appAndroid │ ├── .gitignore │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── mycompany │ │ │ │ └── myapplication │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── mycompany │ │ │ │ │ └── myapplication │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── drawable │ │ │ │ └── ic_launcher_background.xml │ │ │ │ ├── layout │ │ │ │ ├── activity_main.xml │ │ │ │ └── content_main.xml │ │ │ │ ├── menu │ │ │ │ └── menu_main.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── mycompany │ │ │ └── myapplication │ │ │ └── ExampleUnitTest.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── libGo │ │ ├── build.gradle │ │ ├── libs │ │ │ └── .keep │ │ └── src │ │ │ └── main │ │ │ └── AndroidManifest.xml │ └── settings.gradle ├── appGo │ └── .keep ├── appiOS │ ├── .keep │ ├── iosApp.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── iosApp │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 167.png │ │ │ ├── 180.png │ │ │ ├── 20.png │ │ │ ├── 29.png │ │ │ ├── 40.png │ │ │ ├── 50.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift ├── goup.yaml ├── goupw └── libGo │ └── mycompany │ └── myproject │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── pkga │ └── stuff.go │ └── pkgb │ └── ugly.go ├── go.mod ├── go.sum ├── goup.go ├── goupyaml.go ├── helper.go ├── logger.go ├── magic.go ├── path.go ├── path_test.go ├── renovate.json ├── resources.go ├── resources.xml ├── tar.go ├── vendormodule.go ├── versionfile.go └── zip.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .idea 14 | gomobilebuilder 15 | example/.goup 16 | fatLib-sources.jar 17 | fatLib.aar 18 | builds 19 | example/appAndroid/libGo/build 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: github.com/worldiety/goup 3 | go: 4 | - 1.17.x 5 | - tip 6 | 7 | script: 8 | - go test -race -v -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, worldiety GmbH 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoUp (gomobile modules) [![Go Report Card](https://goreportcard.com/badge/github.com/worldiety/goup)](https://goreportcard.com/report/github.com/worldiety/goup) [![GoDoc](https://godoc.org/github.com/worldiety/goup?status.svg)](http://godoc.org/github.com/worldiety/goup) 2 | GoUp (pronounced go-up) is an install and make tool which helps to build go modules with 3 | gomobile for android and ios. It contains an automatic versioned toolchain provisioning, 4 | emulated module (vgo) support for gomobile and an build artifact cache. 5 | 6 | The motivation behind this tool is to bring the simplicity into the gomobile android world 7 | again. Today there are a lot of pitfalls to create a working setup, so we 8 | integrated all current workarounds for Linux/amd64 and MacOS/amd64 for a single selected 9 | toolchain into the tool. The name is inspired from *rustup*, the rust toolchain installer. 10 | Like rustup, GoUp will manage different toolchains (Android NDK, SDK, Java JDK and Go) 11 | in different versions, even for distinct projects, to provide you a stable build experience. 12 | 13 | What is still missing is extensive testing, configuration of more NDK, SDK, JDK and Go versions 14 | which are known to be compatible with each other, windows support and versioning of gomobile. 15 | Also the example project layout is created to support a crossplatform project 16 | layout, but still only contains an android and ios project. 17 | 18 | Our perspective is to evaluate the practicality and to develop and support this tool in the 19 | case of success. 20 | 21 | ## Example 22 | 23 | We've create an Android and iOS [example](https://github.com/worldiety/goup/tree/master/example) 24 | for your pleasure. It contains the android module *libGo* which invokes the GoUp wrapper 25 | script (goupw) which in turn downloads the actual GoUp version for your current platform. 26 | Please note, that the *goupw* script is only a crude bash script, were you need to define 27 | the platforms to build (`TARGETS`) and which GoUp version to use (`VERSION`). 28 | 29 | The gradle script in *libGo* builds the go library intentionally in every configuration phase, 30 | which ensures that you have always the valid generated Java API at your fingertips. 31 | Performance wise the impact is reduced, due to the GoUp artifact caching, which avoids 32 | building if nothing has changed, so in subsequent configure calls the process completes within 33 | a few milliseconds. 34 | 35 | To build, you just need to open the project with Android Studio and wait some minutes, until 36 | GoUp has downloaded and installed all required toolchains. To get some 'entertainment', you 37 | have to switch to the *Build Output* window and toggle the view in Android Studio. 38 | 39 | In general you should not check in the generated artifacts, because the generated aar 40 | file may not be deterministic (bitwise). 41 | 42 | The process in iOS is very comparable and integrates the GoUp compilation phase simply as 43 | a *script phase* in the *build phases* section (just after *Target Dependencies*). Note, that you also 44 | need to disable the bitcode flag in *Build Settings*. The generated framework becomes fairly large, so 45 | a check in may also be inadequate. 46 | 47 | ## how to build 48 | 49 | The core of a GoUp project is the goup.yaml file, which contains all declared versions and related 50 | build information to process your project. 51 | 52 | The build yaml file may look like this: 53 | 54 | ```yaml 55 | # The name is used to setup a custom workspace and tools. 56 | # You should not invoke parallel builds for the same project 57 | name: MySuperProject 58 | 59 | # set custom environment variables, which are always applied into the executing environment, just 60 | # like they have been defined before invoking GoUp 61 | variables: 62 | TEST: "HELLO WORLD" 63 | TEST2: "HELLO WORLD" 64 | 65 | # before_script is executing the following commands before the actual build starts. You can use it, to e.g. work around 66 | # authentication problems with go get and git 67 | before_script: 68 | - git config --global url."https://user:password@gitlab.mycompany.com/".insteadOf "https://gitlab.mycompany.com/" 69 | 70 | 71 | # The build section defines what and how goup should work 72 | build: 73 | # We want a gomobile build, e.g. for ios or android 74 | gomobile: 75 | 76 | # the toolchain section is required to setup a stable gomobile building experience 77 | toolchain: 78 | # which go version? 79 | go: 1.12.4 80 | # which android ndk version? 81 | ndk: r19c 82 | # which android sdk version? 83 | sdk: 4333796 84 | # which java version? 85 | jdk: 8u212b03 86 | # which gomobile version? 87 | gomobile: wdy-v0.0.1 88 | 89 | # The ios section defines how our iOS library is build. This only works on MacOS with XCode installed 90 | ios: 91 | # The gomobile -prefix flag 92 | prefix: MyLib 93 | 94 | # The gomobile -o flag, this will be a folder 95 | out: ./appIOS/MyLib.framework 96 | 97 | # The gomobile -bundleid flag sets the bundle ID to use with the app. 98 | bundleid: 99 | 100 | # The gomobile -ldflags flag 101 | ldflags: 102 | 103 | 104 | # The android section defines how our android build is executed 105 | android: 106 | # The gomobile -javapkg flag prefixes the generated packages 107 | javapkg: com.mycompany.myproject 108 | 109 | # The gomobile -o flag, this will be an android archive file. You should only ever use 110 | # a single go library in your app. Otherwise there may be some technical issues and 111 | # it also wastes a lot of storage and memory resources in your app. 112 | out: ./appAndroid/libGo/libs/fatLib.aar 113 | 114 | # The gomobile -ldflags flag 115 | ldflags: 116 | 117 | 118 | # The modules section defines a list of all local or remote go modules, which should be included in the build. 119 | # You can have more than one, but probably you only need a single one and want to use 120 | # real go mod dependencies instead. 121 | modules: 122 | - ./libGo/mycompany/myproject 123 | 124 | # The export section defines all exported packages which are passed to gobind by gomobile. 125 | # Gomobile does not generate transitives exports, so you need to declare all 126 | # packages containing types and methods which you want to have bindings for. 127 | # Be careful with name conflicts, because the last part of the package will be used 128 | # to scope the types. 129 | export: 130 | # contains handsome wrappers to allow passing unsupported types (interfaces, maps, slices) 131 | # through gomobile. In our case pkgb wants to export those types. 132 | - github.com/worldiety/std 133 | # our actual local packages 134 | - mycompany/myproject 135 | - mycompany/myproject/pkga 136 | - mycompany/myproject/pkgb 137 | 138 | 139 | 140 | ``` 141 | 142 | GoUp has a few optional commandline arguments, and also evaluates the environment variable GOUP_HOME. 143 | 144 | ```bash 145 | goup -help 146 | -buildFile string 147 | Use a build file to load. (default "./goup.yaml") 148 | -clean 149 | Removes the project workspace, but keeps toolchains. 150 | -dir string 151 | Use a custom directory to resolve relative paths from goup.yml. 152 | -help 153 | Shows this help 154 | -home string 155 | Use this as the home directory, where GoUp holds toolchains, projects and workspaces. 156 | -loglevel int 157 | The LogLevel determines what is printed into the console. 0=Debug, 1=Info, 2=Warn, 3=Error 158 | -reset 159 | Performs a reset, delete the home directory and exits 160 | -resources string 161 | XML which describes downloadable toolchains (default "https://raw.githubusercontent.com/worldiety/goup/master/resources.xml") 162 | -targets string 163 | The targets to build, e.g. gomobile/android or gomobile/ios. Can be concated by : (default "all") 164 | -version 165 | Shows the version 166 | ``` 167 | 168 | You always need an *export* list and every exported module should be declared (at least transitively) 169 | from your *module* projects. All referred dependencies are upgraded and copied into 170 | an artificial go path in `~/.goup//go`, so that gomobile is happy. You can also 171 | define more than one local module, e.g. if you have multiple local dependent or related 172 | modules. But probably it would be better to only ever have a single local module and 173 | refer to external versioned go dependencies. 174 | 175 | Toolchains are installed in `~/.goup/toolchains`, one for each type and version. Also 176 | GoUp uses interprocess filelocks for modifying toolchains and projects, to allow 177 | at least concurrent (but sequentialized) builds without corruptions. 178 | 179 | 180 | ## hint 181 | Important things like maps, slices, derived basic and value types won't work with gomobile. 182 | To mitigate these limitations, you can use the module https://github.com/worldiety/std. 183 | Do not forget to export it, as shown in the example. 184 | -------------------------------------------------------------------------------- /args.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Torben Schinke 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "flag" 19 | "fmt" 20 | "os" 21 | "path/filepath" 22 | "runtime" 23 | "strings" 24 | ) 25 | 26 | // Args contains the arguments which have been used to invoke GoUp 27 | type Args struct { 28 | // The BaseDir is used to resolve paths in goup.yaml 29 | BaseDir Path 30 | 31 | // The goup.yml file to use 32 | BuildFile Path 33 | 34 | // HomeDir is the place where GoUp caches toolchains, projects and workspaces. 35 | HomeDir Path 36 | 37 | // The LogLevel determines what is printed into the console 38 | LogLevel LogLevel 39 | 40 | // ResourcesURL is used to update the external resources list 41 | ResourcesURL string 42 | 43 | // Targets contains the different build targets, e.g. gomobile/android or gomobile/ios 44 | Targets []string 45 | 46 | // ClearWorkspace does not reuse the workspace 47 | ClearWorkspace bool 48 | } 49 | 50 | // Evaluate reads all flags and parses them into the receiver. 51 | // On failures or if help requested it may also print to the console 52 | // and exit 53 | func (a *Args) Evaluate() { 54 | defaultHome, err := os.UserHomeDir() 55 | if err != nil { 56 | defaultHome = "/" 57 | } 58 | defaultHome = filepath.Join(defaultHome, "."+goup) 59 | 60 | overriddenDefaultHome := os.Getenv("GOUP_HOME") 61 | if len(overriddenDefaultHome) > 0 { 62 | defaultHome = overriddenDefaultHome 63 | } 64 | 65 | baseDir := flag.String("dir", CWD(), "Use a custom directory to resolve relative paths from "+goup+".yml.") 66 | buildFile := flag.String("buildFile", "./"+goup+".yaml", "Use a build file to load.") 67 | homeDir := flag.String("home", defaultHome, "Use this as the home directory, where "+goUp+" holds toolchains, projects and workspaces.") 68 | logLevel := flag.Int("loglevel", int(Error), "The LogLevel determines what is printed into the console. 0=Debug, 1=Info, 2=Warn, 3=Error") 69 | resourcesURL := flag.String("resources", defaultResourcesURL, "XML which describes downloadable toolchains") 70 | targets := flag.String("targets", "all", "The targets to build, e.g. gomobile/android or gomobile/ios. Can be concated by :") 71 | 72 | showVersion := flag.Bool("version", false, "Shows the version") 73 | showHelp := flag.Bool("help", false, "Shows this help") 74 | doReset := flag.Bool("reset", false, "Performs a reset, delete the home directory and exits") 75 | doClean := flag.Bool("clean", false, "Removes the project workspace, but keeps toolchains.") 76 | 77 | flag.Parse() 78 | if *showHelp { 79 | flag.PrintDefaults() 80 | os.Exit(0) 81 | } 82 | 83 | if *showVersion { 84 | fmt.Println(goUp + " " + version) 85 | os.Exit(0) 86 | } 87 | 88 | a.BaseDir = Path(*baseDir) 89 | a.BuildFile = Path(*buildFile).Resolve(a.BaseDir) 90 | a.HomeDir = Path(*homeDir) 91 | a.LogLevel = LogLevel(*logLevel) 92 | a.ResourcesURL = *resourcesURL 93 | a.Targets = strings.Split(*targets, ":") 94 | a.ClearWorkspace = *doClean 95 | 96 | logger = &defaultLogger{a.LogLevel} 97 | 98 | logger.Debug(Fields{"Name": goUp, "Version": version, "GOARCH": runtime.GOARCH, "GOOS": runtime.GOOS}) 99 | logger.Debug(Fields{"BaseDir": a.BaseDir, "BuildFile": a.BuildFile, "HomeDir": a.HomeDir, "LogLevel": a.LogLevel, "ResourcesURL": a.ResourcesURL, "Targets": a.Targets}) 100 | 101 | if *doReset { 102 | err := os.RemoveAll(a.HomeDir.String()) 103 | must(err) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /artifactcache.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Torben Schinke 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "crypto/sha1" 19 | "encoding/base64" 20 | "encoding/json" 21 | "fmt" 22 | "io/ioutil" 23 | "os" 24 | "strings" 25 | ) 26 | 27 | // A ArtifactCache contains information about a build, to decide if it should get compiled again. 28 | // Actually these are just the program arguments. 29 | // 30 | // Calculating the hash is exact but very expensive, we should use a file tree with last mod time stamps. 31 | type ArtifactCache struct { 32 | // The sha sum of all input files 33 | InHash string 34 | 35 | // The sha sum of the output 36 | OutHash string 37 | } 38 | 39 | // calculateInHash takes all input files, like *.go and go.mod and gomobile.build. We do not want to check 40 | // remote changes, which may cause unstable builds, but that is a user problem, not ours. 41 | func (g *GoUp) calculateInHash() string { 42 | extensions := []string{".go", "go.mod", "go.sum"} 43 | hasher := sha1.New() 44 | hasher.Write(sloppyBytes(ioutil.ReadFile(g.args.BuildFile.String()))) 45 | for _, modPath := range g.config.Build.Gomobile.Modules { 46 | resolvedPath := Path(modPath).Resolve(g.args.BaseDir) 47 | if !resolvedPath.Exists() { 48 | // this is the external case, we will never check that for performance reasons 49 | continue 50 | } 51 | files, err := ListFiles(resolvedPath.String()) 52 | if err != nil { 53 | panic(err) 54 | } 55 | for _, file := range files { 56 | acceptable := false 57 | for _, ext := range extensions { 58 | if strings.HasSuffix(file, ext) { 59 | acceptable = true 60 | break 61 | } 62 | } 63 | if acceptable { 64 | logger.Debug(Fields{"in-artifact": file}) 65 | 66 | hasher.Write(sloppyBytes(ioutil.ReadFile(file))) 67 | } 68 | } 69 | 70 | } 71 | hash := base64.URLEncoding.EncodeToString(hasher.Sum(nil)) 72 | logger.Debug(Fields{"in-hash": hash}) 73 | return hash 74 | } 75 | 76 | // calculateOutHash takes the generated out files to hash them. Absent files are hashed as 0 bytes. 77 | func (g *GoUp) calculateOutHash() string { 78 | extensions := []string{".h", ".plist", ".modulemap"} 79 | hasher := sha1.New() 80 | if g.hasAndroidBuild() { 81 | outFile := g.config.Build.Gomobile.Android.Out.Resolve(g.args.BaseDir) 82 | // we need to hash the file, to avoid rebuilding failures when switching android build on and the dir is missing 83 | hasher.Write([]byte(outFile.String())) 84 | hasher.Write(sloppyBytes(ioutil.ReadFile(outFile.String()))) 85 | } 86 | if g.hasIosBuild() { 87 | outFolder := g.config.Build.Gomobile.Ios.Out.Resolve(g.args.BaseDir) 88 | // we need to hash the folder, to avoid rebuilding failures when switching ios build on and the dir is missing 89 | hasher.Write([]byte(outFolder.String())) 90 | files, err := ListFiles(outFolder.String()) 91 | if err != nil { 92 | panic(err) 93 | } 94 | for _, file := range files { 95 | acceptable := false 96 | for _, ext := range extensions { 97 | if strings.HasSuffix(file, ext) { 98 | acceptable = true 99 | break 100 | } 101 | } 102 | if acceptable { 103 | logger.Debug(Fields{"in-artifact": file}) 104 | 105 | hasher.Write(sloppyBytes(ioutil.ReadFile(file))) 106 | } 107 | } 108 | } 109 | hash := base64.URLEncoding.EncodeToString(hasher.Sum(nil)) 110 | logger.Debug(Fields{"out-hash": hash}) 111 | return hash 112 | } 113 | 114 | // Save serializes the cache data into json 115 | func (b *ArtifactCache) Save(fname string) error { 116 | data, err := json.Marshal(b) 117 | if err != nil { 118 | return fmt.Errorf("failed to marshal: %v", err) 119 | } 120 | err = ioutil.WriteFile(fname, data, os.ModePerm) 121 | if err != nil { 122 | return fmt.Errorf("failed to save: %v", err) 123 | } 124 | return nil 125 | } 126 | 127 | // Load deserializes the cache data from json and ensures that the cache is cleared. 128 | func (b *ArtifactCache) Load(fname string) error { 129 | data, err := ioutil.ReadFile(fname) 130 | if err != nil { 131 | return fmt.Errorf("failed to load json: %v", err) 132 | } 133 | err = json.Unmarshal(data, b) 134 | if err != nil { 135 | return fmt.Errorf("failed to unmarshal: %v", err) 136 | } 137 | return nil 138 | } 139 | 140 | func sloppyBytes(data []byte, err error) []byte { 141 | if err != nil { 142 | fmt.Println(err) 143 | } 144 | return data 145 | } 146 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | rm -rf builds 6 | mkdir -p builds 7 | 8 | 9 | mkdir -p builds/linux-amd64 10 | env GOOS=linux GOARCH=amd64 go build 11 | mv goup builds/linux-amd64 12 | 13 | mkdir -p builds/darwin-amd64 14 | env GOOS=darwin GOARCH=amd64 go build 15 | mv goup builds/darwin-amd64 16 | 17 | mkdir -p builds/darwin-arm64 18 | env GOOS=darwin GOARCH=arm64 go build 19 | mv goup builds/darwin-arm64 20 | 21 | mkdir -p builds/windows-amd64 22 | env GOOS=windows GOARCH=amd64 go build 23 | mv goup.exe builds/windows-amd64 -------------------------------------------------------------------------------- /cmd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Torben Schinke 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | func main() { 18 | 19 | args := &Args{} 20 | args.Evaluate() 21 | 22 | gp, err := NewGoUp(args) 23 | must(err) 24 | 25 | err = gp.Build() 26 | must(err) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /example/appAndroid/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /example/appAndroid/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /example/appAndroid/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.mycompany.myapplication" 7 | minSdkVersion 15 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation project(":libGo") 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'com.android.support:appcompat-v7:28.0.0' 25 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 26 | implementation 'com.android.support:design:28.0.0' 27 | testImplementation 'junit:junit:4.12' 28 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 29 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 30 | } 31 | -------------------------------------------------------------------------------- /example/appAndroid/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/androidTest/java/com/mycompany/myapplication/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.myapplication; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.mycompany.myapplication", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/java/com/mycompany/myapplication/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.myapplication; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.View; 9 | import android.view.Menu; 10 | import android.view.MenuItem; 11 | 12 | import com.mycompany.myproject.myproject.Myproject; 13 | import com.mycompany.myproject.pkga.HelloCallback; 14 | import com.mycompany.myproject.pkga.Pkga; 15 | import com.mycompany.myproject.pkgb.Pkgb; 16 | import com.mycompany.myproject.std.StrSlice; 17 | import com.mycompany.myproject.std.StrStrMap; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | Toolbar toolbar = findViewById(R.id.toolbar); 26 | setSupportActionBar(toolbar); 27 | 28 | FloatingActionButton fab = findViewById(R.id.fab); 29 | fab.setOnClickListener(new View.OnClickListener() { 30 | @Override 31 | public void onClick(View view) { 32 | System.out.println(Myproject.anExportedProjectLevelFunc()); 33 | String fromGo = Pkga.niceCallback(new HelloCallback() { 34 | @Override 35 | public String yourName() { 36 | return "GoUp"; 37 | } 38 | }); 39 | System.out.println("Hello Mr. " + fromGo); 40 | try { 41 | System.out.println(Pkgb.getMap2().get(Pkgb.getMap2().keys().get(0))); 42 | } catch (Exception e) { 43 | throw new RuntimeException(e); 44 | } 45 | } 46 | }); 47 | 48 | StrStrMap map = Pkgb.getMap2(); 49 | 50 | for (int i = 0; i < map.keys().len(); i++) { 51 | try { 52 | String key = map.keys().get(i); 53 | String value = map.get(key); 54 | System.out.println(i + " - " + key +": " + value); 55 | } catch (Exception e) { 56 | 57 | } 58 | } 59 | } 60 | 61 | @Override 62 | public boolean onCreateOptionsMenu (Menu menu){ 63 | // Inflate the menu; this adds items to the action bar if it is present. 64 | getMenuInflater().inflate(R.menu.menu_main, menu); 65 | return true; 66 | } 67 | 68 | @Override 69 | public boolean onOptionsItemSelected (MenuItem item){ 70 | // Handle action bar item clicks here. The action bar will 71 | // automatically handle clicks on the Home/Up button, so long 72 | // as you specify a parent activity in AndroidManifest.xml. 73 | int id = item.getItemId(); 74 | 75 | //noinspection SimplifiableIfStatement 76 | if (id == R.id.action_settings) { 77 | return true; 78 | } 79 | 80 | return super.onOptionsItemSelected(item); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 | 71 | 76 | 81 | 86 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 136 | 141 | 146 | 151 | 156 | 161 | 166 | 171 | 172 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 20 | 21 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worldiety/goup/602ced741e7ba802edfbf19dc3aa9946e767795f/example/appAndroid/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 4 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | My Application 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /example/appAndroid/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |