├── LICENSE ├── Makefile └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dmitry Danilov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME?=project 2 | 3 | DOCKER_CC?=clang 4 | DOCKER_CXX?=clang++ 5 | 6 | DOCKER_DEPS_REPO?=${PROJECT_NAME}/ 7 | DOCKER_DEPS_IMAGE?=${PROJECT_NAME}_build 8 | DOCKER_DEPS_VERSION?=latest 9 | DOCKER_DEPS_CONTAINER?=${DOCKER_DEPS_IMAGE} 10 | DOCKER_DEPS_FILE?=DockerfileBuildEnv 11 | 12 | DOCKER_DEPS_IMAGE_BUILD_FLAGS?=--no-cache=true 13 | 14 | DOCKER_PREPEND_MAKEFILES?= 15 | DOCKER_APPEND_MAKEFILES?= 16 | 17 | DOCKER_CMAKE_FLAGS?= 18 | 19 | DOCKER_SHELL?=bash 20 | LOCAL_SOURCE_PATH?=${CURDIR} 21 | DOCKER_SOURCE_PATH?=/${PROJECT_NAME} 22 | DOCKER_BUILD_DIR?=build 23 | DOCKER_CTEST_TIMEOUT?=5000 24 | 25 | DOCKER_TEST_CORE_DIR?=${DOCKER_BUILD_DIR}/cores 26 | 27 | DOCKER_ADDITIONAL_RUN_PARAMS?= 28 | 29 | DOCKER_USER_ROOT=OFF 30 | 31 | ifeq ($(DOCKER_USER_ROOT),OFF) 32 | DOCKER_USER?=--user $(shell id -u):$(shell id -g) 33 | else 34 | endif 35 | 36 | DOCKER_BASIC_RUN_PARAMS?=-it --init --rm \ 37 | ${DOCKER_USER} \ 38 | --memory-swap=-1 \ 39 | --ulimit core=-1 \ 40 | --name="${DOCKER_DEPS_CONTAINER}" \ 41 | --workdir=${DOCKER_SOURCE_PATH} \ 42 | --mount type=bind,source=${LOCAL_SOURCE_PATH},target=${DOCKER_SOURCE_PATH} \ 43 | ${DOCKER_ADDITIONAL_RUN_PARAMS} \ 44 | ${DOCKER_DEPS_REPO}${DOCKER_DEPS_IMAGE}:${DOCKER_DEPS_VERSION} 45 | 46 | IF_CONTAINER_RUNS=$(shell docker container inspect -f '{{.State.Running}}' ${DOCKER_DEPS_CONTAINER} 2>/dev/null) 47 | 48 | .DEFAULT_GOAL:=build 49 | 50 | -include ${DOCKER_PREPEND_MAKEFILES} 51 | 52 | .PHONY: help 53 | help: ## 54 | @cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | \ 55 | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 56 | 57 | .PHONY: gen_cmake 58 | gen_cmake: ## Generate cmake files, used internally 59 | docker run ${DOCKER_BASIC_RUN_PARAMS} \ 60 | ${DOCKER_SHELL} -c \ 61 | "mkdir -p ${DOCKER_SOURCE_PATH}/${DOCKER_BUILD_DIR} && \ 62 | cd ${DOCKER_BUILD_DIR} && \ 63 | CC=${DOCKER_CC} CXX=${DOCKER_CXX} \ 64 | cmake ${DOCKER_CMAKE_FLAGS} .." 65 | @echo 66 | @echo "CMake finished." 67 | 68 | .PHONY: build 69 | build: gen_cmake ## Build source. In order to build a specific target run: make TARGET=. 70 | docker run ${DOCKER_BASIC_RUN_PARAMS} \ 71 | ${DOCKER_SHELL} -c \ 72 | "cd ${DOCKER_BUILD_DIR} && \ 73 | make -j $$(nproc) ${TARGET}" 74 | @echo 75 | @echo "Build finished. The binaries are in ${CURDIR}/${DOCKER_BUILD_DIR}" 76 | 77 | .PHONY: test 78 | test: ## Run all tests 79 | docker run ${DOCKER_BASIC_RUN_PARAMS} \ 80 | ${DOCKER_SHELL} -c \ 81 | "mkdir -p ${DOCKER_TEST_CORE_DIR} && \ 82 | cd ${DOCKER_BUILD_DIR} && \ 83 | ctest --timeout ${DOCKER_CTEST_TIMEOUT} --output-on-failure" 84 | 85 | .PHONY: clean 86 | clean: ## Clean build directory 87 | docker run ${DOCKER_BASIC_RUN_PARAMS} \ 88 | ${DOCKER_SHELL} -c \ 89 | "rm -rf ${DOCKER_BUILD_DIR}" 90 | 91 | .PHONY: login 92 | login: ## Login to the container. Note: if the container is already running, login into existing one 93 | @if [ "${IF_CONTAINER_RUNS}" != "true" ]; then \ 94 | docker run ${DOCKER_BASIC_RUN_PARAMS} \ 95 | ${DOCKER_SHELL}; \ 96 | else \ 97 | docker exec -it ${DOCKER_DEPS_CONTAINER} \ 98 | ${DOCKER_SHELL}; \ 99 | fi 100 | 101 | .PHONY: build-docker-deps-image 102 | build-docker-deps-image: ## Build the deps image. 103 | docker build ${DOCKER_DEPS_IMAGE_BUILD_FLAGS} -t ${DOCKER_DEPS_REPO}${DOCKER_DEPS_IMAGE}:latest \ 104 | -f ./${DOCKER_DEPS_FILE} . 105 | @echo 106 | @echo "Build finished. Docker image name: \"${DOCKER_DEPS_REPO}${DOCKER_DEPS_IMAGE}:latest\"." 107 | @echo "Before you push it to Docker Hub, please tag it(DOCKER_DEPS_VERSION + 1)." 108 | @echo "If you want the image to be the default, please update the following variables:" 109 | @echo "${CURDIR}/Makefile: DOCKER_DEPS_VERSION" 110 | 111 | -include ${DOCKER_APPEND_MAKEFILES} 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 2 | 3 | # Dockerized C/C++ Build Environment 4 | 5 | This repository contains a single highly customizable Makefile helping to build C/C++ projects in a docker container. 6 | 7 | ## Usage 8 | 9 | * Add this repository as a git submodule to your project, for example as directory build_tools:
10 | `git submodule add https://github.com/f-squirrel/dockerized_cpp.git build_tools/` 11 | * Create a Makefile in the root of your project's source tree 12 | * Override the variables from the [list](#list-of-variables) in the Makefile 13 | * Include the Makefile from this repository in your new Makefile: `include build_tools/Makefile` 14 | 15 | In order to see available commands including user-defined ones, run `make help`: 16 | 17 | ```plain 18 | $ make help 19 | gen_cmake Generate cmake files, used internally 20 | build Build source. In order to build a specific target run: make TARGET=. 21 | test Run all tests 22 | clean Clean build directory 23 | login Login to the container. Note: if the container is already running, login into existing one 24 | build-docker-deps-image Build the deps image. 25 | ``` 26 | 27 | ## Example 28 | 29 | An example of usage can be found in the repository ["Dockerized C/C++ Build Example"](https://github.com/f-squirrel/dockerized_cpp_build_example). 30 | 31 | ## List of variables 32 | 33 | | Variable name | Default value | Description | 34 | | ------------- | ------------- | ----------- | 35 | | `PROJECT_NAME` | project | Name of the project, by default used in multiple places | 36 | | `DOCKER_CC` | clang | C compiler used in the project | 37 | | `DOCKER_CXX` | clang++ | C++ copmiler used in the project | 38 | | `DOCKER_DEPS_REPO` | `${PROJECT_NAME}/` | Docker repository where the build image is stored | 39 | | `DOCKER_DEPS_IMAGE` | `${PROJECT_NAME}_build` | The name of the build image | 40 | | `DOCKER_DEPS_VERSION` | latest | Docker image version | 41 | | `DOCKER_DEPS_CONTAINER` | `${DOCKER_DEPS_IMAGE}` | The name of build's docker container | 42 | | `DOCKER_DEPS_FILE` | DockerfileBuildEnv | Dockerfile used for building the build image | 43 | | `DOCKER_DEPS_IMAGE_BUILD_FLAGS` | `--no-cache=true` | Flags used for building the image, note with this flag on, docker rebuilds from scratch the whole image | 44 | | `DOCKER_PREPEND_MAKEFILES` | empty | The list of space-separated custom Makefiles to be included before default targets | 45 | | `DOCKER_APPEND_MAKEFILES` | empty | The list of space-separated ustom Makefiles to be included after default targets | 46 | | `DOCKER_CMAKE_FLAGS` | empty | Project specific CMake flags | 47 | | `DOCKER_SHELL` | bash | Shell used in the container | 48 | | `LOCAL_SOURCE_PATH` | Current directory | The path to the source files | 49 | | `DOCKER_SOURCE_PATH` | `/${PROJECT_NAME}` | Path where source files are mounted in the container | 50 | | `DOCKER_BUILD_DIR` | build | Cmake build directory | 51 | | `DOCKER_CTEST_TIMEOUT` | 5000 | CMake test timeout | 52 | | `DOCKER_TEST_CORE_DIR` | `${DOCKER_BUILD_DIR}/cores` | Path to the core files. For more information on configuring core dumps in docker please refer [here](https://ddanilov.me/how-to-configure-core-dump-in-docker-container) | 53 | | `DOCKER_ADDITIONAL_RUN_PARAMS` | empty | Additional docker run commands | 54 | | `DOCKER_BASIC_RUN_PARAMS` | [link to the code](https://github.com/f-squirrel/dockerized_cpp/blob/master/Makefile#L29) | Default commands used for running the build container | 55 | | `DOCKER_USER_ROOT` | `OFF` | Runs container as root user | 56 | --------------------------------------------------------------------------------