1#------------------------------------------------------------- -*- makefile -*-
2# rules.vc --
3#
4# Part of the nmake based build system for Tcl and its extensions.
5# This file does all the hard work in terms of parsing build options,
6# compiler switches, defining common targets and macros. The Tcl makefile
7# directly includes this. Extensions include it via "rules-ext.vc".
8#
9# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for
10# detailed documentation.
11#
12# See the file "license.terms" for information on usage and redistribution
13# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14#
15# Copyright (c) 2001-2003 David Gravereaux.
16# Copyright (c) 2003-2008 Patrick Thoyts
17# Copyright (c) 2017      Ashok P. Nadkarni
18#------------------------------------------------------------------------------
19
20!ifndef _RULES_VC
21_RULES_VC = 1
22
23# The following macros define the version of the rules.vc nmake build system
24# For modifications that are not backward-compatible, you *must* change
25# the major version.
26RULES_VERSION_MAJOR = 1
27RULES_VERSION_MINOR = 9
28
29# The PROJECT macro must be defined by parent makefile.
30!if "$(PROJECT)" == ""
31!error *** Error: Macro PROJECT not defined! Please define it before including rules.vc
32!endif
33
34!if "$(PRJ_PACKAGE_TCLNAME)" == ""
35PRJ_PACKAGE_TCLNAME = $(PROJECT)
36!endif
37
38# Also special case Tcl and Tk to save some typing later
39DOING_TCL = 0
40DOING_TK  = 0
41!if "$(PROJECT)" == "tcl"
42DOING_TCL = 1
43!elseif "$(PROJECT)" == "tk"
44DOING_TK = 1
45!endif
46
47!ifndef NEED_TK
48# Backwards compatibility
49!ifdef PROJECT_REQUIRES_TK
50NEED_TK = $(PROJECT_REQUIRES_TK)
51!else
52NEED_TK = 0
53!endif
54!endif
55
56!ifndef NEED_TCL_SOURCE
57NEED_TCL_SOURCE = 0
58!endif
59
60!ifdef NEED_TK_SOURCE
61!if $(NEED_TK_SOURCE)
62NEED_TK = 1
63!endif
64!else
65NEED_TK_SOURCE = 0
66!endif
67
68################################################################
69# Nmake is a pretty weak environment in syntax and capabilities
70# so this file is necessarily verbose. It's broken down into
71# the following parts.
72#
73# 0. Sanity check that compiler environment is set up and initialize
74#    any built-in settings from the parent makefile
75# 1. First define the external tools used for compiling, copying etc.
76#    as this is independent of everything else.
77# 2. Figure out our build structure in terms of the directory, whether
78#    we are building Tcl or an extension, etc.
79# 3. Determine the compiler and linker versions
80# 4. Build the nmakehlp helper application
81# 5. Determine the supported compiler options and features
82# 6. Parse the OPTS macro value for user-specified build configuration
83# 7. Parse the STATS macro value for statistics instrumentation
84# 8. Parse the CHECKS macro for additional compilation checks
85# 9. Extract Tcl, and possibly Tk, version numbers from the headers
86# 10. Based on this selected configuration, construct the output
87#     directory and file paths
88# 11. Construct the paths where the package is to be installed
89# 12. Set up the actual options passed to compiler and linker based
90#     on the information gathered above.
91# 13. Define some standard build targets and implicit rules. These may
92#     be optionally disabled by the parent makefile.
93# 14. (For extensions only.) Compare the configuration of the target
94#     Tcl and the extensions and warn against discrepancies.
95#
96# One final note about the macro names used. They are as they are
97# for historical reasons. We would like legacy extensions to
98# continue to work with this make include file so be wary of
99# changing them for consistency or clarity.
100
101# 0. Sanity check compiler environment
102
103# Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or
104# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir)
105
106!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR)
107MSG = ^
108Visual C++ compiler environment not initialized.
109!error $(MSG)
110!endif
111
112# We need to run from the directory the parent makefile is located in.
113# nmake does not tell us what makefile was used to invoke it so parent
114# makefile has to set the MAKEFILEVC macro or we just make a guess and
115# warn if we think that is not the case.
116!if "$(MAKEFILEVC)" == ""
117
118!if exist("$(PROJECT).vc")
119MAKEFILEVC = $(PROJECT).vc
120!elseif exist("makefile.vc")
121MAKEFILEVC = makefile.vc
122!endif
123!endif # "$(MAKEFILEVC)" == ""
124
125!if !exist("$(MAKEFILEVC)")
126MSG = ^
127You must run nmake from the directory containing the project makefile.^
128If you are doing that and getting this message, set the MAKEFILEVC^
129macro to the name of the project makefile.
130!message WARNING: $(MSG)
131!endif
132
133
134################################################################
135# 1. Define external programs being used
136
137#----------------------------------------------------------
138# Set the proper copy method to avoid overwrite questions
139# to the user when copying files and selecting the right
140# "delete all" method.
141#----------------------------------------------------------
142
143RMDIR	= rmdir /S /Q
144CPY	= xcopy /i /y >NUL
145CPYDIR  = xcopy /e /i /y >NUL
146COPY	= copy /y >NUL
147MKDIR   = mkdir
148
149######################################################################
150# 2. Figure out our build environment in terms of what we're building.
151#
152# (a) Tcl itself
153# (b) Tk
154# (c) a Tcl extension using libraries/includes from an *installed* Tcl
155# (d) a Tcl extension using libraries/includes from Tcl source directory
156#
157# This last is needed because some extensions still need
158# some Tcl interfaces that are not publicly exposed.
159#
160# The fragment will set the following macros:
161# ROOT - root of this module sources
162# COMPATDIR - source directory that holds compatibility sources
163# DOCDIR - source directory containing documentation files
164# GENERICDIR - platform-independent source directory
165# WIN_DIR - Windows-specific source directory
166# TESTDIR - directory containing test files
167# TOOLSDIR - directory containing build tools
168# _TCLDIR - root of the Tcl installation OR the Tcl sources. Not set
169#    when building Tcl itself.
170# _INSTALLDIR - native form of the installation path. For Tcl
171#    this will be the root of the Tcl installation. For extensions
172#    this will be the lib directory under the root.
173# TCLINSTALL  - set to 1 if _TCLDIR refers to
174#    headers and libraries from an installed Tcl, and 0 if built against
175#    Tcl sources. Not set when building Tcl itself. Yes, not very well
176#    named.
177# _TCL_H - native path to the tcl.h file
178#
179# If Tk is involved, also sets the following
180# _TKDIR - native form Tk installation OR Tk source. Not set if building
181#    Tk itself.
182# TKINSTALL - set 1 if _TKDIR refers to installed Tk and 0 if Tk sources
183# _TK_H - native path to the tk.h file
184
185# Root directory for sources and assumed subdirectories
186ROOT = $(MAKEDIR)\..
187# The following paths CANNOT have spaces in them as they appear on the
188# left side of implicit rules.
189!ifndef COMPATDIR
190COMPATDIR	= $(ROOT)\compat
191!endif
192!ifndef DOCDIR
193DOCDIR		= $(ROOT)\doc
194!endif
195!ifndef GENERICDIR
196GENERICDIR	= $(ROOT)\generic
197!endif
198!ifndef TOOLSDIR
199TOOLSDIR	= $(ROOT)\tools
200!endif
201!ifndef TESTDIR
202TESTDIR	= $(ROOT)\tests
203!endif
204!ifndef LIBDIR
205!if exist("$(ROOT)\library")
206LIBDIR          = $(ROOT)\library
207!else
208LIBDIR          = $(ROOT)\lib
209!endif
210!endif
211!ifndef DEMODIR
212!if exist("$(LIBDIR)\demos")
213DEMODIR		= $(LIBDIR)\demos
214!else
215DEMODIR		= $(ROOT)\demos
216!endif
217!endif # ifndef DEMODIR
218# Do NOT use WINDIR because it is Windows internal environment
219# variable to point to c:\windows!
220WIN_DIR		= $(ROOT)\win
221
222!ifndef RCDIR
223!if exist("$(WIN_DIR)\rc")
224RCDIR           = $(WIN_DIR)\rc
225!else
226RCDIR           = $(WIN_DIR)
227!endif
228!endif
229RCDIR = $(RCDIR:/=\)
230
231# The target directory where the built packages and binaries will be installed.
232# INSTALLDIR is the (optional) path specified by the user.
233# _INSTALLDIR is INSTALLDIR using the backslash separator syntax
234!ifdef INSTALLDIR
235### Fix the path separators.
236_INSTALLDIR	= $(INSTALLDIR:/=\)
237!else
238### Assume the normal default.
239_INSTALLDIR	= $(HOMEDRIVE)\Tcl
240!endif
241
242!if $(DOING_TCL)
243
244# BEGIN Case 2(a) - Building Tcl itself
245
246# Only need to define _TCL_H
247_TCL_H = ..\generic\tcl.h
248
249# END Case 2(a) - Building Tcl itself
250
251!elseif $(DOING_TK)
252
253# BEGIN Case 2(b) - Building Tk
254
255TCLINSTALL = 0 # Tk always builds against Tcl source, not an installed Tcl
256!if "$(TCLDIR)" == ""
257!if [echo TCLDIR = \> nmakehlp.out] \
258   || [nmakehlp -L generic\tcl.h >> nmakehlp.out]
259!error *** Could not locate Tcl source directory.
260!endif
261!include nmakehlp.out
262!endif # TCLDIR == ""
263
264_TCLDIR	= $(TCLDIR:/=\)
265_TCL_H  = $(_TCLDIR)\generic\tcl.h
266!if !exist("$(_TCL_H)")
267!error Could not locate tcl.h. Please set the TCLDIR macro to point to the Tcl *source* directory.
268!endif
269
270_TK_H = ..\generic\tk.h
271
272# END Case 2(b) - Building Tk
273
274!else
275
276# BEGIN Case 2(c) or (d) - Building an extension other than Tk
277
278# If command line has specified Tcl location through TCLDIR, use it
279# else default to the INSTALLDIR setting
280!if "$(TCLDIR)" != ""
281
282_TCLDIR	= $(TCLDIR:/=\)
283!if exist("$(_TCLDIR)\include\tcl.h") # Case 2(c) with TCLDIR defined
284TCLINSTALL	= 1
285_TCL_H          = $(_TCLDIR)\include\tcl.h
286!elseif exist("$(_TCLDIR)\generic\tcl.h") # Case 2(d) with TCLDIR defined
287TCLINSTALL	= 0
288_TCL_H          = $(_TCLDIR)\generic\tcl.h
289!endif
290
291!else  #  # Case 2(c) for extensions with TCLDIR undefined
292
293# Need to locate Tcl depending on whether it needs Tcl source or not.
294# If we don't, check the INSTALLDIR for an installed Tcl first
295
296!if exist("$(_INSTALLDIR)\include\tcl.h") && !$(NEED_TCL_SOURCE)
297
298TCLINSTALL	= 1
299TCLDIR          = $(_INSTALLDIR)\..
300# NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions
301# later so the \.. accounts for the /lib
302_TCLDIR		= $(_INSTALLDIR)\..
303_TCL_H          = $(_TCLDIR)\include\tcl.h
304
305!else # exist(...) && !$(NEED_TCL_SOURCE)
306
307!if [echo _TCLDIR = \> nmakehlp.out] \
308   || [nmakehlp -L generic\tcl.h >> nmakehlp.out]
309!error *** Could not locate Tcl source directory.
310!endif
311!include nmakehlp.out
312TCLINSTALL      = 0
313TCLDIR         = $(_TCLDIR)
314_TCL_H          = $(_TCLDIR)\generic\tcl.h
315
316!endif # exist(...) && !$(NEED_TCL_SOURCE)
317
318!endif # TCLDIR
319
320!ifndef _TCL_H
321MSG =^
322Failed to find tcl.h. The TCLDIR macro is set incorrectly or is not set and default path does not contain tcl.h.
323!error $(MSG)
324!endif
325
326# Now do the same to locate Tk headers and libs if project requires Tk
327!if $(NEED_TK)
328
329!if "$(TKDIR)" != ""
330
331_TKDIR = $(TKDIR:/=\)
332!if exist("$(_TKDIR)\include\tk.h")
333TKINSTALL      = 1
334_TK_H          = $(_TKDIR)\include\tk.h
335!elseif exist("$(_TKDIR)\generic\tk.h")
336TKINSTALL      = 0
337_TK_H          = $(_TKDIR)\generic\tk.h
338!endif
339
340!else # TKDIR not defined
341
342# Need to locate Tcl depending on whether it needs Tcl source or not.
343# If we don't, check the INSTALLDIR for an installed Tcl first
344
345!if exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE)
346
347TKINSTALL      = 1
348# NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions
349# later so the \.. accounts for the /lib
350_TKDIR         = $(_INSTALLDIR)\..
351_TK_H          = $(_TKDIR)\include\tk.h
352TKDIR          = $(_TKDIR)
353
354!else # exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE)
355
356!if [echo _TKDIR = \> nmakehlp.out] \
357   || [nmakehlp -L generic\tk.h >> nmakehlp.out]
358!error *** Could not locate Tk source directory.
359!endif
360!include nmakehlp.out
361TKINSTALL      = 0
362TKDIR          = $(_TKDIR)
363_TK_H          = $(_TKDIR)\generic\tk.h
364
365!endif # exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE)
366
367!endif # TKDIR
368
369!ifndef _TK_H
370MSG =^
371Failed to find tk.h. The TKDIR macro is set incorrectly or is not set and default path does not contain tk.h.
372!error $(MSG)
373!endif
374
375!endif # NEED_TK
376
377!if $(NEED_TCL_SOURCE) && $(TCLINSTALL)
378MSG = ^
379*** Warning: This extension requires the source distribution of Tcl.^
380*** Please set the TCLDIR macro to point to the Tcl sources.
381!error $(MSG)
382!endif
383
384!if $(NEED_TK_SOURCE)
385!if $(TKINSTALL)
386MSG = ^
387*** Warning: This extension requires the source distribution of Tk.^
388*** Please set the TKDIR macro to point to the Tk sources.
389!error $(MSG)
390!endif
391!endif
392
393
394# If INSTALLDIR set to Tcl installation root dir then reset to the
395# lib dir for installing extensions
396!if exist("$(_INSTALLDIR)\include\tcl.h")
397_INSTALLDIR=$(_INSTALLDIR)\lib
398!endif
399
400# END Case 2(c) or (d) - Building an extension
401!endif # if $(DOING_TCL)
402
403################################################################
404# 3. Determine compiler version and architecture
405# In this section, we figure out the compiler version and the
406# architecture for which we are building. This sets the
407# following macros:
408# VCVERSION - the internal compiler version as 1200, 1400, 1910 etc.
409#     This is also printed by the compiler in dotted form 19.10 etc.
410# VCVER - the "marketing version", for example Visual C++ 6 for internal
411#     compiler version 1200. This is kept only for legacy reasons as it
412#     does not make sense for recent Microsoft compilers. Only used for
413#     output directory names.
414# ARCH - set to IX86 or AMD64 depending on 32- or 64-bit target
415# NATIVE_ARCH - set to IX86 or AMD64 for the host machine
416# MACHINE - same as $(ARCH) - legacy
417# _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed
418
419cc32		= $(CC)   # built-in default.
420link32		= link
421lib32		= lib
422rc32		= $(RC)   # built-in default.
423
424#----------------------------------------------------------------
425# Figure out the compiler architecture and version by writing
426# the C macros to a file, preprocessing them with the C
427# preprocessor and reading back the created file
428
429_HASH=^#
430_VC_MANIFEST_EMBED_EXE=
431_VC_MANIFEST_EMBED_DLL=
432VCVER=0
433!if ![echo VCVERSION=_MSC_VER > vercl.x] \
434    && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
435    && ![echo ARCH=IX86 >> vercl.x] \
436    && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
437    && ![echo ARCH=AMD64 >> vercl.x] \
438    && ![echo $(_HASH)endif >> vercl.x] \
439    && ![$(cc32) -nologo -TC -P vercl.x 2>NUL]
440!include vercl.i
441!if $(VCVERSION) < 1900
442!if ![echo VCVER= ^\> vercl.vc] \
443    && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
444!include vercl.vc
445!endif
446!else
447# The simple calculation above does not apply to new Visual Studio releases
448# Keep the compiler version in its native form.
449VCVER = $(VCVERSION)
450!endif
451!endif
452
453!if ![del 2>NUL /q/f vercl.x vercl.i vercl.vc]
454!endif
455
456#----------------------------------------------------------------
457# The MACHINE macro is used by legacy makefiles so set it as well
458!ifdef MACHINE
459!if "$(MACHINE)" == "x86"
460!undef MACHINE
461MACHINE = IX86
462!elseif "$(MACHINE)" == "x64"
463!undef MACHINE
464MACHINE = AMD64
465!endif
466!if "$(MACHINE)" != "$(ARCH)"
467!error Specified MACHINE macro $(MACHINE) does not match detected target architecture $(ARCH).
468!endif
469!else
470MACHINE=$(ARCH)
471!endif
472
473#---------------------------------------------------------------
474# The PLATFORM_IDENTIFY macro matches the values returned by
475# the Tcl platform::identify command
476!if "$(MACHINE)" == "AMD64"
477PLATFORM_IDENTIFY = win32-x86_64
478!else
479PLATFORM_IDENTIFY = win32-ix86
480!endif
481
482# The MULTIPLATFORM macro controls whether binary extensions are installed
483# in platform-specific directories. Intended to be set/used by extensions.
484!ifndef MULTIPLATFORM_INSTALL
485MULTIPLATFORM_INSTALL = 0
486!endif
487
488#------------------------------------------------------------
489# Figure out the *host* architecture by reading the registry
490
491!if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86]
492NATIVE_ARCH=IX86
493!else
494NATIVE_ARCH=AMD64
495!endif
496
497# Since MSVC8 we must deal with manifest resources.
498!if $(VCVERSION) >= 1400
499_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
500_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
501!endif
502
503################################################################
504# 4. Build the nmakehlp program
505# This is a helper app we need to overcome nmake's limiting
506# environment. We will call out to it to get various bits of
507# information about supported compiler options etc.
508#
509# Tcl itself will always use the nmakehlp.c program which is
510# in its own source. It will be kept updated there.
511#
512# Extensions built against an installed Tcl will use the installed
513# copy of Tcl's nmakehlp.c if there is one and their own version
514# otherwise. In the latter case, they would also be using their own
515# rules.vc. Note that older versions of Tcl do not install nmakehlp.c
516# or rules.vc.
517#
518# Extensions built against Tcl sources will use the one from the Tcl source.
519#
520# When building an extension using a sufficiently new version of Tcl,
521# rules-ext.vc will define NMAKEHLPC appropriately to point to the
522# copy of nmakehlp.c to be used.
523
524!ifndef NMAKEHLPC
525# Default to the one in the current directory (the extension's own nmakehlp.c)
526NMAKEHLPC = nmakehlp.c
527
528!if !$(DOING_TCL)
529!if $(TCLINSTALL)
530!if exist("$(_TCLDIR)\lib\nmake\nmakehlp.c")
531NMAKEHLPC = $(_TCLDIR)\lib\nmake\nmakehlp.c
532!endif
533!else # !$(TCLINSTALL)
534!if exist("$(_TCLDIR)\win\nmakehlp.c")
535NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c
536!endif
537!endif # $(TCLINSTALL)
538!endif # !$(DOING_TCL)
539
540!endif # NMAKEHLPC
541
542# We always build nmakehlp even if it exists since we do not know
543# what source it was built from.
544!if [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul]
545!endif
546
547################################################################
548# 5. Test for compiler features
549# Visual C++ compiler options have changed over the years. Check
550# which options are supported by the compiler in use.
551#
552# The following macros are set:
553# OPTIMIZATIONS - the compiler flags to be used for optimized builds
554# DEBUGFLAGS - the compiler flags to be used for debug builds
555# LINKERFLAGS - Flags passed to the linker
556#
557# Note that these are the compiler settings *available*, not those
558# that will be *used*. The latter depends on the OPTS macro settings
559# which we have not yet parsed.
560#
561# Also note that some of the flags in OPTIMIZATIONS are not really
562# related to optimization. They are placed there only for legacy reasons
563# as some extensions expect them to be included in that macro.
564
565# -Op improves float consistency. Note only needed for older compilers
566# Newer compilers do not need or support this option.
567!if [nmakehlp -c -Op]
568FPOPTS  = -Op
569!endif
570
571# Strict floating point semantics - present in newer compilers in lieu of -Op
572!if [nmakehlp -c -fp:strict]
573FPOPTS  = $(FPOPTS) -fp:strict
574!endif
575
576!if "$(MACHINE)" == "IX86"
577### test for pentium errata
578!if [nmakehlp -c -QI0f]
579!message *** Compiler has 'Pentium 0x0f fix'
580FPOPTS  = $(FPOPTS) -QI0f
581!else
582!message *** Compiler does not have 'Pentium 0x0f fix'
583!endif
584!endif
585
586### test for optimizations
587# /O2 optimization includes /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy as per
588# documentation. Note we do NOT want /Gs as that inserts a _chkstk
589# stack probe at *every* function entry, not just those with more than
590# a page of stack allocation resulting in a performance hit.  However,
591# /O2 documentation is misleading as its stack probes are simply the
592# default page size locals allocation probes and not what is implied
593# by an explicit /Gs option.
594
595OPTIMIZATIONS = $(FPOPTS)
596
597!if [nmakehlp -c -O2]
598OPTIMIZING = 1
599OPTIMIZATIONS   = $(OPTIMIZATIONS) -O2
600!else
601# Legacy, really. All modern compilers support this
602!message *** Compiler does not have 'Optimizations'
603OPTIMIZING = 0
604!endif
605
606# Checks for buffer overflows in local arrays
607!if [nmakehlp -c -GS]
608OPTIMIZATIONS  = $(OPTIMIZATIONS) -GS
609!endif
610
611# Link time optimization. Note that this option (potentially) makes
612# generated libraries only usable by the specific VC++ version that
613# created it. Requires /LTCG linker option
614!if [nmakehlp -c -GL]
615OPTIMIZATIONS  = $(OPTIMIZATIONS) -GL
616CC_GL_OPT_ENABLED = 1
617!else
618# In newer compilers -GL and -YX are incompatible.
619!if [nmakehlp -c -YX]
620OPTIMIZATIONS  = $(OPTIMIZATIONS) -YX
621!endif
622!endif # [nmakehlp -c -GL]
623
624DEBUGFLAGS     = $(FPOPTS)
625
626# Run time error checks. Not available or valid in a release, non-debug build
627# RTC is for modern compilers, -GZ is legacy
628!if [nmakehlp -c -RTC1]
629DEBUGFLAGS     = $(DEBUGFLAGS) -RTC1
630!elseif [nmakehlp -c -GZ]
631DEBUGFLAGS     = $(DEBUGFLAGS) -GZ
632!endif
633
634#----------------------------------------------------------------
635# Linker flags
636
637# LINKER_TESTFLAGS are for internal use when we call nmakehlp to test
638# if the linker supports a specific option. Without these flags link will
639# return "LNK1561: entry point must be defined" error compiling from VS-IDE:
640# They are not passed through to the actual application / extension
641# link rules.
642!ifndef LINKER_TESTFLAGS
643LINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmakehlp.out
644!endif
645
646LINKERFLAGS     =
647
648# If compiler has enabled link time optimization, linker must too with -ltcg
649!ifdef CC_GL_OPT_ENABLED
650!if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)]
651LINKERFLAGS     = $(LINKERFLAGS) -ltcg
652!endif
653!endif
654
655
656################################################################
657# 6. Extract various version numbers from headers
658# For Tcl and Tk, version numbers are extracted from tcl.h and tk.h
659# respectively. For extensions, versions are extracted from the
660# configure.in or configure.ac from the TEA configuration if it
661# exists, and unset otherwise.
662# Sets the following macros:
663# TCL_MAJOR_VERSION
664# TCL_MINOR_VERSION
665# TCL_RELEASE_SERIAL
666# TCL_PATCH_LEVEL
667# TCL_PATCH_LETTER
668# TCL_VERSION
669# TK_MAJOR_VERSION
670# TK_MINOR_VERSION
671# TK_RELEASE_SERIAL
672# TK_PATCH_LEVEL
673# TK_PATCH_LETTER
674# TK_VERSION
675# DOTVERSION - set as (for example) 2.5
676# VERSION - set as (for example 25)
677#--------------------------------------------------------------
678
679!if [echo REM = This file is generated from rules.vc > versions.vc]
680!endif
681!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
682   && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
683!endif
684!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
685   && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
686!endif
687!if [echo TCL_RELEASE_SERIAL = \>> versions.vc] \
688   && [nmakehlp -V "$(_TCL_H)" TCL_RELEASE_SERIAL >> versions.vc]
689!endif
690!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
691   && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
692!endif
693
694!if defined(_TK_H)
695!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
696   && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
697!endif
698!if [echo TK_MINOR_VERSION = \>> versions.vc] \
699   && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
700!endif
701!if [echo TK_RELEASE_SERIAL = \>> versions.vc] \
702   && [nmakehlp -V "$(_TK_H)" TK_RELEASE_SERIAL >> versions.vc]
703!endif
704!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
705   && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
706!endif
707!endif # _TK_H
708
709!include versions.vc
710
711TCL_VERSION	= $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
712TCL_DOTVERSION	= $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
713!if [nmakehlp -f $(TCL_PATCH_LEVEL) "a"]
714TCL_PATCH_LETTER = a
715!elseif [nmakehlp -f $(TCL_PATCH_LEVEL) "b"]
716TCL_PATCH_LETTER = b
717!else
718TCL_PATCH_LETTER = .
719!endif
720
721!if defined(_TK_H)
722
723TK_VERSION	= $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
724TK_DOTVERSION	= $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
725!if [nmakehlp -f $(TK_PATCH_LEVEL) "a"]
726TK_PATCH_LETTER = a
727!elseif [nmakehlp -f $(TK_PATCH_LEVEL) "b"]
728TK_PATCH_LETTER = b
729!else
730TK_PATCH_LETTER = .
731!endif
732
733!endif
734
735# Set DOTVERSION and VERSION
736!if $(DOING_TCL)
737
738DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
739VERSION = $(TCL_VERSION)
740
741!elseif $(DOING_TK)
742
743DOTVERSION = $(TK_DOTVERSION)
744VERSION = $(TK_VERSION)
745
746!else # Doing a non-Tk extension
747
748# If parent makefile has not defined DOTVERSION, try to get it from TEA
749# first from a configure.in file, and then from configure.ac
750!ifndef DOTVERSION
751!if [echo DOTVERSION = \> versions.vc] \
752   || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc]
753!if [echo DOTVERSION = \> versions.vc] \
754   || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc]
755!error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc.
756!endif
757!endif
758!include versions.vc
759!endif # DOTVERSION
760VERSION         = $(DOTVERSION:.=)
761
762!endif # $(DOING_TCL) ... etc.
763
764# Windows RC files have 3 version components. Ensure this irrespective
765# of how many components the package has specified. Basically, ensure
766# minimum 4 components by appending 4 0's and then pick out the first 4.
767# Also take care of the fact that DOTVERSION may have "a" or "b" instead
768# of "." separating the version components.
769DOTSEPARATED=$(DOTVERSION:a=.)
770DOTSEPARATED=$(DOTSEPARATED:b=.)
771!if [echo RCCOMMAVERSION = \> versions.vc] \
772  || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc]
773!error *** Could not generate RCCOMMAVERSION ***
774!endif
775!include versions.vc
776
777########################################################################
778# 7. Parse the OPTS macro to work out the requested build configuration.
779# Based on this, we will construct the actual switches to be passed to the
780# compiler and linker using the macros defined in the previous section.
781# The following macros are defined by this section based on OPTS
782# STATIC_BUILD - 0 -> Tcl is to be built as a shared library
783#                1 -> build as a static library and shell
784# TCL_THREADS - legacy but always 1 on Windows since winsock requires it.
785# DEBUG - 1 -> debug build, 0 -> release builds
786# SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's
787# PROFILE - 1 -> generate profiling info, 0 -> no profiling
788# PGO     - 1 -> profile based optimization, 0 -> no
789# MSVCRT  - 1 -> link to dynamic C runtime even when building static Tcl build
790#           0 -> link to static C runtime for static Tcl build.
791#           Does not impact shared Tcl builds (STATIC_BUILD == 0)
792#           Default: 1 for Tcl 8.7 and up, 0 otherwise.
793# TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions
794#           in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does
795#           not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 8.7.
796# USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation.
797#           0 -> Use the non-thread allocator.
798# UNCHECKED - 1 -> when doing a debug build with symbols, use the release
799#           C runtime, 0 -> use the debug C runtime.
800# USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking
801# CONFIG_CHECK - 1 -> check current build configuration against Tcl
802#           configuration (ignored for Tcl itself)
803# _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build
804#           (CRT library should support this, not needed for Tcl 9.x)
805# TCL_UTF_MAX=4 - forces a build allowing 4-byte UTF-8 sequences internally.
806#           (Not needed for Tcl 9.x)
807# Further, LINKERFLAGS are modified based on above.
808
809# Default values for all the above
810STATIC_BUILD	= 0
811TCL_THREADS	= 1
812DEBUG		= 0
813SYMBOLS		= 0
814PROFILE		= 0
815PGO		= 0
816MSVCRT		= 1
817TCL_USE_STATIC_PACKAGES	= 0
818USE_THREAD_ALLOC = 1
819UNCHECKED	= 0
820CONFIG_CHECK    = 1
821!if $(DOING_TCL)
822USE_STUBS       = 0
823!else
824USE_STUBS       = 1
825!endif
826
827# If OPTS is not empty AND does not contain "none" which turns off all OPTS
828# set the above macros based on OPTS content
829!if "$(OPTS)" != "" && ![nmakehlp -f "$(OPTS)" "none"]
830
831# OPTS are specified, parse them
832
833!if [nmakehlp -f $(OPTS) "static"]
834!message *** Doing static
835STATIC_BUILD	= 1
836!endif
837
838!if [nmakehlp -f $(OPTS) "nostubs"]
839!message *** Not using stubs
840USE_STUBS	= 0
841!endif
842
843!if [nmakehlp -f $(OPTS) "nomsvcrt"]
844!message *** Doing nomsvcrt
845MSVCRT		= 0
846!else
847!if [nmakehlp -f $(OPTS) "msvcrt"]
848!message *** Doing msvcrt
849!else
850!if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7 && $(STATIC_BUILD)
851MSVCRT		= 0
852!endif
853!endif
854!endif # [nmakehlp -f $(OPTS) "nomsvcrt"]
855
856!if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD)
857!message *** Doing staticpkg
858TCL_USE_STATIC_PACKAGES	= 1
859!endif
860
861!if [nmakehlp -f $(OPTS) "nothreads"]
862!message *** Compile explicitly for non-threaded tcl
863TCL_THREADS = 0
864USE_THREAD_ALLOC= 0
865!endif
866
867!if $(TCL_MAJOR_VERSION) == 8
868!if [nmakehlp -f $(OPTS) "time64bit"]
869!message *** Force 64-bit time_t
870_USE_64BIT_TIME_T = 1
871!endif
872
873!if [nmakehlp -f $(OPTS) "utfmax"]
874!message *** Force allowing 4-byte UTF-8 sequences internally
875TCL_UTF_MAX = 4
876!endif
877!endif
878
879# Yes, it's weird that the "symbols" option controls DEBUG and
880# the "pdbs" option controls SYMBOLS. That's historical.
881!if [nmakehlp -f $(OPTS) "symbols"]
882!message *** Doing symbols
883DEBUG		= 1
884!else
885DEBUG		= 0
886!endif
887
888!if [nmakehlp -f $(OPTS) "pdbs"]
889!message *** Doing pdbs
890SYMBOLS		= 1
891!else
892SYMBOLS		= 0
893!endif
894
895!if [nmakehlp -f $(OPTS) "profile"]
896!message *** Doing profile
897PROFILE		= 1
898!else
899PROFILE		= 0
900!endif
901
902!if [nmakehlp -f $(OPTS) "pgi"]
903!message *** Doing profile guided optimization instrumentation
904PGO		= 1
905!elseif [nmakehlp -f $(OPTS) "pgo"]
906!message *** Doing profile guided optimization
907PGO		= 2
908!else
909PGO		= 0
910!endif
911
912!if [nmakehlp -f $(OPTS) "loimpact"]
913!message *** Warning: ignoring option "loimpact" - deprecated on modern Windows.
914!endif
915
916# TBD - should get rid of this option
917!if [nmakehlp -f $(OPTS) "thrdalloc"]
918!message *** Doing thrdalloc
919USE_THREAD_ALLOC = 1
920!endif
921
922!if [nmakehlp -f $(OPTS) "tclalloc"]
923USE_THREAD_ALLOC = 0
924!endif
925
926!if [nmakehlp -f $(OPTS) "unchecked"]
927!message *** Doing unchecked
928UNCHECKED = 1
929!else
930UNCHECKED = 0
931!endif
932
933!if [nmakehlp -f $(OPTS) "noconfigcheck"]
934CONFIG_CHECK = 1
935!else
936CONFIG_CHECK = 0
937!endif
938
939!endif # "$(OPTS)" != ""  && ... parsing of OPTS
940
941# Set linker flags based on above
942
943!if $(PGO) > 1
944!if [nmakehlp -l -ltcg:pgoptimize $(LINKER_TESTFLAGS)]
945LINKERFLAGS	= $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize
946!else
947MSG=^
948This compiler does not support profile guided optimization.
949!error $(MSG)
950!endif
951!elseif $(PGO) > 0
952!if [nmakehlp -l -ltcg:pginstrument $(LINKER_TESTFLAGS)]
953LINKERFLAGS	= $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument
954!else
955MSG=^
956This compiler does not support profile guided optimization.
957!error $(MSG)
958!endif
959!endif
960
961################################################################
962# 8. Parse the STATS macro to configure code instrumentation
963# The following macros are set by this section:
964# TCL_MEM_DEBUG - 1 -> enables memory allocation instrumentation
965#                 0 -> disables
966# TCL_COMPILE_DEBUG - 1 -> enables byte compiler logging
967#                     0 -> disables
968
969# Default both are off
970TCL_MEM_DEBUG	    = 0
971TCL_COMPILE_DEBUG   = 0
972
973!if "$(STATS)" != "" && ![nmakehlp -f "$(STATS)" "none"]
974
975!if [nmakehlp -f $(STATS) "memdbg"]
976!message *** Doing memdbg
977TCL_MEM_DEBUG	    = 1
978!else
979TCL_MEM_DEBUG	    = 0
980!endif
981
982!if [nmakehlp -f $(STATS) "compdbg"]
983!message *** Doing compdbg
984TCL_COMPILE_DEBUG   = 1
985!else
986TCL_COMPILE_DEBUG   = 0
987!endif
988
989!endif
990
991####################################################################
992# 9. Parse the CHECKS macro to configure additional compiler checks
993# The following macros are set by this section:
994# WARNINGS - compiler switches that control the warnings level
995# TCL_NO_DEPRECATED - 1 -> disable support for deprecated functions
996#                     0 -> enable deprecated functions
997
998# Defaults - Permit deprecated functions and warning level 3
999TCL_NO_DEPRECATED	    = 0
1000WARNINGS		    = -W3
1001
1002!if "$(CHECKS)" != "" && ![nmakehlp -f "$(CHECKS)" "none"]
1003
1004!if [nmakehlp -f $(CHECKS) "nodep"]
1005!message *** Doing nodep check
1006TCL_NO_DEPRECATED	    = 1
1007!endif
1008
1009!if [nmakehlp -f $(CHECKS) "fullwarn"]
1010!message *** Doing full warnings check
1011WARNINGS		    = -W4
1012!if [nmakehlp -l -warn:3 $(LINKER_TESTFLAGS)]
1013LINKERFLAGS		    = $(LINKERFLAGS) -warn:3
1014!endif
1015!endif
1016
1017!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
1018!message *** Doing 64bit portability warnings
1019WARNINGS		    = $(WARNINGS) -Wp64
1020!endif
1021
1022!endif
1023
1024
1025################################################################
1026# 10. Construct output directory and file paths
1027# Figure-out how to name our intermediate and output directories.
1028# In order to avoid inadvertent mixing of object files built using
1029# different compilers, build configurations etc.,
1030#
1031# Naming convention (suffixes):
1032#   t = full thread support. (Not used for Tcl >= 8.7)
1033#   s = static library (as opposed to an import library)
1034#   g = linked to the debug enabled C run-time.
1035#   x = special static build when it links to the dynamic C run-time.
1036#
1037# The following macros are set in this section:
1038# SUFX - the suffix to use for binaries based on above naming convention
1039# BUILDDIRTOP - the toplevel default output directory
1040#      is of the form {Release,Debug}[_AMD64][_COMPILERVERSION]
1041# TMP_DIR - directory where object files are created
1042# OUT_DIR - directory where output executables are created
1043# Both TMP_DIR and OUT_DIR are defaulted only if not defined by the
1044# parent makefile (or command line). The default values are
1045# based on BUILDDIRTOP.
1046# STUBPREFIX - name of the stubs library for this project
1047# PRJIMPLIB - output path of the generated project import library
1048# PRJLIBNAME - name of generated project library
1049# PRJLIB     - output path of generated project library
1050# PRJSTUBLIBNAME - name of the generated project stubs library
1051# PRJSTUBLIB - output path of the generated project stubs library
1052# RESFILE - output resource file (only if not static build)
1053
1054SUFX	    = tsgx
1055
1056!if $(DEBUG)
1057BUILDDIRTOP = Debug
1058!else
1059BUILDDIRTOP = Release
1060!endif
1061
1062!if "$(MACHINE)" != "IX86"
1063BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
1064!endif
1065!if $(VCVER) > 6
1066BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
1067!endif
1068
1069!if !$(DEBUG) || $(TCL_VERSION) > 86 || $(DEBUG) && $(UNCHECKED)
1070SUFX	    = $(SUFX:g=)
1071!endif
1072
1073TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX
1074
1075!if !$(STATIC_BUILD)
1076TMP_DIRFULL = $(TMP_DIRFULL:Static=)
1077SUFX	    = $(SUFX:s=)
1078EXT	    = dll
1079TMP_DIRFULL = $(TMP_DIRFULL:X=)
1080SUFX	    = $(SUFX:x=)
1081!else
1082TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
1083EXT	    = lib
1084!if !$(MSVCRT)
1085TMP_DIRFULL = $(TMP_DIRFULL:X=)
1086SUFX	    = $(SUFX:x=)
1087!endif
1088!endif
1089
1090!if !$(TCL_THREADS) || $(TCL_VERSION) > 86
1091TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
1092SUFX	    = $(SUFX:t=)
1093!endif
1094
1095!ifndef TMP_DIR
1096TMP_DIR	    = $(TMP_DIRFULL)
1097!ifndef OUT_DIR
1098OUT_DIR	    = .\$(BUILDDIRTOP)
1099!endif
1100!else
1101!ifndef OUT_DIR
1102OUT_DIR	    = $(TMP_DIR)
1103!endif
1104!endif
1105
1106# Relative paths -> absolute
1107!if [echo OUT_DIR = \> nmakehlp.out] \
1108   || [nmakehlp -Q "$(OUT_DIR)" >> nmakehlp.out]
1109!error *** Could not fully qualify path OUT_DIR=$(OUT_DIR)
1110!endif
1111!if [echo TMP_DIR = \>> nmakehlp.out] \
1112   || [nmakehlp -Q "$(TMP_DIR)" >> nmakehlp.out]
1113!error *** Could not fully qualify path TMP_DIR=$(TMP_DIR)
1114!endif
1115!include nmakehlp.out
1116
1117# The name of the stubs library for the project being built
1118STUBPREFIX      = $(PROJECT)stub
1119
1120#
1121# Set up paths to various Tcl executables and libraries needed by extensions
1122#
1123
1124# TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc
1125TCLSCRIPTZIPNAME = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip
1126TKSCRIPTZIPNAME = libtk$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip
1127
1128!if $(DOING_TCL)
1129TCLSHNAME       = $(PROJECT)sh$(VERSION)$(SUFX).exe
1130TCLSH		= $(OUT_DIR)\$(TCLSHNAME)
1131TCLIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
1132TCLLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
1133TCLLIB		= $(OUT_DIR)\$(TCLLIBNAME)
1134TCLSCRIPTZIP    = $(OUT_DIR)\$(TCLSCRIPTZIPNAME)
1135
1136TCLSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
1137TCLSTUBLIB	= $(OUT_DIR)\$(TCLSTUBLIBNAME)
1138TCL_INCLUDES    = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
1139
1140!else # !$(DOING_TCL)
1141
1142!if $(TCLINSTALL) # Building against an installed Tcl
1143
1144# When building extensions, we need to locate tclsh. Depending on version
1145# of Tcl we are building against, this may or may not have a "t" suffix.
1146# Try various possibilities in turn.
1147TCLSH		= $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
1148!if !exist("$(TCLSH)")
1149TCLSH           = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
1150!endif
1151
1152TCLSTUBLIB	= $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib
1153TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
1154# When building extensions, may be linking against Tcl that does not add
1155# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
1156!if !exist("$(TCLIMPLIB)")
1157TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib
1158!endif
1159TCL_LIBRARY	= $(_TCLDIR)\lib
1160TCLREGLIB	= $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib
1161TCLDDELIB	= $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib
1162TCLSCRIPTZIP	= $(_TCLDIR)\lib\$(TCLSCRIPTZIPNAME)
1163TCLTOOLSDIR	= \must\have\tcl\sources\to\build\this\target
1164TCL_INCLUDES    = -I"$(_TCLDIR)\include"
1165
1166!else # Building against Tcl sources
1167
1168TCLSH		= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe
1169!if !exist($(TCLSH))
1170TCLSH		= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
1171!endif
1172TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib
1173TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
1174# When building extensions, may be linking against Tcl that does not add
1175# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
1176!if !exist("$(TCLIMPLIB)")
1177TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib
1178!endif
1179TCL_LIBRARY	= $(_TCLDIR)\library
1180TCLREGLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib
1181TCLDDELIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib
1182TCLSCRIPTZIP	= $(_TCLDIR)\win\$(BUILDDIRTOP)\$(TCLSCRIPTZIPNAME)
1183TCLTOOLSDIR	= $(_TCLDIR)\tools
1184TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
1185
1186!endif # TCLINSTALL
1187
1188tcllibs = "$(TCLSTUBLIB)" "$(TCLIMPLIB)"
1189
1190!endif # $(DOING_TCL)
1191
1192# We need a tclsh that will run on the host machine as part of the build.
1193# IX86 runs on all architectures.
1194!ifndef TCLSH_NATIVE
1195!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
1196TCLSH_NATIVE	= $(TCLSH)
1197!else
1198!error You must explicitly set TCLSH_NATIVE for cross-compilation
1199!endif
1200!endif
1201
1202# Do the same for Tk and Tk extensions that require the Tk libraries
1203!if $(DOING_TK) || $(NEED_TK)
1204WISHNAMEPREFIX = wish
1205WISHNAME = $(WISHNAMEPREFIX)$(TK_VERSION)$(SUFX).exe
1206TKLIBNAME8	= tk$(TK_VERSION)$(SUFX).$(EXT)
1207TKLIBNAME9	= tcl9tk$(TK_VERSION)$(SUFX).$(EXT)
1208!if $(TCL_MAJOR_VERSION) == 8
1209TKLIBNAME	= tk$(TK_VERSION)$(SUFX).$(EXT)
1210TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX).lib
1211!else
1212TKLIBNAME	= tcl9tk$(TK_VERSION)$(SUFX).$(EXT)
1213TKIMPLIBNAME	= tcl9tk$(TK_VERSION)$(SUFX).lib
1214!endif
1215TKSTUBLIBNAME	= tkstub$(TK_VERSION).lib
1216
1217!if $(DOING_TK)
1218WISH 		= $(OUT_DIR)\$(WISHNAME)
1219TKSTUBLIB	= $(OUT_DIR)\$(TKSTUBLIBNAME)
1220TKIMPLIB	= $(OUT_DIR)\$(TKIMPLIBNAME)
1221TKLIB		= $(OUT_DIR)\$(TKLIBNAME)
1222TK_INCLUDES     = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
1223TKSCRIPTZIP     = $(OUT_DIR)\$(TKSCRIPTZIPNAME)
1224
1225!else # effectively NEED_TK
1226
1227!if $(TKINSTALL) # Building against installed Tk
1228WISH		= $(_TKDIR)\bin\$(WISHNAME)
1229TKSTUBLIB	= $(_TKDIR)\lib\$(TKSTUBLIBNAME)
1230TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
1231# When building extensions, may be linking against Tk that does not add
1232# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
1233!if !exist("$(TKIMPLIB)")
1234TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
1235TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
1236!endif
1237TK_INCLUDES     = -I"$(_TKDIR)\include"
1238TKSCRIPTZIP     = $(_TKDIR)\lib\$(TKSCRIPTZIPNAME)
1239
1240!else # Building against Tk sources
1241
1242WISH		= $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME)
1243TKSTUBLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME)
1244TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
1245# When building extensions, may be linking against Tk that does not add
1246# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
1247!if !exist("$(TKIMPLIB)")
1248TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
1249TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
1250!endif
1251TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
1252TKSCRIPTZIP     = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSCRIPTZIPNAME)
1253
1254!endif # TKINSTALL
1255
1256tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)"
1257
1258!endif # $(DOING_TK)
1259!endif # $(DOING_TK) || $(NEED_TK)
1260
1261# Various output paths
1262PRJIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
1263PRJLIBNAME8	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
1264PRJLIBNAME9	= tcl9$(PROJECT)$(VERSION)$(SUFX).$(EXT)
1265!if $(TCL_MAJOR_VERSION) == 8
1266PRJLIBNAME	= $(PRJLIBNAME8)
1267!else
1268PRJLIBNAME	= $(PRJLIBNAME9)
1269!endif
1270PRJLIB		= $(OUT_DIR)\$(PRJLIBNAME)
1271
1272PRJSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
1273PRJSTUBLIB	= $(OUT_DIR)\$(PRJSTUBLIBNAME)
1274
1275# If extension parent makefile has not defined a resource definition file,
1276# we will generate one from standard template.
1277!if !$(DOING_TCL) && !$(DOING_TK) && !$(STATIC_BUILD)
1278!ifdef RCFILE
1279RESFILE = $(TMP_DIR)\$(RCFILE:.rc=.res)
1280!else
1281RESFILE = $(TMP_DIR)\$(PROJECT).res
1282!endif
1283!endif
1284
1285###################################################################
1286# 11. Construct the paths for the installation directories
1287# The following macros get defined in this section:
1288# LIB_INSTALL_DIR - where libraries should be installed
1289# BIN_INSTALL_DIR - where the executables should be installed
1290# DOC_INSTALL_DIR - where documentation should be installed
1291# SCRIPT_INSTALL_DIR - where scripts should be installed
1292# INCLUDE_INSTALL_DIR - where C include files should be installed
1293# DEMO_INSTALL_DIR - where demos should be installed
1294# PRJ_INSTALL_DIR - where package will be installed (not set for Tcl and Tk)
1295
1296!if $(DOING_TCL) || $(DOING_TK)
1297LIB_INSTALL_DIR		= $(_INSTALLDIR)\lib
1298BIN_INSTALL_DIR		= $(_INSTALLDIR)\bin
1299DOC_INSTALL_DIR		= $(_INSTALLDIR)\doc
1300!if $(DOING_TCL)
1301SCRIPT_INSTALL_DIR	= $(_INSTALLDIR)\lib\$(PROJECT)$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
1302MODULE_INSTALL_DIR	= $(_INSTALLDIR)\lib\tcl$(TCL_MAJOR_VERSION)
1303!else # DOING_TK
1304SCRIPT_INSTALL_DIR	= $(_INSTALLDIR)\lib\$(PROJECT)$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
1305!endif
1306DEMO_INSTALL_DIR	= $(SCRIPT_INSTALL_DIR)\demos
1307INCLUDE_INSTALL_DIR	= $(_INSTALLDIR)\include
1308
1309!else # extension other than Tk
1310
1311PRJ_INSTALL_DIR         = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
1312!if $(MULTIPLATFORM_INSTALL)
1313LIB_INSTALL_DIR		= $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY)
1314BIN_INSTALL_DIR		= $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY)
1315!else
1316LIB_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
1317BIN_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
1318!endif
1319DOC_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
1320SCRIPT_INSTALL_DIR	= $(PRJ_INSTALL_DIR)
1321DEMO_INSTALL_DIR	= $(PRJ_INSTALL_DIR)\demos
1322INCLUDE_INSTALL_DIR	= $(_INSTALLDIR)\..\include
1323
1324!endif
1325
1326###################################################################
1327# 12. Set up actual options to be passed to the compiler and linker
1328# Now we have all the information we need, set up the actual flags and
1329# options that we will pass to the compiler and linker. The main
1330# makefile should use these in combination with whatever other flags
1331# and switches are specific to it.
1332# The following macros are defined, names are for historical compatibility:
1333# OPTDEFINES - /Dxxx C macro flags based on user-specified OPTS
1334# COMPILERFLAGS - /Dxxx C macro flags independent of any configuration opttions
1335# crt - Compiler switch that selects the appropriate C runtime
1336# cdebug - Compiler switches related to debug AND optimizations
1337# cwarn - Compiler switches that set warning levels
1338# cflags - complete compiler switches (subsumes cdebug and cwarn)
1339# ldebug - Linker switches controlling debug information and optimization
1340# lflags - complete linker switches (subsumes ldebug) except subsystem type
1341# dlllflags - complete linker switches to build DLLs (subsumes lflags)
1342# conlflags - complete linker switches for console program (subsumes lflags)
1343# guilflags - complete linker switches for GUI program (subsumes lflags)
1344# baselibs - minimum Windows libraries required. Parent makefile can
1345#    define PRJ_LIBS before including rules.rc if additional libs are needed
1346
1347OPTDEFINES	= /DSTDC_HEADERS /DUSE_NMAKE=1
1348!if $(VCVERSION) > 1600
1349OPTDEFINES	= $(OPTDEFINES) /DHAVE_STDINT_H=1
1350!else
1351OPTDEFINES	= $(OPTDEFINES) /DMP_NO_STDINT=1
1352!endif
1353!if $(VCVERSION) >= 1800
1354OPTDEFINES	= $(OPTDEFINES) /DHAVE_INTTYPES_H=1 /DHAVE_STDBOOL_H=1
1355!endif
1356
1357!if $(TCL_MEM_DEBUG)
1358OPTDEFINES	= $(OPTDEFINES) /DTCL_MEM_DEBUG
1359!endif
1360!if $(TCL_COMPILE_DEBUG)
1361OPTDEFINES	= $(OPTDEFINES) /DTCL_COMPILE_DEBUG /DTCL_COMPILE_STATS
1362!endif
1363!if $(TCL_THREADS) && $(TCL_VERSION) < 87
1364OPTDEFINES	= $(OPTDEFINES) /DTCL_THREADS=1
1365!if $(USE_THREAD_ALLOC) && $(TCL_VERSION) < 87
1366OPTDEFINES	= $(OPTDEFINES) /DUSE_THREAD_ALLOC=1
1367!endif
1368!endif
1369!if $(STATIC_BUILD)
1370OPTDEFINES	= $(OPTDEFINES) /DSTATIC_BUILD
1371!elseif $(TCL_VERSION) > 86
1372OPTDEFINES	= $(OPTDEFINES) /DTCL_WITH_EXTERNAL_TOMMATH
1373!if "$(MACHINE)" == "AMD64"
1374OPTDEFINES	= $(OPTDEFINES) /DMP_64BIT
1375!endif
1376!endif
1377!if $(TCL_NO_DEPRECATED)
1378OPTDEFINES	= $(OPTDEFINES) /DTCL_NO_DEPRECATED
1379!endif
1380
1381!if $(USE_STUBS)
1382# Note we do not define USE_TCL_STUBS even when building tk since some
1383# test targets in tk do not use stubs
1384!if !$(DOING_TCL)
1385USE_STUBS_DEFS  = /DUSE_TCL_STUBS /DUSE_TCLOO_STUBS
1386!if $(NEED_TK)
1387USE_STUBS_DEFS  = $(USE_STUBS_DEFS) /DUSE_TK_STUBS
1388!endif
1389!endif
1390!endif # USE_STUBS
1391
1392!if !$(DEBUG)
1393OPTDEFINES	= $(OPTDEFINES) /DNDEBUG
1394!if $(OPTIMIZING)
1395OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_OPTIMIZED
1396!endif
1397!endif
1398!if $(PROFILE)
1399OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_PROFILED
1400!endif
1401!if "$(MACHINE)" == "AMD64"
1402OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_DO64BIT
1403!endif
1404!if $(VCVERSION) < 1300
1405OPTDEFINES	= $(OPTDEFINES) /DNO_STRTOI64=1
1406!endif
1407
1408!if "$(TCL_MAJOR_VERSION)" == "8"
1409!if "$(_USE_64BIT_TIME_T)" == "1"
1410OPTDEFINES	= $(OPTDEFINES) /D_USE_64BIT_TIME_T=1
1411!endif
1412!if "$(TCL_UTF_MAX)" == "4"
1413OPTDEFINES	= $(OPTDEFINES) /DTCL_UTF_MAX=4
1414!endif
1415
1416# _ATL_XP_TARGETING - Newer SDK's need this to build for XP
1417COMPILERFLAGS  = /D_ATL_XP_TARGETING
1418!endif
1419
1420# Like the TEA system only set this non empty for non-Tk extensions
1421# Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME
1422# so we pass both
1423!if !$(DOING_TCL) && !$(DOING_TK)
1424PKGNAMEFLAGS = /DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1425               /DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1426               /DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
1427               /DMODULE_SCOPE=extern
1428!endif
1429
1430# crt picks the C run time based on selected OPTS
1431!if $(MSVCRT)
1432!if $(DEBUG) && !$(UNCHECKED)
1433crt = -MDd
1434!else
1435crt = -MD
1436!endif
1437!else
1438!if $(DEBUG) && !$(UNCHECKED)
1439crt = -MTd
1440!else
1441crt = -MT
1442!endif
1443!endif
1444
1445# cdebug includes compiler options for debugging as well as optimization.
1446!if $(DEBUG)
1447
1448# In debugging mode, optimizations need to be disabled
1449cdebug = -Zi -Od $(DEBUGFLAGS)
1450
1451!else
1452
1453cdebug = $(OPTIMIZATIONS)
1454!if $(SYMBOLS)
1455cdebug = $(cdebug) -Zi
1456!endif
1457
1458!endif # $(DEBUG)
1459
1460# cwarn includes default warning levels.
1461cwarn = $(WARNINGS)
1462
1463!if "$(MACHINE)" == "AMD64"
1464# Disable pointer<->int warnings related to cast between different sizes
1465# There are a gadzillion of these due to use of ClientData and
1466# clutter up compiler
1467# output increasing chance of a real warning getting lost. So disable them.
1468# Eventually some day, Tcl will be 64-bit clean.
1469cwarn = $(cwarn) -wd4311 -wd4312
1470!endif
1471
1472### Common compiler options that are architecture specific
1473!if "$(MACHINE)" == "ARM"
1474carch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
1475!else
1476carch =
1477!endif
1478
1479!if $(DEBUG)
1480# Turn warnings into errors
1481cwarn = $(cwarn) -WX
1482!endif
1483
1484INCLUDES = $(TCL_INCLUDES) $(TK_INCLUDES) $(PRJ_INCLUDES)
1485!if !$(DOING_TCL) && !$(DOING_TK)
1486INCLUDES = $(INCLUDES) -I"$(GENERICDIR)" -I"$(WIN_DIR)" -I"$(COMPATDIR)"
1487!endif
1488
1489# These flags are defined roughly in the order of the pre-reform
1490# rules.vc/makefile.vc to help visually compare that the pre- and
1491# post-reform build logs
1492
1493# cflags contains generic flags used for building practically all object files
1494cflags = -nologo -c $(COMPILERFLAGS) $(carch) $(cwarn) -Fp$(TMP_DIR)^\ $(cdebug)
1495
1496# appcflags contains $(cflags) and flags for building the application
1497# object files (e.g. tclsh, or wish) pkgcflags contains $(cflags) plus
1498# flags used for building shared object files The two differ in the
1499# BUILD_$(PROJECT) macro which should be defined only for the shared
1500# library *implementation* and not for its caller interface
1501
1502appcflags_nostubs = $(cflags) $(crt) $(INCLUDES) $(TCL_DEFINES) $(PRJ_DEFINES) $(OPTDEFINES)
1503appcflags = $(appcflags_nostubs) $(USE_STUBS_DEFS)
1504pkgcflags = $(appcflags) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT)
1505pkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT)
1506
1507# stubscflags contains $(cflags) plus flags used for building a stubs
1508# library for the package.  Note: /DSTATIC_BUILD is defined in
1509# $(OPTDEFINES) only if the OPTS configuration indicates a static
1510# library. However the stubs library is ALWAYS static hence included
1511# here irrespective of the OPTS setting.
1512#
1513# TBD - tclvfs has a comment that stubs libs should not be compiled with -GL
1514# without stating why. Tcl itself compiled stubs libs with this flag.
1515# so we do not remove it from cflags. -GL may prevent extensions
1516# compiled with one VC version to fail to link against stubs library
1517# compiled with another VC version. Check for this and fix accordingly.
1518stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) /Zl /GL- /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS)
1519
1520# Link flags
1521
1522!if $(DEBUG)
1523ldebug	= -debug -debugtype:cv
1524!else
1525ldebug	= -release -opt:ref -opt:icf,3
1526!if $(SYMBOLS)
1527ldebug	= $(ldebug) -debug -debugtype:cv
1528!endif
1529!endif
1530
1531# Note: Profiling is currently only possible with the Visual Studio Enterprise
1532!if $(PROFILE)
1533ldebug= $(ldebug) -profile
1534!endif
1535
1536### Declarations common to all linker versions
1537lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
1538
1539!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
1540lflags	= $(lflags) -nodefaultlib:libucrt.lib
1541!endif
1542
1543dlllflags = $(lflags) -dll
1544conlflags = $(lflags) -subsystem:console
1545guilflags = $(lflags) -subsystem:windows
1546
1547# Libraries that are required for every image.
1548# Extensions should define any additional libraries with $(PRJ_LIBS)
1549winlibs   = kernel32.lib advapi32.lib
1550
1551!if $(NEED_TK)
1552winlibs = $(winlibs) gdi32.lib user32.lib uxtheme.lib
1553!endif
1554
1555# Avoid 'unresolved external symbol __security_cookie' errors.
1556# c.f. http://support.microsoft.com/?id=894573
1557!if "$(MACHINE)" == "AMD64"
1558!if $(VCVERSION) > 1399 && $(VCVERSION) < 1500
1559winlibs   = $(winlibs) bufferoverflowU.lib
1560!endif
1561!endif
1562
1563baselibs = $(winlibs) $(PRJ_LIBS)
1564
1565!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
1566baselibs   = $(baselibs) ucrt.lib
1567!endif
1568
1569################################################################
1570# 13. Define standard commands, common make targets and implicit rules
1571
1572CCPKGCMD = $(cc32) $(pkgcflags) -Fo$(TMP_DIR)^\
1573CCAPPCMD = $(cc32) $(appcflags) -Fo$(TMP_DIR)^\
1574CCSTUBSCMD = $(cc32) $(stubscflags) -Fo$(TMP_DIR)^\
1575
1576LIBCMD = $(lib32) -nologo $(LINKERFLAGS) -out:$@
1577DLLCMD = $(link32) $(dlllflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
1578
1579CONEXECMD = $(link32) $(conlflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
1580GUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
1581RESCMD  = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \
1582	    $(TCL_INCLUDES) \
1583	    /DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
1584	    /DCOMMAVERSION=$(RCCOMMAVERSION) \
1585	    /DDOTVERSION=\"$(DOTVERSION)\" \
1586	    /DVERSION=\"$(VERSION)\" \
1587	    /DSUFX=\"$(SUFX)\" \
1588	    /DPROJECT=\"$(PROJECT)\" \
1589	    /DPRJLIBNAME=\"$(PRJLIBNAME)\"
1590
1591!ifndef DEFAULT_BUILD_TARGET
1592DEFAULT_BUILD_TARGET = $(PROJECT)
1593!endif
1594
1595default-target: $(DEFAULT_BUILD_TARGET)
1596
1597!if $(MULTIPLATFORM_INSTALL)
1598default-pkgindex:
1599	@echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl
1600	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
1601	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl
1602	@echo } else { >> $(OUT_DIR)\pkgIndex.tcl
1603	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
1604	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl
1605	@echo } >> $(OUT_DIR)\pkgIndex.tcl
1606!else
1607default-pkgindex:
1608	@echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl
1609	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
1610	    [list load [file join $$dir $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl
1611	@echo } else { >> $(OUT_DIR)\pkgIndex.tcl
1612	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
1613	    [list load [file join $$dir $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl
1614	@echo } >> $(OUT_DIR)\pkgIndex.tcl
1615!endif
1616
1617default-pkgindex-tea:
1618	@if exist $(ROOT)\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\pkgIndex.tcl.in > $(OUT_DIR)\pkgIndex.tcl
1619@PACKAGE_VERSION@    $(DOTVERSION)
1620@PACKAGE_NAME@       $(PRJ_PACKAGE_TCLNAME)
1621@PACKAGE_TCLNAME@    $(PRJ_PACKAGE_TCLNAME)
1622@PKG_LIB_FILE@       $(PRJLIBNAME)
1623@PKG_LIB_FILE8@      $(PRJLIBNAME8)
1624@PKG_LIB_FILE9@      $(PRJLIBNAME9)
1625<<
1626
1627default-install: default-install-binaries default-install-libraries
1628!if $(SYMBOLS)
1629default-install: default-install-pdbs
1630!endif
1631
1632# Again to deal with historical brokenness, there is some confusion
1633# in terminlogy. For extensions, the "install-binaries" was used to
1634# locate target directory for *binary shared libraries* and thus
1635# the appropriate macro is LIB_INSTALL_DIR since BIN_INSTALL_DIR is
1636# for executables (exes). On the other hand the "install-libraries"
1637# target is for *scripts* and should have been called "install-scripts".
1638default-install-binaries: $(PRJLIB)
1639	@echo Installing binaries to '$(LIB_INSTALL_DIR)'
1640	@if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
1641	@$(CPY) $(PRJLIB) "$(LIB_INSTALL_DIR)" >NUL
1642
1643# Alias for default-install-scripts
1644default-install-libraries: default-install-scripts
1645
1646default-install-scripts: $(OUT_DIR)\pkgIndex.tcl
1647	@echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
1648	@if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)"
1649	@echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
1650	@$(CPY) $(OUT_DIR)\pkgIndex.tcl $(SCRIPT_INSTALL_DIR)
1651
1652default-install-stubs:
1653	@echo Installing stubs library to '$(SCRIPT_INSTALL_DIR)'
1654	@if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
1655	@$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
1656
1657default-install-pdbs:
1658	@echo Installing PDBs to '$(LIB_INSTALL_DIR)'
1659	@if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
1660	@$(CPY) "$(OUT_DIR)\*.pdb" "$(LIB_INSTALL_DIR)\"
1661
1662# "emacs font-lock highlighting fix
1663
1664default-install-docs-html:
1665	@echo Installing documentation files to '$(DOC_INSTALL_DIR)'
1666	@if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)"
1667	@if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.html" "$(DOCDIR)\*.css" "$(DOCDIR)\*.png") do @$(COPY) %f "$(DOC_INSTALL_DIR)"
1668
1669default-install-docs-n:
1670	@echo Installing documentation files to '$(DOC_INSTALL_DIR)'
1671	@if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)"
1672	@if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.n") do @$(COPY) %f "$(DOC_INSTALL_DIR)"
1673
1674default-install-demos:
1675	@echo Installing demos to '$(DEMO_INSTALL_DIR)'
1676	@if not exist "$(DEMO_INSTALL_DIR)" mkdir "$(DEMO_INSTALL_DIR)"
1677	@if exist $(DEMODIR) $(CPYDIR) "$(DEMODIR)" "$(DEMO_INSTALL_DIR)"
1678
1679default-clean:
1680	@echo Cleaning $(TMP_DIR)\* ...
1681	@if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
1682	@echo Cleaning $(WIN_DIR)\nmakehlp.obj, nmakehlp.exe ...
1683	@if exist $(WIN_DIR)\nmakehlp.obj del $(WIN_DIR)\nmakehlp.obj
1684	@if exist $(WIN_DIR)\nmakehlp.exe del $(WIN_DIR)\nmakehlp.exe
1685	@if exist $(WIN_DIR)\nmakehlp.out del $(WIN_DIR)\nmakehlp.out
1686	@echo Cleaning $(WIN_DIR)\nmhlp-out.txt ...
1687	@if exist $(WIN_DIR)\nmhlp-out.txt del $(WIN_DIR)\nmhlp-out.txt
1688	@echo Cleaning $(WIN_DIR)\_junk.pch ...
1689	@if exist $(WIN_DIR)\_junk.pch del $(WIN_DIR)\_junk.pch
1690	@echo Cleaning $(WIN_DIR)\vercl.x, vercl.i ...
1691	@if exist $(WIN_DIR)\vercl.x del $(WIN_DIR)\vercl.x
1692	@if exist $(WIN_DIR)\vercl.i del $(WIN_DIR)\vercl.i
1693	@echo Cleaning $(WIN_DIR)\versions.vc, version.vc ...
1694	@if exist $(WIN_DIR)\versions.vc del $(WIN_DIR)\versions.vc
1695	@if exist $(WIN_DIR)\version.vc del $(WIN_DIR)\version.vc
1696
1697default-hose: default-clean
1698	@echo Hosing $(OUT_DIR)\* ...
1699	@if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)
1700
1701# Only for backward compatibility
1702default-distclean: default-hose
1703
1704default-setup:
1705	@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
1706	@if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
1707
1708!if "$(TESTPAT)" != ""
1709TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
1710!endif
1711
1712default-test: default-setup $(PROJECT)
1713	@set TCLLIBPATH=$(OUT_DIR:\=/)
1714	@if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)"
1715	cd "$(TESTDIR)" && $(DEBUGGER) $(TCLSH) all.tcl $(TESTFLAGS)
1716
1717default-shell: default-setup $(PROJECT)
1718	@set TCLLIBPATH=$(OUT_DIR:\=/)
1719	@if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)"
1720	$(DEBUGGER) $(TCLSH)
1721
1722# Generation of Windows version resource
1723!ifdef RCFILE
1724
1725# Note: don't use $** in below rule because there may be other dependencies
1726# and only the "main" rc must be passed to the resource compiler
1727$(TMP_DIR)\$(PROJECT).res: $(RCDIR)\$(PROJECT).rc
1728	$(RESCMD) $(RCDIR)\$(PROJECT).rc
1729
1730!else
1731
1732# If parent makefile has not defined a resource definition file,
1733# we will generate one from standard template.
1734$(TMP_DIR)\$(PROJECT).res: $(TMP_DIR)\$(PROJECT).rc
1735
1736$(TMP_DIR)\$(PROJECT).rc:
1737	@$(COPY) << $(TMP_DIR)\$(PROJECT).rc
1738#include <winver.h>
1739
1740VS_VERSION_INFO VERSIONINFO
1741 FILEVERSION	COMMAVERSION
1742 PRODUCTVERSION	COMMAVERSION
1743 FILEFLAGSMASK	0x3fL
1744#ifdef DEBUG
1745 FILEFLAGS	VS_FF_DEBUG
1746#else
1747 FILEFLAGS	0x0L
1748#endif
1749 FILEOS		VOS_NT_WINDOWS32
1750 FILETYPE	VFT_DLL
1751 FILESUBTYPE	0x0L
1752BEGIN
1753    BLOCK "StringFileInfo"
1754    BEGIN
1755        BLOCK "040904b0"
1756        BEGIN
1757            VALUE "FileDescription",  "Tcl extension " PROJECT
1758            VALUE "OriginalFilename", PRJLIBNAME
1759            VALUE "FileVersion",      DOTVERSION
1760            VALUE "ProductName",      "Package " PROJECT " for Tcl"
1761            VALUE "ProductVersion",   DOTVERSION
1762        END
1763    END
1764    BLOCK "VarFileInfo"
1765    BEGIN
1766        VALUE "Translation", 0x409, 1200
1767    END
1768END
1769
1770<<
1771
1772!endif # ifdef RCFILE
1773
1774!ifndef DISABLE_IMPLICIT_RULES
1775DISABLE_IMPLICIT_RULES = 0
1776!endif
1777
1778!if !$(DISABLE_IMPLICIT_RULES)
1779# Implicit rule definitions - only for building library objects. For stubs and
1780# main application, the makefile should define explicit rules.
1781
1782{$(ROOT)}.c{$(TMP_DIR)}.obj::
1783	$(CCPKGCMD) @<<
1784$<
1785<<
1786
1787{$(WIN_DIR)}.c{$(TMP_DIR)}.obj::
1788	$(CCPKGCMD) @<<
1789$<
1790<<
1791
1792{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
1793	$(CCPKGCMD) @<<
1794$<
1795<<
1796
1797{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
1798	$(CCPKGCMD) @<<
1799$<
1800<<
1801
1802{$(RCDIR)}.rc{$(TMP_DIR)}.res:
1803	$(RESCMD) $<
1804
1805{$(WIN_DIR)}.rc{$(TMP_DIR)}.res:
1806	$(RESCMD) $<
1807
1808{$(TMP_DIR)}.rc{$(TMP_DIR)}.res:
1809	$(RESCMD) $<
1810
1811.SUFFIXES:
1812.SUFFIXES:.c .rc
1813
1814!endif
1815
1816################################################################
1817# 14. Sanity check selected options against Tcl build options
1818# When building an extension, certain configuration options should
1819# match the ones used when Tcl was built. Here we check and
1820# warn on a mismatch.
1821!if !$(DOING_TCL)
1822
1823!if $(TCLINSTALL) # Building against an installed Tcl
1824!if exist("$(_TCLDIR)\lib\nmake\tcl.nmake")
1825TCLNMAKECONFIG = "$(_TCLDIR)\lib\nmake\tcl.nmake"
1826!endif
1827!else # !$(TCLINSTALL) - building against Tcl source
1828!if exist("$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake")
1829TCLNMAKECONFIG	= "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake"
1830!endif
1831!endif # TCLINSTALL
1832
1833!if $(CONFIG_CHECK)
1834!ifdef TCLNMAKECONFIG
1835!include $(TCLNMAKECONFIG)
1836
1837!if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)"
1838!error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)).
1839!endif
1840!if $(TCL_VERSION) < 87 && defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC)
1841!message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)).
1842!endif
1843!if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG)
1844!message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)).
1845!endif
1846!endif
1847
1848!endif # TCLNMAKECONFIG
1849
1850!endif # !$(DOING_TCL)
1851
1852
1853#----------------------------------------------------------
1854# Display stats being used.
1855#----------------------------------------------------------
1856
1857!if !$(DOING_TCL)
1858!message *** Building against Tcl at '$(_TCLDIR)'
1859!endif
1860!if !$(DOING_TK) && $(NEED_TK)
1861!message *** Building against Tk at '$(_TKDIR)'
1862!endif
1863!message *** Intermediate directory will be '$(TMP_DIR)'
1864!message *** Output directory will be '$(OUT_DIR)'
1865!message *** Installation, if selected, will be in '$(_INSTALLDIR)'
1866!message *** Suffix for binaries will be '$(SUFX)'
1867!message *** Compiler version $(VCVER). Target $(MACHINE), host $(NATIVE_ARCH).
1868
1869!endif # ifdef _RULES_VC
1870