// Clang 19.x.x
//------------------------------------------------------------------------------
//
// Detect Clang
//
// We search in the following locations, in order of preference:
//  1) Vendorized in External (side by side with this bff)
//  2) Part of a Visual Studio installation (Program Files)
//  3) Default install location
//

#include "../../CPP/CPPHelper.bff"

#if file_exists( "19.1.5/bin/clang-cl.exe" )
    // Vendorized
    .Clang19_BasePath   = '$_CURRENT_BFF_DIR_$/19.1.5'
    .Clang19_Version    = '19.1.5'
#else
    #if file_exists( "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/LLVM/x64/bin/clang-cl.exe" )
        // Installed with VS2022
        .Clang19_BasePath = 'C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/LLVM/x64'
        .Clang19_Version    = '19.x.x'
    #else
        #if file_exists( "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/LLVM/x64/bin/clang-cl.exe" )
            // Installed with VS2022
            .Clang19_BasePath = 'C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/LLVM/x64'
            .Clang19_Version    = '19.x.x'
        #else
            #if file_exists( "C:/Program Files/LLVM/bin/clang-cl.exe" )
                // Default Install
                .Clang19_BasePath = 'C:/Program Files/LLVM'
                .Clang19_Version    = '19.x.x'
            #else
                //
                // Failed
                //
                Print( '----------------------------------------------------------------------' )
                Print( '- Unable to auto-detect Clang - please specify installation manually -' )
                Print( '----------------------------------------------------------------------' )
                .Clang19_BasePath   = .Set_Path_Here    // <-- Set path here
                .Clang19_Version    = .Set_Version_Here // <-- Set version here
            #endif
        #endif
    #endif
#endif

// Print details of used version. TODO:C Move to Clang.bff
Print( 'Using Clang $Clang19_Version$ from $Clang19_BasePath$' )

// Compiler
//------------------------------------------------------------------------------
Compiler( 'Compiler-Clang19' )
{
    .Root                           = '$Clang19_BasePath$'
    .ExtraFiles                     = {
                                        '$Root$/bin/concrt140.dll'
                                        '$Root$/bin/msvcp140.dll'
                                        '$Root$/bin/vcruntime140.dll'
                                        '$Root$/bin/vcruntime140_1.dll'
                                      }
    .Executable                     = '$Root$\bin\clang-cl.exe'

    // Allow tests to activate some experimental behavior
    #if ENABLE_RELATIVE_PATHS
        .UseRelativePaths_Experimental = true
    #endif
    #if ENABLE_SOURCE_MAPPING
        .SourceMapping_Experimental = '/fastbuild-test-mapping'
    #endif
}

// Compiler
//------------------------------------------------------------------------------
Compiler( 'Compiler-Clang19-NonCL' )
{
    .Root                           = '$Clang19_BasePath$'
    .ExtraFiles                     = {
                                        '$Root$/bin/msvcp140.dll'
                                        '$Root$/bin/vcruntime140.dll'
                                      }
    .Executable                     = '$Root$\bin\clang.exe'

    // Allow tests to activate some experimental behavior
    #if ENABLE_RELATIVE_PATHS
        .UseRelativePaths_Experimental = true
    #endif
    #if ENABLE_SOURCE_MAPPING
        .SourceMapping_Experimental = '/fastbuild-test-mapping'
    #endif
}

// ToolChain
//------------------------------------------------------------------------------
.ToolChain_Clang_Windows_Common =
[
    // Clang for Windows relies on the VS being present:
    //  - crt headers
    //  - crt libs/dlls
    Using( .ToolChain_VS_Windows_X64 )

    .Platform                       = 'x64Clang'

    // Librarian
    .Librarian                      = '$Clang19_BasePath$\bin\llvm-ar.exe'
    .LibrarianOptions               = 'rc "%2" "%1"' // NOTE: output must come first
                                    // = '/c echo %1 > %2' // Debug options
    // Linker
    .Linker                         = '$Clang19_BasePath$\bin\lld-link.exe'
    .LinkerOptions                  = '/NODEFAULTLIB /WX /NOLOGO /INCREMENTAL:NO /OUT:"%2" "%1" /DEBUG'
                                    + .VSLibPaths

    // Compiler Warnings
    .CommonCompilerWarningOptions   // Enable warnings
                                    = ' -Wall -Wextra -Weverything'     // All warnings
                                    + ' -Werror -Wfatal-errors'         // Warnings as fatal errors

                                    // Warnings that are not useful
                                    + ' -Wno-#pragma-messages'          // warning : %s [-W#pragma-messages]
                                    + ' -Wno-c++98-compat-pedantic'     // variadic macros are incompatible with C++98
                                    + ' -Wno-exit-time-destructors'     // declaration requires an exit-time destructor
                                    + ' -Wno-global-constructors'       // declaration requires a global destructor
                                    + ' -Wno-invalid-offsetof'          // we get the offset of members in non-POD types
                                    + ' -Wno-missing-prototypes'        // no previous prototype for function '%s'
                                    + ' -Wno-missing-variable-declarations' // no previous extern declaration for non-static variable '%s'
                                    + ' -Wno-gnu-line-marker'           // Clang complains about directives its own preprocessor generated
                                    + ' -Wno-switch-enum'               // Allow the use of "default" labels (we keep -Wswitch to ensure all cases are handled)
                                    + ' -Wno-switch-default'            // Don't require default: when all cases are already handled
                                    + .CPPCompilerWarningOptions

                                    // Warnings that fire but might be best to be fixed
                                    + ' -Wno-anon-enum-enum-conversion' // conversions between unrelated anonymous enums
                                    + ' -Wno-cast-function-type-strict' // converts to incompatible function type
                                    + ' -Wno-cast-qual'                 // cast from 'const %s *' to '%s *' drops const qualifier
                                    + ' -Wno-deprecated-copy-dtor'      // definition of implicit copy constructor for '%s' is deprecated because it has a user-declared destructor
                                    + ' -Wno-missing-noreturn'          // function '%s' could be declared with attribute 'noreturn'
                                    + ' -Wno-old-style-cast'            // use of old-style cast
                                    + ' -Wno-unsafe-buffer-usage'       // unsafe pointer arithmetic

    // File Extensions
    .LibExtension                   = '.a'
    .ExeExtension                   = '.exe'
]

// ToolChain
//------------------------------------------------------------------------------
.ToolChain_Clang_Windows =
[
    Using( .ToolChain_Clang_Windows_Common )

    // Compiler Options
    .Compiler                       = 'Compiler-Clang19'
    .CommonCompilerOptions          = ' -c'                             // Compile only
                                    + ' /Z7'                            // Include debug info
                                    + ' -D_CRT_SECURE_NO_WARNINGS'

                                    // Unicode
                                    + ' /utf-8'
                                    + ' /D "_UNICODE" /D "UNICODE"'

                                    // Include paths
                                    + ' -I"./"'
                                    + .VSIncludePaths_ClangCl

                                    // x64
                                    + ' -m64'
                                    + ' --target=x86_64-windows-msvc'

                                    // No RTTI
                                    + ' /GR-'

                                    // No Exceptions
                                    + ' /EHs-c-'

                                    // Warnings
                                    + .CommonCompilerWarningOptions

    .CompilerOptions                = ' /TP -o"%2" "%1" $CommonCompilerOptions$'
                                    + .CPPVersion
    .CompilerOptionsC               = ' /TC -o"%2" "%1" $CommonCompilerOptions$'
    .PCHOptions                     = ' /TP $CommonCompilerOptions$ "%1" /Fo"%3" /Fp"%2" /Yc"PrecompiledHeader.h"'
                                    + .CPPVersion
]

// ToolChain
//------------------------------------------------------------------------------
.ToolChain_ClangNonCL_Windows =
[
    Using( .ToolChain_Clang_Windows_Common )

    // Compiler Options
    .Compiler                       = 'Compiler-Clang19-NonCL'
    .CommonCompilerOptions          = ' -c'                             // Compile only
                                    + ' -g'                             // Include debug info
                                    + ' -D_CRT_SECURE_NO_WARNINGS'
                                    
                                    // Unicode
                                    + ' /utf-8'
                                    + ' /D "_UNICODE" /D "UNICODE"'

                                    // Include paths
                                    + ' "-I./"'

                                    // x64
                                    + ' -m64'
                                    + ' --target=x86_64-windows-msvc'

                                    // No RTTI
                                    + ' -fno-rtti'

                                    // No Exceptions
                                    + ' -fno-exceptions'

                                    // Warnings
                                    + .CommonCompilerWarningOptions

    .CompilerOptions                = ' -x c++ -o"%2" "%1" $CommonCompilerOptions$'
                                    + .CPPVersion
    .CompilerOptionsC               = ' -x c -o"%2" "%1" $CommonCompilerOptions$'
]

//------------------------------------------------------------------------------