diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c223ab7..69a74150 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ name: "CI" -on: push +on: [push, pull_request] jobs: lint: diff --git a/.gitignore b/.gitignore index bc15cacb..79671ce0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /fyne-cross +/*.dmg +/*.xip diff --git a/CHANGELOG.md b/CHANGELOG.md index fb99773b..7d2d96eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,37 @@ # Changelog - Fyne.io fyne-cross -## [1.0.0] +## 1.1.0 - 14 May 2021 + +### Added + +- Add darwin arm64 target #39 +- Add FreeBSD on arm64 target #29 +- Add the `darwin-image` command to build the darwin docker image +- Add the `local` flag for darwin to build directly from the host +- Add a dedicated docker image for macOS +- Add a dedicated docker image for Windows +- Darwin image build: add support for SDK version #45 + +### Changed + +- Update Go to v1.16.4 +- Update fyne CLI to v2.0.3 +- Update FreeBSD SDK to v12.2 #29 +- Refactor docker images layout to ensure compatibility with previous versions of fyne-cross + +### Fixed + +- Fix android keystore path is not resolved correctly +- Fix some release flags are always set even if empty +- Fix appID flag should not have a default #25 +- Fix the option --env does not allow values containing comma #35 + +### Removed + +- Remove darwin 386 target +- Remove the dependency from the docker/golang-cross image for the base image + +## 1.0.0 - 13 December 2020 - Add support for "fyne release" #3 - Add support for creating packaged .tar.gz bundles on freebsd #6 - Add support for Linux Wayland #10 @@ -10,7 +41,7 @@ - Fix build failure for Linux mobile #19 - Update Go to v1.14.13 -## [0.9.0] +## 0.9.0 - 17 October 2020 - Releaseing under project namespace with previous 2.2.1 becoming 0.9.0 in fyne-io namespace diff --git a/Makefile b/Makefile index 764581dc..db173a0b 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,83 @@ tag := $(shell date +"%y.%m.%d") -build-images: - @docker build -f ${CURDIR}/docker/base/Dockerfile -t fyneio/fyne-cross:base-latest . - @docker tag fyneio/fyne-cross:base-latest fyneio/fyne-cross:base-$(tag) - @docker build -f ${CURDIR}/docker/linux-386/Dockerfile -t fyneio/fyne-cross:linux-386-latest . - @docker tag fyneio/fyne-cross:linux-386-latest fyneio/fyne-cross:linux-386-$(tag) - @docker build -f ${CURDIR}/docker/linux-arm/Dockerfile -t fyneio/fyne-cross:linux-arm-latest . - @docker tag fyneio/fyne-cross:linux-arm-latest fyneio/fyne-cross:linux-arm-$(tag) - @docker build -f ${CURDIR}/docker/linux-arm64/Dockerfile -t fyneio/fyne-cross:linux-arm64-latest . - @docker tag fyneio/fyne-cross:linux-arm64-latest fyneio/fyne-cross:linux-arm64-$(tag) - @docker build -f ${CURDIR}/docker/android/Dockerfile -t fyneio/fyne-cross:android-latest . - @docker tag fyneio/fyne-cross:android-latest fyneio/fyne-cross:android-$(tag) - @docker build -f ${CURDIR}/docker/freebsd/Dockerfile -t fyneio/fyne-cross:freebsd-latest . - @docker tag fyneio/fyne-cross:freebsd-latest fyneio/fyne-cross:freebsd-$(tag) - -push-images: - $(eval TAG := $(date +"%y.%m.%d")) - @docker push fyneio/fyne-cross:base-latest - @docker push fyneio/fyne-cross:base-$(tag) - @docker push fyneio/fyne-cross:linux-386-latest - @docker push fyneio/fyne-cross:linux-386-$(tag) - @docker push fyneio/fyne-cross:linux-arm-latest - @docker push fyneio/fyne-cross:linux-arm-$(tag) - @docker push fyneio/fyne-cross:linux-arm64-latest - @docker push fyneio/fyne-cross:linux-arm64-$(tag) - @docker push fyneio/fyne-cross:android-latest - @docker push fyneio/fyne-cross:android-$(tag) - @docker push fyneio/fyne-cross:freebsd-latest - @docker push fyneio/fyne-cross:freebsd-$(tag) +FYNE_CROSS_VERSION := "1.1" + +base: + @docker build -f ${CURDIR}/docker/base/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base . + +base-llvm: base + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/base-llvm/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm . + +android: base + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/android/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-android . + +darwin: base-llvm + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/darwin/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-darwin . + +base-freebsd: base-llvm + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/base-freebsd/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd . + +freebsd: base-freebsd + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/freebsd-amd64/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-amd64 . + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/freebsd-arm64/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-arm64 . + +linux: base + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/linux-386/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-386 . + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/linux-arm/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm . + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/linux-arm64/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm64 . + +windows: base + @docker build --build-arg FYNE_CROSS_VERSION=${FYNE_CROSS_VERSION} -f ${CURDIR}/docker/windows/Dockerfile -t fyneio/fyne-cross:${FYNE_CROSS_VERSION}-windows . + +# build all images for release. Note do not build darwin +build-images: base android freebsd linux windows + +# tag the images with the YY.MM.DD suffix +tag-images: + # tag base images + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-$(tag) + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm-$(tag) + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd-$(tag) + # tag android images + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-android fyneio/fyne-cross:${FYNE_CROSS_VERSION}-android-$(tag) + # tag linux images + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-386 fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-386-$(tag) + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm-$(tag) + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm64 fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm64-$(tag) + # tag freebsd images + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-amd64 fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-amd64-$(tag) + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-arm64 fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-arm64-$(tag) + # tag windows images + @docker tag fyneio/fyne-cross:${FYNE_CROSS_VERSION}-windows fyneio/fyne-cross:${FYNE_CROSS_VERSION}-windows-$(tag) + +# push the latest images +push-latest-images: + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-android + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-386 + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm64 + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-amd64 + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-arm64 + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-windows + +# push the tagged images +push-tag-images: + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-android-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-386-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-linux-arm64-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-amd64-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-freebsd-arm64-$(tag) + @docker push fyneio/fyne-cross:${FYNE_CROSS_VERSION}-windows-$(tag) + +# push all images: latest and tagged +push-images: push-latest-images push-tag-images + +embed: + go run internal/cmd/embed/main.go diff --git a/README.md b/README.md index 377501e0..34ae9c33 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,16 @@ [![CI](https://github.com/fyne-io/fyne-cross/workflows/CI/badge.svg)](https://github.com/fyne-io/fyne-cross/actions?query=workflow%3ACI) [![Go Report Card](https://goreportcard.com/badge/github.com/fyne-io/fyne-cross)](https://goreportcard.com/report/github.com/fyne-io/fyne-cross) [![GoDoc](https://godoc.org/github.com/fyne-io/fyne-cross?status.svg)](http://godoc.org/github.com/fyne-io/fyne-cross) [![version](https://img.shields.io/github/v/tag/fyne-io/fyne-cross?label=version)]() -fyne-cross is a simple tool to cross compile and create distribution packages for [Fyne](https://fyne.io) applications. - -It has been inspired by [xgo](https://github.com/karalabe/xgo) and uses a [docker image](https://hub.docker.com/r/fyneio/fyne-cross) built on top of the [golang-cross](https://github.com/docker/golang-cross) image, that includes the MinGW compiler for windows, and an OSX SDK, along with the Fyne requirements. +fyne-cross is a simple tool to cross compile and create distribution packages +for [Fyne](https://fyne.io) applications using docker images that include Linux, +the MinGW compiler for Windows, FreeBSD, and a macOS SDK, along with the Fyne +requirements. Supported targets are: - darwin/amd64 - - darwin/386 + - darwin/arm64 - freebsd/amd64 + - freebsd/arm64 - linux/amd64 - linux/386 - linux/arm @@ -23,6 +25,9 @@ Supported targets are: > - iOS compilation is supported only on darwin hosts. See [fyne pre-requisites](https://developer.fyne.io/started/#prerequisites) for details. > - macOS packaging for public distrubution (release mode) is supported only on darwin hosts. > - windows packaging for public distrubution (release mode) is supported only on windows hosts. +> - starting from v1.1.0: +> - cross-compile from NOT `darwin` (i.e. linux) to `darwin`: the image with the macOS SDK is no more available via docker hub and has to be built manually, see the [Build the darwin image](#build_darwin_image) section below. +> - cross-compile from `darwin` to `darwin` by default will use under the hood the fyne CLI tool and requires Go and the macOS SDK installed on the host. ## Requirements @@ -109,6 +114,34 @@ fyne-cross linux fyne-cross linux -output bugs ./cmd/bugs ``` +## Build the docker image for OSX/Darwin/Apple cross-compiling +The docker image for darwin is not provided via docker hub and need to build manually since it depends on the macOS SDK. + +**[Please ensure you have read and understood the Xcode license + terms before continuing.](https://www.apple.com/legal/sla/docs/xcode.pdf)** + +To build the image: +1. [Download Command Line Tools for Xcode](https://developer.apple.com/download/more) >= 12.4 (macOS SDK 11.x) +2. Run: `fyne-cross darwin-image --xcode-path /path/to/Command_Line_Tools_for_Xcode_12.5.dmg` + +The command above will: +- install the dependencies required by [osxcross](https://github.com/tpoechtrager/osxcross) to package the macOS SDK and compile the macOS cross toolchain. +- package the macOS SDK +- compile the macOS cross toolchain +- build the `fyneio/fyne-cross:-darwin` image that will be used by fyne-cross + +> NOTE: the creation of the image may take several minutes and may require more than 25 GB of free disk space. + +### [EXPERIMENTAL] Build using a different SDK version + +By default fyne-cross will attempt to auto-detect the latest version of SDK provided by the Xcode package. If for any reason a different SDK version is required, it can be specified using the `--sdk-version` flag. + +Example: + +`fyne-cross darwin-image --sdk-version 11.1 --xcode-path /path/to/Command_Line_Tools_for_Xcode_12.4.dmg` + +> Note: this feature is marked as EXPERIMENTAL + ## Contribute - Fork and clone the repository @@ -119,8 +152,8 @@ fyne-cross linux -output bugs ./cmd/bugs See [contributors](https://github.com/fyne-io/fyne-cross/graphs/contributors) page -## Legal note +## Credits -OSX/Darwin/Apple builds: -**[Please ensure you have read and understood the Xcode license - terms before continuing.](https://www.apple.com/legal/sla/docs/xcode.pdf)** +- [osxcross](https://github.com/tpoechtrager/osxcross) for the macOS Cross toolchain for Linux +- [golang-cross](https://github.com/docker/golang-cross) for the inspiration and the docker images used in the initial versions +- [xgo](https://github.com/karalabe/xgo) for the inspiration diff --git a/docker/CHANGELOG.md b/docker/CHANGELOG.md index dc4f616a..7050659e 100644 --- a/docker/CHANGELOG.md +++ b/docker/CHANGELOG.md @@ -2,31 +2,82 @@ All notable changes to the fyne-cross docker images will be documented in this file. -Release cycle won't follow the fyne-cross one, so the images will be tagged using the label -year.month.day along with the latest one. - -# Release 20.12.13 +## fyne 1.1.x compatible + +Latest versions available on Docker Hub are: + +- fyneio/fyne-cross:1.1-base +- fyneio/fyne-cross:1.1-base-llvm +- fyneio/fyne-cross:1.1-base-freebsd +- fyneio/fyne-cross:1.1-android +- fyneio/fyne-cross:1.1-freebsd-amd64 +- fyneio/fyne-cross:1.1-freebsd-arm64 +- fyneio/fyne-cross:1.1-linux-386 +- fyneio/fyne-cross:1.1-linux-arm64 +- fyneio/fyne-cross:1.1-linux-arm +- fyneio/fyne-cross:1.1-windows + +Release cycle won't follow the fyne-cross one, so the images will be tagged and +available on Docker Hub using the label year.month.day along with the tags +above. + +Example: `fyneio/fyne-cross:1.1-base-21.03.17` + +### Release 21.05.08 +- Update Go to v1.16.4 +- Update fyne CLI to v2.0.3 + +### Release 21.05.03 +- Refactor docker images layout to ensure compatibility with previous versions of fyne-cross +- Add FreeBSD on arm64 target +- Add a dedicated docker image for macOS +- Add a dedicated docker image for Windows +- Update Go to v1.16.3 +- Update fyne CLI to v2.0.2 +- Update FreeBSD SDK to v12.2 +- Remove the dependency from the docker/golang-cross image for the base image + +> Note: the docker image for darwin is not provided anymore and need to build manually since it depends on the OSX SDK. + +## fyne 1.0.x compatible + +Latest versions available on Docker Hub are: +- fyneio/fyne-cross:base-latest +- fyneio/fyne-cross:darwin-latest +- fyneio/fyne-cross:linux-386-latest +- fyneio/fyne-cross:linux-arm64-latest +- fyneio/fyne-cross:linux-arm-latest +- fyneio/fyne-cross:android-latest +- fyneio/fyne-cross:freebsd-latest + +Release cycle won't follow the fyne-cross one, so the images will be tagged and +available on Docker Hub using the label year.month.day along with the tags +above. + +Example: `fyneio/fyne-cross:base-20.12.13` + +### Release 20.12.13 - Update Go to v1.14.13 - Fix build failure for Linux mobile #19 -# Release 20.12.10 +### Release 20.12.10 - Update fyne cli to v1.4.2 > Note: this version is the last that provides Go v1.13.x -# Release 20.12.05 +### Release 20.12.05 - Update fyne cli to v1.4.2-0.20201204171445-8f33697cf611 - Add support for Linux Wayland #10 -# Release 20.11.28 +### Release 20.11.28 - Update fyne cli to v1.4.2-0.20201127180716-f9f91c194737 fyne-io#1609 -# Release 20.11.25 +### Release 20.11.25 - Update fyne cli to v1.4.2-0.20201125075943-97ad77d2abe0 fyne-io#1538 -# Release 20.11.23 +### Release 20.11.23 - Update fyne cli to v1.4.2-0.20201122132119-67b762f56dc0 fyne-io#1527 -# Release 20.11.04 +### Release 20.11.04 - fyne cli updated to v1.4.0 # Archive diff --git a/docker/README.md b/docker/README.md index 8a54d581..3beea24a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,9 +4,17 @@ This folder contains the docker images used by fyne-cross to build the Fyne appl It provides the following images: -- fyneio/fyne-cross:base -- fyneio/fyne-cross:linux-386 -- fyneio/fyne-cross:linux-arm64 -- fyneio/fyne-cross:linux-arm -- fyneio/fyne-cross:android -- fyneio/fyne-cross:freebsd +- fyneio/fyne-cross:1.1-base +- fyneio/fyne-cross:1.1-base-llvm +- fyneio/fyne-cross:1.1-base-freebsd +- fyneio/fyne-cross:1.1-android +- fyneio/fyne-cross:1.1-freebsd-amd64 +- fyneio/fyne-cross:1.1-freebsd-arm64 +- fyneio/fyne-cross:1.1-linux-386 +- fyneio/fyne-cross:1.1-linux-arm64 +- fyneio/fyne-cross:1.1-linux-arm +- fyneio/fyne-cross:1.1-windows + +> Note: +> - images are compatible with fyne-cross 1.1.x +> - the darwin image is not hosted on dockerhub diff --git a/docker/android/Dockerfile b/docker/android/Dockerfile index c398f33a..f4c81339 100644 --- a/docker/android/Dockerfile +++ b/docker/android/Dockerfile @@ -1,4 +1,5 @@ -FROM fyneio/fyne-cross:base-latest +ARG FYNE_CROSS_VERSION +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base ENV JAVA_HOME /usr/local/android_jdk8 ENV ANDROID_HOME /usr/local/android_sdk diff --git a/docker/base-freebsd/Dockerfile b/docker/base-freebsd/Dockerfile new file mode 100644 index 00000000..26e30a9e --- /dev/null +++ b/docker/base-freebsd/Dockerfile @@ -0,0 +1,45 @@ +ARG FYNE_CROSS_VERSION +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm as pkg + +# Build pkg for linux +# Based on https://github.com/freebsd/pkg/blob/release-1.12/.cirrus.yml#L19-L29 +RUN apt-get update -qq \ + && apt-get install -y -q --no-install-recommends \ + libsqlite3-dev \ + libbsd-dev \ + libarchive-dev \ + libssl-dev \ + liblzma-dev \ + liblua5.2-dev \ + nettle-dev \ + liblzo2-dev \ + libattr1-dev \ + libacl1-dev \ + build-essential \ + zlib1g-dev \ + libbz2-dev \ + m4 \ + libexpat1-dev \ + liblz4-dev \ + libxml2-dev \ + libzstd-dev \ + bsdtar \ + && apt-get -qy autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/*; + +RUN mkdir -p /pkg-src \ + && mkdir -p /pkg/etc \ + && curl -L https://github.com/freebsd/pkg/archive/1.12.0.tar.gz | bsdtar -xf - -C /pkg-src \ + && cd /pkg-src/pkg-* \ + && ./scripts/install_deps.sh \ + && ./configure --with-libarchive.pc --prefix=/pkg \ + && make -j4 || make V=1 \ + && make install \ + && rm -rf /pkg-src + +FROM pkg as base-freebsd + +COPY --from=pkg /pkg /pkg + +ENV PATH=/pkg/sbin:${PATH} diff --git a/docker/base-llvm/Dockerfile b/docker/base-llvm/Dockerfile new file mode 100644 index 00000000..94c33dd6 --- /dev/null +++ b/docker/base-llvm/Dockerfile @@ -0,0 +1,18 @@ +ARG LLVM_VERSION=12 +ARG FYNE_CROSS_VERSION + +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base +ARG LLVM_VERSION + +RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \ + && echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-${LLVM_VERSION} main" | tee /etc/apt/sources.list.d/llvm.list > /dev/null \ + && apt-get update -qq \ + && apt-get install -y -q --no-install-recommends \ + clang-${LLVM_VERSION} \ + llvm-${LLVM_VERSION} \ + lld-${LLVM_VERSION} \ + && apt-get -qy autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/*; + +ENV PATH=/usr/lib/llvm-${LLVM_VERSION}/bin:${PATH} diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile index f2f3820e..21dbfb66 100644 --- a/docker/base/Dockerfile +++ b/docker/base/Dockerfile @@ -1,38 +1,28 @@ -# docker cross 1.13.15 -ARG DOCKER_CROSS_VERSION=sha256:11a04661d910f74c419623ef7880024694f9151c17578af15e86c45cdf6c8588 +ARG GO_VERSION=1.16.4 # fyne stable branch -ARG FYNE_VERSION=v1.4.2 +ARG FYNE_VERSION=v2.0.3 -# Build the fyne command utility -FROM dockercore/golang-cross@${DOCKER_CROSS_VERSION} AS fyne +FROM golang:${GO_VERSION}-buster AS tools ARG FYNE_VERSION -RUN GO111MODULE=on go get -ldflags="-w -s" -v "fyne.io/fyne/cmd/fyne@${FYNE_VERSION}" -# Build the gowindres command utility -FROM dockercore/golang-cross@${DOCKER_CROSS_VERSION} AS gowindres -WORKDIR /app -COPY . . -RUN GO111MODULE=on go build -o /go/bin/gowindres -ldflags="-w -s" ./internal/cmd/gowindres - -FROM golang:1.14.13-buster AS golang +# Install the fyne CLI tool +RUN go get -ldflags="-w -s" -v "fyne.io/fyne/v2/cmd/fyne@${FYNE_VERSION}" # Build the fyne-cross base image -FROM dockercore/golang-cross@${DOCKER_CROSS_VERSION} +FROM golang:${GO_VERSION}-buster AS base -COPY --from=fyne /go/bin/fyne /usr/local/bin -COPY --from=gowindres /go/bin/gowindres /usr/local/bin -RUN rm -rf /usr/local/go -COPY --from=golang /usr/local/go /usr/local/go +COPY --from=tools /go/bin/fyne /usr/local/bin RUN apt-get update -qq \ && apt-get install -y -q --no-install-recommends \ + gosu \ + zip \ + unzip \ + # fyne deps libgl1-mesa-dev \ libegl1-mesa-dev \ libgles2-mesa-dev \ xorg-dev \ - gosu \ - zip \ - unzip \ # headers needed by xorg-dev x11proto-dev \ # deps to support wayland diff --git a/docker/darwin/Dockerfile b/docker/darwin/Dockerfile new file mode 100644 index 00000000..fa33533d --- /dev/null +++ b/docker/darwin/Dockerfile @@ -0,0 +1,46 @@ +ARG LLVM_VERSION=12 +ARG OSX_VERSION_MIN=10.12 +ARG OSX_CROSS_COMMIT="8a716a43a72dab1db9630d7824ee0af3730cb8f9" +ARG FYNE_CROSS_VERSION=1.1 + +## Build osxcross toolchain +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm as osxcross +ARG OSX_CROSS_COMMIT +ARG OSX_VERSION_MIN + +RUN apt-get update -qq && apt-get install -y -q --no-install-recommends \ + bzip2 \ + cmake \ + cpio \ + patch \ + libbz2-dev \ + libssl-dev \ + zlib1g-dev \ + liblzma-dev \ + libxml2-dev \ + uuid-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY *.dmg /tmp/command_line_tools_for_xcode.dmg + +WORKDIR "/osxcross" + +RUN curl -L https://github.com/tpoechtrager/osxcross/archive/${OSX_CROSS_COMMIT}.tar.gz | tar -zx --strip-components=1 + +RUN ./tools/gen_sdk_package_tools_dmg.sh /tmp/command_line_tools_for_xcode.dmg + +ARG SDK_VERSION +RUN echo "Available SDKs:" && ls -1 MacOSX*.tar.bz2 && \ + if [ -z "$SDK_VERSION" ] ;\ + then ls -1 MacOSX*.tar.bz2 | sort -Vr | head -1 | xargs -i mv {} tarballs ;\ + else mv MacOSX*.tar.bz2 tarballs ; \ + fi + +RUN UNATTENDED=yes SDK_VERSION=${SDK_VERSION} OSX_VERSION_MIN=${OSX_VERSION_MIN} ./build.sh + + +## Build darwin-latest image +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm + +COPY --from=osxcross /osxcross/target /osxcross/target +ENV PATH=/osxcross/target/bin:$PATH diff --git a/docker/freebsd-amd64/Dockerfile b/docker/freebsd-amd64/Dockerfile new file mode 100644 index 00000000..44d4cf37 --- /dev/null +++ b/docker/freebsd-amd64/Dockerfile @@ -0,0 +1,22 @@ +ARG FYNE_CROSS_VERSION + +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd + +# Download FreeBSD base, extract libs/includes, pkg keys and configs +# and install fyne dependencies +# Based on: https://github.com/myfreeweb/docker-freebsd-cross/tree/fc70196f62c00a10eb61a45a4798e09214e0cdfd +ENV ABI="FreeBSD:12:amd64" +RUN mkdir /freebsd \ + && mkdir /etc/pkg/ \ + && curl https://download.freebsd.org/ftp/releases/amd64/12.2-RELEASE/base.txz | \ + bsdtar -xf - -C /freebsd ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc \ + && cp /freebsd/etc/pkg/FreeBSD.conf /etc/pkg/ \ + && ln -s /freebsd/usr/share/keys /usr/share/keys \ + && pkg -r /freebsd install --yes xorg-minimal glfw + +# Set pkg variables required to compile +ENV PKG_CONFIG_SYSROOT_DIR=/freebsd +ENV PKG_CONFIG_LIBDIR=/freebsd/usr/libdata/pkgconfig:/freebsd/usr/local/libdata/pkgconfig + +# Copy the clang wrappers +COPY ./docker/freebsd-amd64/resources/*-unknown-freebsd12-* /usr/local/bin/ diff --git a/docker/freebsd/resources/x86_64-unknown-freebsd11-clang b/docker/freebsd-amd64/resources/x86_64-unknown-freebsd12-clang similarity index 93% rename from docker/freebsd/resources/x86_64-unknown-freebsd11-clang rename to docker/freebsd-amd64/resources/x86_64-unknown-freebsd12-clang index 57c39c55..d69ecb95 100755 --- a/docker/freebsd/resources/x86_64-unknown-freebsd11-clang +++ b/docker/freebsd-amd64/resources/x86_64-unknown-freebsd12-clang @@ -1,2 +1,2 @@ #!/bin/sh -exec clang --sysroot=/freebsd "$@" --target=x86_64-unknown-freebsd11 \ No newline at end of file +exec clang --sysroot=/freebsd "$@" --target=x86_64-unknown-freebsd12 diff --git a/docker/freebsd/resources/x86_64-unknown-freebsd11-clang++ b/docker/freebsd-amd64/resources/x86_64-unknown-freebsd12-clang++ similarity index 91% rename from docker/freebsd/resources/x86_64-unknown-freebsd11-clang++ rename to docker/freebsd-amd64/resources/x86_64-unknown-freebsd12-clang++ index b9d18f00..f8ebd4ac 100755 --- a/docker/freebsd/resources/x86_64-unknown-freebsd11-clang++ +++ b/docker/freebsd-amd64/resources/x86_64-unknown-freebsd12-clang++ @@ -1,2 +1,2 @@ #!/bin/sh -exec clang++ --sysroot=/freebsd "$@" --target=x86_64-unknown-freebsd11 \ No newline at end of file +exec clang++ --sysroot=/freebsd "$@" --target=x86_64-unknown-freebsd12 diff --git a/docker/freebsd-arm64/Dockerfile b/docker/freebsd-arm64/Dockerfile new file mode 100644 index 00000000..8305f1b6 --- /dev/null +++ b/docker/freebsd-arm64/Dockerfile @@ -0,0 +1,23 @@ +ARG FYNE_CROSS_VERSION + +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-freebsd + +# Download FreeBSD base, extract libs/includes, pkg keys and configs +# and install fyne dependencies +# Based on: https://github.com/myfreeweb/docker-freebsd-cross/tree/fc70196f62c00a10eb61a45a4798e09214e0cdfd +ENV ABI="FreeBSD:12:aarch64" +RUN mkdir /freebsd \ + && mkdir /etc/pkg/ \ + && curl https://download.freebsd.org/ftp/releases/arm64/12.2-RELEASE/base.txz | \ + bsdtar -xf - -C /freebsd ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc \ + && cp /freebsd/etc/pkg/FreeBSD.conf /etc/pkg/ \ + && ln -s /freebsd/usr/share/keys /usr/share/keys +RUN pkg -r /freebsd install --yes xorg glfw + + +# Set pkg variables required to compile +ENV PKG_CONFIG_SYSROOT_DIR=/freebsd +ENV PKG_CONFIG_LIBDIR=/freebsd/usr/libdata/pkgconfig:/freebsd/usr/local/libdata/pkgconfig + +# Copy the clang wrappers +COPY ./docker/freebsd-arm64/resources/*-unknown-freebsd12-* /usr/local/bin/ diff --git a/docker/freebsd-arm64/resources/aarch64-unknown-freebsd12-clang b/docker/freebsd-arm64/resources/aarch64-unknown-freebsd12-clang new file mode 100755 index 00000000..912655b8 --- /dev/null +++ b/docker/freebsd-arm64/resources/aarch64-unknown-freebsd12-clang @@ -0,0 +1,2 @@ +#!/bin/sh +exec clang --sysroot=/freebsd "$@" --target=aarch64-unknown-freebsd12 diff --git a/docker/freebsd-arm64/resources/aarch64-unknown-freebsd12-clang++ b/docker/freebsd-arm64/resources/aarch64-unknown-freebsd12-clang++ new file mode 100755 index 00000000..22baef71 --- /dev/null +++ b/docker/freebsd-arm64/resources/aarch64-unknown-freebsd12-clang++ @@ -0,0 +1,2 @@ +#!/bin/sh +exec clang++ --sysroot=/freebsd "$@" --target=aarch64-unknown-freebsd12 diff --git a/docker/freebsd/Dockerfile b/docker/freebsd/Dockerfile deleted file mode 100644 index 072f780a..00000000 --- a/docker/freebsd/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -FROM fyneio/fyne-cross:base-latest - -# Install pkg -# Based on https://github.com/freebsd/pkg/blob/release-1.12/.cirrus.yml#L19-L29 -# TODO: split run time and build time deps to save space -RUN apt-get update -qq \ - && apt-get install -y -q --no-install-recommends \ - libsqlite3-dev \ - libbsd-dev \ - libarchive-dev \ - libssl-dev \ - liblzma-dev \ - liblua5.2-dev \ - nettle-dev \ - liblzo2-dev \ - libattr1-dev \ - libacl1-dev \ - wget \ - build-essential \ - zlib1g-dev \ - libbz2-dev \ - m4 \ - libexpat1-dev \ - liblz4-dev \ - libxml2-dev \ - libzstd-dev \ - bsdtar \ - && mkdir /pkg \ - && curl -L https://github.com/freebsd/pkg/archive/1.12.0.tar.gz | bsdtar -xf - -C /pkg \ - && cd /pkg/pkg-* \ - && ./scripts/install_deps.sh \ - && ./configure --with-libarchive.pc \ - && make -j4 || make V=1 \ - && make install \ - && rm -rf /pkg \ - && apt-get -qy autoremove \ - && apt-get clean \ - && rm -r /var/lib/apt/lists/*; - -# Download FreeBSD base, extract libs/includes, pkg keys and configs -# and install fyne dependencies -# Based on: https://github.com/myfreeweb/docker-freebsd-cross/tree/fc70196f62c00a10eb61a45a4798e09214e0cdfd -ENV ABI="FreeBSD:11:amd64" -RUN mkdir /freebsd \ - && mkdir /etc/pkg/ \ - && curl https://download.freebsd.org/ftp/releases/amd64/11.2-RELEASE/base.txz | \ - bsdtar -xf - -C /freebsd ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc \ - && cp /freebsd/etc/pkg/FreeBSD.conf /etc/pkg/ \ - && ln -s /freebsd/usr/share/keys /usr/share/keys \ - && pkg -r /freebsd install --yes xorg-minimal glfw - -# Set pkg variables required to compile -ENV PKG_CONFIG_SYSROOT_DIR=/freebsd -ENV PKG_CONFIG_LIBDIR=/freebsd/usr/libdata/pkgconfig:/freebsd/usr/local/libdata/pkgconfig - -# Copy the clang wrappers -COPY ./docker/freebsd/resources/x86_64-unknown-freebsd11-* /usr/local/bin/ - -RUN pkg -r /freebsd install --yes xorg diff --git a/docker/linux-386/Dockerfile b/docker/linux-386/Dockerfile index f2255e0d..8fa51000 100644 --- a/docker/linux-386/Dockerfile +++ b/docker/linux-386/Dockerfile @@ -1,5 +1,7 @@ +ARG FYNE_CROSS_VERSION + # fyne-cross linux 386 image -FROM fyneio/fyne-cross:base-latest +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base RUN dpkg --add-architecture i386 \ && apt-get update -qq \ && apt-get install -y -q --no-install-recommends \ diff --git a/docker/linux-arm/Dockerfile b/docker/linux-arm/Dockerfile index 4600672b..5a7a351c 100644 --- a/docker/linux-arm/Dockerfile +++ b/docker/linux-arm/Dockerfile @@ -1,5 +1,7 @@ +ARG FYNE_CROSS_VERSION + # fyne-cross linux arm image -FROM fyneio/fyne-cross:base-latest +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base RUN dpkg --add-architecture armhf \ && apt-get update -qq \ && apt-get install -y -q --no-install-recommends \ diff --git a/docker/linux-arm64/Dockerfile b/docker/linux-arm64/Dockerfile index 42e0f962..94a6cdf8 100644 --- a/docker/linux-arm64/Dockerfile +++ b/docker/linux-arm64/Dockerfile @@ -1,5 +1,7 @@ +ARG FYNE_CROSS_VERSION + # fyne-cross linux arm64 image -FROM fyneio/fyne-cross:base-latest +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base RUN dpkg --add-architecture arm64 \ && apt-get update -qq \ && apt-get install -y -q --no-install-recommends \ diff --git a/docker/windows/Dockerfile b/docker/windows/Dockerfile new file mode 100644 index 00000000..243eb195 --- /dev/null +++ b/docker/windows/Dockerfile @@ -0,0 +1,22 @@ +ARG FYNE_CROSS_VERSION + +## Build the gowindres CLI tool +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base AS builder + +WORKDIR /app +COPY . . + +RUN go build -o /go/bin/gowindres -ldflags="-w -s" ./internal/cmd/gowindres + +# Build the windows-base image +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base AS windows-base + +COPY --from=builder /go/bin/gowindres /usr/local/bin + +RUN apt-get update \ + && apt-get install -y -q --no-install-recommends \ + gcc-mingw-w64 \ + parallel \ + && apt-get -qy autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/*; diff --git a/internal/cmd/embed/main.go b/internal/cmd/embed/main.go new file mode 100644 index 00000000..ddfb707e --- /dev/null +++ b/internal/cmd/embed/main.go @@ -0,0 +1,33 @@ +// This file embeds resources like Dockerfiles to be used in fyne-cross +// TODO: move to go:embed once the go min version required by fyne-cross will be 1.16 +package main + +import ( + "fmt" + "io/ioutil" + "os" + "text/template" +) + +func main() { + b, err := ioutil.ReadFile("docker/darwin/Dockerfile") + if err != nil { + fmt.Printf("could not read darwin Dockerfile, please run from the project root: %s", err) + os.Exit(1) + } + + f, err := os.Create("internal/resource/darwin_dockerfile.go") + if err != nil { + fmt.Printf("could not write embedded darwin Dockerfile, please run from the project root: %s", err) + os.Exit(1) + } + t := template.Must(template.New("dockerfile").Parse(tpl)) + t.Execute(f, fmt.Sprintf("`%s`", b)) +} + +var tpl = `// auto-generated by cmd/internal/main.go DO NOT EDIT. + +package resource + +const DockerfileDarwin = {{.}} +` diff --git a/internal/command/android.go b/internal/command/android.go index 7b90d328..528c91c5 100644 --- a/internal/command/android.go +++ b/internal/command/android.go @@ -3,6 +3,7 @@ package command import ( "fmt" "os" + "path" "path/filepath" "github.com/fyne-io/fyne-cross/internal/log" @@ -13,7 +14,7 @@ const ( // androidOS is the android OS name androidOS = "android" // androidImage is the fyne-cross image for the Android OS - androidImage = "fyneio/fyne-cross:android-latest" + androidImage = "fyneio/fyne-cross:1.1-android" ) // Android build and package the fyne app for the android OS @@ -187,7 +188,16 @@ func makeAndroidContext(flags *androidFlags, args []string) (Context, error) { ctx.OS = androidOS ctx.ID = androidOS - ctx.Keystore = flags.Keystore + if path.IsAbs(flags.Keystore) { + return Context{}, fmt.Errorf("keystore location must be relative to the project root: %s", ctx.Volume.WorkDirHost()) + } + + _, err = os.Stat(volume.JoinPathHost(ctx.Volume.WorkDirHost(), flags.Keystore)) + if err != nil { + return Context{}, fmt.Errorf("keystore location must be under the project root: %s", ctx.Volume.WorkDirHost()) + } + + ctx.Keystore = volume.JoinPathContainer(ctx.Volume.WorkDirContainer(), flags.Keystore) ctx.KeystorePass = flags.KeystorePass ctx.KeyPass = flags.KeyPass diff --git a/internal/command/android_test.go b/internal/command/android_test.go new file mode 100644 index 00000000..7e66ed11 --- /dev/null +++ b/internal/command/android_test.go @@ -0,0 +1,128 @@ +package command + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_makeAndroidContext(t *testing.T) { + vol, err := mockDefaultVolume() + require.Nil(t, err) + + type args struct { + flags *androidFlags + args []string + } + tests := []struct { + name string + args args + want Context + wantErr bool + }{ + { + name: "keystore path must be relative to project root", + args: args{ + flags: &androidFlags{ + CommonFlags: &CommonFlags{ + AppBuild: 1, + AppID: "com.example.test", + }, + Keystore: "/tmp/my.keystore", + }, + }, + want: Context{}, + wantErr: true, + }, + { + name: "keystore path does not exist", + args: args{ + flags: &androidFlags{ + CommonFlags: &CommonFlags{ + AppBuild: 1, + AppID: "com.example.test", + }, + Keystore: "my.keystore", + }, + }, + want: Context{}, + wantErr: true, + }, + { + name: "default", + args: args{ + flags: &androidFlags{ + CommonFlags: &CommonFlags{ + AppBuild: 1, + AppID: "com.example.test", + }, + Keystore: "testdata/my.keystore", + }, + }, + want: Context{ + AppBuild: "1", + AppID: "com.example.test", + ID: androidOS, + OS: androidOS, + DockerImage: androidImage, + Volume: vol, + CacheEnabled: true, + StripDebug: true, + Package: ".", + Keystore: "/app/testdata/my.keystore", + }, + wantErr: false, + }, + { + name: "default", + args: args{ + flags: &androidFlags{ + CommonFlags: &CommonFlags{ + AppBuild: 1, + AppID: "com.example.test", + }, + Keystore: "./testdata/my.keystore", + }, + }, + want: Context{ + AppBuild: "1", + AppID: "com.example.test", + ID: androidOS, + OS: androidOS, + DockerImage: androidImage, + Volume: vol, + CacheEnabled: true, + StripDebug: true, + Package: ".", + Keystore: "/app/testdata/my.keystore", + }, + wantErr: false, + }, + { + name: "appID is mandatory", + args: args{ + flags: &androidFlags{ + CommonFlags: &CommonFlags{ + AppBuild: 1, + }, + Keystore: "./testdata/my.keystore", + }, + }, + want: Context{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx, err := makeAndroidContext(tt.args.flags, tt.args.args) + + if tt.wantErr { + require.NotNil(t, err) + return + } + require.Nil(t, err) + assert.Equal(t, tt.want, ctx) + }) + } +} diff --git a/internal/command/command.go b/internal/command/command.go index 2e3d786b..af37667f 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -109,7 +109,7 @@ func printUsage(template string, data interface{}) { func checkFyneBinHost(ctx Context) (string, error) { fyne, err := exec.LookPath("fyne") if err != nil { - return "", fmt.Errorf("missed requirement: fyne. To install: `go get fyne.io/fyne/cmd/fyne` and add $GOPATH/bin to $PATH") + return "", fmt.Errorf("missed requirement: fyne. To install: `go get fyne.io/fyne/v2/cmd/fyne` and add $GOPATH/bin to $PATH") } if ctx.Debug { @@ -137,11 +137,15 @@ func fynePackageHost(ctx Context) error { "-os", ctx.OS, "-name", ctx.Name, "-icon", volume.JoinPathContainer(ctx.TmpDirHost(), ctx.ID, icon.Default), - "-appID", ctx.AppID, "-appBuild", ctx.AppBuild, "-appVersion", ctx.AppVersion, } + // add appID to command, if any + if ctx.AppID != "" { + args = append(args, "-appID", ctx.AppID) + } + // add tags to command, if any tags := ctx.Tags if len(tags) > 0 { @@ -179,11 +183,15 @@ func fyneReleaseHost(ctx Context) error { "-os", ctx.OS, "-name", ctx.Name, "-icon", volume.JoinPathContainer(ctx.TmpDirHost(), ctx.ID, icon.Default), - "-appID", ctx.AppID, "-appBuild", ctx.AppBuild, "-appVersion", ctx.AppVersion, } + // add appID to command, if any + if ctx.AppID != "" { + args = append(args, "-appID", ctx.AppID) + } + // add tags to command, if any tags := ctx.Tags if len(tags) > 0 { @@ -192,14 +200,26 @@ func fyneReleaseHost(ctx Context) error { switch ctx.OS { case darwinOS: - args = append(args, "-category", ctx.Category) + if ctx.Category != "" { + args = append(args, "-category", ctx.Category) + } case iosOS: - args = append(args, "-certificate", ctx.Certificate) - args = append(args, "-profile", ctx.Profile) + if ctx.Certificate != "" { + args = append(args, "-certificate", ctx.Certificate) + } + if ctx.Profile != "" { + args = append(args, "-profile", ctx.Profile) + } case windowsOS: - args = append(args, "-certificate", ctx.Certificate) - args = append(args, "-developer", ctx.Developer) - args = append(args, "-password", ctx.Password) + if ctx.Certificate != "" { + args = append(args, "-certificate", ctx.Certificate) + } + if ctx.Developer != "" { + args = append(args, "-developer", ctx.Developer) + } + if ctx.Password != "" { + args = append(args, "-password", ctx.Password) + } } // run the command from the host diff --git a/internal/command/context_test.go b/internal/command/context_test.go index e38a6a49..d734e872 100644 --- a/internal/command/context_test.go +++ b/internal/command/context_test.go @@ -33,6 +33,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -50,6 +51,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -68,6 +70,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -86,6 +89,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -103,6 +107,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -120,6 +125,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -137,6 +143,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -154,6 +161,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -181,6 +189,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -209,6 +218,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -228,6 +238,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", AppVersion: "1.0", Volume: vol, CacheEnabled: true, @@ -247,6 +258,7 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", Volume: vol, CacheEnabled: true, StripDebug: true, @@ -265,6 +277,27 @@ func Test_makeDefaultContext(t *testing.T) { }, want: Context{ AppBuild: "1", + AppID: "", + Volume: vol, + CacheEnabled: true, + StripDebug: true, + Package: ".", + Name: "test", + }, + wantErr: false, + }, + { + name: "appID", + args: args{ + flags: &CommonFlags{ + AppBuild: 1, + AppID: "com.example.test", + Name: "test", + }, + }, + want: Context{ + AppBuild: "1", + AppID: "com.example.test", Volume: vol, CacheEnabled: true, StripDebug: true, diff --git a/internal/command/darwin.go b/internal/command/darwin.go index 5979cb0e..ae8bc38a 100644 --- a/internal/command/darwin.go +++ b/internal/command/darwin.go @@ -1,6 +1,7 @@ package command import ( + "errors" "fmt" "os" "path/filepath" @@ -17,14 +18,15 @@ const ( var ( // darwinArchSupported defines the supported target architectures on darwin - darwinArchSupported = []Architecture{ArchAmd64, Arch386} + darwinArchSupported = []Architecture{ArchAmd64, ArchArm64} // darwinImage is the fyne-cross image for the Darwin OS - darwinImage = "fyneio/fyne-cross:base-latest" + darwinImage = "fyneio/fyne-cross:1.1-darwin" ) // Darwin build and package the fyne app for the darwin OS type Darwin struct { - Context []Context + Context []Context + localBuild bool } // Name returns the one word command name @@ -50,6 +52,11 @@ func (cmd *Darwin) Parse(args []string) error { } flagSet.Var(flags.TargetArch, "arch", fmt.Sprintf(`List of target architecture to build separated by comma. Supported arch: %s`, darwinArchSupported)) + // Add flags to use only on darwin host + if runtime.GOOS == darwinOS { + flagSet.BoolVar(&cmd.localBuild, "local", true, "If set uses the fyne CLI tool installed on the host in place of the docker images") + } + // flags used only in release mode flagSet.StringVar(&flags.Category, "category", "", "The category of the app for store listing") @@ -120,6 +127,14 @@ func (cmd *Darwin) Run() error { if err != nil { return fmt.Errorf("could not package the Fyne app: %v", err) } + } else if cmd.localBuild { + packageName = fmt.Sprintf("%s.app", ctx.Name) + srcFile = volume.JoinPathHost(ctx.WorkDirHost(), packageName) + + err = fynePackageHost(ctx) + if err != nil { + return fmt.Errorf("could not package the Fyne app: %v", err) + } } else { err = goBuild(ctx) if err != nil { @@ -201,6 +216,9 @@ func darwinContext(flags *darwinFlags, args []string) ([]Context, error) { if err != nil { return ctxs, err } + if ctx.AppID == "" { + return ctxs, errors.New("appID is mandatory") + } ctx.Architecture = arch ctx.OS = darwinOS @@ -209,9 +227,9 @@ func darwinContext(flags *darwinFlags, args []string) ([]Context, error) { switch arch { case ArchAmd64: - ctx.Env = append(ctx.Env, "GOOS=darwin", "GOARCH=amd64", "CC=o32-clang") - case Arch386: - ctx.Env = append(ctx.Env, "GOOS=darwin", "GOARCH=386", "CC=o32-clang") + ctx.Env = append(ctx.Env, "GOOS=darwin", "GOARCH=amd64", "CC=o64-clang", "CGO_CFLAGS=-mmacosx-version-min=10.12", "CGO_LDFLAGS=-mmacosx-version-min=10.12") + case ArchArm64: + ctx.Env = append(ctx.Env, "CGO_LDFLAGS=-fuse-ld=lld", "GOOS=darwin", "GOARCH=arm64", "CC=oa64-clang", "CGO_CFLAGS=-mmacosx-version-min=11.1", "CGO_LDFLAGS=-mmacosx-version-min=11.1") } // set context based on command-line flags diff --git a/internal/command/darwin_image.go b/internal/command/darwin_image.go new file mode 100644 index 00000000..fba32e65 --- /dev/null +++ b/internal/command/darwin_image.go @@ -0,0 +1,128 @@ +package command + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + "strings" + + "github.com/fyne-io/fyne-cross/internal/log" + "github.com/fyne-io/fyne-cross/internal/resource" + "github.com/fyne-io/fyne-cross/internal/volume" +) + +// DarwinImage builds the darwin docker image +type DarwinImage struct { + sdkPath string + sdkVersion string +} + +// Name returns the one word command name +func (cmd *DarwinImage) Name() string { + return "darwin-image" +} + +// Description returns the command description +func (cmd *DarwinImage) Description() string { + return "Build the docker image for darwin" +} + +// Parse parses the arguments and set the usage for the command +func (cmd *DarwinImage) Parse(args []string) error { + flagSet.StringVar(&cmd.sdkPath, "xcode-path", "", "Path to the Command Line Tools for Xcode (i.e. /tmp/Command_Line_Tools_for_Xcode_12.5.dmg)") + flagSet.StringVar(&cmd.sdkVersion, "sdk-version", "", "SDK version to use. Default to automatic detection") + + flagSet.Usage = cmd.Usage + flagSet.Parse(args) + + if cmd.sdkPath == "" { + return errors.New("path to the Command Line Tools for Xcode using the 'xcode-path' is required.\nRun 'fyne-cross darwin-image --help' for details") + } + + i, err := os.Stat(cmd.sdkPath) + if os.IsNotExist(err) { + return fmt.Errorf("Command Line Tools for Xcode file %q does not exists", cmd.sdkPath) + } + if err != nil { + return fmt.Errorf("Command Line Tools for Xcode file %q error: %s", cmd.sdkPath, err) + } + if i.IsDir() { + return fmt.Errorf("Command Line Tools for Xcode file %q is a directory", cmd.sdkPath) + } + if !strings.HasSuffix(cmd.sdkPath, ".dmg") { + return fmt.Errorf("Command Line Tools for Xcode file must be in dmg format") + } + + return nil +} + +// Run runs the command +func (cmd *DarwinImage) Run() error { + + workDir, err := ioutil.TempDir(os.TempDir(), "fyne-cross-darwin-build") + if err != nil { + return fmt.Errorf("could not create temporary dir: %s", err) + } + defer os.RemoveAll(workDir) + + log.Info("[i] Building docker darwin image...") + log.Infof("[i] Work dir: %s", workDir) + + xcodeFile := volume.JoinPathHost(workDir, "command_line_tools_for_xcode.dmg") + log.Infof("[i] Copying the Command Line Tools for Xcode from %s to %s...", cmd.sdkPath, xcodeFile) + err = volume.Copy(cmd.sdkPath, xcodeFile) + if err != nil { + return fmt.Errorf("could not copy the Command Line Tools for Xcode file into the work dir: %s", err) + } + log.Infof("[✓] Command Line Tools for Xcode copied") + + err = ioutil.WriteFile(volume.JoinPathHost(workDir, "Dockerfile"), []byte(resource.DockerfileDarwin), 0644) + if err != nil { + return fmt.Errorf("could not create the Dockerfile into the work dir: %s", err) + } + log.Infof("[✓] Dockerfile created") + + log.Info("[i] Building docker image...") + ver := "auto" + if cmd.sdkVersion != "" { + ver = cmd.sdkVersion + } + log.Info("[i] macOS SDK: ", ver) + + // run the command from the host + dockerCmd := exec.Command("docker", "build", "--pull", "--build-arg", fmt.Sprintf("SDK_VERSION=%s", cmd.sdkVersion), "-t", darwinImage, ".") + dockerCmd.Dir = workDir + dockerCmd.Stdout = os.Stdout + dockerCmd.Stderr = os.Stderr + + err = dockerCmd.Run() + if err != nil { + return fmt.Errorf("could not create the docker darwin image: %v", err) + } + log.Infof("[✓] Docker image created: %s", darwinImage) + return nil +} + +// Usage displays the command usage +func (cmd *DarwinImage) Usage() { + data := struct { + Name string + Description string + }{ + Name: cmd.Name(), + Description: cmd.Description(), + } + + template := ` +Usage: fyne-cross {{ .Name }} [options] + +{{ .Description }} + +Options: +` + + printUsage(template, data) + flagSet.PrintDefaults() +} diff --git a/internal/command/docker.go b/internal/command/docker.go index 71cd7806..a78670bc 100644 --- a/internal/command/docker.go +++ b/internal/command/docker.go @@ -189,11 +189,15 @@ func fynePackage(ctx Context) error { "-os", ctx.OS, "-name", ctx.Name, "-icon", volume.JoinPathContainer(ctx.TmpDirContainer(), ctx.ID, icon.Default), - "-appID", ctx.AppID, "-appBuild", ctx.AppBuild, "-appVersion", ctx.AppVersion, } + // add appID to command, if any + if ctx.AppID != "" { + args = append(args, "-appID", ctx.AppID) + } + // add tags to command, if any tags := ctx.Tags if len(tags) > 0 { @@ -249,11 +253,15 @@ func fyneRelease(ctx Context) error { "-os", ctx.OS, "-name", ctx.Name, "-icon", volume.JoinPathContainer(ctx.TmpDirContainer(), ctx.ID, icon.Default), - "-appID", ctx.AppID, "-appBuild", ctx.AppBuild, "-appVersion", ctx.AppVersion, } + // add appID to command, if any + if ctx.AppID != "" { + args = append(args, "-appID", ctx.AppID) + } + // add tags to command, if any tags := ctx.Tags if len(tags) > 0 { @@ -266,16 +274,32 @@ func fyneRelease(ctx Context) error { switch ctx.OS { case androidOS: workDir = volume.JoinPathContainer(workDir, ctx.Package) - args = append(args, "-keyStore", ctx.Keystore) - args = append(args, "-keyStorePass", ctx.KeystorePass) - args = append(args, "-keyPass", ctx.KeyPass) + if ctx.Keystore != "" { + args = append(args, "-keyStore", ctx.Keystore) + } + if ctx.KeystorePass != "" { + args = append(args, "-keyStorePass", ctx.KeystorePass) + } + if ctx.KeyPass != "" { + args = append(args, "-keyPass", ctx.KeyPass) + } case iosOS: - args = append(args, "-certificate", ctx.Certificate) - args = append(args, "-profile", ctx.Profile) + if ctx.Certificate != "" { + args = append(args, "-certificate", ctx.Certificate) + } + if ctx.Profile != "" { + args = append(args, "-profile", ctx.Profile) + } case windowsOS: - args = append(args, "-certificate", ctx.Certificate) - args = append(args, "-developer", ctx.Developer) - args = append(args, "-password", ctx.Password) + if ctx.Certificate != "" { + args = append(args, "-certificate", ctx.Certificate) + } + if ctx.Developer != "" { + args = append(args, "-developer", ctx.Developer) + } + if ctx.Password != "" { + args = append(args, "-password", ctx.Password) + } } runOpts := Options{ diff --git a/internal/command/flag.go b/internal/command/flag.go index b588997b..e46fb19d 100644 --- a/internal/command/flag.go +++ b/internal/command/flag.go @@ -75,11 +75,11 @@ func newCommonFlags() (*CommonFlags, error) { flags := &CommonFlags{} flagSet.IntVar(&flags.AppBuild, "app-build", 1, "Build number, should be greater than 0 and incremented for each build") - flagSet.StringVar(&flags.AppID, "app-id", name, "Application ID used for distribution") + flagSet.StringVar(&flags.AppID, "app-id", "", "Application ID used for distribution") flagSet.StringVar(&flags.AppVersion, "app-version", "1.0", "Version number in the form x, x.y or x.y.z semantic version") flagSet.StringVar(&flags.CacheDir, "cache", cacheDir, "Directory used to share/cache sources and dependencies") flagSet.BoolVar(&flags.NoCache, "no-cache", false, "Do not use the go build cache") - flagSet.Var(&flags.Env, "env", "List of additional env variables specified as KEY=VALUE and separated by comma") + flagSet.Var(&flags.Env, "env", "List of additional env variables specified as KEY=VALUE") flagSet.StringVar(&flags.Icon, "icon", defaultIcon, "Application icon used for distribution") flagSet.StringVar(&flags.DockerImage, "image", "", "Custom docker image to use for build") flagSet.StringVar(&flags.Ldflags, "ldflags", "", "Additional flags to pass to the external linker") @@ -115,23 +115,11 @@ func (ef *envFlag) String() string { // Set is the method to set the flag value, part of the flag.Value interface. // Set's argument is a string to be parsed to set the flag. -// It's a comma-separated list, so we split it. func (ef *envFlag) Set(value string) error { - *ef = []string{} - if len(*ef) > 1 { - return errors.New("flag already set") - } - - for _, v := range strings.Split(value, ",") { - *ef = append(*ef, v) - } - - // validate env vars - for _, v := range *ef { - if !strings.Contains(v, "=") { - return errors.New("env var must defined as KEY=VALUE or KEY=") - } + if !strings.Contains(value, "=") { + return errors.New("env var must defined as KEY=VALUE or KEY=") } + *ef = append(*ef, value) return nil } diff --git a/internal/command/flag_test.go b/internal/command/flag_test.go index ad00eb8f..484a430d 100644 --- a/internal/command/flag_test.go +++ b/internal/command/flag_test.go @@ -5,46 +5,54 @@ import "testing" func Test_envFlag_Set(t *testing.T) { tests := []struct { name string - value string + value []string wantLen int wantErr bool }{ { name: "simple env var", - value: "CGO_ENABLED=1", + value: []string{"CGO_ENABLED=1"}, wantLen: 1, wantErr: false, }, { name: "env var without value", - value: "KEY=", + value: []string{"KEY="}, wantLen: 1, wantErr: false, }, { name: "env var with value containing =", - value: "GOFLAGS=-mod=vendor", + value: []string{"GOFLAGS=-mod=vendor"}, wantLen: 1, wantErr: false, }, { name: "two env vars", - value: "GOFLAGS=-mod=vendor,KEY=value", + value: []string{"GOFLAGS=-mod=vendor", "KEY=value"}, wantLen: 2, wantErr: false, }, { name: "invalid", - value: "GOFLAGS", - wantLen: 1, + value: []string{"GOFLAGS"}, + wantLen: 0, wantErr: true, }, + { + name: "env var with value containing comma", + value: []string{"GOFLAGS=https://goproxy.io,direct"}, + wantLen: 1, + wantErr: false, + }, } for _, tt := range tests { ef := &envFlag{} t.Run(tt.name, func(t *testing.T) { - if err := ef.Set(tt.value); (err != nil) != tt.wantErr { - t.Errorf("envFlag.Set() error = %v, wantErr %v", err, tt.wantErr) + for _, v := range tt.value { + if err := ef.Set(v); (err != nil) != tt.wantErr { + t.Errorf("envFlag.Set() error = %v, wantErr %v", err, tt.wantErr) + } } if len(*ef) != tt.wantLen { t.Errorf("envFlag len error = %v, wantLen %v", len(*ef), tt.wantLen) diff --git a/internal/command/freebsd.go b/internal/command/freebsd.go index 630142c9..eada2f95 100644 --- a/internal/command/freebsd.go +++ b/internal/command/freebsd.go @@ -14,12 +14,14 @@ const ( // freebsdOS it the freebsd OS name freebsdOS = "freebsd" // freebsdImageAmd64 is the fyne-cross image for the FreeBSD OS amd64 arch - freebsdImageAmd64 = "fyneio/fyne-cross:freebsd-latest" + freebsdImageAmd64 = "fyneio/fyne-cross:1.1-freebsd-amd64" + // freebsdImageArm64 is the fyne-cross image for the FreeBSD OS arm64 arch + freebsdImageArm64 = "fyneio/fyne-cross:1.1-freebsd-arm64" ) var ( // freebsdArchSupported defines the supported target architectures on freebsd - freebsdArchSupported = []Architecture{ArchAmd64} + freebsdArchSupported = []Architecture{ArchAmd64, ArchArm64} ) // FreeBSD build and package the fyne app for the freebsd OS @@ -188,7 +190,10 @@ func freebsdContext(flags *freebsdFlags, args []string) ([]Context, error) { switch arch { case ArchAmd64: defaultDockerImage = freebsdImageAmd64 - ctx.Env = append(ctx.Env, "GOOS=freebsd", "GOARCH=amd64", "CC=x86_64-unknown-freebsd11-clang") + ctx.Env = append(ctx.Env, "GOOS=freebsd", "GOARCH=amd64", "CC=x86_64-unknown-freebsd12-clang") + case ArchArm64: + defaultDockerImage = freebsdImageArm64 + ctx.Env = append(ctx.Env, "CGO_LDFLAGS=-fuse-ld=lld", "GOOS=freebsd", "GOARCH=arm64", "CC=aarch64-unknown-freebsd12-clang") } // set context based on command-line flags diff --git a/internal/command/ios.go b/internal/command/ios.go index b65bc5dc..f77cb35e 100644 --- a/internal/command/ios.go +++ b/internal/command/ios.go @@ -14,7 +14,7 @@ const ( // iosOS it the ios OS name iosOS = "ios" // iosImage is the fyne-cross image for the iOS OS - iosImage = "fyneio/fyne-cross:base-latest" + iosImage = "fyneio/fyne-cross:1.1-base" ) // IOS build and package the fyne app for the ios OS diff --git a/internal/command/linux.go b/internal/command/linux.go index e473f4e6..fc0997fe 100644 --- a/internal/command/linux.go +++ b/internal/command/linux.go @@ -14,10 +14,10 @@ const ( // linuxOS it the linux OS name linuxOS = "linux" // linuxImage is the fyne-cross image for the Linux OS - linuxImageAmd64 = "fyneio/fyne-cross:base-latest" - linuxImage386 = "fyneio/fyne-cross:linux-386-latest" - linuxImageArm64 = "fyneio/fyne-cross:linux-arm64-latest" - linuxImageArm = "fyneio/fyne-cross:linux-arm-latest" + linuxImageAmd64 = "fyneio/fyne-cross:1.1-base" + linuxImage386 = "fyneio/fyne-cross:1.1-linux-386" + linuxImageArm64 = "fyneio/fyne-cross:1.1-linux-arm64" + linuxImageArm = "fyneio/fyne-cross:1.1-linux-arm" ) var ( @@ -51,7 +51,7 @@ func (cmd *Linux) Parse(args []string) error { CommonFlags: commonFlags, TargetArch: &targetArchFlag{runtime.GOARCH}, } - flagSet.Var(flags.TargetArch, "arch", fmt.Sprintf(`List of target architecture to build separated by comma. Supported arch: %s`, windowsArchSupported)) + flagSet.Var(flags.TargetArch, "arch", fmt.Sprintf(`List of target architecture to build separated by comma. Supported arch: %s`, linuxArchSupported)) flagSet.Usage = cmd.Usage flagSet.Parse(args) diff --git a/internal/command/testdata/my.keystore b/internal/command/testdata/my.keystore new file mode 100644 index 00000000..30d74d25 --- /dev/null +++ b/internal/command/testdata/my.keystore @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/internal/command/windows.go b/internal/command/windows.go index c48aea35..eacc38b5 100644 --- a/internal/command/windows.go +++ b/internal/command/windows.go @@ -15,7 +15,7 @@ const ( // windowsOS it the windows OS name windowsOS = "windows" // windowsImage is the fyne-cross image for the Windows OS - windowsImage = "fyneio/fyne-cross:base-latest" + windowsImage = "fyneio/fyne-cross:1.1-windows" ) var ( diff --git a/internal/command/windows_test.go b/internal/command/windows_test.go index 11314405..606c3ec7 100644 --- a/internal/command/windows_test.go +++ b/internal/command/windows_test.go @@ -43,7 +43,7 @@ func Test_makeWindowsContext(t *testing.T) { Architecture: "amd64", Env: []string{"GOOS=windows", "GOARCH=amd64", "CC=x86_64-w64-mingw32-gcc"}, LdFlags: []string{"-H windowsgui"}, - DockerImage: "fyneio/fyne-cross:base-latest", + DockerImage: windowsImage, }, }, }, @@ -69,7 +69,7 @@ func Test_makeWindowsContext(t *testing.T) { OS: "windows", Architecture: "386", Env: []string{"GOOS=windows", "GOARCH=386", "CC=i686-w64-mingw32-gcc"}, - DockerImage: "fyneio/fyne-cross:base-latest", + DockerImage: windowsImage, }, }, }, @@ -96,7 +96,7 @@ func Test_makeWindowsContext(t *testing.T) { Architecture: "amd64", Env: []string{"GOOS=windows", "GOARCH=amd64", "CC=x86_64-w64-mingw32-gcc"}, LdFlags: []string{"-X main.version=1.2.3", "-H windowsgui"}, - DockerImage: "fyneio/fyne-cross:base-latest", + DockerImage: windowsImage, }, }, }, diff --git a/internal/resource/darwin_dockerfile.go b/internal/resource/darwin_dockerfile.go new file mode 100644 index 00000000..9291c7f5 --- /dev/null +++ b/internal/resource/darwin_dockerfile.go @@ -0,0 +1,51 @@ +// auto-generated by cmd/internal/main.go DO NOT EDIT. + +package resource + +const DockerfileDarwin = `ARG LLVM_VERSION=12 +ARG OSX_VERSION_MIN=10.12 +ARG OSX_CROSS_COMMIT="8a716a43a72dab1db9630d7824ee0af3730cb8f9" +ARG FYNE_CROSS_VERSION=1.1 + +## Build osxcross toolchain +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm as osxcross +ARG OSX_CROSS_COMMIT +ARG OSX_VERSION_MIN + +RUN apt-get update -qq && apt-get install -y -q --no-install-recommends \ + bzip2 \ + cmake \ + cpio \ + patch \ + libbz2-dev \ + libssl-dev \ + zlib1g-dev \ + liblzma-dev \ + libxml2-dev \ + uuid-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY *.dmg /tmp/command_line_tools_for_xcode.dmg + +WORKDIR "/osxcross" + +RUN curl -L https://github.com/tpoechtrager/osxcross/archive/${OSX_CROSS_COMMIT}.tar.gz | tar -zx --strip-components=1 + +RUN ./tools/gen_sdk_package_tools_dmg.sh /tmp/command_line_tools_for_xcode.dmg + +ARG SDK_VERSION +RUN echo "Available SDKs:" && ls -1 MacOSX*.tar.bz2 && \ + if [ -z "$SDK_VERSION" ] ;\ + then ls -1 MacOSX*.tar.bz2 | sort -Vr | head -1 | xargs -i mv {} tarballs ;\ + else mv MacOSX*.tar.bz2 tarballs ; \ + fi + +RUN UNATTENDED=yes SDK_VERSION=${SDK_VERSION} OSX_VERSION_MIN=${OSX_VERSION_MIN} ./build.sh + + +## Build darwin-latest image +FROM fyneio/fyne-cross:${FYNE_CROSS_VERSION}-base-llvm + +COPY --from=osxcross /osxcross/target /osxcross/target +ENV PATH=/osxcross/target/bin:$PATH +` diff --git a/internal/volume/volume.go b/internal/volume/volume.go index 0c3d763b..59c2ab49 100644 --- a/internal/volume/volume.go +++ b/internal/volume/volume.go @@ -9,6 +9,7 @@ import ( "io" "io/ioutil" "os" + "path" "path/filepath" "strings" @@ -103,13 +104,13 @@ func Mount(workDirHost string, cacheDirHost string) (Volume, error) { // JoinPathContainer joins any number of path elements into a single path, // separating them with the Container OS specific Separator. func JoinPathContainer(elem ...string) string { - return strings.Join(elem, "/") + return path.Clean(strings.Join(elem, "/")) } // JoinPathHost joins any number of path elements into a single path, // separating them with the Host OS specific Separator. func JoinPathHost(elem ...string) string { - return filepath.Join(elem...) + return filepath.Clean(filepath.Join(elem...)) } // Zip compress the source file into a zip archive diff --git a/main.go b/main.go index ecd3869a..cae8faf3 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ func main() { // Define the command to use commands := []command.Command{ + &command.DarwinImage{}, &command.Darwin{}, &command.Linux{}, &command.Windows{},