diff --git a/Makefile.linux b/Makefile.linux index 9571c8a262..70d26f329a 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -1,28 +1,26 @@ # created on 4/12/2006 by James Bentler -# RH says: Might I suggest using -MMD instead of -MM? You can create the -# .o files and the .d files in the same step and avoid rerunning make. -# I'd do it myself, but I don't want to break anything without testing -# it first. - CXX ?= g++ CC ?= gcc NASM ?= nasm +CCDV = @./ccdv ifdef DEBUG - CFLAGS ?= -pipe -Wall -Wno-unused + CFLAGS ?= -pipe -Wall -Wno-unused -fno-strict-aliasing else - CFLAGS ?= -pipe -Wall -Wno-unused -O2 -fomit-frame-pointer -fno-rtti + CFLAGS ?= -pipe -Wall -Wno-unused -fno-strict-aliasing -O2 -fomit-frame-pointer + CXXFLAGS ?= -fno-rtti endif ifdef GC CFLAGS += -ffunction-sections LDFLAGS += -Wl,--gc-sections endif -CFLAGS += -DHAVE_FILELENGTH -D__forceinline=inline -Izlib -IFLAC `sdl-config --cflags` +CFLAGS += -MMD -DHAVE_FILELENGTH -D__forceinline=inline -Izlib -IFLAC `sdl-config --cflags` CFLAGS += -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -DNEED_STRUPR LDFLAGS += -lFLAC++ -lFLAC -lz -lfmod `sdl-config --libs` NASMFLAGS += -f elf -DM_TARGET_LINUX SRCDIRS = src/ $(addprefix src/,g_doom/ g_heretic/ g_hexen/ g_raven/ g_shared/ g_strife/ oplsynth/ sound/ sdl/) +VPATH = $(SRCDIRS) INCLUDES = $(addprefix -I,$(SRCDIRS)) CFLAGS += $(INCLUDES) @@ -62,70 +60,30 @@ COBJS = $(addprefix $(OBJDIR)/,$(CPPOBJFILES) $(COBJFILES)) DEPS = $(patsubst %.o,%.d,$(COBJS)) OBJS = $(addprefix $(OBJDIR)/,$(AOBJFILES)) $(COBJS) -# controls whether to start another instance of make at deps -RESTART?=1 - -# rule pattern for dependencies -define DEPBUILD_PATTERN -_dep_: _src_ - $(CXX) _src_ -MM $(CXXFLAGS) -MT "$$(patsubst %.d,%.o,_dep_) _dep_" -MF _dep_ -endef - -# rule pattern for assembly files -define ASMBUILD_PATTERN -_obj_: _src_ - $(NASM) -o _obj_ $(NASMFLAGS) _src_ -endef - -define CBUILD_PATTERN -_obj_: _src_ - $(CC) -c $(CFLAGS) -o _obj_ -c _src_ -endef - all: $(ZDOOMBIN) toolsandpk3 zdoom.pk3 -$(ZDOOMBIN): $(OBJDIR) $(if $(RESTART),deps) $(OBJS) -ifndef RESTART - $(CXX) $(LDFLAGS) $(OBJDIR)/autostart.o \ +$(ZDOOMBIN): ccdv $(OBJDIR) $(OBJS) + $(CCDV) $(CXX) $(LDFLAGS) $(OBJDIR)/autostart.o \ $(filter-out %/autostart.o %/autozend.o,$(OBJS)) \ $(OBJDIR)/autozend.o -o $(ZDOOMBIN) -endif -# include any of the dep files that already exist if we aren't making clean -$(if !$(findstring clean,$(MAKECMDGOALS)),$(foreach dep,$(DEPS),$(if $(wildcard $(dep)),$(eval include $(dep))))) +$(OBJDIR)/%.o: %.cpp + $(CCDV) $(CXX) $(CXXFLAGS) -o $@ -c $< -# textually substitute in the _dep_ and the _src_ it depends on to create rules -# for creating dependency files without any existing dependency files -$(foreach src,$(CPPSRCS) $(CSRCS), $(eval $(subst _src_,$(src),$(subst \ -_dep_,$(OBJDIR)/$(patsubst %.c,%.d,$(patsubst %.cpp,%.d,$(notdir $$$(src)))),\ -$(DEPBUILD_PATTERN))))) +$(OBJDIR)/%.o: %.c + $(CCDV) $(CC) $(CFLAGS) -o $@ -c $< -# textually substitute in the _obj_ and the _src_ it depends on to create rules -$(foreach src,$(ASRCS), $(eval $(subst _src_,$(src),$(subst \ -_obj_,$(OBJDIR)/$(patsubst %.nas,%.o,$(notdir $$$(src))),$(ASMBUILD_PATTERN))))) +$(OBJDIR)/%.o: %.nas + $(CCDV) $(NASM) -o $@ $(NASMFLAGS) $< -# textually substitute in the _obj_ and the _src_ it depends on to create rules -$(foreach src,$(CSRCS), $(eval $(subst _src_,$(src),$(subst \ -_obj_,$(OBJDIR)/$(patsubst %.c,%.o,$(notdir $$$(src))),$(CBUILD_PATTERN))))) - -$(OBJDIR)/%.o: - $(CXX) -c $(CXXFLAGS) -o $@ -c $< - -# Hi, you Linux people. This works with Makefile.mingw, so i assume it works here too. # This file needs special handling so that it actually gets compiled with SSE2 support. -$(OBJDIR)/nodebuild_classify_sse2.o: src/nodebuild_classify_sse2.cpp - $(CXX) $(CXXFLAGS) -msse2 -mfpmath=sse -c -o $@ $< - -# start a new instance of make after dependency files have been made -deps: $(DEPS) -ifdef RESTART - @make -f $(firstword $(MAKEFILE_LIST)) RESTART= -endif +$(OBJDIR)/nodebuild_classify_sse2.o: nodebuild_classify_sse2.cpp + $(CCDV) $(CXX) $(CXXFLAGS) -msse2 -mfpmath=sse -c -o $@ $< $(OBJDIR): mkdir $(OBJDIR) -toolsandpk3: tools/makewad/makewad tools/dehsupp/dehsupp tools/xlatcc/xlatcc +toolsandpk3: ccdv tools/makewad/makewad tools/dehsupp/dehsupp tools/xlatcc/xlatcc make -C wadsrc/ zdoom.pk3: toolsandpk3 @@ -140,10 +98,16 @@ tools/dehsupp/dehsupp: tools/xlatcc/xlatcc: make -C tools/xlatcc/ -.PHONY : clean cleandeps cleanobjs distclean deps toolsandpk3 +.PHONY : clean cleandeps cleanobjs distclean toolsandpk3 cleantools clean: cleanobjs rm -f $(ZDOOMDEBUG) $(ZDOOM) $(ZDOOM).map + rm -f ccdv + +cleantools: + @$(MAKE) -C tools/makewad clean + @$(MAKE) -C tools/dehsupp clean + @$(MAKE) -C tools/xlatcc clean cleandebug: rm -f $(ZDOOMDEBUG) $(DEBUGOBJ)/*.o $(DEBUGOBJ)/*.d @@ -163,3 +127,9 @@ cleandeps: cleanobjs: rm -f $(RELEASEOBJ)/*.o $(DEBUGOBJ)/*.o +ccdv: ccdv-posix.c + @gcc -Os -s ccdv-posix.c -o ccdv + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif diff --git a/ccdv-posix.c b/ccdv-posix.c new file mode 100644 index 0000000000..7e2aa8bfd2 --- /dev/null +++ b/ccdv-posix.c @@ -0,0 +1,463 @@ +/* ccdv.c */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "") +#define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "") +#define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "") +#define SETCOLOR_COMMAND (gANSIEscapes ? "\033\1331;35m" : "") +#define SETCOLOR_ERROROUTPUT (gANSIEscapes ? "\033\1331;31m" : "") +#define SETCOLOR_WARNINGOUTPUT (gANSIEscapes ? "\033\1331;39m" : "") +#define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "") + +#define TEXT_BLOCK_SIZE 8192 +#define INDENT 2 + +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[32768]; +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; + if(gDumpCmdArgs) + { + printf("%s%s%s", SETCOLOR_COMMAND, gArgsStr, SETCOLOR_NORMAL); + for(i = 0; i < gColumns; ++i) + { + putchar('='); + } + } + printf("%s%s%s", gDumpCmdArgs ? SETCOLOR_ERROROUTPUT : SETCOLOR_WARNINGOUTPUT, + gBuf + strlen(gArgsStr), SETCOLOR_NORMAL); + 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) +{ + char *sUsage = "\ +Usage: ccdv /path/to/cc CFLAGS...\n\ +\n\ +I wrote this to reduce the deluge Make output to make finding actual problems\n\ +easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\ +\n\ + .c.o:\n\ + $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ +\n\ +Rewrite your rule so it looks like:\n\ +\n\ + .c.o:\n\ + @ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ + .cpp.o:\n\ + @ccdv $(CXX) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\ +\n\ +ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n\ + -- Mike Gleason, NcFTP Software \n\ + -- John F Meinel Jr, \n\ + "; + fprintf(stderr, sUsage); + 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; + int yy = 0; + int gcc = 0; + int lemon = 0; + const char *quote; + + if(argc < 2) + Usage(); + + snprintf(gAction, sizeof(gAction), "Running %s", Basename(argv[1])); + memset(gArgsStr, 0, sizeof(gArgsStr)); + + if(strcmp(gAction+8, "ar") == 0) + { + snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i + 1])); + } + else if(strcmp(gAction+8, "cc") == 0 || + strcmp(gAction+8, "ld") == 0 || + strcmp(gAction+8, "gcc") == 0 || + strcmp(gAction+8, "g++") == 0 || + strcmp(gAction+8, "c++") == 0) + { + gcc = 1; + } + else if(strcmp(gAction+8, "lemon") == 0) + { + lemon = 1; + } + + 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(gcc && (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]), ".y", 2) == 0) + { + if(lemon) + { + strcpy(gAction, "Generating"); + snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); + } + yy++; + } + else if(strncasecmp(Extension(argv[i]), ".nas", 3) == 0 || + strncasecmp(Extension(argv[i]), ".asm", 3) == 0 || + strcasecmp(Extension(argv[i]), ".s") == 0) + { + strcpy(gAction, "Assembling"); + 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(cc > 0) + { + strcpy(gAction, yy == 0 ? "Compiling" : "Generating"); + } + + 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 + ("vt100:vt102:vt220:vt320:xterm:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin", + 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 */ + +/* eof ccdv.c */ diff --git a/tools/dehsupp/Makefile b/tools/dehsupp/Makefile index f39d17b94a..4471c399b5 100644 --- a/tools/dehsupp/Makefile +++ b/tools/dehsupp/Makefile @@ -4,7 +4,7 @@ ifeq (Windows_NT,$(OS)) CFLAGS = $(LOC) -Os -Wall -fomit-frame-pointer else EXE = dehsupp - CCDV = + CCDV = @../../ccdv CFLAGS = -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -Os -Wall -fomit-frame-pointer endif diff --git a/tools/lemon/Makefile b/tools/lemon/Makefile index 2f81b77c4a..6c366ab2ad 100644 --- a/tools/lemon/Makefile +++ b/tools/lemon/Makefile @@ -4,7 +4,7 @@ ifeq (Windows_NT,$(OS)) CFLAGS = $(LOC) -D_WIN32 -Os -Wall -Wno-implicit -fomit-frame-pointer else EXE = lemon - CCDV = + CCDV = @../../ccdv CFLAGS = -Os -Wall -Wno-implicit -fomit-frame-pointer endif diff --git a/tools/makewad/Makefile b/tools/makewad/Makefile index 63e62adad2..72716298c5 100644 --- a/tools/makewad/Makefile +++ b/tools/makewad/Makefile @@ -6,7 +6,7 @@ ifeq (Windows_NT,$(OS)) ZLIB = ../../zlib/libz.a else EXE = makewad - CCDV = + CCDV = @../../ccdv CFLAGS = -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -Os -Wall -fomit-frame-pointer LDFLAGS = -s -lz ZLIB = diff --git a/tools/re2c/Makefile b/tools/re2c/Makefile index ee5b950c79..d87e383b37 100644 --- a/tools/re2c/Makefile +++ b/tools/re2c/Makefile @@ -4,7 +4,7 @@ ifeq (Windows_NT,$(OS)) CXXFLAGS = $(LOC) -D_WIN32 -DNDEBUG -Os -Wall -Wno-unused else EXE = re2c - CCDV = + CCDV = @../../ccdv CXXFLAGS = -DHAVE_CONFIG_H -DNDEBUG -Os -Wall -Wno-unused endif diff --git a/tools/xlatcc/Makefile b/tools/xlatcc/Makefile index 27bb00d1be..a07c2f5b52 100644 --- a/tools/xlatcc/Makefile +++ b/tools/xlatcc/Makefile @@ -4,7 +4,7 @@ ifeq (Windows_NT,$(OS)) CFLAGS = $(LOC) -Os -Wall -fomit-frame-pointer else EXE = xlatcc - CCDV = + CCDV = @../../ccdv CFLAGS = -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp $(LOC) -Os -Wall -fomit-frame-pointer endif