@echo off

rem file      : build-msvc.bat.in
rem license   : MIT; see accompanying LICENSE file

setlocal EnableDelayedExpansion
goto start

:usage
echo.
rem echo Usage: %0 [/?] [^<options^>] [^<cl-compiler^>]
echo Usage: %0 [/?] [^<options^>]
echo Options:
echo   --local                Don't build from packages, only from local source.
echo   --no-bpkg              Don't install bpkg nor bdep (requires --local).
echo   --no-bdep              Don't install bdep.
echo   --no-modules           Don't install standard build system modules.
echo   --modules "<list>"     Install only specified standard build system modules.
echo   --install-dir ^<dir^>    Alternative installation directory.
echo   --repo ^<loc^>           Alternative package repository location.
echo   --trust ^<fp^>           Repository certificate fingerprint to trust.
echo   --timeout ^<sec^>        Network operations timeout in seconds.
echo   --verbose ^<level^>      Diagnostics verbosity level between 0 and 6.
echo.
echo By default the batch file will use cl.exe as the C++ compiler and install
echo into C:\build2. It also expects to find the base utilities in the bin\
echo subdirectory of the installation directory ^(C:\build2\bin\ by default^).
echo.
echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
echo and 'no' (trust nothing).
echo.
echo The script by default installs the following standard build system
echo modules:
echo.
echo %standard_modules%
echo.
echo Use --no-modules to suppress installing build system modules or
echo --modules "<list>" to specify a comma-separated subset to install.
echo.
echo See the BOOTSTRAP-WINDOWS-MSVC file for details.
echo.
goto end

:start

set "owd=%CD%"

rem Package repository URL (or path).
rem
if "_%BUILD2_REPO%_" == "__" (
  set "BUILD2_REPO=@BUILD2_REPO@"
)

rem Package versions.
rem
set "build2_ver=@BUILD2_VERSION@"
set "bpkg_ver=@BPKG_VERSION@"
set "bdep_ver=@BDEP_VERSION@"

rem Standard modules comma-separated list and versions.
rem
rem NOTE: we currently print the list as a single line and will need to
rem somehow change that when it becomes too long.
rem
set "standard_modules=kconfig"
set "kconfig_ver=@KCONFIG_VERSION@"

rem The bpkg configuration directory.
rem
set "cver=@CONFIG_VER@"
set "cdir=build2-toolchain-%cver%"

rem Parse options.
rem
set "local="
set "bpkg=true"
set "bdep=true"
set "modules=%standard_modules%"
set "idir=C:\build2"
set "trust="
set "timeout="
set "verbose="

:options
if "_%~1_" == "_/?_"     goto usage
if "_%~1_" == "_-h_"     goto usage
if "_%~1_" == "_--help_" goto usage

if "_%~1_" == "_--local_" (
  set "local=true"
  shift
  goto options
)

if "_%~1_" == "_--no-bpkg_" (
  set "bpkg="
  shift
  goto options
)

if "_%~1_" == "_--no-bdep_" (
  set "bdep="
  shift
  goto options
)

if "_%~1_" == "_--no-modules_" (
  set "modules="
  shift
  goto options
)

if "_%~1_" == "_--modules_" (
  set "modules=%~2"
  shift
  shift
  goto options
)

if "_%~1_" == "_--install-dir_" (
  if "_%~2_" == "__" (
    echo error: installation directory expected after --install-dir
    goto error
  )
  set "idir=%~2"
  shift
  shift
  goto options
)

if "_%~1_" == "_--trust_" (
  if "_%~2_" == "__" (
    echo error: certificate fingerprint expected after --trust
    goto error
  )
  set "trust=%~2"
  shift
  shift
  goto options
)

if "_%~1_" == "_--repo_" (
  if "_%~2_" == "__" (
    echo error: repository location expected after --repo
    goto error
  )
  set "BUILD2_REPO=%~2"
  shift
  shift
  goto options
)

if "_%~1_" == "_--timeout_" (
  if "_%~2_" == "__" (
    echo error: value in seconds expected after --timeout
    goto error
  )
  set "timeout=%~2"
  shift
  shift
  goto options
)

if "_%~1_" == "_--verbose_" (
  if "_%~2_" == "__" (
    echo error: diagnostics level between 0 and 6 expected after --verbose
    goto error
  )
  set "verbose=%~2"
  shift
  shift
  goto options
)

if "_%~1_" == "_--_" shift

rem Validate options and arguments.
rem

rem @@ Temporarily retained for backwards compatibility.
rem
if not "_%1_" == "__" (
  set "idir=%1"
)
if not "_%2_" == "__" (
  set "trust=%2"
)
rem Compiler.
rem
rem if "_%1_" == "__" (
  set "cxx=cl"
rem ) else (
rem  set "cxx=%1"
rem )

rem If --no-bpkg is specified, then we require --local to also be specified
rem since it won't be possible to build things from packages without bpkg.
rem Also imply --no-bdep in this case, since bdep is pretty much useless
rem without bpkg.
rem
if "_%bpkg%_" == "__" (
  if "_%local%_" == "__" (
    echo error: --no-bpkg can only be used for local installation
    echo   info: additionally specify --local
    goto error
  )

  set "bdep="
)

for %%m in (%modules%) do (
  if "_!%%m_ver!_" == "__" (
    echo error: unknown standard build system module '%%m'
    echo   info: available standard modules: %standard_modules%
    goto error
  )
)

rem Convert a relative path to an absolute.
rem
for /F "delims=|" %%D in ("%idir%") do set "idir=%%~dpnxD"

rem Certificate to trust.
rem
if not "_%trust%_" == "__" (
  if "_%trust%_" == "_yes_" (
    set "trust=--trust-yes"
  ) else (
    if "_%trust%_" == "_no_" (
      set "trust=--trust-no"
    ) else (
      set "trust=--trust %trust%"
    )
  )
)

rem Network timeout.
rem
if not "_%timeout%_" == "__" (
  set "timeout=--fetch-timeout %timeout%"
)

rem Diagnostics verbosity.
rem
if not "_%verbose%_" == "__" (
  set "verbose=--verbose %verbose%"
)

if not exist %idir%\bin\ (
  echo error: %idir%\bin\ does not exist
  goto error
)

if exist build\config.build (
  echo error: current directory already configured, start with clean source
  goto error
)

if "_%local%_" == "__" (
  if exist ..\%cdir%\ (
    echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
    goto error
  )
)

set "PATH=%idir%\bin;%PATH%"

rem Show the steps we are performing.
rem
@echo on

@rem Verify the compiler works.
@rem
%cxx%
@if errorlevel 1 goto error

@rem Suppress loading of default options files.
@rem
set "BUILD2_DEF_OPT=0"
set "BPKG_DEF_OPT=0"
set "BDEP_DEF_OPT=0"

@rem Bootstrap.
@rem
cd build2

@rem Execute in a separate cmd.exe to preserve the echo mode.
@rem
cmd /C bootstrap-msvc.bat %cxx%
@if errorlevel 1 goto error

build2\b-boot --version
@if errorlevel 1 goto error

build2\b-boot %verbose% config.cxx=%cxx% config.bin.lib=static build2\exe{b}
@if errorlevel 1 goto error

move /y build2\b.exe build2\b-boot.exe
@if errorlevel 1 goto error

build2\b-boot --version
@if errorlevel 1 goto error

cd ..

@rem Local installation early return.
@rem
@if "_%local%_" == "__" goto stage

build2\build2\b-boot %verbose% configure^
 config.cxx=%cxx%^
 config.cc.coptions=/O2^
 config.bin.lib=shared^
 config.install.root=%idir%
@if errorlevel 1 goto error

@rem Install toolchain.
@rem
@set "projects=build2\"

@if "_%bpkg%_" == "_true_" (
  set "projects=%projects% bpkg\"
)

@if "_%bdep%_" == "_true_" (
  set "projects=%projects% bdep\"
)

build2\build2\b-boot %verbose% install: %projects%
@if errorlevel 1 goto error

where b
@if errorlevel 1 goto error

b --version
@if errorlevel 1 goto error

@if "_%bpkg%_" == "__" goto bpkg_vle

where bpkg
@if errorlevel 1 goto error

bpkg --version
@if errorlevel 1 goto error

:bpkg_vle

@if "_%bdep%_" == "__" goto bdep_vle

where bdep
@if errorlevel 1 goto error

bdep --version
@if errorlevel 1 goto error

:bdep_vle

@rem Install modules.
@rem
@set "projects="
@set "tests="

@for %%m in (%modules%) do @(
  set "projects=!projects! libbuild2-%%m\"
  set "tests=!tests! tests\libbuild2-%%m-tests\"
)

@if "_%projects%_" == "__" goto mods_ile

b install: %projects:~1%
@if errorlevel 1 goto error

b noop: %tests:~1%
@if errorlevel 1 goto error

:mods_ile

@echo off

echo.
echo Toolchain installation: %idir%\bin
echo Build configuration:    %owd%
echo.

goto end

@rem Build and stage the build system and the package manager.
@rem
:stage

build2\build2\b-boot %verbose% configure^
 config.cxx=%cxx%^
 config.bin.lib=shared^
 config.bin.suffix=-stage^
 config.install.root=%idir%^
 config.install.data_root=root\stage
@if errorlevel 1 goto error

build2\build2\b-boot %verbose% install: build2\ bpkg\
@if errorlevel 1 goto error

where b-stage
@if errorlevel 1 goto error

b-stage --version
@if errorlevel 1 goto error

where bpkg-stage
@if errorlevel 1 goto error

bpkg-stage --version
@if errorlevel 1 goto error

@rem Build the entire toolchain from packages.
@rem
cd ..

md %cdir%
@if errorlevel 1 goto error

cd %cdir%

@rem Save full path for later.
@rem
@set "cdir=%CD%"

bpkg-stage %verbose% create^
 cc^
 config.cxx=%cxx%^
 config.cc.coptions=/O2^
 config.bin.lib=shared^
 config.install.root=%idir%
@if errorlevel 1 goto error

bpkg-stage %verbose% add %BUILD2_REPO%
@if errorlevel 1 goto error

bpkg-stage %verbose% %timeout% %trust% fetch
@if errorlevel 1 goto error

@set "packages=build2/%build2_ver% bpkg/%bpkg_ver%"

@if "_%bdep%_" == "_true_" (
  set "packages=%packages% bdep/%bdep_ver%"
)

bpkg-stage %verbose% %timeout% build --for install --yes --plan= %packages%
@if errorlevel 1 goto error

bpkg-stage %verbose% install --all
@if errorlevel 1 goto error

where b
@if errorlevel 1 goto error

b --version
@if errorlevel 1 goto error

where bpkg
@if errorlevel 1 goto error

bpkg --version
@if errorlevel 1 goto error

@if "_%bdep%_" == "__" goto bdep_vpe

where bdep
@if errorlevel 1 goto error

bdep --version
@if errorlevel 1 goto error

:bdep_vpe

@rem Build, install, and verify the build system modules.
@rem
@set "packages="
@set "tests="

@for %%m in (%modules%) do @(
  set "packages=!packages! libbuild2-%%m/!%%m_ver!"
  set "tests=!tests! tests\libbuild2-%%m-tests\"
)

@if "_%packages%_" == "__" goto mods_ipe

bpkg build --for install %packages:~1%
@if errorlevel 1 goto error

bpkg install --all-pattern=libbuild2-*
@if errorlevel 1 goto error

:mods_ipe

cd %owd%

@if "_%tests%_" == "__" goto mods_lpe

b noop: %tests:~1%
@if errorlevel 1 goto error

:mods_lpe

@rem Clean up stage.
@rem
b %verbose% uninstall: build2\ bpkg\
@if errorlevel 1 goto error

@echo off

echo.
echo Toolchain installation: %idir%\bin
echo Build configuration:    %cdir%
echo.

goto end

:error
@echo off
cd %owd%
endlocal
exit /b 1

:end
endlocal