summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavygrvy <davygrvy>2002-03-28 23:23:03 (GMT)
committerdavygrvy <davygrvy>2002-03-28 23:23:03 (GMT)
commit8548465e0dcb84c58c381dc6d2c8e91c19d01c65 (patch)
tree64a7d4eacc4548a71dd1f2cb8b45ee3356516b18
parent07bf7a5bb6e4b4cbc9386f9860487d0cf70c39e4 (diff)
downloadtk-8548465e0dcb84c58c381dc6d2c8e91c19d01c65.zip
tk-8548465e0dcb84c58c381dc6d2c8e91c19d01c65.tar.gz
tk-8548465e0dcb84c58c381dc6d2c8e91c19d01c65.tar.bz2
* win/.cvsignore (new):
* win/lamp.bmp (new): * win/makefile.vc: * win/nmakehlp.c (new): * win/rules.vc: Brought the makefile up-to-date with Tcl's one. This now has support for Win9x issues and the winhelp target now exists. Color scheme can be changed. I'm just imparting a first suggestion using orange :) I'll have to think about the install portion of the helpfile as I'll need to do some tricks to insert tk's contents file into Tcl's using some special winhlp32.exe switches. [Bug 533862 527941]
-rw-r--r--win/.cvsignore15
-rw-r--r--win/lamp.bmpbin0 -> 2102 bytes
-rw-r--r--win/makefile.vc171
-rw-r--r--win/nmakehlp.c297
-rw-r--r--win/rules.vc111
5 files changed, 521 insertions, 73 deletions
diff --git a/win/.cvsignore b/win/.cvsignore
new file mode 100644
index 0000000..b986cda
--- /dev/null
+++ b/win/.cvsignore
@@ -0,0 +1,15 @@
+Debug
+Release
+*.opt
+*.ncb
+*.plg
+*.00?
+*.o
+*.obj
+*.i
+*.asm
+Makefile
+tcl.hpj
+tclConfig.sh
+nmakehlp.exe
+.#*
diff --git a/win/lamp.bmp b/win/lamp.bmp
new file mode 100644
index 0000000..834c0f9
--- /dev/null
+++ b/win/lamp.bmp
Binary files differ
diff --git a/win/makefile.vc b/win/makefile.vc
index 28933e4..31838f1 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -9,10 +9,10 @@
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001 ActiveState Corporation.
-# Copyright (c) 2001 Tomasoft Engineering.
+# Copyright (c) 2001-2002 David Gravereaux.
#
#------------------------------------------------------------------------------
-# RCS: @(#) $Id: makefile.vc,v 1.52 2002/03/21 17:48:54 davygrvy Exp $
+# RCS: @(#) $Id: makefile.vc,v 1.53 2002/03/28 23:23:03 davygrvy Exp $
#------------------------------------------------------------------------------
!if "$(MSVCDIR)" == ""
@@ -62,6 +62,8 @@ the environment. Jump to this line to read the new instructions.
# Sets the location for where to find the Tcl headers and
# libraries. The install point is assumed when not
# specified. This can be the source tree or an installation.
+# Tk does need the source directory, though. Tk comes very close
+# to not needing the sources.
#
# INSTALLDIR=<path>
# Sets where to install Tcl from the built binaries.
@@ -205,27 +207,26 @@ TCL_LIBRARY = $(INSTALLDIR)\lib
TCLREGLIB = $(INSTALLDIR)\lib\$(TCLREGLIBNAME)
TCLDDELIB = $(INSTALLDIR)\lib\$(TCLDDELIBNAME)
TCLTMP_DIR = \must\have\tcl\sources\to\build\this\target
+COFFBASE = \must\have\tcl\sources\to\build\this\target
+TOOLSDIR = \must\have\tcl\sources\to\build\this\target
!else
-TCLSH = $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLNAMEPREFIX)sh$(VERSION)$(SUFX).exe
+TCLSH = $(TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(VERSION)$(SUFX).exe
TCLSTUBLIB = $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLSTUBLIBNAME)
TCLIMPLIB = $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLIMPLIBNAME)
TCL_LIBRARY = $(TCLDIR)\library
TCLREGLIB = $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLREGLIBNAME)
TCLDDELIB = $(TCLDIR)\win\$(BUILDDIRTOP)\$(TCLDDELIBNAME)
TCLTMP_DIR = $(TCLDIR)\win\$(TMP_DIR:tk=tcl)
+COFFBASE = $(TCLDIR)\win\coffbase.txt
+TOOLSDIR = $(TCLDIR)\tools
!endif
WISH = $(OUT_DIR)\$(WISHNAMEPREFIX)$(VERSION)$(SUFX).exe
WISHC = $(OUT_DIR)\$(WISHNAMEPREFIX)c$(VERSION)$(SUFX).exe
-#TKHLPBASE = $(PROJECT)$(VERSION)
-#TKHLP = $(OUT_DIR)\$(TKHLPBASE).hlp
-#TKHLPCNT = $(OUT_DIR)\$(TKHLPBASE).cnt
-
TKTEST = $(OUT_DIR)\$(PROJECT)test.exe
CAT32 = $(OUT_DIR)\cat32.exe
RMDIR = .\rmd.bat
-MKDIR = .\mkd.bat
RM = del
LIB_INSTALL_DIR = $(INSTALLDIR)\lib
@@ -369,6 +370,7 @@ WINDIR = $(ROOT)\win
GENERICDIR = $(ROOT)\generic
XLIBDIR = $(ROOT)\xlib
BITMAPDIR = $(ROOT)\bitmaps
+DOCDIR = $(ROOT)\doc
RCDIR = $(WINDIR)\rc
!if $(TCLINSTALL)
@@ -399,7 +401,15 @@ cdebug = -Oti
!endif
# declarations common to all compiler options
-cflags = -nologo -c -W3 -Fp$(TMP_DIR)^\ -YX
+cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
+
+!if $(PENT_0F_ERRATA)
+cflags = $(cflags) -QI0f
+!endif
+
+!if $(ITAN_B_ERRATA)
+cflags = $(cflags) -QIA64_Bx
+!endif
!if $(MSVCRT)
crt = -MD$(DBGX)
@@ -418,29 +428,35 @@ WISH_CFLAGS = $(BASE_CLFAGS) $(TK_DEFINES)
#---------------------------------------------------------------------
!if $(DEBUG)
-ldebug = -debug:full -debugtype:cv
+ldebug = -debug:full -debugtype:cv
!else
-ldebug = -release
+ldebug = -release -opt:ref -opt:icf,3
!endif
# declarations common to all linker options
-lflags = -nologo -machine:$(MACHINE)
-
-# declarations for use on Intel i386, i486, and Pentium systems
-!IF "$(MACHINE)" == "IX86"
-DLLENTRY = @12
-dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
-!ELSE IF "$(MACHINE)" == "IA64"
-DLLENTRY = @12
-dlllflags = $(lflags) -dll
-!ELSE
-dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
-!ENDIF
-
-conlflags = $(lflags) -subsystem:console -entry:mainCRTStartup
-guilflags = $(lflags) -subsystem:windows -entry:WinMainCRTStartup
-
-baselibs = kernel32.lib advapi32.lib user32.lib
+lflags = -nologo -machine:$(MACHINE) $(ldebug)
+
+!if $(PROFILE)
+lflags = $(lflags) -profile
+!endif
+
+!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
+# align sections for PE size savings.
+lflags = $(lflags) -opt:nowin98
+!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
+# align sections for speed in loading by choosing the virtual page size.
+lflags = $(lflags) -align:4096
+!endif
+
+!if $(LOIMPACT)
+lflags = $(lflags) -ws:aggressive
+!endif
+
+dlllflags = $(lflags) -dll
+conlflags = $(lflags) -subsystem:console
+guilflags = $(lflags) -subsystem:windows
+
+baselibs = kernel32.lib advapi32.lib user32.lib
guilibs = $(baselibs) gdi32.lib comdlg32.lib winspool.lib imm32.lib comctl32.lib
@@ -496,8 +512,8 @@ rundemo: setup $(TKTEST) $(TKLIB) $(CAT32)
$(TKTEST) $(ROOT)\library\demos\widget
setup:
- @$(MKDIR) $(TMP_DIR)
- @$(MKDIR) $(OUT_DIR)
+ @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
+ @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
console-wish : $(WISHC)
@@ -511,7 +527,8 @@ $(TKLIB): $(TKOBJS)
$**
<<
!else
- $(link32) $(ldebug) $(dlllflags) -out:$@ $(guilibs) $(TCLSTUBLIB) @<<
+ $(link32) $(ldebug) $(dlllflags) -base:@$(COFFBASE),tk -out:$@ \
+ $(guilibs) $(TCLSTUBLIB) @<<
$**
<<
-@del $*.exp
@@ -568,34 +585,68 @@ genstubs:
# Regenerate the windows help files.
#---------------------------------------------------------------------
-#MAN2TCL = $(TOOLSDIR)\man2tcl
-#TCLRTF = $(TOOLSDIR)\tcl.rtf
-#MAN2HELP = $(TOOLSDIR)\man2help.tcl
-#TCLHPJ = $(TOOLSDIR)\tcl.hpj
-
-#winhelp: $(TCLHLP)
-
-#$(TCLHLP): $(TCLRTF)
-# cd $(TOOLSDIR)
-# start /wait hcrtf.exe -x tcl.hpj
-# cd $(MAKEDIR)
-# copy $(TOOLSDIR)\$(TCLHLPBASE).hlp $(OUT_DIR)
-# copy $(TOOLSDIR)\$(TCLHLPBASE).cnt $(OUT_DIR)
-
-#$(TCLHPJ): $(TCLHPJ).in
-# copy $(TCLHPJ).in $(TCLHPJ)
+TCLHLPBASE = $(PROJECT)$(VERSION)
+HELPFILE = $(OUT_DIR)\$(TCLHLPBASE).hlp
+HELPCNT = $(OUT_DIR)\$(TCLHLPBASE).cnt
+DOCTMP_DIR = $(OUT_DIR)\$(PROJECT)_docs
+HELPRTF = $(DOCTMP_DIR)\$(PROJECT).rtf
+MAN2HELP = $(DOCTMP_DIR)\man2help.tcl
+MAN2HELP2 = $(DOCTMP_DIR)\man2help2.tcl
+INDEX = $(DOCTMP_DIR)\index.tcl
+BMP = $(DOCTMP_DIR)\lamp.bmp
+BMP_NOPATH = lamp.bmp
+MAN2TCL = $(DOCTMP_DIR)\man2tcl.exe
+
+winhelp: docsetup $(HELPFILE)
+
+docsetup:
+ @if not exist $(DOCTMP_DIR)\nul mkdir $(DOCTMP_DIR)
+
+$(MAN2HELP) $(MAN2HELP2) $(INDEX): $(TOOLSDIR)\$$(@F)
+ copy $(TOOLSDIR)\$(@F) $(@D)
+
+$(BMP):
+ copy $(WINDIR)\$(@F) $(@D)
+
+$(HELPFILE): $(HELPRTF) $(BMP)
+ cd $(DOCTMP_DIR)
+ start /wait hcrtf.exe -x <<$(PROJECT).hpj
+[OPTIONS]
+COMPRESS=12 Hall Zeck
+LCID=0x409 0x0 0x0 ; English (United States)
+TITLE=Tcl/Tk Reference Manual
+BMROOT=.
+CNT=$(@B).cnt
+HLP=$(@B).hlp
+
+[FILES]
+$(PROJECT).rtf
+
+[WINDOWS]
+main="Tcl/Tk Reference Manual",,27648,(r15263976),(r4227327)
+
+[CONFIG]
+BrowseButtons()
+CreateButton(1, "Web", ExecFile("http://www.tcl.tk"))
+CreateButton(2, "SF", ExecFile("http://sf.net/projects/tcl"))
+CreateButton(3, "Wiki", ExecFile("http://wiki.tcl.tk"))
+CreateButton(4, "FAQ", ExecFile("http://www.purl.org/NET/Tcl-FAQ/"))
+<<
+ cd $(MAKEDIR)
+ copy "$(DOCTMP_DIR)\$(@B).hlp" "$(OUT_DIR)"
+ copy "$(DOCTMP_DIR)\$(@B).cnt" "$(OUT_DIR)"
-#$(MAN2TCL).exe: $(MAN2TCL).obj
-# cd $(TOOLSDIR)
-# $(cc32) -nologo -G4 -ML -O2 $(MAN2TCL).c
-# cd $(MAKEDIR)
+$(MAN2TCL): $(TOOLSDIR)\$$(@B).c
+ $(cc32) -nologo -G4 -ML -O2 -Fo$(@D)\ $(TOOLSDIR)\$(@B).c -link -out:$@
-#$(TCLRTF): $(MAN2TCL).exe $(TCLSH)
-# cd $(TOOLSDIR)
-# ..\win\$(TCLSH) $(MAN2HELP) $(PROJECT) $(VERSION) $(ROOT)/doc \
-# ../../tk$(DOTVERSION)/doc
-# cd $(MAKEDIR)
+$(HELPRTF): $(MAN2TCL) $(MAN2HELP) $(MAN2HELP2) $(INDEX)
+ $(TCLSH) $(MAN2HELP:\=/) -bitmap $(BMP_NOPATH) $(PROJECT) $(VERSION) $(DOCDIR:\=/)
+install-docs:
+!if exist($(HELPFILE))
+ @xcopy /i /y "$(HELPFILE)" "$(DOC_INSTALL_DIR)\"
+ @xcopy /i /y "$(HELPCNT)" "$(DOC_INSTALL_DIR)\"
+!endif
#---------------------------------------------------------------------
# Special case object file targets
@@ -675,7 +726,15 @@ $(GENERICDIR)/tkMenu.c: $(GENERICDIR)/tkMenu.h
$(GENERICDIR)/tkMenuDraw.c: $(GENERICDIR)/tkMenu.h
$(WINDIR)/tkWinMenu.c: $(GENERICDIR)/tkMenu.h
+!if exist("$(OUT_DIR)\depend.mk")
+!include "$(OUT_DIR)\depend.mk"
+!message *** Dependency rules in effect.
+!else
+!message *** Dependency rules are not being used.
+!endif
+### add a spacer in the output
+!message
#---------------------------------------------------------------------
# Implicit rules
diff --git a/win/nmakehlp.c b/win/nmakehlp.c
new file mode 100644
index 0000000..9a27028
--- /dev/null
+++ b/win/nmakehlp.c
@@ -0,0 +1,297 @@
+/* ----------------------------------------------------------------------------
+ * nmakehlp.c --
+ *
+ * This is used to fix limitations within nmake and the environment.
+ *
+ * Copyright (c) 2002 by David Gravereaux.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * ----------------------------------------------------------------------------
+ * RCS: @(#) $Id: nmakehlp.c,v 1.1 2002/03/28 23:23:03 davygrvy Exp $
+ * ----------------------------------------------------------------------------
+ */
+#include <windows.h>
+#pragma comment (lib, "user32.lib")
+#pragma comment (lib, "kernel32.lib")
+
+/* protos */
+int CheckForCompilerFeature (const char *option);
+int CheckForLinkerFeature (const char *option);
+int IsIn (const char *string, const char *substring);
+DWORD WINAPI ReadFromPipe (LPVOID args);
+
+/* globals */
+typedef struct {
+ HANDLE pipe;
+ char buffer[1000];
+} pipeinfo;
+
+pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
+pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
+
+
+
+/* exitcodes: 0 == no, 1 == yes, 2 == error */
+int
+main (int argc, char *argv[])
+{
+ char msg[300];
+ DWORD dwWritten;
+ int chars;
+
+ if (argc > 1 && *argv[1] == '-') {
+ switch (*(argv[1]+1)) {
+ case 'c':
+ if (argc != 3) {
+ chars = wsprintf(msg, "usage: %s -c <compiler option>\n"
+ "Tests for whether cl.exe supports an option\n"
+ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+ return 2;
+ }
+ return CheckForCompilerFeature(argv[2]);
+ case 'l':
+ if (argc != 3) {
+ chars = wsprintf(msg, "usage: %s -l <linker option>\n"
+ "Tests for whether link.exe supports an option\n"
+ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+ return 2;
+ }
+ return CheckForLinkerFeature(argv[2]);
+ case 'f':
+ if (argc == 2) {
+ chars = wsprintf(msg, "usage: %s -f <string> <substring>\n"
+ "Find a substring within another\n"
+ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+ return 2;
+ } else if (argc == 3) {
+ /* if the string is blank, there is no match */
+ return 0;
+ } else {
+ return IsIn(argv[2], argv[3]);
+ }
+ }
+ }
+ chars = wsprintf(msg, "usage: %s -c|-l|-f ...\n"
+ "This is a little helper app to equalize shell differences between WinNT and\n"
+ "Win9x and get nmake.exe to accomplish its job.\n",
+ argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+ return 2;
+}
+
+int
+CheckForCompilerFeature (const char *option)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ SECURITY_ATTRIBUTES sa;
+ DWORD threadID;
+ char msg[300];
+ BOOL ok;
+ HANDLE hProcess, h, pipeThreads[2];
+ char cmdline[100];
+
+ hProcess = GetCurrentProcess();
+
+ ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&si, sizeof(STARTUPINFO));
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = INVALID_HANDLE_VALUE;
+
+ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = FALSE;
+
+ /* create a non-inheritible pipe. */
+ CreatePipe(&Out.pipe, &h, &sa, 0);
+
+ /* dupe the write side, make it inheritible, and close the original. */
+ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput,
+ 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+ /* Same as above, but for the error side. */
+ CreatePipe(&Err.pipe, &h, &sa, 0);
+ DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
+ 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+ /* base command line */
+ strcpy(cmdline, "cl.exe -nologo -c -TC -Fdtemp ");
+ /* append our option for testing */
+ strcat(cmdline, option);
+ /* filename to compile, which exists, but is nothing and empty. */
+ strcat(cmdline, " nul");
+
+ ok = CreateProcess(
+ NULL, /* Module name. */
+ cmdline, /* Command line. */
+ NULL, /* Process handle not inheritable. */
+ NULL, /* Thread handle not inheritable. */
+ TRUE, /* yes, inherit handles. */
+ DETACHED_PROCESS, /* No console for you. */
+ NULL, /* Use parent's environment block. */
+ NULL, /* Use parent's starting directory. */
+ &si, /* Pointer to STARTUPINFO structure. */
+ &pi); /* Pointer to PROCESS_INFORMATION structure. */
+
+ if (!ok) {
+ DWORD err = GetLastError();
+ int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
+ (300-chars), 0);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
+ return 2;
+ }
+
+ /* close our references to the write handles that have now been inherited. */
+ CloseHandle(si.hStdOutput);
+ CloseHandle(si.hStdError);
+
+ WaitForInputIdle(pi.hProcess, 5000);
+ CloseHandle(pi.hThread);
+
+ /* start the pipe reader threads. */
+ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
+ pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
+
+ /* block waiting for the process to end. */
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ CloseHandle(pi.hProcess);
+
+ /* clean up temporary files before returning */
+ DeleteFile("temp.idb");
+ DeleteFile("temp.pdb");
+
+ /* wait for our pipe to get done reading, should it be a little slow. */
+ WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
+ CloseHandle(pipeThreads[0]);
+ CloseHandle(pipeThreads[1]);
+
+ /* look for the commandline warning code in both streams. */
+ return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL);
+}
+
+int
+CheckForLinkerFeature (const char *option)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ SECURITY_ATTRIBUTES sa;
+ DWORD threadID;
+ char msg[300];
+ BOOL ok;
+ HANDLE hProcess, h, pipeThreads[2];
+ char cmdline[100];
+
+ hProcess = GetCurrentProcess();
+
+ ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&si, sizeof(STARTUPINFO));
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = INVALID_HANDLE_VALUE;
+
+ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ /* create a non-inheritible pipe. */
+ CreatePipe(&Out.pipe, &h, &sa, 0);
+
+ /* dupe the write side, make it inheritible, and close the original. */
+ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput,
+ 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+ /* Same as above, but for the error side. */
+ CreatePipe(&Err.pipe, &h, &sa, 0);
+ DuplicateHandle(hProcess, h, hProcess, &si.hStdError,
+ 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+ /* base command line */
+ strcpy(cmdline, "link.exe -nologo ");
+ /* append our option for testing */
+ strcat(cmdline, option);
+ /* filename to compile, which exists, but is nothing and empty. */
+// strcat(cmdline, " nul");
+
+ ok = CreateProcess(
+ NULL, /* Module name. */
+ cmdline, /* Command line. */
+ NULL, /* Process handle not inheritable. */
+ NULL, /* Thread handle not inheritable. */
+ TRUE, /* yes, inherit handles. */
+ DETACHED_PROCESS, /* No console for you. */
+ NULL, /* Use parent's environment block. */
+ NULL, /* Use parent's starting directory. */
+ &si, /* Pointer to STARTUPINFO structure. */
+ &pi); /* Pointer to PROCESS_INFORMATION structure. */
+
+ if (!ok) {
+ DWORD err = GetLastError();
+ int chars = wsprintf(msg, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID) &msg[chars],
+ (300-chars), 0);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg), &err, NULL);
+ return 2;
+ }
+
+ /* close our references to the write handles that have now been inherited. */
+ CloseHandle(si.hStdOutput);
+ CloseHandle(si.hStdError);
+
+ WaitForInputIdle(pi.hProcess, 5000);
+ CloseHandle(pi.hThread);
+
+ /* start the pipe reader threads. */
+ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
+ pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
+
+ /* block waiting for the process to end. */
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ CloseHandle(pi.hProcess);
+
+ /* wait for our pipe to get done reading, should it be a little slow. */
+ WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
+ CloseHandle(pipeThreads[0]);
+ CloseHandle(pipeThreads[1]);
+
+ /* look for the commandline warning code in the stderr stream. */
+ return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL);
+}
+
+DWORD WINAPI
+ReadFromPipe (LPVOID args)
+{
+ pipeinfo *pi = (pipeinfo *) args;
+ char *lastBuf = pi->buffer;
+ DWORD dwRead;
+ BOOL ok;
+
+again:
+ ok = ReadFile(pi->pipe, lastBuf, 25, &dwRead, 0L);
+ if (!ok || dwRead == 0) {
+ CloseHandle(pi->pipe);
+ return 0;
+ }
+ lastBuf += dwRead;
+ goto again;
+
+ return 0; /* makes the compiler happy */
+}
+
+int
+IsIn (const char *string, const char *substring)
+{
+ return (strstr(string, substring) != NULL);
+}
diff --git a/win/rules.vc b/win/rules.vc
index 95f33fe..402a5d9 100644
--- a/win/rules.vc
+++ b/win/rules.vc
@@ -7,10 +7,10 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# Copyright (c) 2001 Tomasoft Engineering.
+# Copyright (c) 2001-2002 David Gravereaux.
#
#------------------------------------------------------------------------------
-# RCS: @(#) $Id: rules.vc,v 1.1 2001/11/13 02:46:23 davygrvy Exp $
+# RCS: @(#) $Id: rules.vc,v 1.2 2002/03/28 23:23:03 davygrvy Exp $
#------------------------------------------------------------------------------
!ifndef _RULES_VC
@@ -29,61 +29,128 @@ INSTALLDIR = C:\Progra~1\Tcl
MACHINE = IX86
!endif
+!message ===============================================================================
+
+#----------------------------------------------------------
+# build the helper app we need to overcome nmake's limiting
+# environment.
+#----------------------------------------------------------
+
+!if !exist(nmakehlp.exe)
+!if [$(cc32) -nologo -ML nmakehlp.c -link -subsystem:console > nul]
+!endif
+!endif
+
+#----------------------------------------------------------
+# Test for compiler features
+#----------------------------------------------------------
+
+### test for optimizations
+!if [nmakehlp -c -Ox]
+!message *** Compiler has 'Optimizations'
+OPTIMIZING = 1
+!else
+!message *** Compiler doesn't have 'Optimizations'
+OPTIMIZING = 0
+!endif
+
+!if "$(MACHINE)" == "IX86"
+### test for pentium errata
+!if [nmakehlp -c -QI0f]
+!message *** Compiler has 'Pentium 0x0f fix'
+PENT_0F_ERRATA = 1
+!else
+!message *** Compiler doesn't have 'Pentium 0x0f fix'
+PENT_0F_ERRATA = 0
+!endif
+### test for -align:4096, when align:512 will do.
+!if [nmakehlp -l -opt:nowin98]
+!message *** Linker has 'Win98 alignment problem'
+ALIGN98_HACK = 1
+!else
+!message *** Linker doesn't have 'Win98 alignment problem'
+ALIGN98_HACK = 0
+!endif
+!else
+PENT_0F_ERRATA = 0
+ALIGN98_HACK = 0
+!endif
+
+!if "$(MACHINE)" == "IA64"
+### test for Itanium errata
+!if [nmakehlp -c -QIA64_Bx]
+!message *** Compiler has 'B-stepping errata workarounds'
+ITAN_B_ERRATA = 1
+!else
+!message *** Compiler doesn't have 'B-stepping errata workarounds'
+ITAN_B_ERRATA = 0
+!endif
+!else
+ITAN_B_ERRATA = 0
+!endif
#----------------------------------------------------------
# Decode the options requested.
#----------------------------------------------------------
-!if "$(OPTS)" == "" || ![echo $(OPTS) | find /i "none" > nul]
+
+!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
STATIC_BUILD = 0
TCL_THREADS = 0
DEBUG = 0
PROFILE = 0
MSVCRT = 0
+LOIMPACT = 0
TCL_LINKWITHEXTENSIONS = 0
!else
-!if ![echo $(OPTS) | find /i "static" > nul]
+!if [nmakehlp -f $(OPTS) "static"]
!message *** Doing static
STATIC_BUILD = 1
!else
STATIC_BUILD = 0
!endif
-!if ![echo $(OPTS) | find /i "msvcrt" > nul]
+!if [nmakehlp -f $(OPTS) "msvcrt"]
!message *** Doing msvcrt
MSVCRT = 1
!else
MSVCRT = 0
!endif
-!if ![echo $(OPTS) | find /i "linkexten" > nul]
+!if [nmakehlp -f $(OPTS) "linkexten"]
!message *** Doing linkexten
TCL_LINKWITHEXTENSIONS = 1
!else
TCL_LINKWITHEXTENSIONS = 0
!endif
-!if ![echo $(OPTS) | find /i "threads" > nul]
+!if [nmakehlp -f $(OPTS) "threads"]
!message *** Doing threads
TCL_THREADS = 1
!else
TCL_THREADS = 0
!endif
-!if ![echo $(OPTS) | find /i "symbols" > nul]
+!if [nmakehlp -f $(OPTS) "symbols"]
!message *** Doing symbols
DEBUG = 1
!else
DEBUG = 0
!endif
-!if ![echo $(OPTS) | find /i "profile" > nul]
+!if [nmakehlp -f $(OPTS) "profile"]
!message *** Doing profile
PROFILE = 1
!else
PROFILE = 0
!endif
+!if [nmakehlp -f $(OPTS) "loimpact"]
+!message *** Doing loimpact
+LOIMPACT = 1
+!else
+LOIMPACT = 0
+!endif
!endif
!if !$(STATIC_BUILD)
# Make sure we don't build overly fat DLLs.
MSVCRT = 1
-# Shouldn't statically put the extensions inside the shell when dynamic.
+# We shouldn't statically put the extensions inside the shell when dynamic.
TCL_LINKWITHEXTENSIONS = 0
!endif
@@ -140,25 +207,22 @@ OUT_DIR = $(TMP_DIR)
!endif
!endif
-!message *** Intermediate directory will be '$(TMP_DIR)'
-!message *** Output directory will be '$(OUT_DIR)'
-!message *** Suffix for binaries will be '$(SUFX)'
-
#----------------------------------------------------------
# Decode the statistics requested.
#----------------------------------------------------------
-!if "$(STATS)" == "" || ![echo $(STATS) | find /i "none" > nul]
+
+!if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"]
TCL_MEM_DEBUG = 0
TCL_COMPILE_DEBUG = 0
!else
-!if ![echo $(STATS) | find /i "memdbg" > nul]
+!if [nmakehlp -f $(STATS) "memdbg"]
!message *** Doing memdbg
TCL_MEM_DEBUG = 1
!else
TCL_MEM_DEBUG = 0
!endif
-!if ![echo $(STATS) | find /i "compdbg" > nul]
+!if [nmakehlp -f $(STATS) "compdbg"]
!message *** Doing compdbg
TCL_COMPILE_DEBUG = 1
!else
@@ -166,6 +230,11 @@ TCL_COMPILE_DEBUG = 0
!endif
!endif
+
+#----------------------------------------------------------
+# Set our defines armed with our options.
+#----------------------------------------------------------
+
OPTDEFINES =
!if $(TCL_MEM_DEBUG)
OPTDEFINES = -DTCL_MEM_DEBUG
@@ -180,6 +249,14 @@ OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1
OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD
!endif
+
+#----------------------------------------------------------
+# Display stats being used.
+#----------------------------------------------------------
+
+!message *** Intermediate directory will be '$(TMP_DIR)'
+!message *** Output directory will be '$(OUT_DIR)'
+!message *** Suffix for binaries will be '$(SUFX)'
!message *** Optional defines are '$(OPTDEFINES)'
!endif