Skip to content

Windows (MSVC) bootstrapping script #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ For other versions, check the git tags of this repository.
* all: Deleted unused files.
* LLVM: Support .lib extension for static zstd.
* LLVM: Copied CMake modules from out of tree.
* LLVM: Portable handling of .def linker flag
* Clang: Disable building of libclang-cpp.so.
* LLD: Added additional include directory to Zig's libunwind.
* zlib: Delete the ability to build a shared library.
Expand Down Expand Up @@ -59,6 +60,20 @@ significantly affect how long it takes to build:

When it succeeds, output can be found in `out/zig-<triple>-<cpu>/`.

## Windows Build Instructions

Bootstrapping on Windows with MSVC is also possible via `build.bat`, which
takes the same arguments as `build` above.

This script requires that the "C++ CMake tools for Windows" component be
installed via the Visual Studio installer.

The script must be run within the `Developer Command Prompt for VS 2019` shell:

```
build.bat <arch>-<os>-<abi> <mcpu>
```

### Supported Triples

If you try a "not tested" one and find a problem please file an issue,
Expand Down
258 changes: 258 additions & 0 deletions build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
@echo off

SETLOCAL EnableDelayedExpansion
if NOT DEFINED VSCMD_VER (
echo error: this script must be run within the visual studio developer command prompt
exit /b 1
)

where ninja >nul 2>nul
if %ERRORLEVEL% neq 0 (
echo error: this script requires ninja to be installed, as the Visual Studio cmake generator doesn't support alternate compilers
exit /b %ERRORLEVEL%
)

if "%1" == "" (set "TARGET=x86_64-windows-gnu") ELSE (set TARGET=%~1)
if "%2" == "" (set "MCPU=native") ELSE (set MCPU=%~2)

set TARGET_ABI=
set TARGET_OS_CMAKE=
FOR /F "tokens=2,3 delims=-" %%i IN ("%TARGET%") DO (
IF "%%i"=="macos" set "TARGET_OS_CMAKE=Darwin"
IF "%%i"=="freebsd" set "TARGET_OS_CMAKE=FreeBSD"
IF "%%i"=="windows" set "TARGET_OS_CMAKE=Windows"
IF "%%i"=="linux" set "TARGET_OS_CMAKE=Linux"
set TARGET_ABI=%%j
)

set OUTDIR=out-win
set ROOTDIR=%~dp0
set "ROOTDIR_CMAKE=%ROOTDIR:\=/%"
set ZIG_VERSION=0.11.0-dev.995+7350f0d9b

set JOBS_ARG=

pushd %ROOTDIR%

rem Build zlib for the host
mkdir "%ROOTDIR%%OUTDIR%\build-zlib-host"
cd "%ROOTDIR%%OUTDIR%\build-zlib-host"
cmake "%ROOTDIR%/zlib" ^
-G "Ninja" ^
-DCMAKE_INSTALL_PREFIX="%ROOTDIR%/%OUTDIR%/host" ^
-DCMAKE_PREFIX_PATH="%ROOTDIR%/%OUTDIR%/host" ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_USER_MAKE_RULES_OVERRIDE="%ROOTDIR%/zig/cmake/c_flag_overrides.cmake"
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

cmake --build . %JOBS_ARG% --target install
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

rem Build the libraries for Zig to link against, as well as native `llvm-tblgen` using msvc
mkdir "%ROOTDIR%%OUTDIR%\build-llvm-host"
cd "%ROOTDIR%%OUTDIR%\build-llvm-host"
cmake "%ROOTDIR%/llvm" ^
-G "Ninja" ^
-DLLVM_ENABLE_PROJECTS="lld;clang" ^
-DLLVM_ENABLE_LIBXML2=OFF ^
-DLLVM_ENABLE_ZSTD=OFF ^
-DCMAKE_INSTALL_PREFIX="%ROOTDIR%/%OUTDIR%/host" ^
-DCMAKE_PREFIX_PATH="%ROOTDIR%/%OUTDIR%/host" ^
-DLLVM_INCLUDE_TESTS=OFF ^
-DLLVM_INCLUDE_GO_TESTS=OFF ^
-DLLVM_INCLUDE_EXAMPLES=OFF ^
-DLLVM_INCLUDE_BENCHMARKS=OFF ^
-DLLVM_ENABLE_BINDINGS=OFF ^
-DLLVM_ENABLE_OCAMLDOC=OFF ^
-DLLVM_ENABLE_Z3_SOLVER=OFF ^
-DCLANG_BUILD_TOOLS=OFF ^
-DCLANG_INCLUDE_DOCS=OFF ^
-DLLVM_INCLUDE_DOCS=OFF ^
-DLLVM_USE_CRT_RELEASE=MT ^
-DCMAKE_BUILD_TYPE=Release
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%
cmake --build . %JOBS_ARG% --target install
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

rem Build an x86_64-windows-msvc zig using msvc, linking against LLVM/Clang/LLD/zlib built by msvc
mkdir "%ROOTDIR%%OUTDIR%\build-zig-host"
cd "%ROOTDIR%%OUTDIR%\build-zig-host"
cmake "%ROOTDIR%/zig" ^
-G "Ninja" ^
-DCMAKE_INSTALL_PREFIX="%ROOTDIR_CMAKE%%OUTDIR%/host" ^
-DCMAKE_PREFIX_PATH="%ROOTDIR_CMAKE%%OUTDIR%/host" ^
-DCMAKE_BUILD_TYPE=Release ^
-DZIG_STATIC=ON ^
-DZIG_STATIC_ZSTD=OFF ^
-DZIG_TARGET_TRIPLE=x86_64-windows-msvc ^
-DZIG_TARGET_MCPU=baseline

if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%
cmake --build . %JOBS_ARG% --target install
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

IF "%TARGET_ABI%"=="msvc" (
echo Building a target with the msvc ABI isn't supported yet
exit /b
)

set ZIG=%ROOTDIR%%OUTDIR%\host\bin\zig.exe
set "ZIG=%ZIG:\=/%"

rem CMP0091=NEW is required in order for the CMAKE_MSVC_RUNTIME_LIBRARY value to be respected,
rem which we need to be set to MultiThreaded when building msvc ABI targets

rem Cross compile zlib for the target
mkdir "%ROOTDIR%%OUTDIR%\build-zlib-%TARGET%-%MCPU%"
cd "%ROOTDIR%%OUTDIR%\build-zlib-%TARGET%-%MCPU%"
cmake "%ROOTDIR%/zlib" ^
-G "Ninja" ^
-DCMAKE_INSTALL_PREFIX="%ROOTDIR_CMAKE%%OUTDIR%/%TARGET%-%MCPU%" ^
-DCMAKE_PREFIX_PATH="%ROOTDIR_CMAKE%%OUTDIR%/%TARGET%-%MCPU%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_CROSSCOMPILING=True ^
-DCMAKE_SYSTEM_NAME="%TARGET_OS_CMAKE%" ^
-DCMAKE_C_COMPILER="%ZIG%;cc;-fno-sanitize=all;-s;-target;%TARGET%;-mcpu=%MCPU%" ^
-DCMAKE_CXX_COMPILER="%ZIG%;c++;-fno-sanitize=all;-s;-target;%TARGET%;-mcpu=%MCPU%" ^
-DCMAKE_ASM_COMPILER="%ZIG%;cc;-fno-sanitize=all;-s;-target;%TARGET%;-mcpu=%MCPU%" ^
-DCMAKE_RC_COMPILER="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-rc.exe" ^
-DCMAKE_AR="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-ar.exe" ^
-DCMAKE_RANLIB="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-ranlib.exe" ^
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ^
-DCMAKE_POLICY_DEFAULT_CMP0091=NEW
cmake --build . %JOBS_ARG% --target install
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

rem Cross compile zstd for the target
mkdir "%ROOTDIR%%OUTDIR%\%TARGET%-%MCPU%\lib"
copy "%ROOTDIR%\zstd\lib\zstd.h" "%ROOTDIR%%OUTDIR%\%TARGET%-%MCPU%\include\zstd.h"
cd "%ROOTDIR%%OUTDIR%\%TARGET%-%MCPU%\lib"
%ZIG% build-lib ^
--name zstd ^
-target %TARGET% ^
-mcpu=%MCPU% ^
-fstrip ^
-OReleaseFast ^
-lc ^
"%ROOTDIR%\zstd\lib\decompress\zstd_ddict.c" ^
"%ROOTDIR%\zstd\lib\decompress\zstd_decompress.c" ^
"%ROOTDIR%\zstd\lib\decompress\huf_decompress.c" ^
"%ROOTDIR%\zstd\lib\decompress\huf_decompress_amd64.S" ^
"%ROOTDIR%\zstd\lib\decompress\zstd_decompress_block.c" ^
"%ROOTDIR%\zstd\lib\compress\zstdmt_compress.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_opt.c" ^
"%ROOTDIR%\zstd\lib\compress\hist.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_ldm.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_fast.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_compress_literals.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_double_fast.c" ^
"%ROOTDIR%\zstd\lib\compress\huf_compress.c" ^
"%ROOTDIR%\zstd\lib\compress\fse_compress.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_lazy.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_compress.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_compress_sequences.c" ^
"%ROOTDIR%\zstd\lib\compress\zstd_compress_superblock.c" ^
"%ROOTDIR%\zstd\lib\deprecated\zbuff_compress.c" ^
"%ROOTDIR%\zstd\lib\deprecated\zbuff_decompress.c" ^
"%ROOTDIR%\zstd\lib\deprecated\zbuff_common.c" ^
"%ROOTDIR%\zstd\lib\common\entropy_common.c" ^
"%ROOTDIR%\zstd\lib\common\pool.c" ^
"%ROOTDIR%\zstd\lib\common\threading.c" ^
"%ROOTDIR%\zstd\lib\common\zstd_common.c" ^
"%ROOTDIR%\zstd\lib\common\xxhash.c" ^
"%ROOTDIR%\zstd\lib\common\debug.c" ^
"%ROOTDIR%\zstd\lib\common\fse_decompress.c" ^
"%ROOTDIR%\zstd\lib\common\error_private.c" ^
"%ROOTDIR%\zstd\lib\dictBuilder\zdict.c" ^
"%ROOTDIR%\zstd\lib\dictBuilder\divsufsort.c" ^
"%ROOTDIR%\zstd\lib\dictBuilder\fastcover.c" ^
"%ROOTDIR%\zstd\lib\dictBuilder\cover.c"
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

rem Ideally we could use ZLIB_USE_STATIC_LIBS here (which would detect zlib correctly),
rem but this was added in 3.24 and the MSVC-bundled CMake is 3.20. Instead, for the msvc
rem ABI the zlib path is specified explicitly.

IF "%TARGET_ABI%"=="msvc" (
set ZLIB_LIBRARY=-DZLIB_LIBRARY="%ROOTDIR_CMAKE%%OUTDIR%/%TARGET%-%MCPU%/lib/z.lib"
) else (
set ZLIB_LIBRARY=
)
rem Cross compile LLVM for the target
mkdir "%ROOTDIR%%OUTDIR%\build-llvm-%TARGET%-%MCPU%"
cd "%ROOTDIR%%OUTDIR%\build-llvm-%TARGET%-%MCPU%"
cmake "%ROOTDIR%/llvm" ^
-G "Ninja" ^
-DCMAKE_INSTALL_PREFIX="%ROOTDIR_CMAKE%%OUTDIR%/%TARGET%-%MCPU%" ^
-DCMAKE_PREFIX_PATH="%ROOTDIR_CMAKE%%OUTDIR%/%TARGET%-%MCPU%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_CROSSCOMPILING=True ^
-DCMAKE_SYSTEM_NAME="%TARGET_OS_CMAKE%" ^
-DCMAKE_C_COMPILER="%ZIG%;cc;-fno-sanitize=all;-s;-target;%TARGET%;-mcpu=%MCPU%" ^
-DCMAKE_CXX_COMPILER="%ZIG%;c++;-fno-sanitize=all;-s;-target;%TARGET%;-mcpu=%MCPU%" ^
-DCMAKE_ASM_COMPILER="%ZIG%;cc;-fno-sanitize=all;-s;-target;%TARGET%;-mcpu=%MCPU%" ^
-DCMAKE_RC_COMPILER="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-rc.exe" ^
-DCMAKE_AR="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-ar.exe" ^
-DCMAKE_RANLIB="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-ranlib.exe" ^
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ^
-DCMAKE_POLICY_DEFAULT_CMP0091=NEW ^
-DLLVM_ENABLE_BACKTRACES=OFF ^
-DLLVM_ENABLE_BINDINGS=OFF ^
-DLLVM_ENABLE_CRASH_OVERRIDES=OFF ^
-DLLVM_ENABLE_LIBEDIT=OFF ^
-DLLVM_ENABLE_LIBPFM=OFF ^
-DLLVM_ENABLE_LIBXML2=OFF ^
-DLLVM_ENABLE_OCAMLDOC=OFF ^
-DLLVM_ENABLE_PLUGINS=OFF ^
-DLLVM_ENABLE_PROJECTS="lld;clang" ^
-DLLVM_ENABLE_TERMINFO=OFF ^
-DLLVM_ENABLE_Z3_SOLVER=OFF ^
-DLLVM_ENABLE_ZLIB=FORCE_ON ^
-DLLVM_ENABLE_ZSTD=FORCE_ON ^
-DLLVM_USE_STATIC_ZSTD=ON ^
-DLLVM_TABLEGEN="%ROOTDIR_CMAKE%%OUTDIR%/host/bin/llvm-tblgen.exe" ^
-DLLVM_BUILD_TOOLS=OFF ^
-DLLVM_BUILD_STATIC=ON ^
-DLLVM_INCLUDE_UTILS=OFF ^
-DLLVM_INCLUDE_TESTS=OFF ^
-DLLVM_INCLUDE_GO_TESTS=OFF ^
-DLLVM_INCLUDE_EXAMPLES=OFF ^
-DLLVM_INCLUDE_BENCHMARKS=OFF ^
-DLLVM_INCLUDE_DOCS=OFF ^
-DLLVM_DEFAULT_TARGET_TRIPLE=%TARGET% ^
-DLLVM_TOOL_LLVM_LTO2_BUILD=OFF ^
-DLLVM_TOOL_LLVM_LTO_BUILD=OFF ^
-DLLVM_TOOL_LTO_BUILD=OFF ^
-DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF ^
-DCLANG_TABLEGEN="%ROOTDIR_CMAKE%%OUTDIR%/build-llvm-host/bin/clang-tblgen.exe" ^
-DCLANG_BUILD_TOOLS=OFF ^
-DCLANG_INCLUDE_DOCS=OFF ^
-DCLANG_INCLUDE_TESTS=OFF ^
-DCLANG_ENABLE_ARCMT=ON ^
-DCLANG_TOOL_CLANG_IMPORT_TEST_BUILD=OFF ^
-DCLANG_TOOL_CLANG_LINKER_WRAPPER_BUILD=OFF ^
-DCLANG_TOOL_C_INDEX_TEST_BUILD=OFF ^
-DCLANG_TOOL_ARCMT_TEST_BUILD=OFF ^
-DCLANG_TOOL_C_ARCMT_TEST_BUILD=OFF ^
-DCLANG_TOOL_LIBCLANG_BUILD=OFF ^
-DZLIB_USE_STATIC_LIBS=ON ^
%ZLIB_LIBRARY% ^
-DLIBCLANG_BUILD_STATIC=ON
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%
cmake --build . %JOBS_ARG% --target install
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

rem Finally, we can cross compile Zig itself, with Zig.
cd "%ROOTDIR%\zig"
%ZIG% build ^
--prefix "%ROOTDIR%%OUTDIR%\zig-%TARGET%-%MCPU%" ^
--search-prefix "%ROOTDIR%%OUTDIR%\%TARGET%-%MCPU%" ^
-Dstatic-llvm ^
-Drelease ^
-Dstrip ^
-Dtarget="%TARGET%" ^
-Dcpu="%MCPU%" ^
-Dversion-string="%ZIG_VERSION%"
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%

popd
13 changes: 12 additions & 1 deletion llvm/cmake/modules/AddLLVM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function(add_llvm_symbol_exports target_name export_file)
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script,\"${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}\"")
endif()
else()
elseif(WIN32)
set(native_export_file "${target_name}.def")

add_custom_command(OUTPUT ${native_export_file}
Expand All @@ -129,7 +129,18 @@ function(add_llvm_symbol_exports target_name export_file)
COMMENT "Creating export file for ${target_name}")
set(export_file_linker_flag "${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
if(MSVC)
# cl.exe or clang-cl, i.e. MSVC style command line interface
set(export_file_linker_flag "/DEF:\"${export_file_linker_flag}\"")
elseif(CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
# clang in msvc mode, calling a link.exe/lld-link style linker
set(export_file_linker_flag "-Wl,/DEF:\"${export_file_linker_flag}\"")
elseif(MINGW)
# ${export_file_linker_flag}, which is the plain file name, works as is
# when passed to the compiler driver, which then passes it on to the
# linker as an input file.
set(export_file_linker_flag "\"${export_file_linker_flag}\"")
else()
message(FATAL_ERROR "Unsupported Windows toolchain")
endif()
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " ${export_file_linker_flag}")
Expand Down