null

Удаленная отладка приложений на C++ или как оставить систему в живых

Постановка проблемы

Шла середина февраля некого года, когда один маленький Java-разработчик решил своими жабьями лапками собрать и запустить один исследовательский проект, разрабатывавшийся на великом и могучем C++. Маленький Java-разработчик привык, что программы запускаются в рамках виртуальной Java-машины, установка любых зависимостей выглядит как подключение нужной строчки в конфигурационном файле Maven или Gradle. И вот герою нашей истории довелось потрогать руками Make, CMake, Conan для сборки одного исследовательского проекта на С++. Как оказалось, проекту необходима версия boost-а 1.X, которому, в свою очередь, необходимы shared библиотеки (надо поставить apt-ом в случае Ubuntu) A, B, C версий 1.X. Но вот проблема - в репозитории Ubuntu 22 есть только библиотеки версии 1.Y (X <= Y). Маленький Java-разработчик решил, что можно подключить apt-репозиторий Ubuntu 20 (есть библиотекии версии 1.X) к живой Ubuntu 22... После нескольких вызовов утилиты apt умирает гном...

Вот и сказочке конец. Была Ubuntu 22, да развалилась. Несколько бессонных ночей в попытках починить сломанные зависимости, которые не дают системе запуститься в штатном режиме, не дали своих плодов и маленькому Java-разработчику пришлось переустанавливать ОС.

Решение проблемы

Спутся несколько месяцев гнева, нецензурных слов и отрицания пришла пора таки собрать один исследовательский проект на С++, потому что так надо. В качестве решения проблемы отсутствия нужных зависимостей в стандартном apt-репозитории Ubuntu 22 было принято решение поднять docker-контейнер с Ubuntu 20 (и как следствие с нужными shared либами). Казалось бы, очевидное решение, и почему маленькому Java-разработчику не пришло это на ум сразу?

FROM ubuntu:20.04

ARG DEBIAN_FRONTEND=noninteractive

COPY ./project /project
RUN apt update && \
	apt install -y make cmake python3-pip python3-dev software-properties-common

RUN pip install conan==1.54.0 && pip install numpy && \
	conan remote add bincrafters https://bincrafters.jfrog.io/artifactory/api/conan/public-conan && \
	conan config set general.revisions_enabled=1

WORKDIR /project
RUN make

CMD ["/project/run/project_runner"]

Уже лучше, чем ничего - можно собрать проект и запустить его в контейнере. Однако остается проблема с запуском в режиме "дебага", причем хотелось бы иметь возможность ставить бряки и просматривать содержимое памяти с удобством и блэкджеком прямиком из любимой IDE. Кроме того, нет возможности запустить отдельно модульные тесты без необходимости собирать весь проект целиком (сборки под плюсы, как известно, процесс небыстрый).

Оказалось, что и эти проблемы решаются относительно просто - "современные", "продвинутые" IDE имеют в своем арсенале фичу "remote development", благодаря чему становится возможным проводить сборки, запускать с использованием дебаггеров, запускать модульные тесты на удаленной машине. Например, дока JetBrains CLionдока Microsoft Visual Studio. А раз возможно на удаленной машине, то и возможно в docker-контейнере.

# Taken from https://github.com/shuhaoliu/docker-clion-dev/blob/master/Dockerfile

FROM ubuntu:20.04 as base-image

ARG DEBIAN_FRONTEND=noninteractive

########################################################
# Essential packages for remote debugging and login in
########################################################

RUN apt-get update && apt-get upgrade -y && apt-get install -y \
    apt-utils gcc g++ openssh-server cmake build-essential gdb gdbserver rsync vim

# Taken from - https://docs.docker.com/engine/examples/running_ssh_service/#environment-variables

RUN mkdir /var/run/sshd
RUN echo 'root:root' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

# 22 for ssh server. 7777 for gdb server.
EXPOSE 22 7777

RUN useradd -ms /bin/bash debugger
RUN echo 'debugger:pwd' | chpasswd

########################################################
# Add custom packages and development environment here
########################################################

FROM base-image as image-with-deps

RUN apt update && \
	apt install -y make cmake python3-pip python3-dev software-properties-common

RUN pip install conan==1.54.0 && pip install numpy && \
	conan remote add bincrafters https://bincrafters.jfrog.io/artifactory/api/conan/public-conan && \
	conan config set general.revisions_enabled=1

########################################################

FROM image-with-deps
CMD ["/usr/sbin/sshd", "-D"]

Далее приведу пример конфигурации самой  IDE на примере JetBrains CLion (2023.1.2):

  1. Настроить RemoteHost Toolchain в IDE - открываем File -> Settings -> Build, Execution, Deployment -> Toolchains, добавляем новый Toolchain с типом RemoteHost. Минимально необходимо указать credentials (имеется в виду ssh креды) и в качестве дебаггера выбрать Remote Host GDB.
  2. Настроить Deployment - открываем File -> Settings -> Build, Execution, Deployment -> Deployment, добавляем SFTP deployment. Минимально необходимо указать credentials (имеется в виду ssh креды), root path (путь, относительно которого будут вычисляться маппинги), mappings. В mappings нужно указать что локальное и куда удаленно мы хотим заливать.
  3. Запустить билд CMake (CMake для примера), чтобы убедиться, что все робит, и чтобы IDE осознала обновленную конфигурацию.
  4. Осталось настроить Run/Debug Configurations персонально для вашего проекта (если конфигурации не подтянулись после пункта 3 автоматически) и можно пользоваться.

 

Всем добра, желаю никому не ломать свою ОС :)