C++ with Crow, CMake, and Docker [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 15 days ago.
Improve this question
Goal
I would like to compile an Crow Project with CMake and deploy it in a docker container.
Code
So far, I compiled in Visual Studio and installed Crow via VCPKG similar to this Tutorial.
example main.cpp from Crow website:
#include "crow.h"
//#include "crow_all.h"
int main()
{
crow::SimpleApp app; //define your crow application
//define your endpoint at the root directory
CROW_ROUTE(app, "/")([](){
return "Hello world";
});
//set the port, set the app to run on multiple threads, and run the app
app.port(18080).multithreaded().run();
}
I want to build my docker image with docker build -t main_app:1 . and then run a container with docker run -d -it -p 443:18080 --name app main_app:1.
Therefore, I considered something similar like this:
Dockerfile:
FROM ubuntu:latest
RUN apt-get update -y
RUN apt-get upgrade -y
# is it necessary to install all of them?
RUN apt-get install -y g++ gcc cmake make git gdb pkg-config
RUN git clone --depth 1 https://github.com/microsoft/vcpkg
RUN ./vcpkg/bootstrap-vcpkg.sh
RUN /vcpkg/vcpkg install crow
CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
project(project_name)
include(/vcpkg/scripts/buildsystems/vcpkg.cmake)
find_package(Crow CONFIG REQUIRED)
add_executable(exe_name "main.cpp")
target_link_libraries(exe_name PUBLIC Crow::Crow)
Questions
However, obviously this is not complete and thus will not work. Hence, I would like to know how a proper (and simple) Dockerfile and CMakeLists.txt would look like for this main.cpp?
Is it possible to create my image without VCPKG? I am a little bit concerned about my image and container size, here.
How would it work with the crow_all.h header only file?
Is it possible to build an image from an already compiled name.exe, as well - so I won't have to compile anything while building the image?
Since this ought to be a minimal example, would there be any conflicts with a file structure like this:
docker_project
|__Dockerfile
|__CMakeLists.txt
|__header.hpp
|__class.cpp
|__main.cpp
Thanks for your help :)

After further research and testing I could solve this issue on two ways:
Crow.h Project compiled with CMake in Docker container
Dockerfile
# get baseimage
FROM ubuntu:latest
RUN apt-get update -y
RUN apt-get upgrade -y
# reinstall certificates, otherwise git clone command might result in an error
RUN apt-get install --reinstall ca-certificates -y
# install developer dependencies
RUN apt-get install -y git build-essential cmake --no-install-recommends
# install vcpkg package manager
RUN git clone https://github.com/microsoft/vcpkg
RUN apt-get install -y curl zip
RUN vcpkg/bootstrap-vcpkg.sh
# install crow package
RUN /vcpkg/vcpkg install crow
# copy files from local directory to container
COPY . /project
# define working directory from container
WORKDIR /build
# compile with CMake
RUN bash -c "cmake ../project && cmake --build ."
# run executable (name has to match with CMakeLists.txt file)
CMD [ "./app" ]
Docker directory would look like this:
Docker
|__vcpkg
|__ ...
|__project
|__CMakeLists.txt
|__main.cpp
|__build
|__app
|__ ...
CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(project)
# full path from root directory
include(/vcpkg/scripts/buildsystems/vcpkg.cmake)
find_package(Crow CONFIG REQUIRED)
add_executable(
app
main.cpp
)
target_link_libraries(app PUBLIC Crow::Crow)
build Docker image in local directory
project
|__Dockerfile
|__CMakeLists.txt
|__main.cpp
Navigate to project folder in shell and run docker build -t image_name:1 . to build the Docker image and run Docker container with docker run -d -it --rm --name container_name -p 443:18080 image_name:1.
Crow Project compiled with g++ command and header only library in Docker container
I created the crow_all.h header only file from Crow Github repository and downloaded the asio package via VCPKG on my PC and copied the header files (C:\vcpkg\packages\asio_x64-windows\include) to my project folder into a subdirectory called asio. Hence, my project directory look like this:
project
|__asio
|__asio.hpp
|__asio
|__ ...
|__crow_all.h
|__Dockerfile
|__main.cpp
I build and run the Docker image/container with the same commands as above.
Dockerfile
(entire content from project directory gets copied into /usr/src/ directory in Docker container)
# get baseimage
FROM gcc:12
# copy files from local folder to destination
COPY . /usr/src
# define working directory in container
WORKDIR /usr/src
# compile main.cpp (-I/usr/src/asio/ link path starting from root)
RUN g++ -I/usr/src/asio/ main.cpp -lpthread -o app
# run executable
CMD [ "./app" ]
To the other questions
I still do not know, whether that is possible.
With such a (still) simple file structure no serious conflicts appeared.

Related

GitHub Continuous Integration CMake/C++

I am trying to set up a CI for my cmake/c++ project hosted on a private repository on GitHub.
The project depends on lots of third party libraries that should be git-cloned and built. The latter takes a while, hence, I created a docker image with all dependencies installed and hosted it on the docker hub. (Ideally, I would like the docker image to be private also, but if it is not possible, I can make it public.)
I want to achieve the following:
On pull requests to the master branch, the application is automatically built on the docker container(because all dependencies are there), all unit tests (gtest) are run and, if everything is alright, the branch is merged to master.
Ideally, I would like to see the logs and statistics generated by gcovr/lcov.
OS: Ubuntu 18.04
I wonder if this is even achievable as I have been searching for 2 days with no luck and a billion of possible readings.
My 2 cents (more a comment) on controlled build using docker.
For automatic merge, I don't know since I would be against it since code review can't be replaced by CI only IMHO...
Take a look at https://github.com/Mizux/cmake-cpp
Introduction
I use a Makefile for orchestration (docker command can be way too long ;)) and docker for isolated build on various distro.
pro:
Be able to test locally (Just need a GNU/Linux distro with Docker & Make)
Can migrate easily to various CI runners provider (Travis-CI, GitHub Workflow, gitlab-runner, bitbucket?)
Contributors can test locally before sending a PR
cons:
Less coupled to github -> more complex to maintain.
more difficult to have a cache between workflow
note: Dockerfile are stored in the repository in ci/docker i.e. I rebuild the images in the first steps but you should be able to replace this step by a simple docker load if your image is located on docker hub (not tested)
Setup
Dockerfile
I split my Dockerfile in several stages (mostly for debug).
note: you can replace ubuntu:rolling with your own image...
ci/docker/ubuntu/Dockerfile:
# Create a virtual environment with all tools installed
# ref: https://hub.docker.com/_/ubuntu
FROM ubuntu:rolling AS env
# Install system build dependencies
# note: here we use the CMake package provided by Ubuntu
# see: https://repology.org/project/cmake/versions
ENV PATH=/usr/local/bin:$PATH
RUN apt-get update -q && \
apt-get install -yq git build-essential cmake && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
CMD [ "/bin/sh" ]
# Add the library src to our build env
FROM env AS devel
# Create lib directory
WORKDIR /home/lib
# Bundle lib source
COPY . .
# Build in an other stage
FROM devel AS build
# CMake configure
RUN cmake -H. -Bbuild
# CMake build
RUN cmake --build build --target all
# CMake install
RUN cmake --build build --target install
# Create an install image to check cmake install config
FROM env AS install
# Copy lib from build to install
COPY --from=build /usr/local /usr/local/
# Copy sample
WORKDIR /home/sample
COPY ci/sample .
Runner jobs
Github action runners have docker installed.
note: you can have one badge per yml file. e.g. You could should use one job per distro for example to have one jobs per distro or one file for Release and one file for Debug...
.github/workflows/docker.yml:
name: C++ CI
on: [push, pull_request]
jobs:
build-docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Build env image
run: docker build --target=env --tag project:env -f ci/docker/ubuntu/Dockerfile .
- name: Build devel image
run: docker build --target=devel --tag project:devel -f ci/docker/ubuntu/Dockerfile .
- name: Build build image
run: docker build --target=build --tag project:build -f ci/docker/ubuntu/Dockerfile .
For testing you can add an other stage or run it using the project:build image:
docker run --rm --init -t --name test project:build cmake --build build --target test
Annexes
Faster build
You can add a .dockerignore file to remove unneeded files (e.g. LICENCES, doc, local build dir if testing locally...) to reduce docker context and the COPY . .
.dockerignore:
# Project Files unneeded by docker
ci/cache
ci/docker
ci/Makefile
.git
.gitignore
.github
.dockerignore
.travis.yml
.appveyor.yml
.clang-format
AUTHORS
CONTRIBUTING.md
CONTRIBUTHORS
INSTALL
LICENSE
README.md
doc
# Native CMake build
build/
# Editor directories and files
*.user
*.swp
Custom CMake version install
You can use the following instead of apt install -y cmake
Can take time since you rebuild CMake...
# Install CMake 3.16.4
RUN wget "https://cmake.org/files/v3.16/cmake-3.16.4.tar.gz" \
&& tar xzf cmake-3.16.4.tar.gz \
&& rm cmake-3.16.4.tar.gz \
&& cd cmake-3.16.4 \
&& ./bootstrap --prefix=/usr/local/ \
&& make \
&& make install \
&& cd .. \
&& rm -rf cmake-3.16.4
so you can use the prebuild version instead using:
# Install CMake 3.16.4
RUN wget "https://cmake.org/files/v3.16/cmake-3.16.4-Linux-x86_64.sh" \
&& chmod a+x cmake-3.16.4-Linux-x86_64.sh \
&& ./cmake-3.16.4-Linux-x86_64.sh --prefix=/usr/local/ --skip-license \
&& rm cmake-3.16.4-Linux-x86_64.sh

how to integrate cmake in gitlab repository for Continuous Integration(CI)

I was able to run the C++ Program and build & test it using GitLab CI unit with the help of Docker Image of gcc. But now I want to compile the program in docker using cmake instead of g++. How to change the '.gitlab-ci.yml' file to support cmake.
Current File : .gitlab-ci.yml
image: gcc
before_script:
- apt-get install --yes cmake libmatio-dev libblas-dev libsqlite3-dev libcurl4-openssl-dev
- apt-get install --yes libarchive-dev liblzma-dev
build:
script:
- ./runner.sh
- ./bin/hello
./runner.sh
cmake -H. -Bbuild
cmake --build build -- -j3
I think you need to add apt-get update in order to get cmake to install. See this
image: gcc
before_script:
- apt-get update --yes
- apt-get install --yes cmake
build:
script:
- ./runner.sh
- ./bin/hello
In general, you can figure stuff out by jumping into the docker image to debug (in your case the image is the debian-based gcc:latest):
sudo docker run -it --rm gcc
If you had run your original apt-get install command inside the gcc container, you would have seen following error message that you could have then googled to figure out that apt-get update was needed
sudo docker run -it --rm gcc apt-get install --yes cmake
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package cmake is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
E: Package 'cmake' has no installation candidate
As this blog post mentions, you can do a test run locally by downloading the gitlab-runner executable:
gitlab-runner exec docker build
Running the gitlab-runner locally will have gitlab clone your repo and run through all the steps in the .gitlab-ci.yml and you can see the output and debug locally rather quickly.

docker-compose not downloading additions to requirements.txt file

I have a Django project running in docker.
When I add some packages to my requirments.txt file, they don't get downloaded when I run docker-compose up
Here is the relevant commands from my Dockerfile:
ADD ./evdc/requirements.txt /opt/evdc-venv/
ADD ./env-requirements.txt /opt/evdc-venv/
# Active venv
RUN . /opt/evdc-venv/bin/activate && pip install -r /opt/evdc- venv/requirements.txt
RUN . /opt/evdc-venv/bin/activate && pip install -r /opt/evdc-venv/env-requirements.txt
It seems docker is using a cached version of my requirements.txt file, as when I shell into the container, the requirements.txt file in /opt/evdc-venv/requirements.txt does not include the new packages.
Is there some way I can delete this cached version of requirements.txt?
Dev OS: Windows 10
Docker: 17.03.0-ce
docker-compose: 1.11.2
docker-compose up doesn't build a new image unless you have the build section defined with your Dockerfile and you pass it the --build parameter. Without that, it will reuse the existing image.
If your docker-compose.yml does not include the build section, and your build your images with docker build ..., then after you recreate your image, a docker-compose up will recreate the impacted containers.

Compiling a file leaves files in my home directory when doing vagrant provision

I am using Vagrant to setup a linux box. I need to add a file I compiled to the system and I do so using the following commands -
sudo git clone https://github.com/thewtex/tmux-mem-cpu-load.git /tmp/tmuxcpu
sudo cmake /tmp/tmuxcpu
sudo make clean /tmp/tmuxcpu
sudo make install clean /tmp/tmuxcpu
However, this leaves tons of files including a makefile, config files, and other garbage inside the /home/vagrant/ folder. How do I make and install from tmp without littering the home directory with garbage?
The above commands work, but it leaves tons of files in the /home/vagrant folder that I don't want there. Is it possible to cmake, make, and make install without leaving 'trash'?
I have solved my issue with the help of Etan Reisner and reinierpost.
## CPU LOAD
sudo git clone https://github.com/thewtex/tmux-mem-cpu-load.git /tmp/tmuxcpu
sudo sh -c "cd /tmp/tmuxcpu && sudo cmake . && sudo make && sudo make install";
My install script now uses the above commands and this has resolved my issue. By keeping the files in /tmp, they are removed the moment I reboot the box. I am using this technique for several other items during the vagrant setup now and it works perfectly. This has solved numerous issues for me.

Run Keter without GHC and cabal

I have a server and want to deploy my Yesod applications without installing GHC and Cabal. I am not sure if is possible: a Teacher told me that I must first compile Keter in my machine and, after that, put keter executable on the server, though I am not sure how to do that.
To build Keter, first you'll need to clone the sources from its GitHub repository. Then you'll need to set up a Haskell build environment and use cabal build or cabal install to build the sources. Personally, I use a Docker container derived from an image based on the following Dockerfile:
FROM haskell:7.10.2
RUN apt-get update && apt-get install -y \
git
RUN mkdir /src
RUN cd src && \
git clone https://github.com/snoyberg/keter && \
cd keter && \
git checkout e8b5a3fd5e14dfca466f8acff2a02f0415fceeb0
WORKDIR /src/keter
RUN cabal update
RUN cabal install keter
ENTRYPOINT /bin/bash
This is an image containing the Keter sources checked out at a specific revision with the minimum GHC toolchain required to build it all. The cabal command lines pull down all the project's dependencies and compiles the whole thing. Once this has completed, you can grab the keter executable from ~/.cabal/bin/keter.
Even if you choose not to use Docker, this file should give you a rough idea how to set up your environment.
Now you have Keter compiled, you can run it inside another Docker container. Here's a rough idea what the Dockerfile for the corresponding image might look like:
FROM debian
RUN apt-get update && apt-get install -y \
libgmp-dev \
nano \
postgresql
COPY keter /opt/keter/bin/
COPY keter-config.yaml /opt/keter/etc/
EXPOSE 80
CMD ["/opt/keter/bin/keter", "/opt/keter/etc/keter-config.yaml"]
Ths will take a base Debian image and install a minimal set of packages on top of it. It then copies the keter executable and configuration file into the image. If you then run a container from the resulting image it will start the keter executable.
Fair warning: This whole process is fairly involved. I'm still working on tweaking the exact details myself. Good luck!