Wie oft stellen sich User wie ich die Frage, wie weit der Compile ist bzw wieviel noch fehlt…
Im Gentoo‐Wiki habe ich folgenden C++ Lösungsansatz gefunden, welchen ich als eprogress.cpp ablege und schliesslich mit g++ compile (g++ eprogress.cpp ‑o eprogress):
#include <dirent .h>
#include „fcntl.h“
#include <string>
#include <fstream>
using namespace std;
#define srccount 5
#define objcount 2
int countfiles(char *path, int& todo, int& done);
int dft(char *name);
int findproc(char *name);
int main() {
char *path, *action;
char line[256];
char *est;
est = „“;
int done = 0, todo = 0, percent = 0;
path = „/usr/tmp/portage/“;
struct dirent *entry; //This structure will hold file information
struct stat file_status; //This structure will be used to query file status
DIR *dir = opendir(path); //This pointer references the directory stream
// printf(„Emerge Progress v4.20 C++:\n“);
//Make sure we have a directory stream pointer
if (!dir) { perror(„opendir failure“); exit(1); }
chdir(path);
while ( (entry = readdir(dir)) != NULL) {
//Don’t bother with the .. and . directories
if ((strcmp(entry->d_name, „.“) != 0) && (strcmp(entry->d_name, „..“) != 0)) {
//Get the status info for the current file
if (stat(entry->d_name, &file_status) == 0) {
//Is this a directory, or a file?
if (S_ISDIR(file_status.st_mode)) {
strcpy(line,entry->d_name);
strcat(line,“/work“);
todo = 0; done = 0;
if (countfiles(line,todo,done) == 1) { if (todo == 0) { percent=0; } else { percent=100 * done / todo; }
if (done > todo) {
todo = done++;
est = „~“;
percent=100 * done / todo;}
//Is it running?
if (findproc(entry->d_name) == 1) { action=„C“; } else { action=„X“; }
printf(„ * [%s] %s: %d/%d — %s%d%\n“,action,entry->d_name,done,todo,est,percent);
}
chdir(path);
}
}
}
}
//Make sure we close the directory stream
if (closedir(dir) == ‑1) { perror(„closedir failure“); exit(1); }
}
int countfiles(char *path, int& T, int& D) {
int c = 0,res = 0;
struct dirent *entry;
struct stat file_status;
DIR *dir = opendir(path);
if (!dir) { return 0; }
//Change directory to the given path
chdir(path);
//Loop through all files and directories
while ( (entry = readdir(dir)) != NULL) {
//Don’t bother with the .. and . directories
if ((strcmp(entry->d_name, „.“) != 0) && (strcmp(entry->d_name, „..“) != 0)) {
//Get the status info for the current file
if (stat(entry->d_name, &file_status) == 0) {
//Is this a directory, or a file?
if (S_ISDIR(file_status.st_mode)) {
//Call countfiles again (recursion) and add the result to the count total
countfiles(entry->d_name,T,D);
chdir(„..“);
} else {
//We’ve found a file, increment the count
res=dft(entry->d_name);
if (res==1) { T=T+1; } else if (res==2) { D=D+1; }
}
}
}
}
//Make sure we close the directory stream
if (closedir(dir) == ‑1) { perror(„closedir failure“); exit(1); }
//Return the file count
return 1;
}
int dft(char *name)
{
//Find out file type..
//0= none
//1= todo
//2= done
int c;
char * tmp;
char *src[] = {„.c/“,“.cpp/“,“.C/“,“.java/“,“.cc/“};
char *obj[] = {„.o/“,“.class/“};
strcpy(tmp,name);
strcat(tmp,“/“);
for(c=0; c<srccount ;++c){ if (strstr(tmp,src[c]) !=NULL) { return 1; } }
for(c=0; c<objcount;++c){ if (strstr(tmp,obj[c]) !=NULL) { return 2; } }
//Neither
return 0;
}
int findproc(char *name)
{
//Find the proc of portage
int c = 0;
char *res;
char *path, *tmp;
char buffer[256];
path = „/proc/“;
struct dirent *entry;
struct stat file_status;
DIR *dir = opendir(path);
if (!dir) { return 0; }
//Change directory to the given path
chdir(path);
//Loop through all files and directories
while ( (entry = readdir(dir)) != NULL) {
//Don’t bother with the .. and . directories
if ((strcmp(entry->d_name, „.“) != 0) && (strcmp(entry->d_name, „..“) != 0)) {
//Get the status info for the current file
if (stat(entry->d_name, &file_status) == 0) {
//Is this a directory, or a file?
if (S_ISDIR(file_status.st_mode)) {
chdir(entry->d_name);
ifstream rfile („cmdline“);
if (rfile.is_open()) {
rfile.getline (buffer,100);
if (strstr(buffer,name) != NULL) { return 1; }
}
rfile.close();
chdir(„..“);
}
}
}
}
//Make sure we close the directory stream
if (closedir(dir) == ‑1) { perror(„closedir failure“); exit(1); }
//Return the file count
return 0;
}
Dieses Programm zählt die vorhandenen Source‐Dateien und vergleicht sie mit der Anzahl der schon compilierten .o‑Files — dies ermöglicht uns eine Schätzung, wie weit das aktuelle Programm compiled ist;
So weit so gut — das Programm mit watch aufgerufen aktualisiert den Output periodisch bis es schliesslich mit STRG + C abgebrochen wird.
Komfort und Tuning: Für Leute wie mich, die inzwischen auch schon Xorg erobert haben und sich bis zu einem Desktop vorgewagt haben, bietet sich die Verwendung von xosd an:
eprogress | osd_cat –font=“-adobe-helvetica-bold-*-*-*-24-*-*-*-*-*-*-*“ ‑c „#33CC33“ ‑A right ‑o 60 ‑i 50 ‑d 3
… was uns einen kleinen Schriftzug mit dem aktuellen Emerge (falls laufend) in die rechte obere Ecke des Bildschirms zaubert, welcher nach 3 Sekunden wieder verschwindet. Ein kleines Bash‐Script mit einer Schleife lässt den Schriftzug immer wieder aufflackern, was ich persönlich als störend empfinde. Mein Workaround sieht wie folgt aus:
#!/bin/bash
while true; do
eprogress | osd_cat –font=“-adobe-helvetica-bold-*-*-*-24-*-*-*-*-*-*-*“ ‑c „#33CC33“ ‑A right ‑o 60 ‑i 50 ‑d 3 &
sleep 2.7s
done
Xosd_cat wird in den Hintergrund versetzt und alle 2,7 Sekunden aufgerufen. Da eprogress eine gewisse Zeit benötigt bis es seinen Job erledigt hat und die Ausgabe weitergegeben wird liegen die beiden Schriftzüge für einen Sekundenbruchteil übereinander und es entsteht der Effekt von verschwimmenden Zahlen. Da der Rest der Ausgabe statisch ist, merkt man dort keinen Unterschied.
Probleme:
Ich bin natürlich nicht böse wenn jemand die komplette Prozedur in C implementiert und als Hintergrunddienst zur Verfügung stellt…