-
Notifications
You must be signed in to change notification settings - Fork 113
vs2008_linux_wine
title: Visual C++ 2008 build environment on Linux using Wine description: Running the VS2008 x86 command-line toolchain (cl/link) in a 32-bit Wine prefix — for plugin_max builds and pipeline_max reference-arithmetic probes published: true date: 2026-07-07T00:00:00.000Z tags: editor: markdown dateCreated: 2026-07-07T00:00:00.000Z
Companion page to 3ds Max 9 on Linux using Wine, which covers the usual prefix conventions. This page covers the command-line toolchain only (
cl.exe,link.exe,lib.exe,nmake.exe) — not the Visual Studio IDE, which is not worth fighting under Wine. {.is-info}
Why this exists: the
~/pipeline_exportreference outputs were produced by 3ds Max 2010, a VS2008 x86 build (see the provenance note in the pipeline_max design document, §10i). Reproducing the reference exporter's float arithmetic bit-for-bit therefore means VS2008 x86 codegen. This environment is for building small kernel probe harnesses (decompose/normal/vertex-path kernels compiled with the same compiler, run under Wine, outputs compared against the headless x64 exporters) and, if ever needed, theplugin_maxbinaries themselves. {.is-info}
Same conventions as the Max 9 page: a dedicated 32-bit prefix under ~/.local/share/wineprefixes/.
WINEARCH=win32 WINEPREFIX=~/.local/share/wineprefixes/vs2008/ winecfg
WINEARCH=win32 WINEPREFIX=~/.local/share/wineprefixes/vs2008/ winetricksIn Winetricks, Install a Windows DLL or component:
- vcrun2008 (the CRT the produced binaries and the toolchain itself expect)
- msxml6 (some SDK tools want it; harmless to have)
The .NET components are only needed if you attempt the full installer (below) — the toolchain itself does not use .NET.
Headless / scripted setup — winetricks' unattended mode makes the whole prefix reproducible from a script:
export WINEARCH=win32 WINEPREFIX=~/.local/share/wineprefixes/vs2008/
WINEDLLOVERRIDES="mscoree,mshtml=" wineboot -i # init the prefix, skip Mono/Gecko prompts
winetricks -q vcrun2008 msxml6On a machine with no display at all (CI, plain ssh), wrap the winetricks call in xvfb-run -a — some component installers open a window even when silenced. vcrun2008/msxml6 are reliable unattended; the dotnet35 verb (Route B only) is slow and flaky under -q, one more reason to prefer Route A.
Route A — copy an existing install (recommended, and the route this page assumes). The compiler does not need registry state; a working install tree is enough. From the existing local VS2008 install, copy into the prefix's drive_c:
-
Program Files/Microsoft Visual Studio 9.0/VC/—bin/,include/,lib/(x86 only;bin/amd64etc. are irrelevant here) -
Program Files/Microsoft Visual Studio 9.0/Common7/IDE/—cl.exeloadsmspdb80.dll(and friendsmsobj80.dll,mspdbcore.dll) from here; either keep the directory and add it toPATH, or copy those DLLs next tocl.exe -
Program Files/Microsoft SDKs/Windows/v6.0A/—Include/andLib/(the Windows SDK headers/libs VS2008 shipped with)
If the local install already lives in a Wine prefix (e.g. it was used to build plugin_max), point the environment below at that prefix instead — nothing more to do.
Route B — run the installer under Wine. Known-troublesome: the VS2008 setup chain wants Windows Installer sequencing and .NET 3.5 (winetricks dotnet35 in a win32 prefix, slow and fragile), and partial-failure states are common. If the installer must be used, deselect everything except Visual C++ and expect to iterate. Route A is strictly less pain when any Windows machine or existing install is available.
Wine maps the Unix environment into the Windows process environment, so vcvars32.bat is unnecessary — export the three variables from the shell. Keep a wrapper script, e.g. ~/bin/winecl:
#!/bin/sh
export WINEPREFIX=~/.local/share/wineprefixes/vs2008/
VS='C:\Program Files\Microsoft Visual Studio 9.0'
SDK='C:\Program Files\Microsoft SDKs\Windows\v6.0A'
export INCLUDE="$VS\\VC\\include;$SDK\\Include"
export LIB="$VS\\VC\\lib;$SDK\\Lib"
export WINEPATH="$VS\\VC\\bin;$VS\\Common7\\IDE"
export WINEDEBUG=-all
exec wine "$VS\\VC\\bin\\cl.exe" "$@"(WINEPATH appends to the Windows PATH; it is how cl.exe finds mspdb80.dll in Common7/IDE without copying DLLs around.)
Smoke test:
printf '#include <stdio.h>\nint main(){printf("%%a\\n", 1.0f/3.0f);return 0;}\n' > /tmp/t.c
winecl /nologo /O2 /Z7 /Fe:t.exe t.c # run from the source directory
wine t.exe-
/Z7, never/Zi./Zispawnsmspdbsrv.exe(the PDB server process), which is unreliable under Wine and hangs builds./Z7embeds the debug info in the object files and never starts it. For probe harnesses just omit debug info entirely. -
Case sensitivity. Windows-authored sources
#include <WinDef.h>with arbitrary casing; the SDK tree copied onto a case-sensitive filesystem will miss them. Keeping the trees inside the prefix'sdrive_cand letting Wine do the path lookup handles most of it; stubborn cases wantciopfs/casefoldor a lowercase-normalized copy of the include dirs. -
Response files and long command lines work fine (
cl @args.rsp); prefer them over heroic shell quoting of\-ridden paths. -
Parallelism:
cl /MPworks, but eachclis a Wine process — for the small probe harnesses this page targets, plain serial compiles are simpler and fast enough.
To match the Max 2010-era plugin codegen, compile probes the way the plugin was built:
-
/O2 /fp:precise(VS2008 defaults for release; no/arch:SSE*— the x87 blended default is the point of the exercise) - The CRT initializes the x87 control word to 53-bit precision (
_PC_53); a probe that wants Max-identical behavior should leave it alone (do not call_controlfp), since the reference ran with the CRT default. - Link
/SUBSYSTEM:CONSOLE; dump results as text (hex float bits,printf("%08x")on the bit pattern) so outputs diff cleanly against the Linux x64 exporters' dumps.
decomp_affine and the other decomp.h/geom utilities are exports of Max's own geom.dll (import library geom.lib in the Max 2010 SDK) — they are Autodesk-compiled code, not headers, which is exactly why no recompilation on the Linux side can reproduce their bits. A probe exe that links geom.lib and sits next to Max 2010's geom.dll (plus its direct dependencies; check with winedump -j import geom.dll) runs the actual reference decompose. That is the scoped experiment for the DefaultRotQuat/Scale byte-identity question (design doc §10i). Deeper Max internals (Mesh::buildRenderNormals in mesh.dll) pull progressively more of the Max runtime as dependencies — feasibility drops fast; the angle-weighted replication in pipeline_max_export_shape plus its 1e-4 verdict tier is the accepted answer there.
mspdb80.dll not found — verify WINEPATH includes Common7\IDE, or copy mspdb80.dll, mspdbcore.dll, msobj80.dll next to cl.exe.
Mixed mspdb* DLL versions between VC/bin and Common7/IDE (e.g. trees copied from different service-pack levels). Copy both directories from the same install.
LIB doesn't reach the Windows SDK Lib directory — the VC lib directory alone only has the CRT.