From e960b2948084e5ede0f32144c3d4f066acaa3934 Mon Sep 17 00:00:00 2001 From: Bart Beumer Date: Fri, 16 Jan 2026 22:26:53 +0000 Subject: [PATCH] Dev container now uses pre-built packages. Added mechanism to create these packages. Prepared cross-platform support. Extensive changes have been made to the build environment. The dev-container now downloads packages instead of building them every time a dev-container is re-built. Seperate from that a mechanism has been created to consistenly build these packages, even cross platform. --- .devcontainer/Dockerfile | 22 ---------- .devcontainer/devcontainer.json | 16 +++++-- .devcontainer/postcreate.py | 36 ++++++++++++++++ README.md | 34 +++++++++++++++ applications/text2image/CMakeLists.txt | 4 +- bmrshared-freetype/CMakeLists.txt | 4 +- bmrshared-magic/lib/CMakeLists.txt | 4 +- bmrshared-magic/tst/CMakeLists.txt | 2 +- bmrshared/lib/CMakeLists.txt | 2 +- bmrshared/tst/CMakeLists.txt | 2 +- conanfile.py | 22 +++++++--- dev-environment.json | 6 +++ dev-prep-conan-pkgs.Dockerfile | 43 +++++++++++++++++++ devcontainer.Dockerfile | 32 ++++++++++++++ .../dev-prep-conan-pkgs.py | 39 +++++++++++++++++ scripts/dev-prep-conan-pkgs/entrypoint.sh | 5 +++ 16 files changed, 233 insertions(+), 40 deletions(-) delete mode 100644 .devcontainer/Dockerfile create mode 100755 .devcontainer/postcreate.py create mode 100644 README.md create mode 100644 dev-environment.json create mode 100644 dev-prep-conan-pkgs.Dockerfile create mode 100644 devcontainer.Dockerfile create mode 100644 scripts/dev-prep-conan-pkgs/dev-prep-conan-pkgs.py create mode 100644 scripts/dev-prep-conan-pkgs/entrypoint.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 796c970..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM alpine:3.21.3 - -# Install tools required for building. -RUN apk update && \ - apk add --no-cache \ - autoconf \ - bash \ - build-base \ - cmake \ - clang \ - clang-extra-tools \ - gdb \ - git \ - libstdc++ \ - libtool \ - linux-headers \ - m4 \ - perl \ - python3 \ - py3-pip && \ - pip install --break-system-packages conan && \ - conan profile detect diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1e64a64..335fe98 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,18 +1,26 @@ { - "name": "C++", + "name": "4beumer.nl C++", "build": { - "dockerfile": "Dockerfile" + "dockerfile": "../devcontainer.Dockerfile", }, + "postCreateCommand": "${containerWorkspaceFolder}/.devcontainer/postcreate.py --environment=${containerWorkspaceFolder}/dev-environment.json", // Configure tool-specific properties. "customizations": { "vscode": { - "settings": {}, + "settings": { + "conan-extension.installArgs": [ + "-of build", + "-s build_type=Debug", + "-s compiler.cppstd=23" + ], + }, "extensions": [ "ms-vscode.cpptools", + "ms-python.python", "twxs.cmake", "ms-vscode.cmake-tools", "konicy.conan-extension" ] } } -} \ No newline at end of file +} diff --git a/.devcontainer/postcreate.py b/.devcontainer/postcreate.py new file mode 100755 index 0000000..d0a2ac1 --- /dev/null +++ b/.devcontainer/postcreate.py @@ -0,0 +1,36 @@ +#! /usr/bin/python +import argparse +import json +import os +import subprocess +import sys + +def runcmd(command): + print('RUN ' + command) + process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + for line in iter(process.stdout.readline, b''): # b'' indicates EOF + print(line.decode('utf-8'), end='') + +def load_environment(filename): + with open(filename) as f: + return json.load(f) + + +parser = argparse.ArgumentParser() +parser.add_argument('--environment') +args = parser.parse_args() +environment = load_environment(args.environment) + + +env_build_type = environment["build_type"] +env_cppstd = environment["cppstd"] +env_conan_remote_fallback = environment["conan_remote_fallback"] +env_conan_remote_upload = environment["conan_remote_upload"] + +runcmd('conan remote remove conancenter') +runcmd('conan remote add conan-upload ' + env_conan_remote_upload) +runcmd('conan remote add conan-remote ' + env_conan_remote_fallback) + +runcmd('conan install . -of build -s compiler.cppstd=' + env_cppstd + ' -s build_type=' + env_build_type + ' --build=never') + +sys.exit(0) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..bfddae5 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Network experiment +This repository mostly contains personal experiments related to C++, CMake, conan, and some stuff that might end up on a raspberry pi. I have tried to rely mostly on development containers and almost no tools on the host. This should make it possible to build/develop/use this code on any machine that runs dev container, including ARM systems and Windows. + +## How to use: +### Start developing +1. Clone the repository to a location of your liking. +2. Have an IDE that supports dev containers. I have used Visual studio code. +3. Open the project in your IDE, it should offer to open the project in a dev container. + +Also take into consideration the following files: +1. ``dev-environment.json`` + This file contains information about the type of build, the C++ version to use, and conan remotes used to retrieve packages. +2. ``.devcontainer/devcontainer.json`` + Also contains configuration on plugins used (and some duplicated config on build type and C++ version). + +### Building conan dependencies +Available in this repository is a ``dev-pre-conan-pkgs.Dockerfile`` that can be used to build all the conan dependencies and upload them to a remote. +1. Use dev-environment.json to configure the remotes (Where retrieve info, where to upload binaries). +2. Build the docker image using the following command: + ``docker build -t tmp_bldconan -f dev-prep-conan-pkgs.Dockerfile .`` +3. Run using the image to build & upload packages: + ``docker run -ti tmp_bldconan`` + - While running a username and password will be required to login. + - Do not forget to remove the image if you do not need it anymore. + +Building conan packages for other architectures is also possible using "buildx". See external documentation on how to setup this feature. When setup, the following commands can be used to build for both 32 and 64 bit ARM (useful for raspberry pi). + + +- ``docker buildx build -t tmp_bldconan_arm64 -f dev-prep-conan-pkgs.Dockerfile . --load --platform=linux/arm64`` +- ``docker buildx build -t tmp_bldconan_arm32 -f dev-prep-conan-pkgs.Dockerfile . --load --platform=linux/arm`` +- ``docker run -ti --platform=linux/arm64 tmp_bldconan_arm64 `` +- ``docker run -ti --platform linux/arm tmp_bldconan_arm32`` + + diff --git a/applications/text2image/CMakeLists.txt b/applications/text2image/CMakeLists.txt index b02592d..8a7a26b 100644 --- a/applications/text2image/CMakeLists.txt +++ b/applications/text2image/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -find_package(Boost 1.84.0 REQUIRED COMPONENTS program_options headers CONFIG) +find_package(Boost 1.90.0 REQUIRED COMPONENTS program_options headers CONFIG) find_package(JPEG REQUIRED) project(text2image) @@ -11,7 +11,7 @@ add_executable( set_property( TARGET ${PROJECT_NAME} - PROPERTY CXX_STANDARD 20 + PROPERTY CXX_STANDARD 23 ) target_link_libraries( diff --git a/bmrshared-freetype/CMakeLists.txt b/bmrshared-freetype/CMakeLists.txt index 5bac2b0..c7c34b6 100644 --- a/bmrshared-freetype/CMakeLists.txt +++ b/bmrshared-freetype/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) find_package(freetype REQUIRED) -find_package(Boost 1.84.0 REQUIRED COMPONENTS headers CONFIG) +find_package(Boost 1.90.0 REQUIRED COMPONENTS headers CONFIG) project(bmrshared-freetype) @@ -14,7 +14,7 @@ add_library( set_property( TARGET ${PROJECT_NAME} - PROPERTY CXX_STANDARD 20 + PROPERTY CXX_STANDARD 23 ) target_include_directories( diff --git a/bmrshared-magic/lib/CMakeLists.txt b/bmrshared-magic/lib/CMakeLists.txt index c5863d4..06b9e3d 100644 --- a/bmrshared-magic/lib/CMakeLists.txt +++ b/bmrshared-magic/lib/CMakeLists.txt @@ -11,7 +11,7 @@ add_library( set_property( TARGET ${PROJECT_NAME} - PROPERTY CXX_STANDARD 20 + PROPERTY CXX_STANDARD 23 ) target_include_directories( @@ -26,6 +26,6 @@ target_link_libraries( ) install( - FILES ${CONAN_LIBMAGIC_PACKAGE_FOLDER}/res/magic.mgc + FILES ${BLDENV_LIBMAGIC_PACKAGE_FOLDER}/res/magic.mgc DESTINATION bin ) diff --git a/bmrshared-magic/tst/CMakeLists.txt b/bmrshared-magic/tst/CMakeLists.txt index ef84587..e1b1f6e 100644 --- a/bmrshared-magic/tst/CMakeLists.txt +++ b/bmrshared-magic/tst/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable( set_property( TARGET ${PROJECT_NAME} - PROPERTY CXX_STANDARD 20 + PROPERTY CXX_STANDARD 23 ) target_link_libraries( diff --git a/bmrshared/lib/CMakeLists.txt b/bmrshared/lib/CMakeLists.txt index 3992ce5..2610f3f 100644 --- a/bmrshared/lib/CMakeLists.txt +++ b/bmrshared/lib/CMakeLists.txt @@ -11,7 +11,7 @@ add_library( set_property( TARGET ${PROJECT_NAME} - PROPERTY CXX_STANDARD 20 + PROPERTY CXX_STANDARD 23 ) target_include_directories( diff --git a/bmrshared/tst/CMakeLists.txt b/bmrshared/tst/CMakeLists.txt index 244ea75..c32efa9 100644 --- a/bmrshared/tst/CMakeLists.txt +++ b/bmrshared/tst/CMakeLists.txt @@ -15,7 +15,7 @@ add_executable( set_property( TARGET ${PROJECT_NAME} - PROPERTY CXX_STANDARD 20 + PROPERTY CXX_STANDARD 23 ) target_link_libraries( diff --git a/conanfile.py b/conanfile.py index 7d9d643..5eb6dbf 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,18 +3,30 @@ from conan import ConanFile from conan.tools.files import copy from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps -class HelloConan(ConanFile): +class BmrConan(ConanFile): settings = "os", "compiler", "build_type", "arch" - requires = "boost/1.84.0", "gtest/1.14.0", "libmagic/5.45", "freetype/2.13.3", "libjpeg/9f" generators = "CMakeDeps" - build_policy = "*" + build_policy = "never" + + def configure(self): + self.options["boost"].without_cobalt = True + if self.settings.arch == "armv7": + self.options["libpng"].neon = False + + + def requirements(self): + self.requires("boost/1.90.0") + self.requires("gtest/1.16.0") + self.requires("libmagic/5.45") + self.requires("freetype/2.14.1") + self.requires("libjpeg/9f") + self.requires("libpng/1.6.54") def generate(self): # We need to find the folder of libmagic and supply it to cmake so that # we can deploy the magic file. libmagic = self.dependencies["libmagic"] - tc = CMakeToolchain(self) - tc.variables["CONAN_LIBMAGIC_PACKAGE_FOLDER"] = libmagic.package_folder + tc.variables["BLDENV_LIBMAGIC_PACKAGE_FOLDER"] = libmagic.package_folder tc.generate() diff --git a/dev-environment.json b/dev-environment.json new file mode 100644 index 0000000..edf8d69 --- /dev/null +++ b/dev-environment.json @@ -0,0 +1,6 @@ +{ + "build_type": "Debug", + "cppstd" : "23", + "conan_remote_fallback" : "https://artifacts.4beumer.nl/repository/conan-center-proxy/", + "conan_remote_upload" : "https://artifacts.4beumer.nl/repository/conan-bmrdev/" +} diff --git a/dev-prep-conan-pkgs.Dockerfile b/dev-prep-conan-pkgs.Dockerfile new file mode 100644 index 0000000..b2d3fd9 --- /dev/null +++ b/dev-prep-conan-pkgs.Dockerfile @@ -0,0 +1,43 @@ +FROM alpine:3.22.2 + +# Install packages needed in both building and running. +RUN apk update && \ + apk add --no-cache \ + libstdc++ + +# Install tools required for building. +RUN mkdir -p /root/.local/bin +ENV PATH="${PATH}:/root/.local/bin" + +RUN apk add --no-cache \ + autoconf \ + bash \ + binutils \ + build-base \ + cmake \ + clang \ + clang-extra-tools \ + gdb \ + git \ + libtool \ + linux-headers \ + ninja \ + m4 \ + perl \ + python3 \ + pipx + +RUN pipx ensurepath \ + && pipx install conan \ + && conan profile detect + +RUN mkdir -p /tmpdev +WORKDIR /tmpdev + +ADD conanfile.py . +ADD dev-environment.json . +ADD --chmod=544 ./scripts/dev-prep-conan-pkgs/dev-prep-conan-pkgs.py . +ADD --chmod=544 ./scripts/dev-prep-conan-pkgs/entrypoint.sh . + +ENTRYPOINT ["./entrypoint.sh"] + diff --git a/devcontainer.Dockerfile b/devcontainer.Dockerfile new file mode 100644 index 0000000..d46b6af --- /dev/null +++ b/devcontainer.Dockerfile @@ -0,0 +1,32 @@ +FROM alpine:3.22.2 + +# Install packages needed in both building and running. +RUN apk update && \ + apk add --no-cache \ + libstdc++ + +# Install tools required for building. +RUN mkdir -p /root/.local/bin +ENV PATH="${PATH}:/root/.local/bin" + +RUN apk add --no-cache \ + autoconf \ + bash \ + binutils \ + build-base \ + cmake \ + clang \ + clang-extra-tools \ + gdb \ + git \ + libtool \ + linux-headers \ + ninja \ + m4 \ + perl \ + python3 \ + pipx + +RUN pipx ensurepath \ + && pipx install conan \ + && conan profile detect diff --git a/scripts/dev-prep-conan-pkgs/dev-prep-conan-pkgs.py b/scripts/dev-prep-conan-pkgs/dev-prep-conan-pkgs.py new file mode 100644 index 0000000..891d624 --- /dev/null +++ b/scripts/dev-prep-conan-pkgs/dev-prep-conan-pkgs.py @@ -0,0 +1,39 @@ +#! /usr/bin/python +import argparse +import json +import os +import subprocess +import sys + +def runcmd(command): + print('RUN ' + command) + process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + for line in iter(process.stdout.readline, b''): # b'' indicates EOF + print(line.decode('utf-8'), end='') + +def load_environment(filename): + with open(filename) as f: + return json.load(f) + + +parser = argparse.ArgumentParser() +parser.add_argument('--environment') +args = parser.parse_args() +environment = load_environment(args.environment) + + +env_build_type = environment["build_type"] +env_cppstd = environment["cppstd"] +env_conan_remote_fallback = environment["conan_remote_fallback"] +env_conan_remote_upload = environment["conan_remote_upload"] + +with open('CMakeLists.txt', 'w') as fp: + pass + +runcmd('conan remote remove conancenter') +runcmd('conan remote add conan-upload ' + env_conan_remote_upload) +runcmd('conan remote add conan-remote ' + env_conan_remote_fallback) + +runcmd('conan install . -of build -s compiler.cppstd=' + env_cppstd + ' -s build_type=' + env_build_type + ' --build=*') + +sys.exit(0) \ No newline at end of file diff --git a/scripts/dev-prep-conan-pkgs/entrypoint.sh b/scripts/dev-prep-conan-pkgs/entrypoint.sh new file mode 100644 index 0000000..c61d88b --- /dev/null +++ b/scripts/dev-prep-conan-pkgs/entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +./dev-prep-conan-pkgs.py --environment=dev-environment.json + +conan upload -r conan-upload "*/*" --check -c