# than the local version of klibc
#USE_KLIBC = true
+# make the build silent (well, at least the udev part) Set this
+# to something else to make it noisy again.
+V=false
+
# set up PWD so that older versions of make will work with our build.
PWD = $(shell pwd)
AR = $(CROSS)ar
STRIP = $(CROSS)strip
RANLIB = $(CROSS)ranlib
+HOSTCC = gcc
export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS ARCH_LIB_OBJS CRT0
TDB = tdb/tdb.o \
tdb/spinlock.o
-SYSFS = $(PWD)/libsysfs/sysfs_bus.o \
- $(PWD)/libsysfs/sysfs_class.o \
- $(PWD)/libsysfs/sysfs_device.o \
- $(PWD)/libsysfs/sysfs_dir.o \
- $(PWD)/libsysfs/sysfs_driver.o \
- $(PWD)/libsysfs/sysfs_utils.o \
- $(PWD)/libsysfs/dlist.o
+SYSFS = libsysfs/sysfs_bus.o \
+ libsysfs/sysfs_class.o \
+ libsysfs/sysfs_device.o \
+ libsysfs/sysfs_dir.o \
+ libsysfs/sysfs_driver.o \
+ libsysfs/sysfs_utils.o \
+ libsysfs/dlist.o
OBJS = udev_lib.o \
udev_config.o \
KLIBC_FIXUP = klibc_fixups.o
endif
+ifeq ($(strip $(V)),false)
+ QUIET=@./ccdv
+ HOST_PROGS=ccdv
+else
+ QUIET=
+ HOST_PROGS=
+endif
+
# header files automatically generated
GEN_HEADERS = udev_version.h
+ccdv:
+ @echo "Building ccdv"
+ @$(HOSTCC) -O1 ccdv.c -o ccdv
+
# Rules on how to create the generated header files
udev_version.h:
@echo \#define UDEV_VERSION \"$(VERSION)\" > $@
# Rules on how to create the generated config files
$(LOCAL_CFG_DIR)/udev.conf:
- sed -e "s:@udevdir@:$(udevdir):" -e "s:@configdir@:$(configdir):" < $(LOCAL_CFG_DIR)/udev.conf.in > $@
+ @./ccdv sed -e "s:@udevdir@:$(udevdir):" -e "s:@configdir@:$(configdir):" < $(LOCAL_CFG_DIR)/udev.conf.in > $@
GEN_MANPAGES = udev.8
GEN_MANPAGESIN = udev.8.in
# Rules on how to create the man pages
$(GEN_MANPAGES): $(GEN_MANPAGESIN)
- sed -e "s:@udevdir@:$(udevdir):" < $@.in > $@
+ @./ccdv sed -e "s:@udevdir@:$(udevdir):" < $@.in > $@
$(OBJS): $(GEN_HEADERS)
-$(ROOT).o: $(GEN_HEADERS)
+$(ROOT).o: $(GEN_HEADERS) $(HOST_PROGS)
$(TESTER).o: $(GEN_HEADERS)
$(INFO).o: $(GEN_HEADERS)
$(DAEMON).o: $(GEN_HEADERS)
$(WAIT).o: $(GEN_HEADERS)
$(ROOT): $(LIBC) $(ROOT).o $(STARTER).o $(OBJS) $(HEADERS) $(GEN_MANPAGES)
- $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o udevstart.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o udevstart.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
$(TESTER): $(LIBC) $(TESTER).o $(OBJS) $(HEADERS)
- $(LD) $(LDFLAGS) -o $@ $(CRT0) udevtest.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevtest.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
$(INFO): $(LIBC) $(INFO).o $(OBJS) $(HEADERS)
- $(LD) $(LDFLAGS) -o $@ $(CRT0) udevinfo.o udev_lib.o udev_config.o udevdb.o $(SYSFS) $(TDB) $(LIB_OBJS) $(ARCH_LIB_OBJS)
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevinfo.o udev_lib.o udev_config.o udevdb.o $(SYSFS) $(TDB) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
$(DAEMON): $(LIBC) $(DAEMON).o $(OBJS) udevd.h
- $(LD) $(LDFLAGS) -o $@ $(CRT0) udevd.o udev_lib.o $(KLIBC_FIXUP) $(LIB_OBJS) $(ARCH_LIB_OBJS)
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevd.o udev_lib.o $(KLIBC_FIXUP) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
$(SENDER): $(LIBC) $(SENDER).o $(OBJS) udevd.h
- $(LD) $(LDFLAGS) -o $@ $(CRT0) udevsend.o udev_lib.o $(LIB_OBJS) $(ARCH_LIB_OBJS)
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevsend.o udev_lib.o $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
$(RULER): $(LIBC) $(RULER).o $(OBJS) $(HEADERS)
- $(LD) $(LDFLAGS) -o $@ $(CRT0) udevruler.o udev_lib.o udev_config.o udevdb.o $(SYSFS) $(TDB) $(LIB_OBJS) $(ARCH_LIB_OBJS) -lnewt
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevruler.o udev_lib.o udev_config.o udevdb.o $(SYSFS) $(TDB) $(LIB_OBJS) $(ARCH_LIB_OBJS) -lnewt
+ $(QUIET) $(STRIPCMD) $@
$(WAIT): $(WAIT).o $(OBJS) $(HEADERS) $(LIBC)
- $(LD) $(LDFLAGS) -o $@ $(CRT0) $(WAIT).o $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
- $(STRIPCMD) $@
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) $(WAIT).o $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
+
+#.c.o:
+# $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) -c -o $@ $<
+.c.o:
+ $(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
+
clean:
-find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
| xargs rm -f
-rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(GEN_MANPAGES) $(INFO) $(DAEMON) $(SENDER) $(TESTER) $(RULER) $(WAIT)
+ - rm -f ccdv
$(MAKE) -C klibc clean
@extras="$(EXTRAS)" ; for target in $$extras ; do \
echo $$target ; \
--- /dev/null
+/* ccdv.c
+ *
+ * Copyright (C) 2002-2003, by Mike Gleason, NcFTP Software.
+ * All Rights Reserved.
+ *
+ * Licensed under the GNU Public License.
+ */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "")
+#define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "")
+#define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "")
+#define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "")
+
+#define TEXT_BLOCK_SIZE 8192
+#define INDENT 2
+
+#define TERMS "vt100:vt102:vt220:vt320:xterm:xterm-color:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin"
+
+size_t gNBufUsed = 0, gNBufAllocated = 0;
+char *gBuf = NULL;
+int gCCPID;
+char gAction[64] = "";
+char gTarget[64] = "";
+char gAr[32] = "";
+char gArLibraryTarget[64] = "";
+int gDumpCmdArgs = 0;
+char gArgsStr[800];
+int gColumns = 80;
+int gANSIEscapes = 0;
+int gExitStatus = 95;
+
+static void DumpFormattedOutput(void)
+{
+ char *cp;
+ char spaces[8 + 1] = " ";
+ char *saved;
+ int curcol;
+ int i;
+
+ curcol = 0;
+ saved = NULL;
+ for (cp = gBuf + ((gDumpCmdArgs == 0) ? strlen(gArgsStr) : 0); ; cp++) {
+ if (*cp == '\0') {
+ if (saved != NULL) {
+ cp = saved;
+ saved = NULL;
+ } else break;
+ }
+ if (*cp == '\r')
+ continue;
+ if (*cp == '\t') {
+ saved = cp + 1;
+ cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8));
+ }
+ if (curcol == 0) {
+ for (i = INDENT; --i >= 0; )
+ putchar(' ');
+ curcol = INDENT;
+ }
+ putchar(*cp);
+ if (++curcol == (gColumns - 1)) {
+ putchar('\n');
+ curcol = 0;
+ } else if (*cp == '\n')
+ curcol = 0;
+ }
+ free(gBuf);
+} /* DumpFormattedOutput */
+
+
+
+/* Difftime(), only for timeval structures. */
+static void TimeValSubtract(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
+{
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+ tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+ if (tdiff->tv_usec < 0) {
+ tdiff->tv_sec--;
+ tdiff->tv_usec += 1000000;
+ }
+} /* TimeValSubtract */
+
+
+
+static void Wait(void)
+{
+ int pid2, status;
+
+ do {
+ status = 0;
+ pid2 = (int) waitpid(gCCPID, &status, 0);
+ } while (((pid2 >= 0) && (! WIFEXITED(status))) || ((pid2 < 0) && (errno == EINTR)));
+ if (WIFEXITED(status))
+ gExitStatus = WEXITSTATUS(status);
+} /* Wait */
+
+
+
+static int SlurpProgress(int fd)
+{
+ char s1[71];
+ char *newbuf;
+ int nready;
+ size_t ntoread;
+ ssize_t nread;
+ struct timeval now, tnext, tleft;
+ fd_set ss;
+ fd_set ss2;
+ const char *trail = "/-\\|", *trailcp;
+
+ trailcp = trail;
+ snprintf(s1, sizeof(s1), "%s%s%s... ", gAction, gTarget[0] ? " " : "", gTarget);
+ printf("\r%-70s%-9s", s1, "");
+ fflush(stdout);
+
+ gettimeofday(&now, NULL);
+ tnext = now;
+ tnext.tv_sec++;
+ tleft.tv_sec = 1;
+ tleft.tv_usec = 0;
+ FD_ZERO(&ss2);
+ FD_SET(fd, &ss2);
+ for(;;) {
+ if (gNBufUsed == (gNBufAllocated - 1)) {
+ if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) {
+ perror("ccdv: realloc");
+ return (-1);
+ }
+ gNBufAllocated += TEXT_BLOCK_SIZE;
+ gBuf = newbuf;
+ }
+ for (;;) {
+ ss = ss2;
+ nready = select(fd + 1, &ss, NULL, NULL, &tleft);
+ if (nready == 1)
+ break;
+ if (nready < 0) {
+ if (errno != EINTR) {
+ perror("ccdv: select");
+ return (-1);
+ }
+ continue;
+ }
+ gettimeofday(&now, NULL);
+ if ((now.tv_sec > tnext.tv_sec) || ((now.tv_sec == tnext.tv_sec) && (now.tv_usec >= tnext.tv_usec))) {
+ tnext = now;
+ tnext.tv_sec++;
+ tleft.tv_sec = 1;
+ tleft.tv_usec = 0;
+ printf("\r%-71s%c%-7s", s1, *trailcp, "");
+ fflush(stdout);
+ if (*++trailcp == '\0')
+ trailcp = trail;
+ } else {
+ TimeValSubtract(&tleft, &tnext, &now);
+ }
+ }
+ ntoread = (gNBufAllocated - gNBufUsed - 1);
+ nread = read(fd, gBuf + gNBufUsed, ntoread);
+ if (nread < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("ccdv: read");
+ return (-1);
+ } else if (nread == 0) {
+ break;
+ }
+ gNBufUsed += nread;
+ gBuf[gNBufUsed] = '\0';
+ }
+ snprintf(s1, sizeof(s1), "%s%s%s: ", gAction, gTarget[0] ? " " : "", gTarget);
+ Wait();
+ if (gExitStatus == 0) {
+ printf("\r%-70s", s1);
+ printf("[%s%s%s]", ((gNBufUsed - strlen(gArgsStr)) < 4) ? SETCOLOR_SUCCESS : SETCOLOR_WARNING, "OK", SETCOLOR_NORMAL);
+ printf("%-5s\n", " ");
+ } else {
+ printf("\r%-70s", s1);
+ printf("[%s%s%s]", SETCOLOR_FAILURE, "ERROR", SETCOLOR_NORMAL);
+ printf("%-2s\n", " ");
+ gDumpCmdArgs = 1; /* print cmd when there are errors */
+ }
+ fflush(stdout);
+ return (0);
+} /* SlurpProgress */
+
+
+
+static int SlurpAll(int fd)
+{
+ char *newbuf;
+ size_t ntoread;
+ ssize_t nread;
+
+ printf("%s%s%s.\n", gAction, gTarget[0] ? " " : "", gTarget);
+ fflush(stdout);
+
+ for(;;) {
+ if (gNBufUsed == (gNBufAllocated - 1)) {
+ if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) {
+ perror("ccdv: realloc");
+ return (-1);
+ }
+ gNBufAllocated += TEXT_BLOCK_SIZE;
+ gBuf = newbuf;
+ }
+ ntoread = (gNBufAllocated - gNBufUsed - 1);
+ nread = read(fd, gBuf + gNBufUsed, ntoread);
+ if (nread < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("ccdv: read");
+ return (-1);
+ } else if (nread == 0) {
+ break;
+ }
+ gNBufUsed += nread;
+ gBuf[gNBufUsed] = '\0';
+ }
+ Wait();
+ gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */
+ return (0);
+} /* SlurpAll */
+
+
+
+static const char *Basename(const char *path)
+{
+ const char *cp;
+ cp = strrchr(path, '/');
+ if (cp == NULL)
+ return (path);
+ return (cp + 1);
+} /* Basename */
+
+
+
+static const char * Extension(const char *path)
+{
+ const char *cp = path;
+ cp = strrchr(path, '.');
+ if (cp == NULL)
+ return ("");
+ return (cp);
+} /* Extension */
+
+
+
+static void Usage(void)
+{
+ fprintf(stderr, "Usage: ccdv /path/to/cc CFLAGS...\n\n");
+ fprintf(stderr, "I wrote this to reduce the deluge Make output to make finding actual problems\n");
+ fprintf(stderr, "easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\n");
+ fprintf(stderr, "\t.c.o:\n");
+ fprintf(stderr, "\t\t$(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n");
+ fprintf(stderr, "\nRewrite your rule so it looks like:\n\n");
+ fprintf(stderr, "\t.c.o:\n");
+ fprintf(stderr, "\t\t@ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\n");
+ fprintf(stderr, "ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n");
+ fprintf(stderr, " -- Mike Gleason, NcFTP Software <http://www.ncftp.com>\n");
+ exit(96);
+} /* Usage */
+
+
+
+int main(int argc, char **argv)
+{
+ int pipe1[2];
+ int devnull;
+ char emerg[256];
+ int fd;
+ int nread;
+ int i;
+ int cc = 0, pch = 0;
+ const char *quote;
+
+ if (argc < 2)
+ Usage();
+
+ snprintf(gAction, sizeof(gAction), "Running %s", Basename(argv[1]));
+ memset(gArgsStr, 0, sizeof(gArgsStr));
+ for (i = 1; i < argc; i++) {
+ quote = (strchr(argv[i], ' ') != NULL) ? "\"" : "";
+ snprintf(gArgsStr + strlen(gArgsStr), sizeof(gArgsStr) - strlen(gArgsStr), "%s%s%s%s%s", (i == 1) ? "" : " ", quote, argv[i], quote, (i == (argc - 1)) ? "\n" : "");
+ if ((strcmp(argv[i], "-o") == 0) && ((i + 1) < argc)) {
+ if (strcasecmp(Extension(argv[i + 1]), ".o") != 0) {
+ strcpy(gAction, "Linking");
+ snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i + 1]));
+ }
+ } else if (strchr("-+/", (int) argv[i][0]) != NULL) {
+ continue;
+ } else if (strncasecmp(Extension(argv[i]), ".c", 2) == 0) {
+ cc++;
+ snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i]));
+ } else if ((strncasecmp(Extension(argv[i]), ".h", 2) == 0) && (cc == 0)) {
+ pch++;
+ snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i]));
+ } else if ((i == 1) && (strcmp(Basename(argv[i]), "ar") == 0)) {
+ snprintf(gAr, sizeof(gAr), "%s", Basename(argv[i]));
+ } else if ((gArLibraryTarget[0] == '\0') && (strcasecmp(Extension(argv[i]), ".a") == 0)) {
+ snprintf(gArLibraryTarget, sizeof(gArLibraryTarget), "%s", Basename(argv[i]));
+ }
+ }
+ if ((gAr[0] != '\0') && (gArLibraryTarget[0] != '\0')) {
+ strcpy(gAction, "Creating library");
+ snprintf(gTarget, sizeof(gTarget), "%s", gArLibraryTarget);
+ } else if (pch > 0) {
+ strcpy(gAction, "Precompiling");
+ } else if (cc > 0) {
+ strcpy(gAction, "Compiling");
+ }
+
+ if (pipe(pipe1) < 0) {
+ perror("ccdv: pipe");
+ exit(97);
+ }
+
+ (void) close(0);
+ devnull = open("/dev/null", O_RDWR, 00666);
+ if ((devnull != 0) && (dup2(devnull, 0) == 0))
+ close(devnull);
+
+ gCCPID = (int) fork();
+ if (gCCPID < 0) {
+ (void) close(pipe1[0]);
+ (void) close(pipe1[1]);
+ perror("ccdv: fork");
+ exit(98);
+ } else if (gCCPID == 0) {
+ /* Child */
+ (void) close(pipe1[0]); /* close read end */
+ if (pipe1[1] != 1) { /* use write end on stdout */
+ (void) dup2(pipe1[1], 1);
+ (void) close(pipe1[1]);
+ }
+ (void) dup2(1, 2); /* use write end on stderr */
+ execvp(argv[1], argv + 1);
+ perror(argv[1]);
+ exit(99);
+ }
+
+ /* parent */
+ (void) close(pipe1[1]); /* close write end */
+ fd = pipe1[0]; /* use read end */
+
+ gColumns = (getenv("COLUMNS") != NULL) ? atoi(getenv("COLUMNS")) : 80;
+ gANSIEscapes = (getenv("TERM") != NULL) && (strstr(TERMS, getenv("TERM")) != NULL);
+ gBuf = (char *) malloc(TEXT_BLOCK_SIZE);
+ if (gBuf == NULL)
+ goto panic;
+ gNBufUsed = 0;
+ gNBufAllocated = TEXT_BLOCK_SIZE;
+ if (strlen(gArgsStr) < (gNBufAllocated - 1)) {
+ strcpy(gBuf, gArgsStr);
+ gNBufUsed = strlen(gArgsStr);
+ }
+
+ if (isatty(1)) {
+ if (SlurpProgress(fd) < 0)
+ goto panic;
+ } else {
+ if (SlurpAll(fd) < 0)
+ goto panic;
+ }
+ DumpFormattedOutput();
+ exit(gExitStatus);
+
+panic:
+ gDumpCmdArgs = 1; /* print cmd when there are errors */
+ DumpFormattedOutput();
+ while ((nread = read(fd, emerg, (size_t) sizeof(emerg))) > 0)
+ (void) write(2, emerg, (size_t) nread);
+ Wait();
+ exit(gExitStatus);
+} /* main */