Compare commits
16 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0354eb79c0 | ||
|
|
9a2ff2b530 | ||
|
|
ff1556d0f3 | ||
|
|
1843df3521 | ||
|
|
00b7710b7c | ||
|
|
a025f91dc5 | ||
|
|
34b7c9efbe | ||
|
|
a8ebd1b810 | ||
|
|
052ee0cea8 | ||
|
|
bdf952007c | ||
|
|
efb76cb64a | ||
|
|
78f4c97dcd | ||
|
|
b005380ac1 | ||
|
|
b6d8836cb6 | ||
|
|
3e5bed9c18 | ||
|
|
238416a849 |
8 changed files with 325 additions and 0 deletions
45
Dockerfile
Normal file
45
Dockerfile
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
FROM fedora:25
|
||||
MAINTAINER Honza Horak <hhorak@redhat.com>
|
||||
|
||||
LABEL io.k8s.description="Platform for building C and C++ applications" \
|
||||
io.k8s.display-name="Fedora variant of Developer Toolset's C/C++ Toolchain from Software Collections"
|
||||
|
||||
ENV NAME=toolchain VERSION=1 RELEASE=15 ARCH=x86_64
|
||||
|
||||
LABEL com.redhat.component="$NAME" \
|
||||
name="$FGC/$NAME" \
|
||||
version="$VERSION" \
|
||||
release="$RELEASE.$DISTTAG" \
|
||||
architecture="$ARCH"
|
||||
|
||||
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
|
||||
|
||||
# Use entrypoint so path is correctly adjusted already at the time the command
|
||||
# is searching, so something like docker run IMG gcc runs binary from SCL.
|
||||
COPY contrib/bin/container-entrypoint /usr/bin/container-entrypoint
|
||||
|
||||
# Install the usage script with base image usage informations
|
||||
COPY contrib/bin/usage /usr/bin/usage
|
||||
|
||||
# Copy README.md to the container
|
||||
COPY README.md /help.md
|
||||
|
||||
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 && \
|
||||
useradd -u 1001 -r -g default -d ${HOME} -s /sbin/nologin \
|
||||
-c "Default Application User" default && \
|
||||
chown -R 1001:1001 /opt/app-root
|
||||
|
||||
USER 1001
|
||||
|
||||
WORKDIR ${HOME}
|
||||
|
||||
# Set the default CMD to print the usage of the language image
|
||||
ENTRYPOINT ["container-entrypoint"]
|
||||
CMD ["usage"]
|
||||
57
README.md
Normal file
57
README.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
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-6-toolchain-rhel7 in registry.access.redhat.com. Docker container based on CentOS packagess is available as centos/devtoolset-6-toolchain-centos7 in the Docker Hub.
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
Developer Toolset from Red Hat Software Collections provides various tools for C and C++ developers. 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-6-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-6-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-6-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.
|
||||
|
||||
| Volume mount point | Description |
|
||||
| :----------------------- | --------------------------------- |
|
||||
| `/opt/app-root` | Directory for application sources |
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
6
contrib/bin/container-entrypoint
Executable file
6
contrib/bin/container-entrypoint
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
cmd="$1"; shift
|
||||
exec $cmd "$@"
|
||||
|
||||
23
contrib/bin/usage
Executable file
23
contrib/bin/usage
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
cat <<EOF
|
||||
Developer Toolset from Red Hat Software Collections provides various tools for C and C++ developers. The Toolchain part of the Developer Toolset contains tools for building such applications (GCC compiler for C and C++, GDB, gfortran compiler, etc.).
|
||||
|
||||
|
||||
Basic 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-6-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-6-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-6-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).
|
||||
EOF
|
||||
|
||||
19
test/expected-usage
Normal file
19
test/expected-usage
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Developer Toolset from Red Hat Software Collections provides various tools for C and C++ developers. The Toolchain part of the Developer Toolset contains tools for building such applications (GCC compiler for C and C++, GDB, gfortran compiler, etc.).
|
||||
|
||||
|
||||
Basic 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-6-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-6-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 /opt/app-root/src:/opt/app-root/src:z rhscl/devtoolset-6-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).
|
||||
155
test/run
Executable file
155
test/run
Executable file
|
|
@ -0,0 +1,155 @@
|
|||
#!/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.
|
||||
#
|
||||
|
||||
THISDIR=$(dirname ${BASH_SOURCE[0]})
|
||||
|
||||
if [ "$DEBUG" != "" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
IMAGE_NAME=${IMAGE_NAME:-rhscl/devtoolset-4-toolchain-rhel7}
|
||||
|
||||
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) Fedora ' $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