[chrstphrchvz 2019-07-29: much of the info on this page seems outdated; up-to-date instructions can be found at https://www.tcl-lang.org/doc/howto/compile.html#win ]
PT 13-May-2004
Microsoft recently made the optimising version of their C and C++ compiler available for free download [L1 ]. This is fairly useful for building open source projects which often provide a Visual C++ build environment. Tcl is one such OS project.
There are a few issues using the toolkit to build anything useful. There are a few utilities that have not been provided and at least one link library. However, all is not lost. You can get all the bits from alternative free sources.
Firstly, you should install the most recent Platform SDK [L2 ] - this provides all the current libraries and headers for building anything on windows.
Missing utilities: cvtres.exe, lib.exe and nmake.exe. It turns out that you can use the versions provided with the Platform SDK Win64 tools. I suggest copying these utilities from %MSSDK%\bin\win64\ to your VC++ toolkit binaries directory.
Missing msvcrt.lib - this is the link library for the C runtime used by Tcl and most extensions. You can in theory create a link library from a .dll using link -dump -exports dllname and some processing, but I have been unable to make this work. Instead you can install the .NET Framework SDK (free download) and get a copy of msvcrt.lib from this [L3 ]. (It ends up in "Microsoft Visual Studio .NET 2003\Vc7\lib")
Finally, the compiler no longer accepts the -GD option and the linker will not accept -link50compat so you should remove these from your makefiles.
Setup your INCLUDE, LIB and PATH environment variables to point first to the Platform SDK and then the toolkit directories: eg: my vcsetup7.bat file...
@echo off set MSDEVDIR=%VCToolkitInstallDir% set INCLUDE=%MSSDK%\include;%VCToolkitInstallDir%\include set LIB=%MSSDK%\lib;%VCToolkitInstallDir%\lib set PATH=%MSSDK%\bin;%VCToolkitInstallDir%\bin;%PATH%
Now you can build tcl using the <tcl>/win/makefile.vc NMAKE makefile. Or you could use Msys and CC=cl ./configure
Michael Heca 2004-09-04: This binaries builded on Windows XP don't run Windows 98. There is no MSVCR71.DLL and is not installed by Tcl.
AR It is likely to be an issue with manifest. Cf. my notes on it, and http://msdn.microsoft.com/fr-fr/library/ms235591.aspx
male - 25 May 2004: to download the Platform SDK (not to install) use http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm
CLN - 2005-01-29: Take care that there are two versions there: Windows Server2003 and XPSP2.
APN 2010-05-19 If you do not need an IDE, the latest Windows SDK (Windows 7 version) also includes the Visual Studio 9.0 32- and 64-bit compilers.
Michael Heca 2004-09-03: To compile help need file hcrtf.exe. Download it from ftp://ftp.microsoft.com/Softlib/MSLFiles/hcwsetup.exe
jcw - Would it be an idea to start using tclsh to streamline this sort of thing? I know that using tcl to build tcl sounds silly, but since we have several perfectly well-working binaries for Tcl on Windows, I think we can by now rely on it. The bootstrap issue is long behind us for Windows. So as addition to the above, it would now be quite feasible to create a Tcl script which does all of the above (even fetches things not yet present, if you really want to push it). This would make it possible to say to anyone:
To build the latest Tcl/Tk on Windows, get one script and tclkitsh or some such, and do <x>. Done. The script could be as straightforward or clever as we care to make it.
I've used Tcl to drive the "genkit" build system, and have to admit that it really simplifies things, without having to make sure people have wget, a specific shell, etc. On Windows, it would be even more useful, to avoid getting a specific version of msys, or cygwin, and what have you not. In fact, it'd simply be a smaller download.
So I guess the question is really a more general one: could this be a good time to start using Tcl for our own tasks some more?
CL reacts: yes. It strikes me as a pure win. In particular, even if I'm stranded on, let's say, an embedded system which somehow lacks the Tcl I need to bootstrap, I assume I can move to some other host, and ask it (this contemplated Tcl-based generation system *will* have powerful introspection, no?) what I need to do on another system. This improves my life in every dimension when compared to reliance on *make.
mjk: It would be a brilliant idea to use Tcl as a replacement for configure scripts and makefiles. I've been lately struggling with various makefiles, which were made for Visual C nmake utility and I have been converting makefiles for MinGW and Borland Make by hand (these were not related to Tcl/Tk in any way). This Tcl build-script idea would solve all dependencies on various compiler/system-specific tools if made right.
I recommend using bras as a really powerful tcl-based build tool
JH: I'm highly skeptical of using Tcl to build the Tcl core due to bootstrapping issues. I am highly in favor of relying on Tcl more for building Tcl extensions though (TEA or others).
mjk: You are right about the bootstrapping. I forgot to think about that. I hate it when some Scheme or Common LISP implementation depends on older version of itself. But Tcl is (in my opinion) a bit different thing, because Tclkit is available for multiply platforms. Can't say same about other languages. But relying on the fact that Tclkit would be available for all platforms is a bit too optimistic and unrealistic thing to depend on fully. Anyway, using any autoconfig/automake scripts isn't good thing either for all platforms (I'm not going to use Cygwin or MSYS under Windows). Anyway, this page has inspired me to think about some sort of Tcl-based building tool which would be useful for my other projects (I'm aware of bras and aardvark).
SRIV Its a heck of a lot easier to install a tclkit than any other build system on any platform. Boot strapping with a tclkit is trivial.
jcw - It wasn't my intention to suggest "all" (or even "many") platforms. Just Windows - with all its msys/mingw/cygwin/msvc complexities. If we have Tcl, a pretty nifty pool of talented Tcl people, and a goal to deal with 1, then maybe even 2 or 3 compiler options on that platform, we could simplify. To the point where a Tcl script asks "do you want to fetch mingw and set it up?" or "update to latest Tcl sources and rebuild same as last time?". Similar to (and beyond) what genkit does for tclkit on Unix.
I don't have strong feelings about this, nor any particular desire to see tclkit in that role - it's just that by now, the bootstrap issue on Windows (and Mac OS X, another single-binary base) is really no longer a constraint IMO. It doesn't have to be the most recent tcl/tk at all. Pick a solid 8.4 based one, declare its binary as frozen, available from multiple sources, 100% Tcl-compat OSS, and ... start imagining how much nicer life becomes for a Tcler to rely on top-notch scripting + GUI + networking infrastructure.
If it were only about installing binary builds, one could argue for well-known installers, since that's what everyone does.
But this is about source builds. In itself it seems like a useless idea - just ship that one last-release binary to everybody, right? But think about extensions, and how much more leverage Tcl could bring with an option to get a properly installed build system, ready for anyone to build and re-build tons of extensions. And... when repositories become a reality: submit those binaries back.
So I think my argument boils down to: leverage. Giving anyone in the Tcl world on Windows the ability to keep extensions up to date, submit new ones, apply fixes, test on many Windows variants, etc. Tcl/Tk is a tool. The more widespread it works for people, the more it can drive development - some of it is inevitable going to come back as OSS, no?
When in Rome, eh I mean on Windows ... make Tcl/Tk as convenient for developers as you can!
SRIV Then perhaps a static tclsh/w libs, like freetclsh (from freewrap).
TV On the subject of how to build tcl from a free environment I think contributes well to developing reasonably under windows, cygwin, I make a page on Building Tcl under cygwin with MINGW .
2004-09-04 VI I'd recommend smake for tcl based makefiles. I am in no way related to the author (Thanks! Setok). But I've made minor modifications and think it's the answer to all my makefile blues.
2004-10-20 VI If you follow the instructions above for the free install, you end up with the resulting binary depending on msvcrt7.dll. That is a pain because most Windows only have the generic msvcrt.dll. Also note that the visual studio net sdk, (where the msvcrt.lib is) always ends up on the c:\program files irrespective of where you told it to install the .NET sdk. I instead got the DDK CD (Free, shipping is charged though) from http://www.microsoft.com/whdc/devtools/ddk/orderddkcd.mspx . Then I linked against the msvcrt.lib under the lib/w2k/i386 directory. That gave me a tclsh without a dependency on msvcrt7.dll
GWM This must be a new meaning to the word free that I am unaware of (or MS changed their prices) apparently it will cost $199 ($597 for three, so it isn't just shipping).
If you use the path setups like above (which I did), then the makefile doesn't work because it expects MSVCDIR to be set. Just delete those lines in the makefile.vc in both tcl and tk.
To build (assuming they are extracted to parallel dirs):
cd tcl8.4.7\win nmake nmakehlp.exe nmake -f makefile.vc INSTALLDIR=c:\tools\tcl\8.4.7 nmake -f makefile.vc INSTALLDIR=c:\tools\tcl\8.4.7 install cd ..\..\tk8.4.7\win nmake -f makefile.vc TCLDIR=..\..\tcl8.4.7 INSTALLDIR=c:\tools\tcl\8.4.7 nmake -f makefile.vc TCLDIR=..\..\tcl8.4.7 INSTALLDIR=c:\tools\tcl\8.4.7 install
And the customary demo:
c:\tools\tcl\8.4.7\bin\wish84 c:\tools\tcl\8.4.7\lib\tk8.4\demos\widget
The resulting binaries were run on win98 and the demo worked fine.
AR When compiling Tcl/Tk 8.4.19 on Windows XP with Visual Studio Express 2008, the resulting (installed) executable file does not launch (MSVC90.dll not found). This is because the manifest file must be incorporated. It can be done by inserting command:
mt.exe -manifest Release\tclsh84.exe.manifest -outputresource:Release\tclsh84t.exe
before doing the installation.
CLN I guess I'm really missing something 'cuz I installed the VC++ toolkit and the Platform SDK and I don't seem to have any file matching *MAKE.exe on my system. :-(
PT In the installed Platform SDK look in: "C:\Program Files\Microsoft SDK\Bin\Win64" for NMAKE.exe. The Microsoft Driver Development Kit (DDK) also provides nmake, masm and some other handy bits.
ET 4/9/2026 I have with some help from Claude, created a tcl/tk build script using windows batch. There are 2 scripts, the first can get the latest tcl/tk downloaded as 2 zip files into the current directory. The second one can build as static, debug, or release, a complete tcl/tk system using visual studio 2022. VS 2026 will work also, I just tried it.
Copy both of these scripts into say, gettcltk.bat and build.bat and place them in an empty directory (one with no spaces in the directory path). Open a x64 Native Tools Command Prompt Then cd to that directory and issue these commands:
Note, the build script currently assumes version 9.x.
gettcltk.bat build.bat unzip build.bat debug (or release or static)
If you run build.bat help, it will error out with a usage message.
Usage: build.bat [unzip | static [clean [only] | debug [clean [only] | release [clean [only]]]
The default with no arguments is to build a static clean and each of the 3 will build into different directories. If it succeeds, it will output a message showing where the executables live.
Here is the script to download the latest tcl/tk:
get tcl/tk@echo off
setlocal
:: Set download targets
set TCL_ZIP_URL=https://core.tcl-lang.org/tcl/zip/trunk/tcl.zip
set TK_ZIP_URL=https://core.tcl-lang.org/tk/zip/trunk/tk.zip
:: Always run from the directory where this batch file lives
cd /d "%~dp0"
set DEST_DIR=%CD%\
:: Check for spaces in working directory path
if not "%CD%"=="%CD: =%" (
echo ERROR: The working directory path contains spaces:
echo %CD%
echo Please move the script to a directory with no spaces in the path.
exit /b 1
)
:: Make sure destination exists
if not exist %DEST_DIR% (
echo Destination folder %DEST_DIR% does not exist.
exit /b 1
)
echo ================================
echo Downloading Tcl and Tk ZIP files
echo ================================
echo Downloading Tcl...
powershell -Command "Invoke-WebRequest -Uri '%TCL_ZIP_URL%' -OutFile '%DEST_DIR%tcl.zip'" || goto :error
echo Downloading Tk...
powershell -Command "Invoke-WebRequest -Uri '%TK_ZIP_URL%' -OutFile '%DEST_DIR%tk.zip'" || goto :error
echo ================================
echo Downloads complete:
echo Tcl: %DEST_DIR%tcl.zip
echo Tk : %DEST_DIR%tk.zip
echo ================================
goto :eof
:error
echo Download failed. Check your internet connection or permissions.
exit /b 1
And here is the build script:
build tcl/tk on windows with VS@echo off
setlocal ENABLEDELAYEDEXPANSION
:: Always run from the directory where this batch file lives
cd /d "%~dp0"
:: ===========================
:: Check for spaces in working directory path
:: ===========================
if not "%CD%"=="%CD: =%" (
echo ERROR: The working directory path contains spaces:
echo %CD%
echo Please move the script to a directory with no spaces in the path.
exit /b 1
)
:: ===========================
:: Check we're in an x64 Native Tools Command Prompt
:: ===========================
if not defined VSCMD_ARG_TGT_ARCH (
echo ERROR: This script must be run from a Visual Studio Native Tools Command Prompt.
echo Please launch "x64 Native Tools Command Prompt for VS 20xx" from the Start menu.
exit /b 1
)
if /i not "%VSCMD_ARG_TGT_ARCH%"=="x64" (
echo ERROR: This script requires an x64 prompt, but arch is: %VSCMD_ARG_TGT_ARCH%
echo Please launch "x64 Native Tools Command Prompt for VS 20xx" from the Start menu.
exit /b 1
)
:: ===========================
:: Detect Visual Studio version year
:: ===========================
set VSYEAR=Unknown
if defined VisualStudioVersion (
for /f "tokens=1 delims=." %%M in ("%VisualStudioVersion%") do set VSMAJOR=%%M
if "!VSMAJOR!"=="15" set VSYEAR=2017
if "!VSMAJOR!"=="16" set VSYEAR=2019
if "!VSMAJOR!"=="17" set VSYEAR=2022
if "!VSMAJOR!"=="18" set VSYEAR=2026
)
echo ===========================
echo Visual Studio : !VSYEAR! ^(version %VisualStudioVersion%^)
echo Target Arch : %VSCMD_ARG_TGT_ARCH%
echo Working Dir : %CD%
echo ===========================
:: ===========================
:: Parse arguments
:: Usage: %~nx0 [unzip | static [clean [only]] | debug [clean [only]] | release [clean [only]]]
:: Default (no args): static build with clean
:: "clean only" performs the clean step but skips the build
:: ===========================
set BUILDMODE=static
set DOCLEAN=1
set CLEANONLY=0
if /i "%1"=="unzip" goto :do_unzip
if /i "%1"=="static" (
set BUILDMODE=static
set DOCLEAN=0
if /i "%2"=="clean" (
set DOCLEAN=1
if /i "%3"=="only" set CLEANONLY=1
)
goto :do_build
)
if /i "%1"=="debug" (
set BUILDMODE=debug
set DOCLEAN=0
if /i "%2"=="clean" (
set DOCLEAN=1
if /i "%3"=="only" set CLEANONLY=1
)
goto :do_build
)
if /i "%1"=="release" (
set BUILDMODE=release
set DOCLEAN=0
if /i "%2"=="clean" (
set DOCLEAN=1
if /i "%3"=="only" set CLEANONLY=1
)
goto :do_build
)
if "%1"=="" goto :do_build
echo ERROR: Unknown argument "%1"
echo Usage: %~nx0 [unzip ^| static [clean [only]] ^| debug [clean [only]] ^| release [clean [only]]]
exit /b 1
:: ===========================
:: Unzip section
:: ===========================
:do_unzip
echo ===========================
echo Extracting Tcl and Tk from zip files...
echo ===========================
if exist tcl rd /s /q tcl
if exist tk rd /s /q tk
mkdir tcl
mkdir tk
tar -xf tcl.zip -C tcl --strip-components=1 || goto :error
tar -xf tk.zip -C tk --strip-components=1 || goto :error
if not exist "tcl\win\makefile.vc" (
echo ERROR: tcl.zip extracted incorrectly - tcl\win\makefile.vc not found.
echo Please zip the tcl directory itself, not its contents:
echo zip -r tcl.zip tcl
exit /b 1
)
if not exist "tk\win\makefile.vc" (
echo ERROR: tk.zip extracted incorrectly - tk\win\makefile.vc not found.
echo Please zip the tk directory itself, not its contents:
echo zip -r tk.zip tk
exit /b 1
)
echo Extraction verified OK.
echo ===========================
exit /b 0
:: ===========================
:: Build section
:: ===========================
:do_build
set TCLDIR=%CD%\tcl
set TKDIR=%CD%\tk
:: Set install directory, nmake options, and binary suffix based on build mode
:: Binary suffixes: static=s, debug=empty, release=empty
:: Note: using separate if blocks with parentheses to avoid trailing
:: spaces in variable values that the & separator on one line causes
if /i "!BUILDMODE!"=="static" (
set INSTALLDIR=%CD%\tcltk-static
set NMAKEOPTS=OPTS=static
set BINSUFFIX=s
)
if /i "!BUILDMODE!"=="debug" (
set INSTALLDIR=%CD%\tcltk-debug
set NMAKEOPTS=DEBUG=1
set BINSUFFIX=
)
if /i "!BUILDMODE!"=="release" (
set INSTALLDIR=%CD%\tcltk-release
set NMAKEOPTS=
set BINSUFFIX=
)
:: Pre-set install subdirectories to avoid nmake misparsing backslash+word on command line
set TCLINSTALL=!INSTALLDIR!\tcl
set TKINSTALL=!INSTALLDIR!\tk
if not exist "%TCLDIR%\win\makefile.vc" (
echo ERROR: Tcl source tree not found. Run "%~nx0 unzip" first.
exit /b 1
)
if not exist "%TKDIR%\win\makefile.vc" (
echo ERROR: Tk source tree not found. Run "%~nx0 unzip" first.
exit /b 1
)
echo ===========================
echo Build Mode : !BUILDMODE!
echo Install Dir : !INSTALLDIR!
echo Clean First : !DOCLEAN!
echo Clean Only : !CLEANONLY!
echo ===========================
echo ===========================
echo Cleaning up old install folder...
echo ===========================
if exist "!INSTALLDIR!" rd /s /q "!INSTALLDIR!"
if "!DOCLEAN!"=="1" (
echo ===========================
echo Cleaning Tcl build artifacts...
echo ===========================
cd /d %TCLDIR%\win
nmake -f makefile.vc !NMAKEOPTS! clean || goto :error
echo ===========================
echo Cleaning Tk build artifacts...
echo ===========================
cd /d %TKDIR%\win
nmake -f makefile.vc TCLDIR=%TCLDIR% !NMAKEOPTS! clean || goto :error
)
if "!CLEANONLY!"=="1" (
echo ===========================
echo Clean only requested - skipping build.
echo ===========================
goto :eof
)
echo ===========================
echo Building Tcl ^(!BUILDMODE!^)...
echo ===========================
cd /d %TCLDIR%\win
nmake -f makefile.vc !NMAKEOPTS! || goto :error
nmake -f makefile.vc !NMAKEOPTS! INSTALLDIR=!TCLINSTALL! install || goto :error
echo ===========================
echo Building Tk ^(!BUILDMODE!^)...
echo ===========================
cd /d %TKDIR%\win
nmake -f makefile.vc TCLDIR=%TCLDIR% !NMAKEOPTS! || goto :error
nmake -f makefile.vc TCLDIR=%TCLDIR% !NMAKEOPTS! INSTALLDIR=!TKINSTALL! install || goto :error
:: ===========================
:: Detect built Tcl version suffix (e.g. 91, 90) from actual built files
:: For debug/release detect from tcl9*.dll, for static from tclsh9*.exe
:: ===========================
set TCLVERSFX=
if /i "!BUILDMODE!"=="static" (
for %%F in ("!TCLINSTALL!\bin\tclsh9*.exe") do (
set TCLSHNAME=%%~nF
:: Strip "tclsh" prefix and trailing "s" suffix to get e.g. 91
set TCLVERSFX=!TCLSHNAME:tclsh=!
set TCLVERSFX=!TCLVERSFX:~0,-1!
)
) else (
for %%F in ("!TCLINSTALL!\bin\tcl9*.dll") do (
set TCLDLLNAME=%%~nF
set TCLVERSFX=!TCLDLLNAME:tcl=!
)
)
:: ===========================
:: Copy DLLs from Tcl bin to Tk bin for debug and release builds
:: so that wish can find them. Uses wildcard to catch all DLLs
:: including tcl9x.dll, zlib1.dll, libtommath.dll etc.
:: ===========================
if /i "!BUILDMODE!"=="debug" (
echo ===========================
echo Copying DLLs from Tcl bin to Tk bin directory...
echo ===========================
for %%F in ("!TCLINSTALL!\bin\*.dll") do copy /Y "%%F" "!TKINSTALL!\bin\" >nul
echo ===========================
echo Copying debug symbol files ^(.pdb^) to install bin folders...
echo ===========================
:: Find Debug intermediate directory for Tcl
for /d %%D in ("%TCLDIR%\win\Debug_AMD64_VC*") do set TCLDBG=%%D
:: Copy Tcl pdb files
xcopy /Y /I "!TCLDBG!\tclsh!TCLVERSFX!.pdb" "!TCLINSTALL!\bin\" >nul
xcopy /Y /I "!TCLDBG!\tcl!TCLVERSFX!.pdb" "!TCLINSTALL!\bin\" >nul
:: Find Debug intermediate directory for Tk
for /d %%D in ("%TKDIR%\win\Debug_AMD64_VC*") do set TKDBG=%%D
:: Copy Tk pdb files
xcopy /Y /I "!TKDBG!\wish!TCLVERSFX!.pdb" "!TKINSTALL!\bin\" >nul
xcopy /Y /I "!TKDBG!\tcl9tk!TCLVERSFX!.pdb" "!TKINSTALL!\bin\" >nul
)
if /i "!BUILDMODE!"=="release" (
echo ===========================
echo Copying DLLs from Tcl bin to Tk bin directory...
echo ===========================
for %%F in ("!TCLINSTALL!\bin\*.dll") do copy /Y "%%F" "!TKINSTALL!\bin\" >nul
)
echo ===========================
echo Locating library zip files...
echo ===========================
:: The static build produces libtcl9.x.zip and libtk9.x.zip in the lib folder
:: Copy them to a convenient location
if not exist "!INSTALLDIR!\ziplibs" mkdir "!INSTALLDIR!\ziplibs"
copy /Y "!TCLINSTALL!\lib\libtcl*.zip" "!INSTALLDIR!\ziplibs\" >nul 2>&1
copy /Y "!TKINSTALL!\lib\libtk*.zip" "!INSTALLDIR!\ziplibs\" >nul 2>&1
echo ===========================
echo Tcl/Tk Build Complete ^(!BUILDMODE!^)
echo Tclsh: !TCLINSTALL!\bin\tclsh!TCLVERSFX!!BINSUFFIX!.exe
echo Wish : !TKINSTALL!\bin\wish!TCLVERSFX!!BINSUFFIX!.exe
if /i "!BUILDMODE!"=="debug" (
echo PDBs : copied to bin folders
)
echo ===========================
goto :eof
:error
echo Build failed. Check error above.
exit /b 1
See also How to create a minimal Visual C++ install