diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..2f0c1deba --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +# Project Files unneeded by docker +ci/cache +ci/docker +.coin-or +.git +.gitignore +.github +.dockerignore +.clang-format +AUTHORS +INSTALL +install-sh +missing +README.md + +build/ + +# Editor directories and files +*.user +*.swp diff --git a/ci/Makefile b/ci/Makefile new file mode 100644 index 000000000..c4959cb05 --- /dev/null +++ b/ci/Makefile @@ -0,0 +1,142 @@ +PROJECT := coinutils +BRANCH := $(shell git rev-parse --abbrev-ref HEAD) +SHA1 := $(shell git rev-parse --verify HEAD) + +# General commands +.PHONY: help +BOLD=\e[1m +RESET=\e[0m + +help: + @echo -e "${BOLD}SYNOPSIS${RESET}" + @echo -e "\tmake [NOCACHE=1]" + @echo + @echo -e "${BOLD}DESCRIPTION${RESET}" + @echo -e "\ttest build inside docker container to have a reproductible build." + @echo + @echo -e "${BOLD}MAKE TARGETS${RESET}" + @echo -e "\t${BOLD}help${RESET}: display this help and exit." + @echo + @echo -e "\t${BOLD}${RESET}: build docker images for ALL DISTROS." + @echo -e "\t${BOLD}_${RESET}: build docker image for a specific distro." + @echo -e "\t${BOLD}save_${RESET}: Save docker images for ALL DISTROS." + @echo -e "\t${BOLD}save__${RESET}: Save the docker image for a specific distro." + @echo -e "\t${BOLD}sh__${RESET}: run a container using the docker image specified (debug purpose)." + @echo + @echo -e "\tWith ${BOLD}${RESET}:" + @echo -e "\t\t${BOLD}env${RESET}" + @echo -e "\t\t${BOLD}devel${RESET}" + @echo -e "\t\t${BOLD}build${RESET}" + @echo -e "\t\t${BOLD}test${RESET}" + @echo -e "\t\t${BOLD}install_env${RESET}" + @echo -e "\t\t${BOLD}install_devel${RESET}" + @echo -e "\t\t${BOLD}install_build${RESET}" + @echo -e "\t\t${BOLD}install_test${RESET}" + @echo -e "\te.g. 'make build'" + @echo + @echo -e "\tWith ${BOLD}${RESET}:" + @echo -e "\t\t${BOLD}alpine${RESET} (edge)" + @echo -e "\t\t${BOLD}archlinux${RESET} (latest)" + @echo -e "\t\t${BOLD}centos${RESET} (latest)" + @echo -e "\t\t${BOLD}debian${RESET} (latest)" + @echo -e "\t\t${BOLD}fedora${RESET} (latest)" + @echo -e "\t\t${BOLD}opensuse${RESET} (leap)" + @echo -e "\t\t${BOLD}ubuntu${RESET} (latest)" + @echo -e "\te.g. 'make ubuntu_test'" + @echo + @echo -e "\t${BOLD}clean${RESET}: Remove cache and ALL docker images." + @echo -e "\t${BOLD}clean_${RESET}: Remove cache and docker images for the specified distro." + @echo -e "\t${BOLD}clean_${RESET}: Remove virtual machine for the specified vm." + @echo + @echo -e "\t${BOLD}NOCACHE=1${RESET}: use 'docker build --no-cache' when building container (default use cache)." + @echo + @echo -e "branch: $(BRANCH)" + @echo -e "sha1: $(SHA1)" + +# Need to add cmd_distro to PHONY otherwise target are ignored since they do not +# contain recipe (using FORCE do not work here) +.PHONY: all +all: build + +# Delete all implicit rules to speed up makefile +MAKEFLAGS += --no-builtin-rules +.SUFFIXES: +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = +# Keep all intermediate files +# ToDo: try to remove it later +.SECONDARY: + +# Docker image name prefix. +IMAGE := ${PROJECT} + +ifdef NOCACHE +DOCKER_BUILD_CMD := docker build --no-cache +else +DOCKER_BUILD_CMD := docker build +endif + +DOCKER_RUN_CMD := docker run --rm --init --net=host + +# Currently supported distro +DISTROS = alpine archlinux centos debian fedora opensuse ubuntu + +# $* stem +# $< first prerequist +# $@ target name + +############ +## STAGES ## +############ +STAGES = env devel build test install_env install_devel install_build install_test +define make-stage-target = +#$$(info STAGE: $1) +#$$(info Create targets: $1 $(addsuffix _$1, $(DISTROS)).) +targets_$1 = $(addsuffix _$1, $(DISTROS)) +.PHONY: $1 $$(targets_$1) +$1: $$(targets_$1) +$$(targets_$1): %_$1: docker/%/Dockerfile + #@docker image rm -f ${IMAGE}:$$*_$1 2>/dev/null + ${DOCKER_BUILD_CMD} --target=$1 --tag ${IMAGE}:$$*_$1 -f $$< .. + +#$$(info Create targets: save_$1 $(addprefix save_, $(addsuffix _$1, $(DISTROS))) (debug).) +save_targets_$1 = $(addprefix save_, $(addsuffix _$1, $(DISTROS))) +.PHONY: save_$1 $$(save_targets_$1) +save_$1: $$(save_targets_$1) +$$(save_targets_$1): save_%_$1: cache/%/docker_$1.tar +cache/%/docker_$1.tar: %_$1 + @rm -f $$@ + mkdir -p cache/$$* + docker save ${IMAGE}:$$*_$1 -o $$@ + +#$$(info Create targets: $(addprefix sh_, $(addsuffix _$1, $(DISTROS))) (debug).) +sh_targets_$1 = $(addprefix sh_, $(addsuffix _$1, $(DISTROS))) +.PHONY: $$(sh_targets_$1) +$$(sh_targets_$1): sh_%_$1: %_$1 + ${DOCKER_RUN_CMD} -it --name ${IMAGE}_$$*_$1 ${IMAGE}:$$*_$1 + +#$$(info Create targets: $(addprefix clean_, $(addsuffix _$1, $(DISTROS))).) +clean_targets_$1 = $(addprefix clean_, $(addsuffix _$1, $(DISTROS))) +.PHONY: clean_$1 $$(clean_targets_$1) +clean_$1: $$(clean_targets_$1) +$$(clean_targets_$1): clean_%_$1: + docker image rm -f ${IMAGE}:$$*_$1 2>/dev/null + rm -f cache/$$*/docker_$1.tar +endef + +$(foreach stage,$(STAGES),$(eval $(call make-stage-target,$(stage)))) + +## CLEAN ## +clean_targets = $(addprefix clean_, $(DISTROS)) +.PHONY: clean $(clean_targets) +clean: $(clean_targets) + docker container prune -f + docker image prune -f + -rmdir cache +$(clean_targets): clean_%: $(addprefix clean_%_, $(STAGES)) + -rmdir cache/$* + +.PHONY: distclean +distclean: clean + -docker container rm -f $$(docker container ls -aq) + -docker image rm -f $$(docker image ls -aq) diff --git a/ci/docker/alpine/Dockerfile b/ci/docker/alpine/Dockerfile new file mode 100644 index 000000000..da0df2e04 --- /dev/null +++ b/ci/docker/alpine/Dockerfile @@ -0,0 +1,37 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/alpine +FROM alpine:edge AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN apk add --no-cache git build-base linux-headers cmake + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/docker/archlinux/Dockerfile b/ci/docker/archlinux/Dockerfile new file mode 100644 index 000000000..a87a82ca1 --- /dev/null +++ b/ci/docker/archlinux/Dockerfile @@ -0,0 +1,37 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/archlinux/ +FROM archlinux:latest AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN pacman -Syu --noconfirm base-devel git cmake + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/docker/centos/Dockerfile b/ci/docker/centos/Dockerfile new file mode 100644 index 000000000..b724e650d --- /dev/null +++ b/ci/docker/centos/Dockerfile @@ -0,0 +1,43 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/centos +FROM centos:latest AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN yum -y update \ +&& yum -y groupinstall "Development Tools" \ +&& yum -y install epel-release \ +&& yum -y install cmake3 \ +&& ln -s /usr/bin/cmake3 /usr/local/bin/cmake \ +&& yum clean all \ +&& rm -rf /var/cache/yum + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/docker/debian/Dockerfile b/ci/docker/debian/Dockerfile new file mode 100644 index 000000000..cb4850377 --- /dev/null +++ b/ci/docker/debian/Dockerfile @@ -0,0 +1,40 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/debian +FROM debian:latest AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN apt-get update -q \ +&& DEBIAN_FRONTEND=noninteractive apt-get install -yq git build-essential cmake \ +&& apt-get clean \ +&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/docker/fedora/Dockerfile b/ci/docker/fedora/Dockerfile new file mode 100644 index 000000000..66e5eba00 --- /dev/null +++ b/ci/docker/fedora/Dockerfile @@ -0,0 +1,40 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/fedora +FROM fedora:latest AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN dnf -y update \ +&& dnf -y groupinstall "Development Tools" \ +&& dnf -y install cmake gcc-c++ \ +&& dnf clean all + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/docker/opensuse/Dockerfile b/ci/docker/opensuse/Dockerfile new file mode 100644 index 000000000..bfdf290e4 --- /dev/null +++ b/ci/docker/opensuse/Dockerfile @@ -0,0 +1,40 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/r/opensuse/tumbleweed +FROM opensuse/leap AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN zypper up -y \ +&& zypper install -y gcc gcc-c++ cmake git \ +&& zypper clean -a +ENV CC=gcc CXX=g++ + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/docker/ubuntu/Dockerfile b/ci/docker/ubuntu/Dockerfile new file mode 100644 index 000000000..c5502e085 --- /dev/null +++ b/ci/docker/ubuntu/Dockerfile @@ -0,0 +1,40 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/ubuntu +FROM ubuntu:latest AS env +LABEL maintainer="corentinl@google.com" +# Install system build dependencies +ENV PATH=$PATH:/usr/local/bin +RUN apt-get update -q \ +&& DEBIAN_FRONTEND=noninteractive apt-get install -yq git build-essential cmake \ +&& apt-get clean \ +&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Add the library src to our build env +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN cmake --version +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v +RUN cmake --build build --target install -v + +FROM build AS test +RUN cmake --build build --target test -v + +# Test install rules +FROM env AS install_env +COPY --from=build /usr/local /usr/local/ + +FROM install_env AS install_devel +WORKDIR /home/sample +COPY ci/sample . + +FROM install_devel AS install_build +RUN cmake -S. -Bbuild +RUN cmake --build build --target all -v + +FROM install_build AS install_test +RUN cmake --build build --target test -v + diff --git a/ci/sample/CMakeLists.txt b/ci/sample/CMakeLists.txt new file mode 100644 index 000000000..2531c98f7 --- /dev/null +++ b/ci/sample/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.5) +project(Sample VERSION 1.0.0 LANGUAGES CXX) + +include(CTest) +find_package(CoinUtils REQUIRED) + +add_executable(sample main.cpp) +#target_compile_features(sample PUBLIC cxx_std_11) +set_target_properties(sample PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON + VERSION ${PROJECT_VERSION}) +target_link_libraries(sample PRIVATE Coin::CoinUtils) + +if(BUILD_TESTING) + add_test(NAME sample_UT COMMAND sample) +endif() + +include(GNUInstallDirs) +install(TARGETS sample + EXPORT SampleTargets + DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/ci/sample/main.cpp b/ci/sample/main.cpp new file mode 100644 index 000000000..295884931 --- /dev/null +++ b/ci/sample/main.cpp @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char** argv) { + std::cout << "version: " << COINUTILS_VERSION << std::endl; + return 0; +} +