CONAN und Remote Debugging

Neulich hat mich noch das Debugging in Visual Studio von CONAN Projekten beschäftigt und eine einfache CMake Variable löste das Rätsel.

Doch wie geht man das Problem unter Linux an?
Oder: Wie löst man das Abhängigkeitsproblem mit Visual Studio Code?


Das “normale” Visual Studio bietet zwar seit einiger Zeit Linux Debugging an, aber man muss dafür eigene Projekte generieren, was mit CMake aktuell schlecht bzw. gar nicht zusammenspielt.
Oder man hängt sich in ein bereits “vorbereitetes” CMake Projekt via SSH rein, aber genau das funktioniert wieder nicht mit Projekten, wo CMake seine Abhängigkeiten von CONAN hereinbekommt.

Nachdem Visual Studio Code nun endlich auch am Raspberry PI halbwegs stabil läuft, bin ich mehr und mehr von CodeBlocks und K-Develop zu VS-Code übergegangen.
Das war anfangs mühsam weil diese “leere” IDE mit seinen zusammengestückelten Tasks-Aufrufen den “richtigen” IDEs unterlegen war.
Langsam gewöhne mich aber daran und je länger man damit arbeitet um so eher akzeptiert man diese Eigenheiten.

Das CONAN Dependency Problem

Wenn CONAN unser CMake aufruft um die Projektstrukturen zu generieren, werden Include- und Link-Pfade korrekt gesetzt und die Builds sollten damit auch super laufen. Doch wenn man das fertige Programm im Debugger durchlaufen lassen will, schlägt der CONAN Hammer wieder zu:
Alle abhängigen Komponenten (*.dll, *.so) liegen im CONAN Cache und das gebaute Programm steht alleine da.

Die Lösung ist mit conan install .... -g virtualrunenv diverse Scripts zu generieren, die alle Abhängigkeiten in den Pfad (PATH, LD_LIBRARY_PATH, DYLD_LIBRARY_PATH) laden können.

Das Problem bei diversen IDEs und auch VS-Code ist, dass ein Debugging-Prozess nichts von diesen CONAN Script weis und das zu debuggende Programm falsch startet und gleich wieder abbrechen muss.

Lösung: Environment in den Debugger importieren

Wenn man nach einem ausgeführten conan instal .... -g virtualrunenv gleich im Anschluss source activate_run.sh aufruft, hat man die notwendigen Environment Variablen für eine Debugging-Session in der Shell gesetzt. Man kann sich diesen Zustand z.B. per echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH > saved_paths.env sichern.
Kaum ist die Ausführung abgeschlossen gehen die Variablen wieder verloren, aber die .env Datei bleibt.

In launch.json kann man durch das Feld envFile die zuvor gesicherten Variablen zurückholen und in der Debug-Session benutzen. Und schon kann ein debug-tes Programm seine CONAN Abhängigkeiten finden.

Wenn das Programm auch eigene parallel geladene Libs laden können muss, dann kann man diese Pfade auch selbst zusammenstellen und per Shell-Script in der env Datei anfügen. z.B.: mit

1source activate_run.sh && echo \
2  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/target/dir:/path/to/special/dir \
3  >my-conan.env

Und so kann das ganze dann am Ende aussehen:

 1//tasks.json
 2{
 3  "version": "2.0.0",
 4  "tasks": [
 5    {
 6      "label": "conan-install",
 7      "type": "shell",
 8      "command": [
 9        "conan install ${workspaceFolder} -if ${workspaceFolder}/build",
10        " && conan install ${workspaceFolder} ", 
11             "-if ${workspaceFolder}/build -g virtualrunenv",
12        " && source ${workspaceFolder}/build/activate_run.sh",
13        " && echo ", 
14             "LD_LIBRARY_PATH=${workspaceFolder}/build/bin:$LD_LIBRARY_PATH ", 
15             ">${workspaceFolder}/build/conan-libs.env",
16        " && echo DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH ", 
17             ">>${workspaceFolder}/build/conan-libs.env"
18      ]
19    },
20    {
21      "label": "conan-build",
22      "type": "shell",
23      "command": [ 
24        "conan build -if ${workspaceFolder}/build ",
25               "-bf ${workspaceFolder}/build ",
26               "-sf ${workspaceFolder} ${workspaceFolder}" ],
27      "problemMatcher": [ ],
28      "group": {
29        "kind": "build",
30        "isDefault": true
31      }
32    }
33  ]
34}
 1//launch.json
 2{
 3  "version": "0.2.0",
 4  "configurations": [
 5    {
 6      "name": "(gdb) Launch",
 7      "type": "cppdbg",
 8      "request": "launch",
 9      "program": "${workspaceFolder}/build/bin/my_binary",
10      "args": [],
11      "stopAtEntry": false,
12      "cwd": "${workspaceFolder}/build/bin",
13      "environment": [],
14      "externalConsole": false,
15      "MIMode": "gdb",
16      "setupCommands": [
17        {
18          "description": "Enable pretty-printing for gdb",
19          "text": "-enable-pretty-printing",
20          "ignoreFailures": true
21        },
22      ],
23      "envFile": "${workspaceFolder}/build/conan-libs.env"
24    }
25  ]
26}

Fazit

Nun, Mission erfüllt. Wieder ein CONAN Brocken aus dem Weg geräumt … oder sagen wir mal, wir haben einen Workaround dafür gefunden.

Mir wäre es lieber, es gäbe ein CONAN-Plugin, dass sich um solche lästigen Details automatisch kümmert, doch aktuell schafft man mit Boardmitteln nur kleine Hello-World CONAN Programme zu debuggen.
Sobald die Abhängigkeiten zunehmen bleibt einem (laut meinem aktuellen Stand) nichts anderes übrig, als per Scripts alles so hinzubiegen, dass es halbwegs läuft.

Das ist zwar aus meiner Sicht unbefriedigend … aber zumindest ist es mal ein Anfang.

📧 📋 🐘 | 🔔
 

Meine Dokus über:
 
Weitere externe Links zu:
Alle extern verlinkten Webseiten stehen nicht in Zusammenhang mit opengate.at.
Für deren Inhalt wird keine Haftung übernommen.



Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!