 Hallo! Freut mich, dass so viele Leute tatsächlich gekommen sind, um sich Dinge über Valar anzuhören. Kennt jemand Valar hier drin schon oder hat schon mal was davon gehört? Ein, zwei Leute, cool! Dann freut es mich, darauf euch neue Dinge erzählen zu können. Was mich mit diesem Vortrag erreichen möchte, ist es Valar euch näher zu bringen. Erst mal vorzustellen, dann kursieren ein paar Gerüchte über Valar, mit denen ich aufräumen möchte. Ich möchte euch so ein bisschen durch den Prozess durchworgen, wie ich denn mit Valar Anwendung tatsächlich schreibe. Also, ich möchte nicht nur die Sprache beleuchten, sondern ich möchte ein bisschen das Ökosystem um Valar herum beleuchten. Also, was gibt es an Bildsystemen, die wir verwenden können? Dann habe ich ein paar Beispiele für ein Bildsystem mitgebracht, wie man damit zu arbeitet. Dann möchte ich anschauen, wie man Libraries schreibt oder wo Valar besonders tolle Vorteile hat, wenn man Libraries für andere Projekte schreiben möchte. Und ich habe das so als Lernprozess versucht zu designen und ich würde euch bitten, falls ihr irgendwas nicht versteht oder falls euch irgendwie eine Information fehlt, dem Ganzen zu folgen, sofort zu fragen. Ich werde eure Fragen fürs Video wiederholen. Hallo Internet! Und dann können wir gemeinsam da uns dieser Sprache ein wenig nähern. Erstmal wollte ich ja los sagen. Ein bisschen was zu mir. Warum stehe ich hier? Warum rede ich über Valar? Das hat den Grund, dass ich Open Source Projekte mache. Unter anderem LibGTKFlow, LibPartyTPS Everywhere und ich habe da mal so ein Browser geschrieben, der gerade auf GitHub so ein bisschen vor sich hin vegetiert, aber hoffentlich bald wieder Fahrt aufnimmt. Und ich habe da so ein bisschen Erfahrung gesammelt und die würde ich gerne mit euch teilen. Für mich ist Valar zum besten Produktivitätstool geworden, dass ich so kennen lernte. Das hat damit angefangen, als ich mein Fachinformatiker machte, hatte ich ein paar Kumpels, mit denen ich regelmäßig so Projekte zusammengeschrieben habe. Und irgendwann haben wir so gefunden, dass dieses PHP irgendwie komisch ist, weil das macht irgendwie jeder und wir haben uns dann mal überlegt, was könnten wir denn für unsere gemeinsamen Projekte so als Sprache hernehmen und haben verschiedene Sachen evaluiert. Damals waren so D, das sollte ein C Nachfolger werden, hat es aber nie ganz geschafft. Valar war mit im Rennen und so Sachen wie Rust und Go gab es damals noch nicht, also die waren damals noch nicht reif für den tatsächlichen produktiven Einsatz. Also ich programmiere viel mit Valar, deswegen stehe ich heute hier und dann möchte ich euch erstmal Valar selbst vorstellen. Das ist eine Sprache, die wurde von Jürg Billete erfunden damals im Rahmen von GNOME und das ist auch schon Valars größtes Stigma. Das heißt bei mich immer Valar ist diese komische GNOME-Sprache, aber das Valar General Purpose werden wir in den weiteren Folien sehen. Der Grund war damals, dass alle GNOME-Projekte in C geschrieben waren, damit C konnte man gut GTK programmieren, das ist quasi diese Oberflächen Library mit der GNOME-Programme geschrieben werden und C, wenn man da wirklich grafische Programme drin schreiben möchte, das wird unglaublich verbosen. Man muss sehr, sehr, sehr, sehr viel schreiben und da haben sie sich überlegt, okay, wie könnten wir das besser machen und was der Jürg dann versucht hat war, eine Sprache zu entwickeln, die sich ähnlich bedient wie C-Sharp und Java, also hat versucht, die Leute da abzuholen, wo es stehen, wo es viele Entwickler gibt und das werden wir nachher in der Söntags auch sehen, dass da sehr viele Überschneidungen existieren. Hier steht jetzt eine einfach benutzbare Sprache für das Geobject-Type-System. Ich möchte kurz ein paar Worte darüber verlieren, was dann das Geobject-Type-System ist. Geobject ist eine Library, die baut auf die G-Lib auf, das ist quasi diese Standard-Library für C und mit der kann ich in C-Objekt orientiert programmieren. C an sich ist ja erstmal nicht objektorientiert, C ist prozedural, das heißt, wir haben da unsere Statements und unsere Funktionen, aber C kann ja auch structs und wir können uns quasi selbst regeln setzen, dass wir in C-Objekt orientiert programmieren, das heißt, wir definieren unsere structs, das sind unsere Objekte, da wird unser State drin gespeichert und dann definieren wir ein paar Methoden drum herum, die quasi immer ein Pointer auf so ein struct entgegennehmen und dann auf diesem struct operieren und das sind dann unsere Methoden. Dann haben wir noch ein paar Spezielle, die quasi diese structs erzeugen für uns und initiale Operationen machen und das nennt sich dann Konstruktor und dann haben wir noch welche, die Aufräumaktionen machen und das sind dann Destruktoren. Genau, jetzt ist das so, dass C-Object nichts anderes ist als einerseits eine Library, die mir diesen Vorgang erleichtert und einen Satz von Regeln, wie ich den C-Code zu schreiben habe, dass der möglichst standardisiert, leserlich und objektorientiert bleibt. Nichts anderes ist C-Object. Valar ist stark typisiert, folgt dem prozeduralen und dem objektorientierten Paradigma und hat Einflüsse aus C, C-Sharp und ein bisschen aus der funktionalen Welt, da es tatsächlich auch Closures gibt, aber das führt für diesen Vortrag zu weit. Wollen wir mal anschauen, wie so ein Valar-Programm entsteht. Valar ist kein Compiler selbst, sondern Valar erzeugt C, also die objektbasiertes C. Ich habe Valar-Sourcecode, der geht durch den Valar-Compiler, der heißt Valac auf der Kommandozeile, dann fällt der C-Qualcodebell raus und dann jag ich den durch den C-Compiler meiner Wahl. Das kann LLVM sein, das ist Valar ziemlich egal. Das liegt daran, wie wir unser Bildsystem so designen. Und dann wollte ich mit euch ein bisschen syntax gucken. Da habe ich mal angefangen, die Main-Methode aufzuschreiben, weil die Main-Methode auch sehr schön illustriert, wie Methoden generell in Valar geschrieben werden. Wir haben zuerst auf der linken Seite quasi unseren Access-Modifier, wie wir das aus C-Sharp und Java kennen, da wird quasi gesagt, aus welchem Scope ich auf diese Funktion zugreifen kann. Static bedeutet, dass die Methode nicht an einem Objekt klebt, sondern einen allgemeineren Kontext hat. Dann folgt der Rückgabewert, in diesem Fall eine Ganzzahl. Dann kommt der Name der Funktion und ganz am Schluss kommt quasi die Parameter-Liste. Parameter sind im Falle der Main-Funktion quasi die Argumente, die ich von der Kommandozeile übergeben bekomme. Valar ist relativ legär, was dieses Explizit-Schreiben angeht. Also alles, was wir nicht brauchen, können wir auch weglassen. Da ist Java ja ein bisschen strikt da, sobald da irgendwie ein Modifier fehlt, sagt uns, du hast das nicht geschrieben, du hast das nicht geschrieben. Und man hat am Ende immer solche langen Ausdrücke und Zeilen, die man eigentlich gerne kürze haben wollen würde. Dann habe ich mal was über Kontrollstrukturen. Das hier ist das ganz klassische if, if, else. Das, ich glaube, da muss ich nicht viel zu sagen. Das ist relativ zäh, ähnlich. Also ein if-Keywert sagt, wir wollen hier spalten. Dann kommt eine Bedingung hier und innerhalb von diesem Block kommen dann die Statements, die ausgeführt werden sollen. Dann haben wir eine zweite Bedingung, falls die geprüft wird, falls die erste nicht wahr wurde, mit dieser Bedingung geprüft. Dann kommt wieder eine Anweisung, die sagt, was in diesem Fall geschehen sollte und dann noch ein Block nach einem else, der sagt, was im Fall passieren soll, dass keine von den vorangegangenen Bedingungen erfüllt wurde. Unten haben wir noch einen ternären Ausdruck. Das ist quasi die Kurzschreibweise, falls ich irgendwelche Wertzuweisungen machen will. Also sprich, wir betrachten mal, also das hier ist eine variablen Zuweisung, wir betrachten mal den Part hier. Das heißt, wenn x null ist, also leer, dann schreibe 1 in diesem Wert und wenn es nicht null ist, dann schreibe x in diesem Wert rein. Also damit lassen sich zum Beispiel relativ gemütlich die Voltparameter setzen, wenn man sie setzen möchte. Dann haben wir hier mal so ein klassisches Switchcase. Da vergleiche ich quasi einen Wert, den ich rein bekomme, gegen verschiedene Konstanten. In C ist das so, dass die einzigen Typen, die ich da vergleichen darf, Chars sind oder Ints. Hier hingegen kann ich alles reinschmeißen, die einzige Bedingung ist, es muss Konstanz sein. Das ist in manchen Fällen richtig praktisch, weil ich kann dann direkt gegen Strings vergleichen, ohne mir irgendwelche Sachen noch dazu definieren zu müssen. So, da haben wir jetzt ein paar Schleifen. Also diese Schleifen muss ich dazusagen, die machen jetzt aus programmiertechnisch, also nicht unbedingt Sinn. Der Sinn dieser Folie ist es, so viele Kiefer zu wie möglich unterzubringen, damit man ein bisschen was von der Sprache sieht. Also wundert euch nicht. Wir haben am Anfang eine Schleife, die von 0 bis 22 hochzählt. Das ist quasi die Initialisierung. Dann haben wir eine Abbruchbedingung und hier wird quasi die Variable, die wir hochzählen, inkrementiert. Hier wird sie gedruckt und hier sagen wir noch, mach mit der nächsten Schleifen-Iteration weiter. Dann haben wir hier eine Schleife, die einmal LOL ausgibt. Solange diese Bedingung hier wahr ist, True ist immer wahr, wird diese Schleife weiterlaufen und einmal LOL printen. Aber wir sagen hier direkt Break, das heißt verlasse die Schleife und mache mit dem Code da weiter, wo die Schleife aufhört. Und am Schluss gibt es noch etwas Praktisches, nämlich ein ForEach. Mit einem ForEach spar ich mir quasi die Abfrage, wenn ich überall Array iterieren will oder über irgendwas, ein Iterable, dann kann ich mir den Aufruf an die Länge sparen und kann direkt über die in dem Array oder der Liste enthaltene Elemente drüber iterieren. So, noch was kurzes Objekt-Orientiertes. Das hier ist die klasse Schnork und Schnorks werden gefuppt. Ich weiß nicht, ob hier jemand das Buch weniger schlecht programmieren vom Orally-Verlag. Ich habe die Autoren leider vergessen, tut mir leid, gelesen hat, aber ich fand das sehr schön. Wir haben hier jedenfalls eine Klasse, die einen Schnork repräsentiert. Und die Klasse merkt sich in einer sogenannten Eigenschaft. Also das ist kein Attribut der Klasse, sondern es ist eine Property. Die hat einen Default-Wert. Die kann ich setzen und getten. Und die wird manipuliert von einer Methode, die Fub heißt. Und jedes Mal, wenn wir die Schnork fuppen, wird die Times-Fubt-Property um eins inkrementiert. Außerdem gibt es ein weiteres Konzept, das ich euch in dieser Folie zeigen möchte, nämlich Signale. Signale lassen uns eventbasiert das Programmieren machen. Java verwendet hierbei die ganze Zeit irgendwelche Interfaces, die ich in meiner Klasse implementieren muss und die eventuell auch relativ ungemütlich sind. Das ist ein ziemlich direkter Weg. Ein Signal ist erst mal nichts anderes in meiner Klasse als eine Funktion, also eine Methodensignatur ohne Body hinten dran. Das heißt, ich habe auch wieder einen Access-Modifier, also werde ich auf dieses Signal zugreifen. Ich habe das Keyword Signal, das für den Compiler die Methode von anderen unterscheidbar macht. Ich habe einen Rückgabewert. Und ich habe einen Namen und eine Parameterliste, die in diesem Fall leer ist. Und auf dieser Folie sehen wir weiterhin die erste Pitfall, die ich anfühlen möchte. Hier oben sehen wir noch die Syntags für Vererbung. Mein Schnorck erbt von der GLIP-Object-Klasse und jedes Objekt in diesem Geobject-Type-System, das diese tollen Geobject-Feature nutzen möchte, muss von dieser Klasse erben. Das passiert leider nicht implizit. Das müssen wir explizit jedes Mal angeben. Also wenn ihr jemals irgendwie ein Signal definiert und irgendwie reagiert da nichts drauf, dann liegt das höchstvermutlich daran, dass ihr nicht von GLIP-Object geerbt habt. In der nächsten Folie schauen wir uns an, wie das Signal benutzt wird. Ah, eine Frage. Katrin Passig. Hier kommt gerade der Hinweis rein, wer weniger schlecht programmierend geschrieben hat. Das sind Katrin Passig und Johannes Jander. Danke schön. Hier sehen wir, wie wir so einen Schnorck und seinen Signal überhaupt benutzen. Wir instanzieren uns erstmal einen Schnorck. Das passiert hier mit dem New-Operator und dann wird quasi die Klasse und zwei Funktionslammern, um die Konstrukte aufzurufen, abgesetzt. Und das speichern wir in einer My-Schnorck-Variable. Und diese Variable sehen, wie hier statt mit einem expliziten Typ mit Waage initialisiert. Also sprich, wir haben quasi Typ-Inferenz. Wenn eindeutig ist, was hier von Typ rauskommt, müssen wir nicht explizit hier hinschreiben von was von Typ unsere Variable ist. Macht auch einiges an Schreibarbeit, meistens besser, wenn wir irgendwann mal bei einer komplexeren Architektur längere Klassennamen haben. Gut, in der nächsten Zeile connecten wir das Fub-Signal auf eine Methode, auf eine Funktion, die darauf reagiert. Also jedes Mal, wenn mein Schnorck gefubbt wird, führen wir das aus, was in der Klammer steht. Das kann entweder so ein Closure hier sein oder es kann tatsächlich eine Funktion sein, die irgendwo in unserem Code steht. Genau, dann wird einfach geprintet, dass der Schnorck gefubbt wird. Jetzt gibt es im Geobject-System noch eine wesentlich coolere Funktion. Das hier war so ein Beispielsignal. Geobject bringt dieses Beispielsignal sogar schon selber mit. Das müssen wir eigentlich gar nicht implementieren, sondern ein Change von der Variable reagieren ist jetzt eine relativ allgemeine Fall. Das sollten wir nicht selber tun müssen. Deswegen gibt es das Not-DeFi-Signal, direkt von Glib. Da kommt quasi ein Parameter mit dazu, also so ein Array-Zugriffparameter, welche Property wir denn beobachten wollen. Und dann wird auch auf die wieder connected und von da aus funktioniert es gleich. So, eine Frage. Der muss zu dem Zeit auflösbar sein, zu der das Signal gebunden wird, also zu Runtime. Ja. Dann habe ich noch eine Folie über Generics. Das werde ich ganz kurz ansprechen. Wir können Container bauen. Das kennt man vielleicht von C++ so ein bisschen. Wir können Klassen bauen, denen wir Typen übergeben können, mit denen diese Klassen handieren. Das wird quasi zur Compile-Zeit aufgelöst, wie die Klasse das tut. Wir können dieser Klasse hier einen Typ T mitgeben, das kann Int-Sign, das kann String-Sign, das kann auch eine von unseren Klassen sein. Und ab diesem Zeitpunkt kann diese Klasse, wenn sie dann instanziert wird, hier eine Variable dieses Typs in einer Property-Namens-Contained-Object handeln. So, ich habe noch eine unvollständige Liste ausgelassener Themen, weil die Zeit dafür einfach nicht reicht. Es gibt noch asynchrone Methoden. Es gibt Contract-Based Programming, es gibt noch ein sehr interessantes Konzept und hat eine, also in die Sonntags, auch integriertes Zentregix ist. Ich möchte dich nicht unerwähnt lassen. Gleich hier möchte ich mal ein paar Ressourcen ansprechen, die man auf jeden Fall haben sollte, wenn man den Valar programmiert. Das Wichtigste ist dieses Valar-Tutorial, das Offizielle auf den GNOME Wiki. Das macht jeden Aspekt der Sprache einmal durch und man hat danach einfach irgendwie alles drauf, was so verfügbar ist. Das ist Valar.org, das ist die Referenz-AP-Dokumentation. Also sprich, da sind alle Libraries gelistet, mit denen ich so mit Valar arbeiten kann. Und das ist schon inzwischen eine ganze Menge geworden. Dann gibt es noch ein Github-Repository, das ich hier aufwählen möchte. Das ist Valar-Extra-Warpies von Nemecu und da lagern ganz viele Library-Bindings, die noch nicht so gut getestet sind, dass sie in die offizielle Distribution dürfen, aber meistens auch schon relativ gut funktionieren und dann irgendwie an exotischeren Kram ranbinden. Ansonsten gibt es noch den Bakzilla.norm.org. Da finden wir das Valar-Projekt. Eventuell ist es inzwischen auf GNOME's GitLab gemuft. Ich hatte leider nicht mehr die Zeit, das nachzusehen. Aber falls auf Bakzilla seid, werdet ihr dann automatisch weitergelingt. Diese Seite erzähle ich euch, weil man da Bugs an Valar melden kann. Und dann gibt es am Schluss noch den IAC-Channel auf IAC.norm.org. Da findet man ganz viele freundliche Leute, die immer hilfsbereit sind und euch helfen, wenn ihr mal Probleme habt. Und dann wollte ich mal zu den Applikationen gehen. Wir programmieren uns mal eine Applikation. Und in so modernen Applikationen sind UIs immer sehr wichtig und deswegen wollte ich mal mit so einem Gerücht aufräumen. Und zwar habe ich das öfter gehört, wenn ich mit Leuten rede und ich sage, ich mache GTK, dass die dann sagen, was, oh nein, da musst du ja alles irgendwie manuell von Hand schreiben. Und das hält sich echt hartnäckig. Und deswegen zeige ich euch mal den ursprünglichen Weg, wie man das gemacht hat. Manueller UI-Bau mit GTK. Da initialisiere ich zuerst GTK, erzeuge dann die UI-Elemente, die ich brauche. In diesem Falle zum Beispiel ein Window, also ein Fenster, das auf dem Desktop gerendert wird. In dieses Fenster möchte ich einen Button platzieren, der beschriftet sein soll mit Fuba. Ich möchte, dass dieser Button irgendwas tut, wenn ich darauf klicke. Dann möchte ich zu meinem Window den Button hinzufügen. Ich möchte, dass alles auf dem Bildschirm angezeigt wird. Ich möchte dem Window noch eine Margin so an der Seite geben, dass das nicht so gedrückt ausschaut. Und ich möchte noch ein Titel ins Fenster setzen. Und jetzt kann man sich vorstellen, das ist eine unglaublich triviale Anwendung und man kann sich vorstellen, dass das hier noch nicht so gut ist. Und ich möchte noch ein Titel ins Fenster setzen. Und jetzt kann man sich vorstellen, das ist eine globale Anwendung und man kann sich vorstellen, wie das ausartet, wenn man tatsächlich seinen kompletten GUI-Code so schreiben muss. Ist ein bisschen blöd. Kann ich auch verstehen, diese Kritik, dass Leute das nicht verstehen. Aber zum Glück sieht das in der Realität inzwischen besser aus. Da gab es einen Zwischenschritt, und zwar UI-Bau mit GTK-Bilder. Da habe ich hier so eine Applikation, die heißt Glade, mit der kann ich meine UI auf einmal zusammenklicken. Alles, worauf ich achten muss, das ist ein Scheuerelementen, die ich mir hier zusammenklicke, sinnvolle IDs gebe. Weil die muss ich später im Programm wissen, damit ich mit diesen Elementen tatsächlich hantieren kann. Und wenn ich fertig bin, mit Glade Dinge zu bauen, dann fällt da XML raus. Das hier ist im Endeffekt XML, die genau dasselbe beschreibt wie das, was wir vorhin gesehen haben. Da steht dann drin, dass es einen Button gibt, der innerhalb eines Windows ist und die haben verschiedene Parameter gesetzt, die man in der Property Store mit Werten voll definiert. Und die möchte ich jetzt im Code benutzen. Der Code dazu sieht so aus, dass ich mir zuerst einen GTK-Bilder baue. In diesen Bilder lade ich mir eine UI-Pfeil rein. UI ist quasi dieses XML, was wir gerade gesehen haben. Und dann kann ich Signale, die ich vorher in Glade definiert habe, durchkonekten mit Funktionen, die ich in meinem Code habe, auf diese ganze Signale reagieren. Und am Schluss kann ich mir noch mein Window aus dem Bilder rausziehen mit GetObject. Und hier brauche ich diese ID, die ich vorhin vergeben habe und kann sie im Schluss anzeigen. Also sprich, egal wie viele Steuer-Elemente wir haben, der effektive Programmcode wird nicht mehr so hart aufgebläht wie vorher. Und jetzt kommt noch der Königsweg, nämlich GTK Templating. Und da sieht das Ganze so aus. Bei GTK Templating, das ist so Wahler-Explosiv, das habe ich bisher noch in keiner anderen Sprache gesehen, dass das funktioniert, arbeite ich mit Anotationen. Ich fange an, mein Window als Klasse zu designen erstmal. Ich sage, mein Window ist ein GTK-Window-Pult. Und dann sage ich hier drüber, dass dieses Window von einem Template aus einer UI-Datei gefüttert wird. Dann sage ich, was hier denn so drin ist. Und dann sage ich, hey, du bist ein GTK-Child in dieser Anotation. Und diese Entry hier, die Tatsache, dass diese Property Entry heißt, ist quasi denn, bezieht sich auf die ID von einem Steuer-Element, die ich in der UI-File vergeben habe, in meinem UI-Designer. Und das hier ist das Dritte im Bunde, nämlich ein GTK Callback. Das heißt, es ist ein Signal, wo ich von meinem UI-Editor draufbeinden kann. Im Endeffekt sieht das wesentlich aufgeräumte aus als alles, was wir vorhin hatten. Und das ist State of the Arts, so baut man GTK-UIs heute. So, um das so funktionieren zu bringen, müssen wir zwei Dinge noch in unseren Bildprozess einbauen, den ich jetzt ansprechen werde. Und zwar sieht man hier, dass das hier oben irgendwie kein ordentlicher Pfad ist, sondern das ist ein sogenannte Ressourcenpfad. Und Ressourcen möchte ich hier mal kurz erklären. Ressourcen sind die Möglichkeit, Datendateien mit in unseren Code einzubetten, dass sie nicht als Dateien rumfahren, die ich manuell irgendwie laden muss, quasi zur Laufzeit rein streamen muss, irgendwo ablegen muss, sondern diese ganzen Datendateien werden gesammelt und mit einem Resource Compiler in C-Code verwandelt. In diesem C-Code kann ich dann über eine Library direkt in der Binary quasi laden. Und jetzt brauchen wir natürlich auch noch ein Tool, um diesen ganzen Mist zu orchestrieren, weil wir haben jetzt schon Valar, wir haben GTC und wir haben diesen Resource Compiler. Und ihr könnt euch vorstellen, das wird ziemlich stressig, das manuell zu machen und jedes Mal der Compiler Befehle einzugeben. Deswegen möchte ich euch ein Bildsystem vorstellen. Ich habe lange gesucht. Ich hatte Automake, ich hatte CMake, ich hatte Waf, ich hatte... Wir hießen das noch mal. Es war irrelevant. Miesan ist der Weg zu gehen. Miesan habe ich 2016 kennengelernt auf der GUA Deck und das macht einen sehr übersteuigenden Job. Er hat sehr, also nicht anklattert Code und erinnert sehr an Python, was es sehr angenehm macht, damit zu arbeiten. In einem kleinen Miesan-Exkurs möchte ich euch mal kurz durch ein Library-Projekt von mir leiten. Wir haben ja tatsächlich Code aus der LibHarteeTPS Everywhere. Den möchte ich euch mal kurz zeigen. Ganz am Anfang definieren wir ein Projekt. Dann sagen wir, das Projekt hat Namen, dann sagen wir, welche Compiler wir brauchen, in unserem Fall Valor und C und dann können wir noch eine Version bestimmen. Dann können wir auf Package-Config dependen, um zu überprüfen, ob unsere Libraries jeweils Abhängigkeiten brauchen da sind und dann definiere ich hier noch API-Versionen, die quasi eingetragen werden, dass die einmal konstant definiert sind und ich sie nur an einer Stelle ändern muss und dann kann ich noch sagen, hier die Dependencies, kann ich meine Dependencies hier reinholen mit Dependency-Klammer auf, das hier ist der Package-Config-Name und ich kann Subdias inkluden, zum Beispiel unser Source Directory. Am Ende kann ich noch selbst für dieses Paket, was ich gerade baue, den Package-Config-Fall generieren, damit ich die Library wieder in anderen Projekten gemütlich einbinden kann. Am Schluss kann ich noch sagen, dass es so installiert werden soll. Und jetzt geht es aufs Source Level. Also das hier war gerade die Meson-File auf der Route Ebene meines Projektes. Und jetzt gehe ich mal quasi in den Source Ordner und schaue mal an, dass da passiert. In den ersten fünf Zeilen werden einfach die Source Files zusammengetragen. LipartyTPS Everywhere ist recht einfach. Dann bestimme ich einen Namen für eine Geobject-Introspection-File. Da kommen wir gleich im nächsten Kapitel drauf zu sprechen. Und im nächsten Schritt wird tatsächlich diese Library kompiliert. Also ich gebe dir einen Namen. In dem Fall ist das HTTPS Everywhere plus die AP-Nummer, damit wir quasi mehrere AP-Versionen parallel später installiert haben können. Dann sage ich, was ist die Source und dann kommen noch quasi Keyboard-Arguments. Also sprich, ich baue die Dependencyster ein. Ich sage ihm, er soll eine Geobject-Introspection-File bauen. Ich sage ihm, er soll eine Geobject-Introspection-File bauen. Ich sage ihm, er soll eine Geobject-Introspection-File bauen. Ich sage ihm, er soll den C-Header dabei rausgenerieren. Der wird nämlich sonst gelöscht. Ich sage, diese Library, die daraus entsteht, soll installiert werden. Wenn ich dann meine Bildsysteme sage, installiere ich das mal auf der Festplatte. Und ich sage ihm noch, was für eine Library-Version das ist. Die habe ich auch vorher definiert. Dann gibt es noch die Möglichkeit, Geobject-Introspection einzusetzen. Das ist eine coole Möglichkeit, dass man die Geobject-Introspectionen verbinden kann. Das ist eine coole Möglichkeit, um Aufwand zu vermeiden, bindingsgenerieren oder manuell schreiben zu müssen. Das passiert hier in der ersten Zeile. Also, das passiert hier in diesem Abschnitt. Da sage ich quasi, ich möchte ein Custom Target. Also, ich sage die Bildsysteme, ich möchte ein Custom Target. Das heißt, ich kann manuell da Schellbefehle reinschmeißen. Und ich nutze keinen Template, dass das Bildsystem mir vorgibt. Also, ich möchte darauf jetzt momentan nicht eingehen, weil ich da auch später zu sprechen kommen werde. Und hier sei nur kurz angesagt, es besteht auch die Möglichkeit, mit Valadoc manuell also automatisch Dokumentation für die Module zu generieren, die wir schreiben. Das ist noch ein Workaround, den möchte ich kurz als Pitfall erwähnen. Wenn ihr eine etwas ältere Meson-Version habt, dann gab es damals ein kleines Problem, nämlich, dass der InstallHeaders-Command erwartet hat, dass wenn ich ihm sage, installiere mal bitte eine Header-Datei, dass die bereits existiert von Bilden, was natürlich bei Valadoc nicht funktioniert, weil wir die HDTPs Everywhere.h erst dann generieren, wenn Valadoc schon durchgelaufen ist. Und das hat Meson nicht gefallen. Also, wenn jemand mit einer älteren Meson-Version noch rumrennt, ja, erspart euch damit ein Haufen Ärger. Und wie mache ich jetzt so ein Template dann für unsere Anwendung? Möchte ich noch kurz auf das Namens-Mapping zwischen Valar und C zu sprechen kommen. So werden Klassennamen zwischen Valar und C gemapped. In Valar habe ich einen Namespace definiert und in dem, der heißt FU, in dem befindet sich eine klasse bar, dann wird das C struct, auf das ich das bezieht FU-Bar heißen. Also, CamelCase und übernommen, und wäre dieses Bar in CamelCase, wo die B beide groß sind, dann wären auch hier beide B groß. Und deswegen muss ich damit dieses Beispiel von vorhin mit meinem Fenster funktioniert, den Klassennamen etwas umändern, nämlich habe ich ein Namespace angelegt, der MyTool hieß vor allem im Code und deswegen muss mein Fenster, meinen Klassenname hier MyToolWindow heißen. Also, nacheinander Namespace und dann der Klassenname von dem Template, auf das ich diesen Entwurf dann webben möchte. So, ich habe ein paar Benchmarks mitgebracht, die möchte ich kurz durchspielen. Ich habe zwei Algorithmen programmiert in C, Python und Valar und die mal gegeneinander antreten lassen. Wir haben einmal P nach Monte Carlo, das ist eine Methode um P zu berechnen und wir haben QuickSort, das ist ein Average Sorting Algorithmus. P nach Monte Carlo mit 10 Millionen Punkten und QuickSort mit 10 Millionen Zufälligen-Elementen. Das ganze lief auf dieser Kiste hier mit 64-Bit-Linux, Core i5, 4Hz. Lustigerweise hat mir LSCPU gesagt, dass eigentlich 3,4Hz sind. Möchte ich der Vollständigkeit halber noch dazu erwähnen. Bei P nach Monte Carlo sieht das so aus, also man sieht der Overhead zwischen, also die Python Anwendung lief knapp über 0,5 Sekunden, die Valar Anwendung lief 0,8 irgendwas und die C Anwendung in 0,5. Und dann haben wir noch QuickSort. QuickSort ist also da bei QuickSort den Array erstmal initialisieren muss, den ich danach sortiere, kann es sein, dass ungerechte Fälle existieren, in denen quasi das eine Programm den perfekt vorsortierten Array bekommt, was natürlich blöd ist, deswegen habe ich für jede Programmiensprache das Programm 10 mal durchlaufen lassen und dann den Durchschnitt genommen. Da sehen wir, dass C 0,25 Sekunden gebraucht hat, Valar hat 0,5 Sekunden gebraucht und Python dann irgendwie 5, fast. So. Ich habe schon mal angesprochen vorhin in meinem Bildsystem Exkurs, dass wir ein paar andere Sachen machen können für Libraries, also ein bisschen mehr als für Anwendungen, weil wenn ich so eine Anwendung raushaue, dann ist sie fertig, aber bei Libraries ist es so, dass andere Programme meine Library benutzen möchten und ich muss denen ja möglichst gute Arpies Code benutzen können. Und deswegen gibt es da eine Technik Geobject Introspection, die ich auf jeden Fall ansprechen möchte. Das ist quasi eine Art und Weise, wie ich Libraries meine Programme anbinden kann. Und das funktioniert so, dass die generierten Headers von meinem Valar Compiler, von einem sogenannten GIR, also Geobject Introspection Compiler, gelesen werden. Und der generiert dann quasi zuerst ein XML-File, das die API zu dieser Library beschreibt. Diese XML-File wiederum kann ich in Binärformat packen. Und viele, viele Programmiersprachen unter anderem Perl, Python, JavaScript, Lua etc. etc. haben dann Module, die diese binären API-Beschreibungen lesen können. Und ich hatte letztens eine Diskussion. Ich möchte den Aslic grüßen. Wir diskutierten im IASC, warum Geobject Introspection, oder ich habe verteidigt, warum Geobject Introspection eigentlich so cool ist. Und ich konnte das damals nicht wirklich in Worte fassen. Warum? Deswegen habe ich mal grob versucht, das zu formalisieren. Und habe mal geschaut, was müssen wir denn machen, wenn wir ja sowas beurteilen wollen. Deswegen habe ich vier Kategorien festgelegt, in denen ich das mal messen möchte. Setup, also quasi wie viele Aktionen muss ich halt Nutzer machen, wenn ich so eine Library dann aufsetze. Wie dann Aktionen bei API-Änderungen, wie viele Aktionen muss ich manuell machen, wenn ich tatsächlich meine API entweder ein neues Feature hinzufüge oder ein Parameter ändere oder so. Also sprich, sich die API ändert und ich darauf reagieren muss. Wie viele Artefakte werden kreiert, also sprich Dateien pro Sprache, also wie viele Artefakte pro Sprache brauche ich potenziell, damit das funktioniert. Und wie viele Dependencies hole ich mir rein. Und ich habe das mal hier so aufgeschrieben, wir haben quasi bei manuellen Binding-Schreiben auf der Haustsprache gar nichts zu tun. Also manuell das Binding-Schreiben heißt, ich greife über das Foreign Function Interface auf diese Library zu und knüpfe dann manuell an das Foreign Function Interface an. Und das ist so ziemlich die mühsamste Methode das zu tun. Das sieht man auch schon hier. Ich brauche N-Aktionen, wenn sich beim N-Aktionen um für den Guest, also bei der Guest-Danguage, um eine Sprache zu versorgen, weil ich für jede Sprache eine eigene Datei schreiben muss und diese manuell erwarten muss. Also es sind auch sehr teure Ends. Dann AP Changes bei Guest ebenfalls, weil ich für jede Sprache, die ich dran beinden möchte, diese neue API-Änderung einmal einpflegen muss. Krierte Artifakt ist ebenfalls N, weil ich pro Sprache eine Artifakt brauche. Dann gibt es die nächste Möglichkeit und zwar Binding Generators. Also so was wie SWIG. SWIG ist sehr bekannt aus der C++-Welt, denn SWIG generiert Python-Bindings zum Beispiel sehr gut an C++-Projekte dran. Da läuft es so, dass ich einmal, einmalig Aufwand habe bei der Haustsprache, also sprich C++, für die ich dieses Projekt aufsetze und ich habe Null Aufwand beim Guest und ich habe erst wieder auf, also jedes Mal, wenn ich was ändere, passiert das automatisch, weil ich bei SWIG natürlich in meinen Bildprozess ein, muss nichts manuell tun, aber ich kliere halt wieder N-Artifakte pro Sprache und ich ziehe mir eine Dependent-Szene rein. Der Aufwand ist auch wieder N. Und für Ge-Object-Introspection sieht das folgendermaßen aus. Wir haben einmal die Haustsprache, wir müssen einmal quasi das Bildsystem für Ge-Object-Introspection aufsetzen, müssen an der Guestsprache nie wieder etwas tun, wir müssen am Host nie was tun, wir müssen am API-Change nie was tun und kreierte Artefakte ist auch konstant, weil ich nur ein einziges Mal diese Type-Lip rausschreibe und die von allen anderen Sprachen konsumiert wird. Und das ist der Grund, warum ich die Object-Introspection so cool finde. Ja, es gibt auch einen weniger bekannten Classifier für, also ein Exosmodifier, den ich ansprechen möchte, nämlich Internal. Internal ist quasi jedes Element, das sich in meinem variablen Namespace befindet, darf auf diese Property zugreifen. Und es gibt eine weitere Pitfall beim Schreiben von Libraries, wenn ich Introspection benutzen möchte, darf ich eine bestimmte Gruppe von Dingen nicht benutzen, und zwar ist das alles, was mit Templates zu tun hat. Es gibt eine sehr tolle Collection und Container Library namens G in der Valarwelt, die benutzt man sehr gerne, die schreibt sich auch echt angenehm. Ich würde allen Anwendungsentwicklern auch empfehlen, die zu benutzen, allerdings nicht bei Libraries, weil die benutzen Templates. Ich sage dieser Liste, hey, du hast da ein Int in dir, oder ein String, und das ist nicht introspectable. GObject Introspection kann leider noch kein Templating. Es gibt stattdessen die G-Liblist, die handelt sich ein bisschen klankier, aber sie funktioniert. Ich kann von Python, von Perl, von JavaScript aus, kann ich diese benutzen und das funktioniert recht gut. Hier mal einen Aufruf, vielleicht hat der eine oder andere von euch irgendwie sucht noch ein Projekt für seine Compiler-Bauvorlesung oder so. Es gibt einen sehr detaillierten Bug Report zu diesem Thema. Die ganze Vorarbeit ist eigentlich schon gemacht, da hat jemand sehr detailliert aufgeführt, was denn zu machen wäre, damit die Object Introspection jetzt Templates können sollte. Vielleicht hat ja irgendjemand Bock, das mal als Projekt so anzugehen. Ja, kommen wir zu Bindings. Wie beinde ich den Code Anwaler? Das mache ich mit sogenannten WAPI-Files. WAPI-Files haben auch so Annotations, wie wir das beim GTK Templating schon gesehen haben, nur dass ich diesmal nicht Metadaten über GTK oder UI-Informationen gebe, sondern ich gebe dem Compiler-Metadaten darüber, wie er Dinge nach C übersetzen soll. So kann ich auch die Verkorks des Delibrations noch irgendwie an Wala anbinden. Wir erinnern uns, alles wird C nach Wala und deswegen haben wir quasi eine gemeinsame Sprache, auf die wir uns da berufen können. Ich sage so einen typischen WAPI-File zum Beispiel, auf welche C-Header-File es sich bezieht und ich kann ihm sagen, dass er sich für eine bestimmte Klasse auf ein bestimmtes Struct beziehen soll. Ich kann ihm sagen, wie die Free Functions heißen, weil Speichermenagement wird uns von Wala dann abgenommen. In C müssen wir das manuell machen, deswegen müssen wir an dieser Stelle, wo wir anbinden, quasi dem Speichermenagement sagen, wie es dann wieder ein Struct von unserem Arbeitsspeicher ordentlich entfernt. Dann habe ich hier noch eine Story of a Binding-Fuck ab und das ist so die WTF-Anekdote, die ich hier mitbringen möchte, weil ich kundtun möchte. Ich habe mal hier eine von meinen Libraries testen wollen, was die so kann. Das ist die im Hintergrund, diese Flowgrafen malt und ich wollte damit mal so ein Tool bauen, mit dem man im Imagefilterringen pipelineen kann und das habe ich dann getan und dann dachte ich mir, hey, ist es cool, ich verwende da eine Library, die es schon gibt. Die heißt Gaggle, die wird in Gimp verwendet und die ist echt nice, weil ich kann zur Laufzeit aus dieser Library die Filter und ihre Metadaten und alles, was die so können, rausziehen. Dachte ich so, hey, mache ich mir zu Nutze, ich muss ganz wenig Code schreiben, weil alles liegt schon als Daten da. Ich brauche es nur noch zu konsumieren und zu benutzen. Und da gibt es dann so ein Typ, der heißt Paramspect Double, der beschreibt mir quasi, wie eine Double Property aussieht, was die für Grenzwerte hat, was die für Default Values hat und so was kriege ich von der Library quasi zurück, um eine bestimmte Eigenschaft eines Filters zu beschreiben. Als Beispiel zum Beispiel, die Blur Breite bei einem Gaussian Blur Filter, also einem Weichzeichenfilter, kann ich bestimmen, wie weit soll geschmiert werden. Das wäre zum Beispiel so eine typische Property, die so ein Filter hat, die ich einstellen kann. Und über so ein Objekt wird die mir beschrieben. Jetzt heißt das in der G-Lip, sehen wir hier diese beiden Links, heißt das Ding Paramspect Double. Was tatsächlich im Code stand damals, war aber Folgendes. Ich weiß nicht, ob es ein Artifakt einer automatischen Generierung war oder ob jemand nicht aufgepasst hat, jedenfalls stand hier das Paramspect Double explizit drin und das führte dann zu folgender Compiler-Meldung. Hey, du versuchst dir G-Types Paramspect zu verwenden, dass es an die klärt. Ich weiß nicht, was ich damit anfangen soll, soweit so gut. Die Resolution wäre jetzt im normalen Leben einfach irgendwie Bug Report stellen und dann hoffen, dass es besser wird, aber ich hatte dann mal gerade zum Wochenende frei und ich wollte, dass das unbedingt funktioniert. Und dann habe ich einfach Folgendes gemacht. Wir erinnern uns, alle G-Object-Objekte werden im Endeffekt nicht anders als C-Structs und C-Structs funktionieren nach ziemlich strikten Regeln. Deswegen habe ich verfolgendes gemacht. Die Dokumentation beschreibt die Filter und ihre Properties sehr genau. Dann habe ich mir gedacht, okay, ich nehme mir mal eine so eine Property raus von zwei verschiedenen Filtern und gucke mir mal deren Max-Values an. Dann könnte ich die ja theoretisch nach Hex konvertieren und könnte in meinem Speicher nachschauen, ob es tatsächlich diesen Max-Value, ob ich den irgendwo finde und wenn ja, ob es einen zweiten Filter mit einem Max-Value gibt, der seinen Wert genau in dieselbe Stelle schreibt. Und was ich dann rausziehen kann aus dieser Untersuchung ist die Information, an welchem Offset dann so eine Property in so einem Struct drin liegt. Was ich dann gemacht habe ist, dazu muss ich noch kurz das Namensmapping für Funktionen erklären. Ich glaube, das wird relativ klar. Wir erweitern das Beispiel in einem Punkt, nämlich um eine Funktion, die in unserer Klasse drin ist. Die heißt dann, wenn sie im namespace fu ist, in der Klasse bar und bass heißt, dann wird die NC fu underscore bar underscore bass heißen. Also habe ich mir mal eine fu generiert, die ich da im Code irgendwo aufrufe, sodass ich mit dem GNU Debugger da einen Breakpoint setzen kann. Das ist die zweite Zeile hier. Dann habe ich mein Programm gestartet. Dann sage ich ihm, hey, gehen wir aus dieser fu wieder raus und zeig mir, wie die lokalen Variablen aussehen. Und der letzte Befehl ist, printe mir mal bitte den Speicherinhalt von dieser Variable dann. Daraus habe ich dann tatsächlich, wie in der Schematik, diese Offsets errechnen können. Und ich konnte mir selbst ein Double Specs Struct definieren, das ich hier einmal initialisiere. Und da Gelib Memory Operation unterstützt, konnte ich mir das einfach rausziehen und konnte so quasi den Compiler-Bug umschiffen, weiterprogrammieren und mein Wochenende sinnvoll nutzen. Ich hoffe, ich muss nicht erklären, dass man das in Real-Life überhaupt nicht tun sollte. Denn was passiert denn, wenn die Library of Dear Dependent auf einmal einen ABI-Change hat, das ganze Ding fällt auseinander und wir dürften noch mal von vorne anfangen. Also das war so ein Test, mal gucken, ob es geht und es hat funktioniert. Am Schluss möchte ich noch ansprechen, Compiler auf Windows. Eines der Kriterien war für unsere Sprachensuche damals, dass die Programme, die ich schreibe auf den drei Main Desktop Operating Systems laufen sollte, Windows, Linux und MacOS X. Und ich möchte zumindest den Windows Part mal kurz ansprechen. Phosics ähnliche Umgebung auf Windows ist MSis 2. Da befindet sich quasi so ein Packman drin und ich habe dann auf Windows einmal eine Shell, die sich ungewöhnlich heimisch anfühlt und in der kann ich Pakete installieren, meine ganzen Dependencies ziehen. Da ist so gut wie alles, was man für seine typische GTK anwendet. Es ist alles, was man für seine typische GTK Anwendung braucht dabei. Also man kann er sofort loslegen und wenn man MSis noch nicht gehört hat, also es fühlt sich so ähnlich an wie Zickwind. Wichtig ist auch, es handelt sich um MSis 2. Es gibt ein MSis, aber das ist nicht MSis 2. Und da gibt es auch eine Pitfall, auf die ich gleich mal hinweisen will, die mich auch irgendwie so einen halben Tag lang aus dem Konzept gebracht hat. Es gibt da drei Umgebungen, die sich primär darin unterscheiden, wie GCC konfiguriert ist, gegen welche C-Standard-Libraries ninken soll. Es gibt einmal die Umgebung MSis 2. Die dient dazu quasi Pakete für MSis 2 selbst zu bauen. Die linkt auf irgendeine, das ist so deren eigene Implementierung. Ich weiß nicht genau, was die ist. Allerdings was wir für eine native Windows Anwendung haben wollen, ist die MS VCRT, also die Microsoft Visual C Runtime ist, das glaube ich ausgesprochen. Und die wollen wir für tatsächlich Programme, die wir ohne weiteren Kram an unsere Kunden oder unsere Open Source Konsumenten ausliefern wollen, gegen die wollen wir binden, weil die hat jedes Windows dabei, da brauche ich keine weiteren Dependencies. So, ich wollte noch zwei alternative Compiler ansprechen. Also das geht jetzt alles relativ schnell, weil ich möchte nur kurz angesprochen haben, ihr könnt das sich alles nachschauen, wenn euch das interessiert. Und zwar, erst gestern kam wieder der Mail auf die Valermailing Liste, in der ein Mensch erklärte, er würde in Valar Embedded Entwicklung machen. Und ich habe herausgefühlt, es gibt da irgendwie unter dem Schirm der von Radaril, das ist so ein Reverse-Engineering Tool, ein POSIX Valar. Das ist ein Valar Compiler, der ohne G-Lib auskommt, also mit dem ich tatsächlich hier meine Klassen ohne G-Lib zusammenschrauben kann. Und für einige Anwendungen ist das durchaus sinnvoll. Also gerade, wenn ich Low Over hat, wenn den Overhead kleinsten halten, das Paramount ist. Dann habe ich noch ein Compiler für JavaScript gefunden, der ist ein wenig älter, er funktioniert aktuell auch nicht, aber der hat mal funktioniert und das fand ich eigentlich auch ein cooler Ansatz. So, wir könnten mal nach Java, Script kompilieren, um mit Valar das Web zu erobern. Und dann wollte ich noch ein nettes Projekt ansprechen. Und zwar, tut mir leid, das ist der falsche Link. Ich wollte Valum ansprechen. Valum ist ein Web-Framework für Valar. Das schreibt Artemix gerade auf GitHub. Das war Valar-Framework-Valum ist das Repository. Also, Web wird immer wichtiger. Also, falls jemand mal Webbeckend mit Valar ausprobieren möchte, Valum ist euer Freund. Und dann sind wir auch schon am Ende. Das Torz angelangt. Ich würde jetzt noch kurz Q&A machen, wenn jemand Fragen hat. Ich höre sie mir gerne an und versuche darauf zu antworten. Mein eigener GitHub Account ist Grimthold. Und da kann man sich diese Projekte, die ich gemacht habe, alle anschauen. Und da funktioniert das meiste auch relativ gut, was ich hier vorgestellt habe, um einfach mal nachzulesen, wenn man selber irgendwie was machen möchte oder so, wie ist das schon mal gelöst worden. Auch das GNOME-Projekt hat sehr viele Projekte, die funktionieren mit Valar. Unter anderem zum Beispiel die ganzen GNOME Games. Die sind alle in Valar geschrieben mittlerweile. Die wurden zum Teil reimplementiert. Es ist auch ein sehr schönes Nachschlagewerk für, wie arbeite ich mit Valar. Ja, Happy Hacking. Ich wünsche euch erst mal auch noch ein schönes Easter-Hack. Ich hoffe, dass ihr viel Spaß habt. Und vielen Dank für eure Aufmerksamkeit. Ich hoffe, es hat euch gefallen. Eine Frage. Also, wie es intern funktioniert, weiß ich nicht. Ich weiß, dass du kannst hergehen und hinter jedem Typ in Valar ein Fragezeichen schreiben. Damit teilst du dem Valar-Compiler mit, dass der Wert dieser Variablete, die dort ein bisschen näher ist, Null Level sein kann. Ich kann das aber leider, die internen kann ich nicht sagen. Also, die die initiale Frage ist, wie denn das Null von Integern auf internem Level aussieht. Also, wie das wie die nähere Präsentation davon ist. Und meine Antwort darauf war, ich weiß es nicht. Und zweite Frage. Gibt es auch eine schöne C++ Integration? Als Konsument, um von C++ zu konsumieren oder als... Beides. Also, C++ ist ein bisschen blöd. Wir bei Valar freuen uns immer über CRPs, weil CRPs sind schön bindable, während C++-RPs, sobald sie quasi irgendwie eine Klasse im Header haben, blöd sind. Deswegen, CRPs sind der Weg zu gehen und bei C++ hast du leider Probleme. Gibt es weitere Fragen? Keine Fragen? Dann vielen Dank nochmal. Ich würde auch noch einen Workshop anbieten. Wenn irgendjemand Lust hat, sich Valar mal näher, Hands-on anzuschauen, ich kann euch gleich mal mal eine Decknummer geben. Wenn irgendjemand Lust hat, man kann sich jederzeit zusammentelefonieren oder ich bin irgendwo im Hack Center, man erkennt mich an meiner grünen Mütze, sollte nicht allzu schwer sein. Das wollte ich noch anbieten.