Forum: Mikrocontroller und Digitale Elektronik Externe Libs richtig einbinden in C / c++


von Sebastian M. (meeresgott)


Lesenswert?

Ich hoffe ich bin hier im richtigen Subthread.

Ich entwickle aktuell einen Damon der auf einen RaspberryPI läuft und 
verwende die externe Bib wiringPi.
Das Programm schreibe ich auf einer Windows Maschine via git landen die 
Sourcen auf dem PI wo ich es compiliere und ausführe.

Jetzt bin ich auf ein Problem gestoßen, dass ich aus anderen 
Entwicklungen für embedded systems auch kenne. Wie binde ich eine fremde 
Bib richtig ein?

Meine "haupt"-Sprache ist java und dort gibt es Tools wie Grade/Maven, 
die für mich die dependencies auflösen.

Für C / C++ gibt es Makefile, allerdings "verstehe" ich das Konzept zum 
einbinden externe bibs nicht.


Mit diesem Befehl compiliere ich ein blink beispiel:
1
gcc -Wall -o blink blink.c -pthread -lwiringPi -lm -lrt -lcrypt

Vorausgesetzt man hat im Vorfeld wiringPI installiert die anderen bibs 
sind bibs die wiederum wiringPi braucht ( so wie ich es verstanden habe)

In meiner IDE ( Clion) kennt die wiringPi bib allerdings nicht, ist 
schließlich nicht auf meinem Dev-Computer. Aber wie bringe ich dieser 
jetzt bei, dass es dort eine bib gibt? Sodass ich die ganzen 
"Annehmlichkeiten" die mit Verwendung einer IDE kommen benutzen kann 
(Autofill etc.) ?

Also wie sähe eine Makefile aus der dieses repo 
https://github.com/WiringPi/WiringPi includiert und mit dem man das 
blink example compilieren kann:
1
#include <stdio.h>
2
#include <wiringPi.h>
3
4
// LED Pin - wiringPi pin 0 is BCM_GPIO 17.
5
6
#define LED     0
7
8
int main (void)
9
{
10
  printf ("Raspberry Pi - Gertboard Blink\n") ;
11
12
  wiringPiSetup () ;
13
14
  pinMode (LED, OUTPUT) ;
15
16
  for (;;)
17
  {
18
    digitalWrite (LED, 1) ;     // On
19
    delay (500) ;               // mS
20
    digitalWrite (LED, 0) ;     // Off
21
    delay (500) ;
22
  }
23
  return 0 ;
24
}
25
// http://wiringpi.com/examples/gertboard-and-wiringpi/blink/

oder muss ich das Repo von wiringpi selber auschecken? Falls Ihr mit 
maven vertraut seid suche ich nach einem minimal beispiel um nach einem 
Artefakt aufzulösen.

Wäre super, wenn mir jemand das erklären könnte. Links schicken etc. 
Irgendwie bekomme ich den Einstieg bei cmake nicht wirklich gefunden.

von samuel (Gast)


Lesenswert?

Sebastian M. schrieb:
> oder muss ich das Repo von wiringpi selber auschecken?

Das solltest du tun. Man kann das auch in CMake problemlos scripten, 
aber für den Anfang nicht zielführend.

Nur um das klarzustellen, du möchtest Crosscompilen. Also entwickelst 
auf einem x86 Linux Software, die nacher auf dem Raspi läuft?

von Sebastian M. (meeresgott)


Lesenswert?

Okay also wäre best practice die Elemente die ich brauche einfach in 
mein Project zu kopieren also z.B. eine solche Ordnerstruktur:
1
/
2
/src
3
/src/main.cpp
4
/src/{weitere Sourcen}
5
/lib/wiringPi/
6
/lib/wiringPi/{weitere Sourcen}
7
/Makefile

samuel schrieb:
> Nur um das klarzustellen, du möchtest Crosscompilen. Also entwickelst
> auf einem x86 Linux Software, die nacher auf dem Raspi läuft?

Ich entwickle die Software auf einer Windows Maschine compiliere und 
führe die Software aus auf einem Raspi ( Version 4 ist 64Bit - glaube 
drei auch) dessen OS Ubuntu 20.04 amd64 ist. Falls dich das Image 
Interessiert: https://ubuntu.com/download/raspberry-pi

Bin mir selber unsicher aber Corsscompilen wäre wenn ich versuchen 
wollen würde auf einer 64Bit maschine eine 32 Bit version zu 
compilieren, oder sogar noch extremer, wenn ich versuche auf windows für 
Linux zu compilieren oder vertue ich mich da?

EDIT: Habe es nochmal nachgelesen. Nein ich crosscompile nicht. Wenn 
würde ich wahrscheinlich eher den Weg über ein DockerImage o.ä. gehen 
aber ob dass dann immernoch Crosscompilen heiß, da der Virtuelle Host ( 
das Image ) ja das OS hat für welches man kompilieren möchte nur läuft 
der vHost ja auf einem anderen OS.

EDIT2: Jetzt hast du mich auf eine Idee gebracht. Mal gucken ob ich das 
compilieren so hinbekomme wie ich es mir vorstelle - aber zuerst muss 
ich meine Kirschen aus dem WiringPI repo flücken

: Bearbeitet durch User
von Klugscheisser (Gast)


Lesenswert?

Ohne viel Brimborium:
Libs werden mit dem Linker dazugelinkt.
Entweder als Archiv: Dann ist es eine ".a".
Man kann auch die einzelnen Objekte der Lib dazulinken.

Das kopieren ist und war niemals "Best Practice".
Nur Dummbeutel machen das so.
Libs baut man normalerweise extern zu seinem eigenen Projekt.
Im eigenen Projekt landen dann nur die Header und die Library.

von Vincent H. (vinci)


Lesenswert?

Wenn du nicht cross compilest dann wirst du nicht drum rumkommen die 
Header auszuchecken... Woher sollen die sonst kommen?

Wenn du cross compiliern würdest, dann lautet das Stichwort "remote 
headers". Ein Feature dass viele moderne IDEs unterstützen und das 
erlaubt etwa via SSH auf irgendwelche Header Pfade zuzugreifen die am 
Host System nicht existieren.

von Axel S. (a-za-z0-9)


Lesenswert?

Sebastian M. schrieb:
> Ich entwickle aktuell einen Damon der auf einen RaspberryPI läuft und
> verwende die externe Bib wiringPi.

> Das Programm schreibe ich auf einer Windows Maschine via git landen die
> Sourcen auf dem PI wo ich es compiliere und ausführe.

Ein bißchen kompliziert, nicht? Warum nutzt du nicht irgendein Netzwerk- 
Filesystem? Oder gleich eine IDE, die auf dem Pi läuft?

> Jetzt bin ich auf ein Problem gestoßen, dass ich aus anderen
> Entwicklungen für embedded systems auch kenne. Wie binde ich eine fremde
> Bib richtig ein?

Was verstehst du unter "einbinden"?

In C/C++ ruft man Funktionen aus einer (fremden) Library auf. Dazu muß 
der Compiler die Signaturen der Funktionen kennen und evtl. auch 
spezifische Datentypen. Zu diesem Zweck #includiert man ein Headerfile, 
das Bestandteil der Library ist.

Spätestens beim Linken deines Programms muß dann auch der Objektcode der 
Library vorliegen. Entweder als Archiv (libXXX.a) oder als shared object 
(libXXX.so).

Ergo: sowohl der Compiler als auch der Linker brauchen Zugriff auf die 
Library. Wenn du auf dem Pi compilierst, muß die Lib dort also 
vorliegen. Entweder als Teil deines Projekts oder als System-Library. 
Bei libwiringpi vermutlich letzteres.

> Für C / C++ gibt es Makefile, allerdings "verstehe" ich das Konzept zum
> einbinden externe bibs nicht.

Das hat mit dem Makefile auch nur sehr am Rande zu tun.

Eigentlich geht es nur darum, dem Compiler bzw. Linker ein paar 
Kommandozeilenoptionen mitzugeben.

Compiler: -I ... für ein (weiteres) Includeverzeichnis, wo er nach 
Headerfiles sucht.

Linker: -L ... als Suchverzeichnis für Libraries und -l ... einmal für 
jede Library, die dazugelinkt werden soll.

> Mit diesem Befehl compiliere ich ein blink beispiel:
>
1
> gcc -Wall -o blink blink.c -pthread -lwiringPi -lm -lrt -lcrypt
2
>

Weder -I noch -L sind gesetzt, also findet der Compiler die Hederfiles 
nur in den Standard-Verzeichnissen (/include, /usr/include, ...) und der 
Linker sucht auch nur in den Standard-Verzeichnissen (/lib, /usr/lib, 
...). Außerdem werden libwiringPi, libm, librt und libcrypt dazugelinkt. 
Die Libs können entweder als statische Libs vorliegen (libwiringPi.a, 
libm.a ...) und/oder als shared Libraries (libwiringPi.so, libm.so ...). 
Wenn beides, dann bevorzugt der Linker die shared Lib.

> Vorausgesetzt man hat im Vorfeld wiringPI installiert die anderen bibs
> sind bibs die wiederum wiringPi braucht ( so wie ich es verstanden habe)

Sozusagen. "installiert" meint hier: "die Headerfiles und Library-Files 
sind in einem der Standardverzeichnisse für Compiler/Linker gelandet"

Alternativ kann man die Library einfach "irgendwo" hinkippen und die -I 
und -L Optionen passend setzen. Eine IDE versteckt das in einem Dialog 
für Projekteinstellungen. Irgendwo unter "Compiler" und "Linker" und 
dann "Suchpfade".

> In meiner IDE ( Clion) kennt die wiringPi bib allerdings nicht, ist
> schließlich nicht auf meinem Dev-Computer. Aber wie bringe ich dieser
> jetzt bei, dass es dort eine bib gibt? Sodass ich die ganzen
> "Annehmlichkeiten" die mit Verwendung einer IDE kommen benutzen kann
> (Autofill etc.) ?

Am besten: gar nicht.

Das läuft nämlich darauf hinaus, daß du dein Programm crosscompilierst. 
Schließlich wirst du ja auch direkt aus der IDE compilieren wollen und 
dann von einer Fehlermeldung des Compilers direkt in den Code springen 
wollen, oder?

Crosscompilieren ist aufwendig einzurichten. Das macht man nur, wenn es 
auf der Zielplattform nicht geht. Wie bei einem AVR zum Beispiel. Der Pi 
hingegen ist ein vollständiges Linux-System. Da läuft nicht nur ein 
Compiler drauf, sondern auch eine IDE.

Die zweit Hürde handelst du dir mit Windows ein. Wenn dein 
Entwicklungsrechner unter Linux laufen würde, dann hättest du gute 
Chancen, den Crosscompiler und die (Cross-)Libraries für den Pi einfach 
aus dem Paketmanager installieren zu können. Aber für Windows bist du 
darauf angewiesen, das entweder selber zu machen oder jemanden zu 
finden, der es bereits gemacht hat.

von samuel (Gast)


Lesenswert?

Mein Vorschlag wäre dann folgendes:

CLion kann sich per SSH auf den Raspi einloggen und dort kompilieren und 
debuggen. Dann passt das auch mit den Header files.
https://blog.jetbrains.com/clion/2018/09/initial-remote-dev-support-clion/

Alternativ CLion auf den Raspi installieren und per X11-SSH auf den 
developmentrechner nutzen. Setzt aber eine schnelle Netwerkverbindung 
zwischen Raspi und deinem Rechner vorraus.

von Axel S. (a-za-z0-9)


Lesenswert?

samuel schrieb:
> Mein Vorschlag wäre dann folgendes:
>
> CLion kann sich per SSH auf den Raspi einloggen und dort kompilieren und
> debuggen. Dann passt das auch mit den Header files.
> https://blog.jetbrains.com/clion/2018/09/initial-remote-dev-support-clion/

Ach guck, das sieht doch gut aus. Dann reicht es ja, wenn man die C/C++ 
Toolchain auf dem RasPi hat. Die Synchronisiererei macht es zwar sicher 
nicht schneller und SSH und Windows ist auch eher ein Krampf. Aber wenn 
der TO die IDE unbedingt unter Windows laufen lassen will ...

von Johannes S. (Gast)


Lesenswert?

VSCode kann das über SSH inzwischen auch, die Installation ist sehr 
einfach weil automatisch. Solange das Raspian nicht zu alt ist.
Cross Compiling per Eclipse habe ich auch mal gemacht, war auch sehr 
einfach und man kann bequem debuggen, dazu hat hier jemand eine 
Anleitung geschrieben:
Beitrag "Cross-Compile & Remote-Debugging mit Eclipse"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.