1#------------------------------------------------------------------------------
2# rules.vc --
3#
4#	Microsoft Visual C++ makefile include for decoding the commandline
5#	macros.  This file does not need editing to build Tcl.
6#
7#	This version is modified from the Tcl source version to support
8#	building extensions using nmake.
9#
10# See the file "license.terms" for information on usage and redistribution
11# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12#
13# Copyright (c) 2001-2002 David Gravereaux.
14# Copyright (c) 2003-2008 Patrick Thoyts
15#
16#------------------------------------------------------------------------------
17# RCS: @(#) $Id: rules.vc,v 1.1 2008/04/30 15:18:56 patthoyts Exp $
18#------------------------------------------------------------------------------
19
20!ifndef _RULES_VC
21_RULES_VC = 1
22
23cc32		= $(CC)   # built-in default.
24link32		= link
25lib32		= lib
26rc32		= $(RC)   # built-in default.
27
28!ifndef INSTALLDIR
29### Assume the normal default.
30_INSTALLDIR	= C:\Program Files\Tcl
31!else
32### Fix the path separators.
33_INSTALLDIR	= $(INSTALLDIR:/=\)
34!endif
35
36!ifndef MACHINE
37!if "$(CPU)" == "" || "$(CPU)" == "i386"
38MACHINE         = IX86
39!else
40MACHINE         = $(CPU)
41!endif
42!endif
43
44!ifndef CFG_ENCODING
45CFG_ENCODING	= \"cp1252\"
46!endif
47
48#----------------------------------------------------------
49# Set the proper copy method to avoid overwrite questions
50# to the user when copying files and selecting the right
51# "delete all" method.
52#----------------------------------------------------------
53
54!if "$(OS)" == "Windows_NT"
55RMDIR	= rmdir /S /Q
56ERRNULL  = 2>NUL
57!if ![ver | find "4.0" > nul]
58CPY	= echo y | xcopy /i >NUL
59COPY	= copy >NUL
60!else
61CPY	= xcopy /i /y >NUL
62COPY	= copy /y >NUL
63!endif
64!else # "$(OS)" != "Windows_NT"
65CPY	= xcopy /i >_JUNK.OUT # On Win98 NUL does not work here.
66COPY	= copy >_JUNK.OUT # On Win98 NUL does not work here.
67RMDIR	= deltree /Y
68NULL    = \NUL # Used in testing directory existence
69ERRNULL = >NUL # Win9x shell cannot redirect stderr
70!endif
71MKDIR   = mkdir
72
73!message ===============================================================================
74
75#----------------------------------------------------------
76# build the helper app we need to overcome nmake's limiting
77# environment.
78#----------------------------------------------------------
79
80!if !exist(nmakehlp.exe)
81!if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul]
82!endif
83!endif
84
85#----------------------------------------------------------
86# Test for compiler features
87#----------------------------------------------------------
88
89### test for optimizations
90!if [nmakehlp -c -Ot]
91!message *** Compiler has 'Optimizations'
92OPTIMIZING	= 1
93!else
94!message *** Compiler does not have 'Optimizations'
95OPTIMIZING	= 0
96!endif
97
98OPTIMIZATIONS  =
99
100!if [nmakehlp -c -Ot]
101OPTIMIZATIONS  = $(OPTIMIZATIONS) -Ot
102!endif
103
104!if [nmakehlp -c -Oi]
105OPTIMIZATIONS  = $(OPTIMIZATIONS) -Oi
106!endif
107
108!if [nmakehlp -c -Op]
109OPTIMIZATIONS  = $(OPTIMIZATIONS) -Op
110!endif
111
112!if [nmakehlp -c -fp:strict]
113OPTIMIZATIONS  = $(OPTIMIZATIONS) -fp:strict
114!endif
115
116!if [nmakehlp -c -Gs]
117OPTIMIZATIONS  = $(OPTIMIZATIONS) -Gs
118!endif
119
120!if [nmakehlp -c -GS]
121OPTIMIZATIONS  = $(OPTIMIZATIONS) -GS
122!endif
123
124!if [nmakehlp -c -GL]
125OPTIMIZATIONS  = $(OPTIMIZATIONS) -GL
126!endif
127
128DEBUGFLAGS     =
129
130!if [nmakehlp -c -RTC1]
131DEBUGFLAGS     = $(DEBUGFLAGS) -RTC1
132!elseif [nmakehlp -c -GZ]
133DEBUGFLAGS     = $(DEBUGFLAGS) -GZ
134!endif
135
136COMPILERFLAGS  =-W3
137
138# In v13 -GL and -YX are incompatible.
139!if [nmakehlp -c -YX]
140!if ![nmakehlp -c -GL]
141OPTIMIZATIONS  = $(OPTIMIZATIONS) -YX
142!endif
143!endif
144
145!if "$(MACHINE)" == "IX86"
146### test for pentium errata
147!if [nmakehlp -c -QI0f]
148!message *** Compiler has 'Pentium 0x0f fix'
149COMPILERFLAGS  = $(COMPILERFLAGSS) -QI0f
150!else
151!message *** Compiler does not have 'Pentium 0x0f fix'
152!endif
153!endif
154
155!if "$(MACHINE)" == "IA64"
156### test for Itanium errata
157!if [nmakehlp -c -QIA64_Bx]
158!message *** Compiler has 'B-stepping errata workarounds'
159COMPILERFLAGS   = $(COMPILERFLAGS) -QIA64_Bx
160!else
161!message *** Compiler does not have 'B-stepping errata workarounds'
162!endif
163!endif
164
165!if "$(MACHINE)" == "IX86"
166### test for -align:4096, when align:512 will do.
167!if [nmakehlp -l -opt:nowin98]
168!message *** Linker has 'Win98 alignment problem'
169ALIGN98_HACK	= 1
170!else
171!message *** Linker does not have 'Win98 alignment problem'
172ALIGN98_HACK	= 0
173!endif
174!else
175ALIGN98_HACK	= 0
176!endif
177
178LINKERFLAGS     =
179
180!if [nmakehlp -l -ltcg]
181LINKERFLAGS     =-ltcg
182!endif
183
184#----------------------------------------------------------
185# MSVC8 (ships with Visual Studio 2005) generates a manifest
186# file that we should link into the binaries. This is how.
187#----------------------------------------------------------
188
189_VC_MANIFEST_EMBED_EXE=
190_VC_MANIFEST_EMBED_DLL=
191VCVER=0
192!if ![echo VCVERSION=_MSC_VER > vercl.x] \
193    && ![cl -nologo -TC -P vercl.x $(ERRNULL)]
194!include vercl.i
195!if $(VCVERSION) >= 1500
196VCVER=9
197!elseif $(VCVERSION) >= 1400
198VCVER=8
199!elseif $(VCVERSION) >= 1300
200VCVER=7
201!elseif $(VCVERSION) >= 1200
202VCVER=6
203!endif
204!endif
205
206# Since MSVC8 we must deal with manifest resources.
207!if $(VCVERSION) >= 1400
208_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
209_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
210!endif
211
212#----------------------------------------------------------
213# Decode the options requested.
214#----------------------------------------------------------
215
216!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
217STATIC_BUILD	= 0
218TCL_THREADS	= 1
219DEBUG		= 0
220PROFILE		= 0
221MSVCRT		= 0
222LOIMPACT	= 0
223TCL_USE_STATIC_PACKAGES	= 0
224USE_THREAD_ALLOC = 1
225USE_THREAD_STORAGE = 1
226UNCHECKED       = 0
227!else
228!if [nmakehlp -f $(OPTS) "static"]
229!message *** Doing static
230STATIC_BUILD	= 1
231!else
232STATIC_BUILD	= 0
233!endif
234!if [nmakehlp -f $(OPTS) "msvcrt"]
235!message *** Doing msvcrt
236MSVCRT		= 1
237!else
238MSVCRT		= 0
239!endif
240!if [nmakehlp -f $(OPTS) "staticpkg"]
241!message *** Doing staticpkg
242TCL_USE_STATIC_PACKAGES	= 1
243!else
244TCL_USE_STATIC_PACKAGES	= 0
245!endif
246!if [nmakehlp -f $(OPTS) "nothreads"]
247!message *** Compile explicitly for non-threaded tcl
248TCL_THREADS	= 0
249!else
250TCL_THREADS     = 1
251!endif
252!if [nmakehlp -f $(OPTS) "symbols"]
253!message *** Doing symbols
254DEBUG		= 1
255!else
256DEBUG		= 0
257!endif
258!if [nmakehlp -f $(OPTS) "profile"]
259!message *** Doing profile
260PROFILE		= 1
261!else
262PROFILE		= 0
263!endif
264!if [nmakehlp -f $(OPTS) "loimpact"]
265!message *** Doing loimpact
266LOIMPACT	= 1
267!else
268LOIMPACT	= 0
269!endif
270!if [nmakehlp -f $(OPTS) "thrdalloc"]
271!message *** Doing thrdalloc
272USE_THREAD_ALLOC = 1
273!else
274USE_THREAD_ALLOC = 0
275!endif
276!if [nmakehlp -f $(OPTS) "thrdstorage"]
277!message *** Doing thrdstorage
278USE_THREAD_STORAGE = 1
279!else
280USE_THREAD_STORAGE = 0
281!endif
282!if [nmakehlp -f $(OPTS) "unchecked"]
283!message *** Doing unchecked
284UNCHECKED = 1
285!else
286UNCHECKED = 0
287!endif
288!endif
289
290
291!if !$(STATIC_BUILD)
292# Make sure we don't build overly fat DLLs.
293MSVCRT		= 1
294# We shouldn't statically put the extensions inside the shell when dynamic.
295TCL_USE_STATIC_PACKAGES = 0
296!endif
297
298
299#----------------------------------------------------------
300# Figure-out how to name our intermediate and output directories.
301# We wouldn't want different builds to use the same .obj files
302# by accident.
303#----------------------------------------------------------
304
305#----------------------------------------
306# Naming convention:
307#   t = full thread support.
308#   s = static library (as opposed to an
309#	import library)
310#   g = linked to the debug enabled C
311#	run-time.
312#   x = special static build when it
313#	links to the dynamic C run-time.
314#----------------------------------------
315SUFX	    = sgx
316
317!if $(DEBUG)
318BUILDDIRTOP = Debug
319!else
320BUILDDIRTOP = Release
321!endif
322
323!if "$(MACHINE)" != "IX86"
324BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
325!endif
326!if $(VCVER) > 6
327BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
328!endif
329
330!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED)
331SUFX	    = $(SUFX:g=)
332!endif
333
334TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX
335
336!if !$(STATIC_BUILD)
337TMP_DIRFULL = $(TMP_DIRFULL:Static=)
338SUFX	    = $(SUFX:s=)
339EXT	    = dll
340!if $(MSVCRT)
341TMP_DIRFULL = $(TMP_DIRFULL:X=)
342SUFX	    = $(SUFX:x=)
343!endif
344!else
345TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
346EXT	    = lib
347!if !$(MSVCRT)
348TMP_DIRFULL = $(TMP_DIRFULL:X=)
349SUFX	    = $(SUFX:x=)
350!endif
351!endif
352
353!if !$(TCL_THREADS)
354TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
355SUFX	    = $(SUFX:t=)
356!endif
357
358!ifndef TMP_DIR
359TMP_DIR	    = $(TMP_DIRFULL)
360!ifndef OUT_DIR
361OUT_DIR	    = .\$(BUILDDIRTOP)
362!endif
363!else
364!ifndef OUT_DIR
365OUT_DIR	    = $(TMP_DIR)
366!endif
367!endif
368
369
370#----------------------------------------------------------
371# Decode the statistics requested.
372#----------------------------------------------------------
373
374!if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"]
375TCL_MEM_DEBUG	    = 0
376TCL_COMPILE_DEBUG   = 0
377!else
378!if [nmakehlp -f $(STATS) "memdbg"]
379!message *** Doing memdbg
380TCL_MEM_DEBUG	    = 1
381!else
382TCL_MEM_DEBUG	    = 0
383!endif
384!if [nmakehlp -f $(STATS) "compdbg"]
385!message *** Doing compdbg
386TCL_COMPILE_DEBUG   = 1
387!else
388TCL_COMPILE_DEBUG   = 0
389!endif
390!endif
391
392
393#----------------------------------------------------------
394# Decode the checks requested.
395#----------------------------------------------------------
396
397!if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"]
398TCL_NO_DEPRECATED	    = 0
399WARNINGS		    = -W3
400!else
401!if [nmakehlp -f $(CHECKS) "nodep"]
402!message *** Doing nodep check
403TCL_NO_DEPRECATED	    = 1
404!else
405TCL_NO_DEPRECATED	    = 0
406!endif
407!if [nmakehlp -f $(CHECKS) "fullwarn"]
408!message *** Doing full warnings check
409WARNINGS		    = -W4
410!if [nmakehlp -l -warn:3]
411LINKERFLAGS		    = $(LINKERFLAGS) -warn:3
412!endif
413!else
414WARNINGS		    = -W3
415!endif
416!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
417!message *** Doing 64bit portability warnings
418WARNINGS		    = $(WARNINGS) -Wp64
419!endif
420!endif
421
422#----------------------------------------------------------
423# Set our defines now armed with our options.
424#----------------------------------------------------------
425
426OPTDEFINES	= -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS
427
428!if $(TCL_MEM_DEBUG)
429OPTDEFINES	= $(OPTDEFINES) -DTCL_MEM_DEBUG
430!endif
431!if $(TCL_COMPILE_DEBUG)
432OPTDEFINES	= $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
433!endif
434!if $(TCL_THREADS)
435OPTDEFINES	= $(OPTDEFINES) -DTCL_THREADS=1
436!if $(USE_THREAD_ALLOC)
437OPTDEFINES	= $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
438!endif
439!if $(USE_THREAD_STORAGE)
440OPTDEFINES	= $(OPTDEFINES) -DUSE_THREAD_STORAGE=1
441!endif
442!endif
443!if $(STATIC_BUILD)
444OPTDEFINES	= $(OPTDEFINES) -DSTATIC_BUILD
445!endif
446!if $(TCL_NO_DEPRECATED)
447OPTDEFINES	= $(OPTDEFINES) -DTCL_NO_DEPRECATED
448!endif
449
450!if $(DEBUG)
451OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_DEBUG
452!elseif $(OPTIMIZING)
453OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_OPTIMIZED
454!endif
455!if $(PROFILE)
456OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_PROFILED
457!endif
458!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
459OPTDEFINES	= $(OPTDEFINES) -DTCL_CFG_DO64BIT
460!endif
461
462
463#----------------------------------------------------------
464# Get common info used when building extensions.
465#----------------------------------------------------------
466
467!if "$(PROJECT)" != "tcl"
468
469# If INSTALLDIR set to tcl root dir then reset to the lib dir.
470!if exist("$(_INSTALLDIR)\include\tcl.h")
471_INSTALLDIR=$(_INSTALLDIR)\lib
472!endif
473
474!if !defined(TCLDIR)
475!if exist("$(_INSTALLDIR)\..\include\tcl.h")
476TCLINSTALL	= 1
477_TCLDIR		= $(_INSTALLDIR)\..
478_TCL_H          = $(_INSTALLDIR)\..\include\tcl.h
479TCLDIR          = $(_INSTALLDIR)\..
480!else
481MSG=^
482Failed to find tcl.h.  Set the TCLDIR macro.
483!error $(MSG)
484!endif
485!else
486_TCLDIR	= $(TCLDIR:/=\)
487!if exist("$(_TCLDIR)\include\tcl.h")
488TCLINSTALL	= 1
489_TCL_H          = $(_TCLDIR)\include\tcl.h
490!elseif exist("$(_TCLDIR)\generic\tcl.h")
491TCLINSTALL	= 0
492_TCL_H          = $(_TCLDIR)\generic\tcl.h
493!else
494MSG =^
495Failed to find tcl.h.  The TCLDIR macro does not appear correct.
496!error $(MSG)
497!endif
498!endif
499
500!if [echo REM = This file is generated from rules.vc > version.vc]
501!endif
502!if exist("$(_TCL_H)")
503!if [echo TCL_DOTVERSION = \>> version.vc] \
504   && [nmakehlp -V "$(_TCL_H)" TCL_VERSION >> version.vc]
505!endif
506!endif
507!include version.vc
508TCL_VERSION	= $(TCL_DOTVERSION:.=)
509
510!if $(TCLINSTALL)
511TCLSH		= "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
512!if !exist($(TCLSH)) && $(TCL_THREADS)
513TCLSH           = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe"
514!endif
515TCLSTUBLIB	= "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
516TCLIMPLIB	= "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
517TCL_LIBRARY	= $(_TCLDIR)\lib
518TCL_INCLUDES    = -I"$(_TCLDIR)\include"
519!else
520TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
521!if !exist($(TCLSH)) && $(TCL_THREADS)
522TCLSH		= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe"
523!endif
524TCLSTUBLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
525TCLIMPLIB	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
526TCL_LIBRARY	= $(_TCLDIR)\library
527TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
528!endif
529
530!endif
531
532#----------------------------------------------------------
533# Optionally check for Tk info for building extensions.
534#----------------------------------------------------------
535
536!ifdef PROJECT_REQUIRES_TK
537!if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk"
538
539!if !defined(TKDIR)
540!if exist("$(_INSTALLDIR)\..\include\tk.h")
541TKINSTALL      = 1
542_TKDIR         = $(_INSTALLDIR)\..
543_TK_H          = $(_TKDIR)\include\tk.h
544TKDIR          = $(_TKDIR)
545!elseif exist("$(_TCLDIR)\include\tk.h")
546TKINSTALL      = 1
547_TKDIR         = $(_TCLDIR)
548_TK_H          = $(_TKDIR)\include\tk.h
549TKDIR          = $(_TKDIR)
550!endif
551!else
552_TKDIR = $(TKDIR:/=\)
553!if exist("$(_TKDIR)\include\tk.h")
554TKINSTALL      = 1
555_TK_H          = $(_TKDIR)\include\tk.h
556!elseif exist("$(_TKDIR)\generic\tk.h")
557TKINSTALL      = 0
558_TK_H          = $(_TKDIR)\generic\tk.h
559!else
560MSG =^
561Failed to find tk.h. The TKDIR macro does not appear correct.
562!error $(MSG)
563!endif
564!endif
565
566!if defined(TKDIR)
567TK_DOTVERSION = 8.4
568!if exist("$(_TK_H)")
569!if [echo TK_DOTVERSION = \>> version.vc] \
570   && [nmakehlp -V "$(_TK_H)" TK_VERSION >> version.vc]
571!endif
572!endif
573!include version.vc
574TK_VERSION = $(TK_DOTVERSION:.=)
575
576!if $(TKINSTALL)
577WISH		= "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe"
578!if !exist($(WISH)) && $(TCL_THREADS)
579WISH		= "$(_TKDIR)\bin\wish$(TK_VERSION)t$(SUFX).exe"
580!endif
581TKSTUBLIB	= "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib"
582TKIMPLIB	= "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib"
583TK_INCLUDES     = -I"$(_TKDIR)\include"
584TK_LIBRARY	= $(_TKDIR)\lib
585!else
586WISH		= "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe"
587!if !exist($(WISH)) && $(TCL_THREADS)
588WISH		= "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)t$(SUFX).exe"
589!endif
590TKSTUBLIB	= "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib"
591TKIMPLIB	= "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib"
592TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
593TK_LIBRARY	= $(_TKDIR)\library
594!endif
595
596!endif
597!endif
598!endif
599
600#----------------------------------------------------------
601# Display stats being used.
602#----------------------------------------------------------
603
604!message *** Intermediate directory will be '$(TMP_DIR)'
605!message *** Output directory will be '$(OUT_DIR)'
606!message *** Suffix for binaries will be '$(SUFX)'
607!message *** Optional defines are '$(OPTDEFINES)'
608!message *** Compiler version $(VCVER). Target machine is $(MACHINE)
609!message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)'
610!message *** Link options '$(LINKERFLAGS)'
611
612!endif
613