diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..2c463b11 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +* +!docker/*.sh +!scripts/ +!src/ +!build*.sh +!radare2/*/ +radare2/.*/ +radare2/doc +radare2/man +!radare2/config-user.mk.acr +!radare2/configure +!radare2/Makefile diff --git a/docker/Dockerfile-dev b/docker/Dockerfile-dev new file mode 100644 index 00000000..dbc27368 --- /dev/null +++ b/docker/Dockerfile-dev @@ -0,0 +1,70 @@ +FROM alpine:edge AS builder +LABEL maintainer "Philipp Schmied " + +# Prevent build fails because of interactive scripts when compiling +ENV DEBIAN_FRONTEND noninteractive + +# Dependencies +RUN apk add --no-cache \ + bash \ + cmake \ + curl \ + g++ \ + gcc \ + git \ + linux-headers \ + make \ + pkgconfig \ + python3-dev \ + qt5-qtbase \ + qt5-qtsvg-dev \ + qt5-qttools-dev \ + unzip \ + wget + +# install radare2 first +COPY docker/build_radare2.sh /opt/cutter/ +COPY radare2 /opt/cutter/radare2 + +WORKDIR /opt/cutter +RUN bash build_radare2.sh + +COPY docker/build_cutter.sh /opt/cutter/ +COPY scripts /opt/cutter/scripts +COPY src /opt/cutter/src + +RUN bash build_cutter.sh && \ + bash -c 'if [[ ! -x "/opt/cutter/build/Cutter" ]]; then exit -1; fi' + +FROM alpine:edge AS runner +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# Add the dependencies we need for running +RUN apk add --no-cache \ + bash \ + libuuid \ + make \ + python3 \ + qt5-qtbase \ + shadow \ + su-exec + +# Add r2 user +RUN useradd r2 + +# Prepare files to mount configurations later on +RUN mkdir /var/sharedFolder && \ + mkdir -p /home/r2/.config/radare2 && \ + touch /home/r2/.radare2rc && \ + chown -R r2:r2 /var/sharedFolder && \ + chown -R r2:r2 /home/r2/ + +COPY ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh + +# Get the compiled Cutter, r2 libs and bins from the builder +COPY --from=builder /opt/cutter /opt/cutter +COPY --from=builder /usr/lib /usr/lib +COPY --from=builder /usr/share/radare2 /usr/share/radare2 +WORKDIR /opt/cutter/radare2/binr +RUN make install && \ +make symstall install-symlink diff --git a/docker/Makefile b/docker/Makefile index e23d6ac3..f9a2033a 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -17,6 +17,8 @@ VERSION ?= latest IMAGE_NAME ?= radareorg/cutter CONTAINER_NAME ?= cutter +LOCAL_DEV ?= n + # This will output the help for each task # thanks to https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html .PHONY: help @@ -28,10 +30,10 @@ help: ## This help # Build the container build: ## Build the container - sudo docker build --rm -t $(IMAGE_NAME) . + sudo docker build --rm -t $(IMAGE_NAME) $(if $(LOCAL_DEV) == 'y',-f ./Dockerfile-dev ../,.) build-nc: ## Build the container without caching - sudo docker build --rm --no-cache -t $(IMAGE_NAME) . + sudo docker build --rm --no-cache -t $(IMAGE_NAME) $(if $(LOCAL_DEV) == 'y',-f ./Dockerfile-dev ../,.) run: ## Run container XSOCK=/tmp/.X11-unix && \ diff --git a/docker/README.md b/docker/README.md index 913bf37e..003f6632 100644 --- a/docker/README.md +++ b/docker/README.md @@ -6,6 +6,10 @@ These files provide an easy way to deploy *Cutter* in a Docker container. After - Mount directives to mount a shared folder and radare2 configuration files. - The UID and GID of the user executing `make run` will also be used for the internal container user to avoid permission problems when sharing files. +## Using Local Files + +To deploy *Cutter* using local files rather than those in the Master branch set LOCAL_DEV to 'y' when executing `make build` or `make build-nc`, e.g. `make LOCAL_DEV=y build`. This will tell *make* to use `Dockerfile-dev` rather than `Dockerfile` which will copy local files into the container rather than cloning from Git. + ## Mounting and Using a Specific Binary The `Makefile` allows mounting a single binary file as read-only, which will also be used as an input for *Cutter*. To use this feature, execute `make run BINARY=/absolute/path/to/binary`. diff --git a/docker/build_cutter.sh b/docker/build_cutter.sh new file mode 100755 index 00000000..e584fbd6 --- /dev/null +++ b/docker/build_cutter.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +# This script is a work in progress + +#### Constants #### +ERR=0 + +#### User variables #### +BUILD="$(pwd)/build" +QMAKE_CONF=$* +ROOT_DIR=$(pwd) + +find_qmake() { + qmakepath=$(command -v qmake-qt5) + if [ -z "$qmakepath" ]; then + qmakepath=$(command -v qmake) + fi + if [ -z "$qmakepath" ]; then + echo "You need qmake to build Cutter." + echo "Please make sure qmake is in your PATH environment variable." + exit 1 + fi + echo "$qmakepath" +} + +find_lrelease() { + lreleasepath=$(command -v lrelease-qt5) + if [ -z "$lreleasepath" ]; then + lreleasepath=$(command -v lrelease) + fi + if [ -z "$lreleasepath" ]; then + echo "You need lrelease to build Cutter." + echo "Please make sure lrelease is in your PATH environment variable." + exit 1 + fi + echo "$lreleasepath" +} + +find_gmake() { + gmakepath=$(command -v gmake) + if [ -z "$gmakepath" ]; then + gmakepath=$(command -v make) + fi + + ${gmakepath} --help 2>&1 | grep -q gnu + if [ $? != 0 ]; then + echo "You need GNU make to build Cutter." + echo "Please make sure gmake is in your PATH environment variable." + exit 1 + fi + echo "$gmakepath" +} + +prepare_breakpad() { + OS="$(uname -s)" + if [ -z "$OS" ]; then + echo "Could not identify OS, OSTYPE var is empty. You can try to disable breakpad to avoid this error." + exit 1 + fi + + if [ "$OS" = "Linux" ]; then + . $ROOT_DIR/scripts/prepare_breakpad_linux.sh + export PKG_CONFIG_PATH="$CUSTOM_BREAKPAD_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" + elif [ "$OS" = "Darwin" ]; then + . $ROOT_DIR/scripts/prepare_breakpad_macos.sh + fi +} + +# Create translations +$(find_lrelease) ./src/Cutter.pro + +# Build +if [ "${QMAKE_CONF#*CUTTER_ENABLE_CRASH_REPORTS=true}" != "$QMAKE_CONF" ]; then + prepare_breakpad +fi +mkdir -p "$BUILD" +cd "$BUILD" || exit 1 +$(find_qmake) ../src/Cutter.pro "$QMAKE_CONF" +$(find_gmake) -j4 +ERR=$((ERR+$?)) + +# Move translations +mkdir -p "$(pwd)/translations" +find "$ROOT_DIR/src/translations" -maxdepth 1 -type f | grep "cutter_..\.qm" | while read -r SRC_FILE; do + mv "$SRC_FILE" "$(pwd)/translations" +done + +# Finish +if [ ${ERR} -gt 0 ]; then + echo "Something went wrong!" +else + echo "Build complete." + printf "This build of Cutter will be installed. Do you agree? [Y/n] " + read -r answer + if [ -z "$answer" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ]; then + $(find_gmake) install + else + echo "Binary available at $BUILD/Cutter" + fi +fi + +cd .. diff --git a/docker/build_radare2.sh b/docker/build_radare2.sh new file mode 100755 index 00000000..149eae4c --- /dev/null +++ b/docker/build_radare2.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +check_r2() { + r2 -v >/dev/null 2>&1 + if [ $? = 0 ]; then + R2COMMIT=$(r2 -v | tail -n1 | sed "s,commit: \\(.*\\) build.*,\\1,") + SUBMODULE=$(git submodule | grep "radare2" | awk '{print $1}') + if [ "$R2COMMIT" = "$SUBMODULE" ]; then + return 0 + fi + fi + return 1 +} + +# Build radare2 +check_r2 +if [ $? -eq 1 ]; then + printf "A (new?) version of radare2 will be installed. Do you agree? [Y/n] " + read -r answer + if [ -z "$answer" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ]; then + R2PREFIX=${1:-"/usr"} + git submodule init && git submodule update + cd radare2 || exit 1 + ./sys/install.sh "$R2PREFIX" + cd .. + else + echo "Sorry but this script won't work otherwise. Read the README." + exit 1 + fi +else + echo "Correct radare2 version found, skipping..." +fi