(Nach dem Schreiben dieser Mail fiel mir auf, dass wir vom Linuxthema ganz schön weg sind. Aber vermutlich habt ihr die Mail mit dem Subject dann eh schon gelöscht :-)). * lothar.behrens@lollisoft.de wrote on Wed, Dec 21, 2005 at 00:01 +0100:
Ich dachte, dass eine source.tgz Distribution nicht alles ist, was ein Entwickler bereitstellt.
Na ja, man kann ein SPEC mit in source.tgz packen, gar nichts zu RPM tun und/oder SRPM/RPM anbieten :-)
Also was ich möchte ist folgendes:
Ein Binary RPM, das meine Programme und nötigen Shared Libraries installiert. Dabei die Abhängigkeiten aufgelöst werden und ODBC Datenquellen für eine Demo Datenbank (PostgreSQL/MySQL) eingerichtet wird. Inclusive Treiber.
Ein RPM, das meine Quellen irgendwo installiert, damit der Benutzer später alles übersetzen kann. (S-RPM/B-RPM/ oder was auch immer - ist mir egal) Dabei die Abhängigkeiten aufgelöst werden und ODBC Datenquellen für eine Demo Datenbank (PostgreSQL/MySQL) eingerichtet wird. Inclusive Treiber.
Gut. Also sicherheitshalber nochmal: Für beide RPMs brauchst du ein (1) SPEC file. Wenn Du das in /usr/src/packages/SPECS hast (und der Rest stimmt), baut Dir rpmbuild -ba /beide/ RPMs mit den in den vorherigen Mails beschriebenen Eigenschaften. Wenn Du eine source.tgz Distribution hast, ist ein SRPM sozusagen "redundant" zu source.tgz-mit-SPEC-file-drin, macht also nur begrenzt Sinn, beides zu haben (IMHO ist ein source.tgz-mit-SPEC-file-drin auch bequemer: muss ich nicht installieren und dann das SPEC file suchen und dann an rpmbuild übergeben, sondern kann ich gleich rpmbuild -tb s.tgz machen). "fremde" Shared libraries zu installieren ist IMHO falsch, dann lieber eigene RPMs. Ist sonst nachher wie bei Windows, wo jedes WORD erstmal ne mfc.dll mitbringen muss... ODBC Datenquellen und Demo Datenbank einrichten finde ich gemein. Das klingt nach "root-Recht Missbrauch", "Easteregg" oder so. Gut, falls es denn gar keine /etc/odbc.ini oder so gibt, eine anlegen darf sich IMHO ein unixODBC.rpm erlauben - aber bitte keine Applikation. Und Demo-Datenbank einrichten? Sicherheitshalber noch einen Admin Users ins Postgres, damit das Erzeugen auch bestimmt klappt, ohne Passwort natürlich, damit das Script automatisch läuft? Da würde ich mich erst extrem wundern, welcher Hacker in meiner Datenbank gespielt hat und mich dann mächtig ärgern, wenn ich es herausfünde! Übrigens kenn ich ein produktives System, welches als DSN "demo" benutzt. Also keine Annahmen machen :-) Dann lieber ein script nach $d/doc oder $d/sbin oder so und im Programm fehlende Tabellen sauber abfangen: Die Tabelle myPkgVersion konnte nicht gefunden werden. Vermutlich ist die angeschlossene Datenquelle myDSN ($techinfo) für die Verwendung von myPkg nicht vorgesehen oder geeignet. Der Dokumentation liegt ein Datenbankerzeugunsscript und detailte Erklärungen bei. oder sowas. Wie "inklusive Treiber"? Das RPM kann ja gar nicht wissen, welche Datenbank ich verwenden möchte. Vielleicht ist MicroSoft SQL 7 (gut, nicht wirklich ne Datenbank, aber gibt Leute, die nehmen sowas) und dafür gibt es überhaupt keinen (direkten) Treiber. Vielleicht ist lokal oder remote ein PostgreSQL verfügbar, was ich aber nicht nehmen möchte/kann/darf. Vielleicht installiere ich das Packet auch nur mal auf meiner Workstation, weil ich eine lokale Installation der Dokumentation möchte (gut, wir haben daher package-doc.rpms eingeführt, aber Du weisst ja, wass ich meine). Beim Source-RPM ist das IMHO noch viel falscher. Vielleicht wollte ich mir ja bloss mal Deinen tollen Suchalgorithmus angucken oder so, und hab gar keine Datenbank. Leg doch ein Script ab, was alles macht, wenn man möchte, gebe beim installieren einen deutlichen Hinweis darauf ab und lass den Admin entscheiden :)
Naja, eben einen besseren Anreiz, mein Projekt mal zu installieren und zu testen. (Zwecks Feedback, bisher habe ich nur Downloads und das reicht mir nicht)
Hab mir mal kurz die Webseiten angeschaut. Ein Framework, also eine lib, ja? Dann hängt doch die Datenstruktur davon ab, was ich machen möchte? Ich denke, Du hast eine Demoapplikation mit im RPM, die das alles braucht, ja? Da Du Dich an Entwickler wendest (?), liege ich wohl in der Zielgruppe. Ich würde mir lieber viele kleine Scripte und so wünschen, damit ich in aller Ruhe - und Schritt für Schritt - alles ausprobieren kann. Erstmal lege ich mir (per Script) ein paar Tabellen in meiner Testdatenbank an. Da kann ich auch gleich mal Daten aus Testtabellen 'rüberselekten. Dann spiele ich vielleicht mit der DemoApp rum. Hier hab ich vermutlich ein Problem: wenn ich das binary RPM installiere, hab ich die libs. Vermutlich sind auch die header drin (oder Du hast ein -devel, auch egal). Aber wo sind die Demo-Sourcen? Würde ich auch mit reinpacken (ins binary RPM), sollte man natürlich bauen können. Vielleicht ein Unter_source.tgz, welches im source.tgz mit drin ist, bei %install kopiert wird und damit im binär RPM mit drin ist (in doc oder so). Prolog installiert z.B. /usr/lib/pl-5.0.10/dotfiles seh ich hier gerade an einer Shell. Komische Pfade, aber geht auch :) Damit sind lib und DemoApp logisch getrennt, sowas finde ich immer prima und wichtig. Und ich kann mir aussuchen, wo ich die DemoApp bauen möchte. Das schwankt bei mir je Server. Hab sogar Maschinen, da bau ich in /local/tmp (weil da halt Platz ist). So hätte ich alles schön flexibel und würde denke: Mensch, so ein flexibles, sauberes installieren, so schöne Doku, da ist das Framework bestimmt auch prima :) BTW noch ein paar Kommentare, weil Du ja feedback wolltest :) http://www.lollisoft.de/projects/dmf/firstsample.html #includes fehlen im Beispiel lbErrCodes err = ERR_NONE; Empfehle immer modul-Prefixe oder wenigestens namespaces. ERR_NONE kann auch gut von anderer Package definiert werden. Beruflich hab ich mit verschiedenen Libs zu tun, und öfter mal clashes in der Art. lbErrCode ist prima, wenn "lb" die Package ist. lb_I_Module* mm = NULL; mm = getModuleInstance(); sollte in C++ lb_I_Module *mm(getModuleInstance()); oder noch besser lb_I_Module *mm(Module::getInstance()); heissen (IMHO). Ich erwarte ein Singelton. mm->setModuleManager(mm, __FILE__, __LINE__); sowas machen wir in C oft über Macros in der Art #define setModuleManager(mm) setModuleManager_(mm, __FILE__, __LINE__) Die Implementierung hat setModuleManager_(void*, const char *const fileName, int lineNo); oder so, der Aufrufer schreibt aber nur setModuleManager(mm); find ich recht komfortabel. _CL_LOG << "Hello world" LOG_ UAP_REQUEST(mm, lb_I_String, string) mmmm... Sicherlich Geschmacksache, aber UAP_REQUEST würde ich klein schreiben (ob's ein #define ist ist IMHO Implementierungsdetail und kann sich ändern). "_" vorn mmm... Am meisten stören mich die fehlenden ";". Hatte die nach dem Kopieren oben auch schon "automatisch" gesetzt. Ich bin halt gewohnt, ";" zu schreiben, würde das lieber nicht im Macro haben wollen. string->setData("Console logging..."); _CL_LOG << string->charrep() LOG_ versteh ich nicht. string ist nicht deklariert. Was ist das? Muss es ausgerechnet string heissen? Da denke ich immer an std::string. Wenn std::string gemeint ist, sollte man das IMHO auch schreiben. Obwohl "use namespace std;" in .cc Files natürlich erlaubt ist (und in .h Files absolut verboten!), klar, aber steht da ja nicht. Das Beispiel sollte kompilieren, falls man C&P verwendet, denke ich. "In fact, it is cout." (BTW; da war ein k) Ist _CL_LOG wirklich std::cout? Dann geht also sowas wie _CL_LOG << std::hex << static_cast<int>(myVar) << LOG_ ja? LOG_ ist IMHO prädestiniert für Clashes, viel zu allgemein --> gefährlich. "To get any instance for an interface, you need to request for that interface. UAP_REQUEST is a macro and hides some code. " Mal ganz ehrlich: Ich würde keine lib nehmen, die vor mir (dem Entwickler) "some code" verstecken würde! Was passiert da? Deklarationen? Wer gibt den Speicher frei? Sind es Referenzen, kann ich die Dinger tief und/oder flach kopieren? Kann ich UAP_REQUEST(mm, lb_I_String, string) UAP_REQUEST(mm, lb_I_String, string) schreiben oder ist dann ein Bezeichner/irgendwas doppelt? Was bedeutet das überhaupt? Geht ein UAP_REQUEST(mm, lb_I_String, string) { UAP_REQUEST(mm, lb_I_String, string) } oder nicht? usw. Auch bei virtual char *LB_STDCALL getDBName ()=0 Ich kriege einen non-const-Pointer? also kann ich dbName über get ändern? Muss ich free, delete oder delete[] oder gar nichts mit dem Rückgabewert machen? virtual const string& getDBName(void) const = 0; wäre IMHO eindeutiger: ich kann halt den String nur maximal kopieren aber "nichts kaputt machen" und muss auch nicht mit Zeigern handtieren. Allerdings hab ich noch nicht verstanden, was die lib mir genau bietet. Ist es eine ODBC-Zugriffs lib wie die (IMHO recht gute) http://libodbcxx.sourceforge.net/ ? Die hat auch ein recht nettes Memorymanagement, find ich. Ich hoffe, ich konnte ein bisschen helfen. oki, Steffen -- Dieses Schreiben wurde maschinell erstellt, es trägt daher weder Unterschrift noch Siegel.