Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c38100380 |
14 changed files with 423 additions and 0 deletions
1
7-toolchain
Symbolic link
1
7-toolchain
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
.
|
||||||
45
Dockerfile
Normal file
45
Dockerfile
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
FROM registry.fedoraproject.org/f27/s2i-core:latest
|
||||||
|
|
||||||
|
ENV SUMMARY="Fedora variant of Red Hat Developer Toolset's C/C++ Toolchain from Software Collections" \
|
||||||
|
DESCRIPTION="Platform for building C and C++ applications" \
|
||||||
|
NAME=toolchain \
|
||||||
|
VERSION=1 \
|
||||||
|
ARCH=x86_64
|
||||||
|
|
||||||
|
LABEL com.redhat.component="$NAME" \
|
||||||
|
name="$FGC/$NAME" \
|
||||||
|
version="$VERSION" \
|
||||||
|
architecture="$ARCH" \
|
||||||
|
summary="$SUMMARY" \
|
||||||
|
description="$DESCRIPTION" \
|
||||||
|
io.k8s.description="$DESCRIPTION" \
|
||||||
|
io.k8s.display-name="Fedora variant of Developer Toolset's C/C++ Toolchain from Software Collections" \
|
||||||
|
usage="docker run -ti -v /src/app:/opt/app-root/src:z $FGC/$NAME bash" \
|
||||||
|
help="docker run IMAGE cat /help.1 | /usr/bin/groff -t -man -ETascii" \
|
||||||
|
maintainer="SoftwareCollections.org <sclorg@redhat.com>"
|
||||||
|
|
||||||
|
RUN INSTALL_PKGS="gcc gcc-c++ gcc-gfortran gdb make" && \
|
||||||
|
dnf install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
|
||||||
|
rpm -V $INSTALL_PKGS && \
|
||||||
|
dnf clean all -y
|
||||||
|
|
||||||
|
# Copy extra files to the image.
|
||||||
|
COPY ./root/ /
|
||||||
|
|
||||||
|
ENV HOME=/opt/app-root/src \
|
||||||
|
PATH=/opt/app-root/src/bin:/opt/app-root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
|
||||||
|
RUN mkdir -p ${HOME} && \
|
||||||
|
groupadd -r default -f -g 1001 && \
|
||||||
|
usermod -g default default && \
|
||||||
|
chown -R 1001:1001 /opt/app-root /usr/bin/container-entrypoint /usr/bin/usage && \
|
||||||
|
chmod u+x /usr/bin/usage && \
|
||||||
|
rpm-file-permissions
|
||||||
|
|
||||||
|
USER 1001
|
||||||
|
|
||||||
|
WORKDIR ${HOME}
|
||||||
|
|
||||||
|
# Set the default CMD to print the usage of the language image
|
||||||
|
ENTRYPOINT ["container-entrypoint"]
|
||||||
|
CMD ["usage"]
|
||||||
1
Dockerfile.fedora
Symbolic link
1
Dockerfile.fedora
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
Dockerfile
|
||||||
76
README.md
Normal file
76
README.md
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
Toolchain For Building C and C++ Applications Docker Image
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
Developer Toolchain is part of the Red Hat Software Collections and the Toolchain is a subset of tools usable for building C and C++ applications. Docker container based on Red Hat Software Collection packages is available as rhscl/devtoolset-7-toolchain-rhel7 in registry.access.redhat.com. Docker container based on CentOS packagess is available as centos/devtoolset-7-toolchain-centos7 in the Docker Hub.
|
||||||
|
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
Developer Toolset from Red Hat Software Collections provides various tools for C and C++ developers, so they are able to use the Developer Toolset tools without needing to be running a RHEL host. The Toolchain part of the Developer Toolset contains tools for building such applications (GCC compiler for C and C++, GDB, gfortran compiler, etc.). Perftools part contains then tools for debugging and further analysis of the applications (oprofile, valgrind, systemtap, etc.).
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----------
|
||||||
|
Suppose you have a source for a C application in the `/src/app` directory on the host and that we use the RHEL-based variant (Docker image called rhscl/devtoolset-7-toolchain-rhel7). To build such application you can mount the application sources to the container and run appropriate tools interactively:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -ti --rm -v /src/app:/opt/app-root/src:z rhscl/devtoolset-7-toolchain-rhel7 bash
|
||||||
|
bash-4.3$ gcc -o foo -ggdb -g2 foo.c
|
||||||
|
```
|
||||||
|
|
||||||
|
That will compile one file from `/src/app` using GCC from container with options `-ggdb -g2`.
|
||||||
|
|
||||||
|
To run `make` non-interactively, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -ti --rm -v $PWD:/opt/app-root/src:z rhscl/devtoolset-7-toolchain-rhel7 make
|
||||||
|
```
|
||||||
|
|
||||||
|
That will compile the project from current directory using `make` utility.
|
||||||
|
|
||||||
|
In both cases above user must ensure that the directory where GCC will write data into is writable for the user used inside the container (by default UID 1001).
|
||||||
|
|
||||||
|
|
||||||
|
Environment variables and volumes
|
||||||
|
---------------------------------
|
||||||
|
You can set the following mount points by passing the `-v /host:/container` flag to Docker.
|
||||||
|
|
||||||
|
**`/opt/app-root`**
|
||||||
|
Directory for application sources
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Missing dependencies
|
||||||
|
--------------------
|
||||||
|
It may happen that the program combiled in the container won't have all the dependencies available. In that case, the Developer Toolset Container Image is supposed to be used as a starting point for users, so they do not need to spin their own container from scratch. Creating a new layer on top of the existing container image can be done by writing a new Dockerfile, that will use this image in the FROM clause. For example to install `boost-devel` library as a dependency, create the following Dockerfile:
|
||||||
|
|
||||||
|
```
|
||||||
|
FROM rhscl/devtoolset-7-toolchain-rhel7
|
||||||
|
|
||||||
|
USER 0
|
||||||
|
RUN yum install -y --setopt=tsflags=nodocs boost-devel && yum clean all -y
|
||||||
|
USER 1001
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, build the Dockerfile like this (you need a subscribed RHEL-7 machine to install additional RPMs into the RHEL-based container image):
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t myorg/devtoolset-7-toolchain-rhel7 .
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
---------------
|
||||||
|
The error log or standard log if container is run non-interactively is available in the container log. The log can be examined by running:
|
||||||
|
|
||||||
|
docker logs <container>
|
||||||
|
|
||||||
|
|
||||||
|
See also
|
||||||
|
--------
|
||||||
|
Dockerfile and other sources for this container image are available on
|
||||||
|
https://github.com/sclorg/devtoolset-container.
|
||||||
|
In that repository, Dockerfile for CentOS is called Dockerfile, Dockerfile
|
||||||
|
for RHEL is called Dockerfile.rhel7.
|
||||||
|
|
||||||
1
help.md
Symbolic link
1
help.md
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
README.md
|
||||||
101
root/help.1
Normal file
101
root/help.1
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
.TH Toolchain For Building C and C++ Applications Docker Image
|
||||||
|
.PP
|
||||||
|
Developer Toolchain is part of the Red Hat Software Collections and the Toolchain is a subset of tools usable for building C and C++ applications. Docker container based on Red Hat Software Collection packages is available as rhscl/devtoolset\-7\-toolchain\-rhel7 in registry.access.redhat.com. Docker container based on CentOS packagess is available as centos/devtoolset\-7\-toolchain\-centos7 in the Docker Hub.
|
||||||
|
|
||||||
|
.SH Description
|
||||||
|
.PP
|
||||||
|
Developer Toolset from Red Hat Software Collections provides various tools for C and C++ developers, so they are able to use the Developer Toolset tools without needing to be running a RHEL host. The Toolchain part of the Developer Toolset contains tools for building such applications (GCC compiler for C and C++, GDB, gfortran compiler, etc.). Perftools part contains then tools for debugging and further analysis of the applications (oprofile, valgrind, systemtap, etc.).
|
||||||
|
|
||||||
|
.SH Usage
|
||||||
|
.PP
|
||||||
|
Suppose you have a source for a C application in the \fB\fC/src/app\fR directory on the host and that we use the RHEL\-based variant (Docker image called rhscl/devtoolset\-7\-toolchain\-rhel7). To build such application you can mount the application sources to the container and run appropriate tools interactively:
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.nf
|
||||||
|
docker run \-ti \-\-rm \-v /src/app:/opt/app\-root/src:z rhscl/devtoolset\-7\-toolchain\-rhel7 bash
|
||||||
|
bash\-4.3$ gcc \-o foo \-ggdb \-g2 foo.c
|
||||||
|
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.PP
|
||||||
|
That will compile one file from \fB\fC/src/app\fR using GCC from container with options \fB\fC\-ggdb \-g2\fR\&.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
To run \fB\fCmake\fR non\-interactively, run:
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.nf
|
||||||
|
docker run \-ti \-\-rm \-v $PWD:/opt/app\-root/src:z rhscl/devtoolset\-7\-toolchain\-rhel7 make
|
||||||
|
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.PP
|
||||||
|
That will compile the project from current directory using \fB\fCmake\fR utility.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
In both cases above user must ensure that the directory where GCC will write data into is writable for the user used inside the container (by default UID 1001).
|
||||||
|
|
||||||
|
.SH Environment variables and volumes
|
||||||
|
.PP
|
||||||
|
You can set the following mount points by passing the \fB\fC\-v /host:/container\fR flag to Docker.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fB\fB\fC/opt/app\-root\fR\fP
|
||||||
|
.br
|
||||||
|
Directory for application sources
|
||||||
|
|
||||||
|
.SH Missing dependencies
|
||||||
|
.PP
|
||||||
|
It may happen that the program combiled in the container won't have all the dependencies available. In that case, the Developer Toolset Container Image is supposed to be used as a starting point for users, so they do not need to spin their own container from scratch. Creating a new layer on top of the existing container image can be done by writing a new Dockerfile, that will use this image in the FROM clause. For example to install \fB\fCboost\-devel\fR library as a dependency, create the following Dockerfile:
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.nf
|
||||||
|
FROM rhscl/devtoolset\-7\-toolchain\-rhel7
|
||||||
|
|
||||||
|
USER 0
|
||||||
|
RUN yum install \-y \-\-setopt=tsflags=nodocs boost\-devel \&\& yum clean all \-y
|
||||||
|
USER 1001
|
||||||
|
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.PP
|
||||||
|
Then, build the Dockerfile like this (you need a subscribed RHEL\-7 machine to install additional RPMs into the RHEL\-based container image):
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.nf
|
||||||
|
docker build \-t myorg/devtoolset\-7\-toolchain\-rhel7 .
|
||||||
|
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH Troubleshooting
|
||||||
|
.PP
|
||||||
|
The error log or standard log if container is run non\-interactively is available in the container log. The log can be examined by running:
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.RS
|
||||||
|
|
||||||
|
.nf
|
||||||
|
docker logs <container>
|
||||||
|
|
||||||
|
.fi
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH See also
|
||||||
|
.PP
|
||||||
|
Dockerfile and other sources for this container image are available on
|
||||||
|
|
||||||
|
\[la]https://github.com/sclorg/devtoolset-container\[ra]\&.
|
||||||
|
In that repository, Dockerfile for CentOS is called Dockerfile, Dockerfile
|
||||||
|
for RHEL is called Dockerfile.rhel7.
|
||||||
6
root/opt/app-root/etc/scl_enable
Normal file
6
root/opt/app-root/etc/scl_enable
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# IMPORTANT: Do not add more content to this file unless you know what you are
|
||||||
|
# doing. This file is sourced everytime the shell session is opened.
|
||||||
|
#
|
||||||
|
# This will make scl collection binaries work out of box.
|
||||||
|
unset BASH_ENV PROMPT_COMMAND ENV
|
||||||
|
source scl_source enable devtoolset-7
|
||||||
6
root/usr/bin/container-entrypoint
Executable file
6
root/usr/bin/container-entrypoint
Executable file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
cmd="$1"; shift
|
||||||
|
exec $cmd "$@"
|
||||||
|
|
||||||
8
root/usr/bin/usage
Normal file
8
root/usr/bin/usage
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
cat <<EOF
|
||||||
|
This is a devtoolset-7-toolchain base image.
|
||||||
|
|
||||||
|
Sample invocation:
|
||||||
|
docker run -ti devtoolset-7-toolchain-rhel7 /bin/bash
|
||||||
|
EOF
|
||||||
|
|
||||||
0
sources
0
sources
4
test/expected-usage
Normal file
4
test/expected-usage
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
This is a devtoolset-7-toolchain base image.
|
||||||
|
|
||||||
|
Sample invocation:
|
||||||
|
docker run -ti devtoolset-7-toolchain-rhel7 /bin/bash
|
||||||
154
test/run
Executable file
154
test/run
Executable file
|
|
@ -0,0 +1,154 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# The 'run' script performs simple tests that verifies usability
|
||||||
|
# of tools, packaged in toolchain image.
|
||||||
|
#
|
||||||
|
# IMAGE_NAME specifies a name of the candidate image used for testing.
|
||||||
|
# The image has to be available before this script is executed.
|
||||||
|
#
|
||||||
|
# DEBUG environment variable, if not empty, makes 'run' to log every step
|
||||||
|
# of testing.
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ "$DEBUG" != "" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
IMAGE_NAME=${IMAGE_NAME:-rhscl/devtoolset-7-toolchain-rhel7}
|
||||||
|
THISDIR=$(dirname ${BASH_SOURCE[0]})
|
||||||
|
|
||||||
|
function info () {
|
||||||
|
echo -e "\e[1m[INFO] $@\e[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function pass () {
|
||||||
|
echo -e "\e[1;32m[PASS] $@\e[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function error () {
|
||||||
|
echo -e "\e[1;31m[ERROR] $@\e[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_result() {
|
||||||
|
local label="$1"
|
||||||
|
local result="$2"
|
||||||
|
local expected="$3"
|
||||||
|
|
||||||
|
if [[ "$result" = "$expected" ]]; then
|
||||||
|
pass "$label: PASS"
|
||||||
|
else
|
||||||
|
error "$label: FAIL ($result)"
|
||||||
|
RESULT=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_docker_run_usage () {
|
||||||
|
info "Testing 'docker run' usage ..."
|
||||||
|
|
||||||
|
docker run --rm $IMAGE_NAME > $TMPDIR/actual-usage
|
||||||
|
check_result "Exit code is zero" $? 0
|
||||||
|
|
||||||
|
diff "$THISDIR"/expected-usage $TMPDIR/actual-usage &> /dev/null
|
||||||
|
check_result "Usage info matches the expected text" $? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_sanity_gcc_usage () {
|
||||||
|
info "Testing 'gcc -v' usage ..."
|
||||||
|
|
||||||
|
docker run --rm $IMAGE_NAME gcc -v &> $TMPDIR/actual-gcc-v
|
||||||
|
check_result "Exit code is zero" $? 0
|
||||||
|
|
||||||
|
grep 'gcc version ' $TMPDIR/actual-gcc-v &> /dev/null
|
||||||
|
check_result "Output contains gcc version" $? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_sanity_gdb_usage () {
|
||||||
|
info "Testing 'gdb -v' usage ..."
|
||||||
|
|
||||||
|
docker run --rm $IMAGE_NAME gdb -v &> $TMPDIR/actual-gdb-v
|
||||||
|
check_result "Exit code is zero" $? 0
|
||||||
|
|
||||||
|
grep 'GNU gdb (GDB)' $TMPDIR/actual-gdb-v &> /dev/null
|
||||||
|
check_result "Output contains gdb version" $? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_gcc_compile () {
|
||||||
|
info "Testing compilation via 'docker run gcc foo.c ..."
|
||||||
|
|
||||||
|
rm -f $TMPDIR/foo $TMPDIR/foo.c
|
||||||
|
|
||||||
|
cat << EOF > $TMPDIR/foo.c
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) { printf("Hello world from containerized gcc!\n"); return 0; }
|
||||||
|
EOF
|
||||||
|
|
||||||
|
docker run --rm -v $TMPDIR:$TMPDIR:z $IMAGE_NAME gcc -o $TMPDIR/foo $TMPDIR/foo.c
|
||||||
|
check_result "Exit code is zero" $? 0
|
||||||
|
|
||||||
|
test -e $TMPDIR/foo
|
||||||
|
check_result "Compiled binary exists" $? 0
|
||||||
|
|
||||||
|
$TMPDIR/foo &> $TMPDIR/actual-output
|
||||||
|
check_result "Exit code of compiled binary is zero" $? 0
|
||||||
|
|
||||||
|
grep "Hello world from containerized gcc!" $TMPDIR/actual-output &> /dev/null
|
||||||
|
check_result "Compiled binary works" $? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_gdb_batch_debug () {
|
||||||
|
info "Testing debugging via 'docker run gdb -batch ..."
|
||||||
|
|
||||||
|
rm -f $TMPDIR/foo $TMPDIR/foo.c
|
||||||
|
|
||||||
|
cat << EOF > $TMPDIR/foo.c
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *s = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < INT_MAX; i++)
|
||||||
|
s[i] = 'f';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
docker run --rm -v $TMPDIR:$TMPDIR:z $IMAGE_NAME gcc -o $TMPDIR/foo -ggdb -g2 $TMPDIR/foo.c
|
||||||
|
check_result "Compile test binary" $? 0
|
||||||
|
|
||||||
|
test -e $TMPDIR/foo
|
||||||
|
check_result "Test binary exists" $? 0
|
||||||
|
|
||||||
|
docker run --rm --privileged -v $TMPDIR:$TMPDIR:z $IMAGE_NAME gdb -batch -ex 'run' -ex 'bt' $TMPDIR/foo &> $TMPDIR/actual-output
|
||||||
|
check_result "Exit code is zero" $? 0
|
||||||
|
|
||||||
|
grep -q "Program received signal SIGSEGV, Segmentation fault." $TMPDIR/actual-output &> /dev/null
|
||||||
|
check_result "GDB output informs about segfault" $? 0
|
||||||
|
|
||||||
|
grep -q "s\[i\] = 'f';" $TMPDIR/actual-output &> /dev/null
|
||||||
|
check_result "GDB output prints source line" $? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
TMPDIR=`mktemp -d`
|
||||||
|
chmod a+rwx $TMPDIR
|
||||||
|
|
||||||
|
RESULT=0
|
||||||
|
|
||||||
|
test_docker_run_usage
|
||||||
|
test_sanity_gcc_usage
|
||||||
|
test_sanity_gdb_usage
|
||||||
|
test_gcc_compile
|
||||||
|
test_gdb_batch_debug
|
||||||
|
|
||||||
|
rm -rf $TMPDIR
|
||||||
|
|
||||||
|
if [ "$RESULT" = "0" ]; then
|
||||||
|
info "All tests finished"
|
||||||
|
else
|
||||||
|
error "Some tests failed"
|
||||||
|
exit $RESULT
|
||||||
|
fi
|
||||||
14
test/test-app/Makefile
Normal file
14
test/test-app/Makefile
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -g
|
||||||
|
RM = rm -f
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: hello
|
||||||
|
|
||||||
|
Hello: hello.c
|
||||||
|
$(CC) $(CFLAGS) -o hello hello.c
|
||||||
|
|
||||||
|
clean veryclean:
|
||||||
|
$(RM) hello
|
||||||
|
|
||||||
6
test/test-app/hello.c
Normal file
6
test/test-app/hello.c
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf ("Hello from container!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue