1# makefile.vc --                                               -*- Makefile -*-
2#
3# Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
4#
5# This makefile is based upon the Tcl 8.4 Makefile.vc and modified to 
6# make it suitable as a general package makefile. Look for the word EDIT
7# which marks sections that may need modification. As a minumum you will
8# need to change the PROJECT, DOTVERSION and DLLOBJS variables to values
9# relevant to your package.
10#
11# See the file "license.terms" for information on usage and redistribution
12# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13# 
14# Copyright (c) 1995-1996 Sun Microsystems, Inc.
15# Copyright (c) 1998-2000 Ajuba Solutions.
16# Copyright (c) 2001 ActiveState Corporation.
17# Copyright (c) 2001-2002 David Gravereaux.
18# Copyright (c) 2003-2006 Pat Thoyts
19#
20#-------------------------------------------------------------------------
21# RCS: @(#)$Id: makefile.vc,v 8.6 2008/06/29 23:53:57 patthoyts Exp $
22#-------------------------------------------------------------------------
23
24# Check to see we are configured to build with MSVC (MSDEVDIR or MSVCDIR)
25# or with the MS Platform SDK (MSSDK). Visual Studio .NET 2003 and 2005 define
26# VCINSTALLDIR instead. The MSVC Toolkit release defines yet another.
27!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(MSSDK) && !defined(VCINSTALLDIR) && !defined(VCToolkitInstallDir)
28MSG = ^
29You need to run vcvars32.bat from Developer Studio or setenv.bat from the^
30Platform SDK first to setup the environment.  Jump to this line to read^
31the build instructions.
32!error $(MSG)
33!endif
34
35#------------------------------------------------------------------------------
36# HOW TO USE this makefile:
37#
38# 1)  It is now necessary to have %MSVCDir% set in the environment.  This is
39#     used  as a check to see if vcvars32.bat had been run prior to running
40#     nmake or during the installation of Microsoft Visual C++, MSVCDir had
41#     been set globally and the PATH adjusted.  Either way is valid.
42#
43#     You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin
44#     directory to setup the proper environment, if needed, for your current
45#     setup.  This is a needed bootstrap requirement and allows the swapping of
46#     different environments to be easier.
47#
48# 2)  To use the Platform SDK (not expressly needed), run setenv.bat after
49#     vcvars32.bat according to the instructions for it.  This can also turn on
50#     the 64-bit compiler, if your SDK has it.
51#
52# 3)  Targets are:
53#	all       -- Builds everything.
54#       <project> -- Builds the project (eg: nmake sample)
55#	test      -- Builds and runs the test suite.
56#	install   -- Installs the built binaries and libraries to $(INSTALLDIR)
57#		     in an appropriate subdirectory.
58#	clean/realclean/distclean -- varying levels of cleaning.
59#
60# 4)  Macros usable on the commandline:
61#	INSTALLDIR=<path>
62#		Sets where to install Tcl from the built binaries.
63#		C:\Progra~1\Tcl is assumed when not specified.
64#
65#	OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,none
66#		Sets special options for the core.  The default is for none.
67#		Any combination of the above may be used (comma separated).
68#		'none' will over-ride everything to nothing.
69#
70#		static  =  Builds a static library of the core instead of a
71#			   dll.  The shell will be static (and large), as well.
72#		msvcrt  =  Effects the static option only to switch it from
73#			   using libcmt(d) as the C runtime [by default] to
74#			   msvcrt(d). This is useful for static embedding
75#			   support.
76#		staticpkg = Effects the static option only to switch
77#			   tclshXX.exe to have the dde and reg extension linked
78#			   inside it.
79#		nothreads = Turns off multithreading support (not recommended)
80#		thrdalloc = Use the thread allocator (shared global free pool).
81#		symbols =  Adds symbols for step debugging.
82#		profile =  Adds profiling hooks.  Map file is assumed.
83#		loimpact =  Adds a flag for how NT treats the heap to keep memory
84#			   in use, low.  This is said to impact alloc performance.
85#
86#	STATS=memdbg,compdbg,none
87#		Sets optional memory and bytecode compiler debugging code added
88#		to the core.  The default is for none.  Any combination of the
89#		above may be used (comma separated).  'none' will over-ride
90#		everything to nothing.
91#
92#		memdbg   = Enables the debugging memory allocator.
93#		compdbg  = Enables byte compilation logging.
94#
95#	MACHINE=(IX86|IA64|ALPHA|AMD64)
96#		Set the machine type used for the compiler, linker, and
97#		resource compiler.  This hook is needed to tell the tools
98#		when alternate platforms are requested.  IX86 is the default
99#		when not specified. If the CPU environment variable has been
100#		set (ie: recent Platform SDK) then MACHINE is set from CPU.
101#
102#	TMP_DIR=<path>
103#	OUT_DIR=<path>
104#		Hooks to allow the intermediate and output directories to be
105#		changed.  $(OUT_DIR) is assumed to be 
106#		$(BINROOT)\(Release|Debug) based on if symbols are requested.
107#		$(TMP_DIR) will de $(OUT_DIR)\<buildtype> by default.
108#
109#	TESTPAT=<file>
110#		Reads the tests requested to be run from this file.
111#
112#	CFG_ENCODING=encoding
113#		name of encoding for configuration information. Defaults
114#		to cp1252
115#
116# 5)  Examples:
117#
118#	Basic syntax of calling nmake looks like this:
119#	nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]]
120#
121#                        Standard (no frills)
122#       c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat
123#       Setting environment for using Microsoft Visual C++ tools.
124#       c:\tcl_src\win\>nmake -f makefile.vc all
125#       c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl
126#
127#                         Building for Win64
128#       c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat
129#       Setting environment for using Microsoft Visual C++ tools.
130#       c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL
131#       Targeting Windows pre64 RETAIL
132#       c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64
133#
134#------------------------------------------------------------------------------
135#==============================================================================
136###############################################################################
137#------------------------------------------------------------------------------
138
139!if !exist("makefile.vc")
140MSG = ^
141You must run this makefile only from the directory it is in.^
142Please `cd` to its location first.
143!error $(MSG)
144!endif
145
146#-------------------------------------------------------------------------
147# Project specific information (EDIT)
148#
149# You should edit this with the name and version of your project. This
150# information is used to generate the name of the package library and
151# it's install location.
152#
153# For example, the sample extension is  going to build sample04.dll and
154# would install it into $(INSTALLDIR)\lib\sample04
155#
156# You need to specify the object files that need to be linked into your
157# binary here.
158#
159#-------------------------------------------------------------------------
160
161PROJECT = tclx
162
163# Uncomment the following line if this is a Tk extension.
164#PROJECT_REQUIRES_TK=1
165!include "rules.vc"
166
167FULL_VERSION    = 8.4.0
168DOTVERSION      = 8.4
169VERSION         = $(DOTVERSION:.=)
170STUBPREFIX      = $(PROJECT)stub
171
172DLLOBJS = \
173	$(TMP_DIR)\tclXbsearch.obj \
174	$(TMP_DIR)\tclXchmod.obj \
175	$(TMP_DIR)\tclXcmdloop.obj \
176	$(TMP_DIR)\tclXdebug.obj \
177	$(TMP_DIR)\tclXdup.obj \
178	$(TMP_DIR)\tclXfcntl.obj \
179	$(TMP_DIR)\tclXfilecmds.obj \
180	$(TMP_DIR)\tclXfilescan.obj \
181	$(TMP_DIR)\tclXflock.obj \
182	$(TMP_DIR)\tclXfstat.obj \
183	$(TMP_DIR)\tclXgeneral.obj \
184	$(TMP_DIR)\tclXhandles.obj \
185	$(TMP_DIR)\tclXinit.obj \
186	$(TMP_DIR)\tclXkeylist.obj \
187	$(TMP_DIR)\tclXlib.obj \
188	$(TMP_DIR)\tclXlist.obj \
189	$(TMP_DIR)\tclXmath.obj \
190	$(TMP_DIR)\tclXmsgcat.obj \
191	$(TMP_DIR)\tclXprocess.obj \
192	$(TMP_DIR)\tclXprofile.obj \
193	$(TMP_DIR)\tclXselect.obj \
194	$(TMP_DIR)\tclXsignal.obj \
195	$(TMP_DIR)\tclXstring.obj \
196	$(TMP_DIR)\tclXsocket.obj \
197	$(TMP_DIR)\tclXutil.obj \
198	$(TMP_DIR)\tclXoscmds.obj \
199	$(TMP_DIR)\tclXlgets.obj \
200	$(TMP_DIR)\tclXwinCmds.obj \
201	$(TMP_DIR)\tclXwinDup.obj \
202	$(TMP_DIR)\tclXwinId.obj \
203	$(TMP_DIR)\tclXwinOS.obj \
204	$(TMP_DIR)\random.obj \
205	$(TMP_DIR)\getopt.obj \
206!if !$(STATIC_BUILD)
207	$(TMP_DIR)\tclx.res
208!endif
209
210#-------------------------------------------------------------------------
211# Target names and paths ( shouldn't need changing )
212#-------------------------------------------------------------------------
213
214BINROOT		= .
215ROOT            = ..
216
217PRJIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
218PRJLIBNAME	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
219PRJLIB		= $(OUT_DIR)\$(PRJLIBNAME)
220
221PRJSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib
222PRJSTUBLIB	= $(OUT_DIR)\$(PRJSTUBLIBNAME)
223
224### Make sure we use backslash only.
225PRJ_INSTALL_DIR         = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
226LIB_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
227BIN_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
228DOC_INSTALL_DIR		= $(PRJ_INSTALL_DIR)
229SCRIPT_INSTALL_DIR	= $(PRJ_INSTALL_DIR)
230INCLUDE_INSTALL_DIR	= $(_TCLDIR)\include
231
232### The following paths CANNOT have spaces in them.
233GENERICDIR	= $(ROOT)\generic
234WINDIR		= $(ROOT)\win
235LIBDIR          = $(ROOT)\library
236DOCDIR		= $(ROOT)\doc
237TOOLSDIR	= $(ROOT)\tools
238COMPATDIR	= $(ROOT)\compat
239
240#---------------------------------------------------------------------
241# Compile flags
242#---------------------------------------------------------------------
243
244!if !$(DEBUG)
245!if $(OPTIMIZING)
246### This cranks the optimization level to maximize speed
247cdebug	= $(OPTIMIZATIONS)
248!else
249cdebug	=
250!endif
251!else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
252### Warnings are too many, can't support warnings into errors.
253cdebug	= -Zi -Od $(DEBUGFLAGS)
254!else
255cdebug	= -Zi -WX $(DEBUGFLAGS)
256!endif
257
258### Declarations common to all compiler options
259cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE
260cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\
261
262!if $(MSVCRT)
263!if $(DEBUG) && !$(UNCHECKED)
264crt = -MDd
265!else
266crt = -MD
267!endif
268!else
269!if $(DEBUG) && !$(UNCHECKED)
270crt = -MTd
271!else
272crt = -MT
273!endif
274!endif
275
276!if !$(STATIC_BUILD)
277cflags = $(cflags) -DUSE_TCL_STUBS
278!if defined(TKSTUBLIB)
279cflags = $(cflags) -DUSE_TK_STUBS
280!endif
281!endif
282
283INCLUDES	= $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)"
284BASE_CFLAGS	= $(cflags) $(cdebug) $(crt) $(INCLUDES)
285CON_CFLAGS	= $(cflags) $(cdebug) $(crt) -DCONSOLE
286TCL_CFLAGS	= -DPACKAGE_NAME="\"$(PROJECT)\"" \
287		  -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
288		  -DBUILD_$(PROJECT) -DWIN32 \
289		  -DFULL_VERSION="\"$(FULL_VERSION)\"" \
290		  $(BASE_CFLAGS) $(OPTDEFINES)
291
292#---------------------------------------------------------------------
293# Link flags
294#---------------------------------------------------------------------
295
296!if $(DEBUG)
297ldebug	= -debug:full -debugtype:cv
298!if $(MSVCRT)
299ldebug = $(ldebug) -nodefaultlib:msvcrt
300!endif
301!else
302ldebug	= -release -opt:ref -opt:icf,3
303!endif
304
305### Declarations common to all linker options
306lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
307
308!if $(PROFILE)
309lflags	= $(lflags) -profile
310!endif
311
312!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
313### Align sections for PE size savings.
314lflags	= $(lflags) -opt:nowin98
315!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
316### Align sections for speed in loading by choosing the virtual page size.
317lflags	= $(lflags) -align:4096
318!endif
319
320!if $(LOIMPACT)
321lflags	= $(lflags) -ws:aggressive
322!endif
323
324dlllflags = $(lflags) -dll
325conlflags = $(lflags) -subsystem:console
326guilflags = $(lflags) -subsystem:windows
327!if !$(STATIC_BUILD)
328baselibs  = $(TCLSTUBLIB)
329!if defined(TKSTUBLIB)
330baselibs  = $(baselibs) $(TKSTUBLIB)
331!endif
332!endif
333
334# Avoid 'unresolved external symbol __security_cookie' errors.
335# c.f. http://support.microsoft.com/?id=894573
336!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
337!if $(VCVERSION) >= 1400 && $(VCVERSION) < 1500
338baselibs   = $(baselibs) bufferoverflowU.lib
339!endif
340!endif
341
342baselibs   = $(baselibs) ws2_32.lib
343
344#---------------------------------------------------------------------
345# TclTest flags
346#---------------------------------------------------------------------
347
348!IF "$(TESTPAT)" != ""
349TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
350!ENDIF
351
352#---------------------------------------------------------------------
353# Project specific targets (EDIT)
354#---------------------------------------------------------------------
355
356all:	    setup $(PROJECT)
357$(PROJECT): setup pkgIndex $(PRJLIB)
358install:    install-binaries install-libraries install-docs
359pkgIndex:   $(OUT_DIR)\pkgIndex.tcl
360
361test: setup $(PROJECT)
362	@set TCL_LIBRARY=$(TCL_LIBRARY:\=/)
363	@set TCLLIBPATH=$(OUT_DIR_PATH:\=/)
364!if $(TCLINSTALL)
365	@set PATH=$(_TCLDIR)\bin;$(PATH)
366!else
367	@set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH)
368!endif
369	@$(CPY) $(LIBDIR) $(OUT_DIR)\tclx8.4
370!if "$(OS)" == "Windows_NT"  || "$(MSVCDIR)" == "IDE"
371	$(DEBUGGER) $(TCLSH) "$(ROOT)/tests/all.tcl" $(TESTFLAGS)
372!else
373        @echo Please wait while the tests are collected...
374        $(DEBUGGER) $(TCLSH) "$(ROOT)/tests/all.tcl" $(TESTFLAGS) > tests.log
375	type tests.log | more
376!endif
377
378shell: setup $(PROJECT)
379	@set TCL_LIBRARY=$(TCL_LIBRARY:\=/)
380	@set TCLLIBPATH=$(OUT_DIR_PATH:\=/)
381!if $(TCLINSTALL)
382	@set PATH=$(_TCLDIR)\bin;$(PATH)
383!else
384	@set PATH=$(_TCLDIR)\win\$(BUILDDIRTOP);$(PATH)
385!endif
386	@$(CPY) $(LIBDIR) $(OUT_DIR)\tclx8.4
387	$(DEBUGGER) $(TCLSH) $(SCRIPT)
388
389setup:
390	@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
391	@if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
392
393# See <tcl>/win/coffbase.txt for extension base addresses.
394$(PRJLIB): $(DLLOBJS)
395!if $(STATIC_BUILD)
396	$(lib32) -nologo -out:$@ @<<
397$**
398<<
399!else
400	$(link32) $(dlllflags) -base:0x10000000 -out:$@ $(baselibs) @<<
401$**
402<<
403	$(_VC_MANIFEST_EMBED_DLL)
404	-@del $*.exp
405!endif
406
407$(PRJSTUBLIB): $(PRJSTUBOBJS)
408	$(lib32) -nologo -out:$@ $(PRJSTUBOBJS)
409
410#---------------------------------------------------------------------
411# Implicit rules
412#---------------------------------------------------------------------
413
414{$(WINDIR)}.c{$(TMP_DIR)}.obj::
415    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
416$<
417<<
418
419{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
420    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
421$<
422<<
423
424{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
425    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
426$<
427<<
428
429{$(WINDIR)}.rc{$(TMP_DIR)}.res:
430	$(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
431		-DCOMMAVERSION=$(DOTVERSION:.=,),0,0 \
432		-DDOTVERSION=\"$(DOTVERSION)\" \
433		-DVERSION=\"$(VERSION)$(SUFX)\" \
434!if $(DEBUG)
435	-d DEBUG \
436!endif
437!if $(TCL_THREADS)
438	-d TCL_THREADS \
439!endif
440!if $(STATIC_BUILD)
441	-d STATIC_BUILD \
442!endif
443	$<
444
445.SUFFIXES:
446.SUFFIXES:.c .rc
447
448#-------------------------------------------------------------------------
449# Explicit dependency rules
450#
451#-------------------------------------------------------------------------
452
453$(OUT_DIR)\pkgIndex.tcl: $(WINDIR)\pkgIndex.tcl.in
454	@nmakehlp -s << $** > $@
455@PACKAGE_VERSION@    $(DOTVERSION)
456@PACKAGE_NAME@       $(PROJECT)
457@PKG_LIB_FILE@       $(PRJLIBNAME)
458<<
459
460#---------------------------------------------------------------------
461# Installation. (EDIT)
462#
463# You may need to modify this section to reflect the final distribution
464# of your files and possibly to generate documentation.
465#
466#---------------------------------------------------------------------
467
468install-binaries:
469	@echo Installing binaries to '$(SCRIPT_INSTALL_DIR)'
470	@if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
471	@$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
472
473install-libraries: $(OUT_DIR)\pkgIndex.tcl
474	@echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
475	@if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)"
476	@echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
477	@$(CPY) $(OUT_DIR)\pkgIndex.tcl $(SCRIPT_INSTALL_DIR)
478
479install-docs:
480	@echo Installing documentation files to '$(DOC_INSTALL_DIR)'
481	@if exist $(DOCDIR) $(CPY) $(DOCDIR)\*.n "$(DOC_INSTALL_DIR)"
482
483#---------------------------------------------------------------------
484# Clean up
485#---------------------------------------------------------------------
486
487clean:
488	@if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
489	@if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc
490	@if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i
491	@if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x
492	@if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch
493
494realclean: clean
495	@if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)
496
497distclean: realclean
498	@if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
499	@if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj
500