Para o clang/LLVM para Windows, as mesmas opções têm suporte por meio do front-end “semelhante ao MSVC” clang-cl. Algumas opções específicas do conjunto de ferramentas clang são indicadas abaixo.
Padrão da linguagem C++ (/std)
Por padrão, o Visual C++ usa o modo de conformidade C++14. Para habilitar o modo de conformidade C++17, use /std:c++17. As APIs do Microsoft Game Development Kit (GDK) no XBOX requerem C++11 ou posterior, e o uso de C++14 ou posterior tem suporte completo para o desenvolvimento de títulos.
/std:c++latest habilita a conformidade com o rascunho do C++20 no Visual Studio 2017 e no Visual Studio 2019. Como o comportamento de /std:c++latest continua mudando com as atualizações de serviço do Visual C++, ele deve ser usado com alguma cautela.
O VS 2019 (16.11) e o VS 2022 dão suporte à opção /std:c++20. Veja esta postagem de blog.
A partir do VS 2019 (16.8), o compilador Visual C++ dá suporte aPara obter mais informações, veja:/std:c11e/std::c17. No entanto, o GameRuntime e muitos outros cabeçalhos do GDK requerem C++11 ou posterior.
- /std (Specify Language Standard Version) (Microsoft Docs)
- Standards version switches in the compiler (C++ Team Blog)
- C11 and C17 Standard Support Arriving in MSVC (C++ Team Blog)
Usar /O1 /Oi para otimização geral e /O2 para módulos “quentes”
Para a CPU com execução fora de ordem do XBOX One e do XBOX Series X/S, fazer um segmento de código caber no cache de instruções geralmente é mais importante do que ter a versão absolutamente mais rápida do código, por isso otimizar para espaço é preferível. Reserve o uso de otimizar para tempo apenas para módulos ou funções específicos. A geração de intrínsecos vale o código adicional para jogos, pois melhora o desempenho de ponto flutuante. Você também pode habilitar otimizar para tempo em uma função específica ou em um conjunto de funções envolvendo-os com #pragma optimize("t", on) / #pragma optimize("", on ). Lembre-se de que otimizar para tempo (/O2 ou /Ox) pode resultar em um aumento drástico no tamanho do programa devido ao desenrolamento agressivo de loops.
As otimizações do autovetorizador Single Instruction Multiple Data (SIMD) só são habilitadas com
/O2 ou /Ox. A otimização guiada por perfil (PGO) pode fazer escolhas melhores sobre onde exatamente aplicar otimizar para tempo versus otimizar para espaço.Por motivos históricos, é importante observar que /Ox é quase igual a O2, mas não inclui /GF (Eliminate Duplicate Strings) nem /Gy (Enable Function-Level Linking). Portanto, em geral, você deve preferir usar /O2 em vez de /Ox. Se você usar /Ox, habilite explicitamente pelo menos /Gy, que é importante para habilitar a otimização do vinculador.Opção do compilador /fp:fast
O sinalizador /fp, introduzido com o Visual Studio 2005, controla os vários modelos de ponto flutuante usados pelo compilador (fast, precise, strict, except). O modelo de ponto flutuante rápido usa várias otimizações que não fazem parte das regras básicas do “C”. O modelo de ponto flutuante preciso desabilita essas otimizações extras e é o padrão. Recomendamos usar /fp:fast para jogos.
Para obter mais informações, veja:
- /fp (Specify floating-point behavior) (Microsoft Docs)
- Do You Prefer Fast or Precise? (C++ Team Blog)
Opção do compilador /arch
O padrão implícito para plataformas nativas x64 é /arch:SSE2. Para os consoles XBOX One (CPU AMD Jaguar), você deve usar /arch:AVX. Para o XBOX Series X/S (CPU AMD Hercules), recomendamos usar /arch:AVX2.
O principal benefício de usar /arch:AVX ou /arch:AVX2 é que isso faz o compilador gerar versões com prefixo VEX das instruções SSE, que usam uma codificação não destrutiva de 3 operandos em vez da codificação padrão de 2 operandos, na qual um dos operandos de origem é substituído pelo resultado. Isso afeta tanto o ponto flutuante escalar no código nativo x64 que usa instruções SSE quanto o uso explícito de intrínsecos SSE. Isso ajuda a reduzir a pressão de agendamento de registradores e pode eliminar algumas instruções movaps.
Para obter mais informações, veja:
- /arch (x64) (Microsoft Docs)
- AVX2 floating point improvements in Visual Studio 2019 version 16.5 (C++ Team Blog)
/d2vzeroupper para otimizar de acordo com o comportamento preferido da CPU AMD Hercules quanto ao uso da instrução vzeroupper. Para a otimização de programa inteiro (/LTCG), o equivalente necessário do vinculador é /d2:-vzeroupper. Esse é o comportamento padrão do compilador do VS 2022.
Para o XBOX One usando o Visual Studio 2022, você também deve usar /d2vzeroupper- para otimizar de acordo com o comportamento preferido da CPU AMD Jaguar quanto ao uso da instrução vzeroupper. Para a otimização de programa inteiro (/LTCG), o equivalente necessário do vinculador é /d2:-vzeroupper-. Esse é o comportamento padrão do compilador do VS 2019.
Para o clang/LLVM, use-march=btver2para o XBOX One (CPU AMD Jaguar) e-march=znver2para o XBOX Series X/S (CPU AMD Hercules).
Para o desenvolvimento para PC, você pode contar com o suporte a SSE e SSE2 em todas as CPUs nativas x64, pois isso faz parte da definição da arquitetura. Você também pode exigir SSE3 com segurança, pois ele tem suporte em todas as CPUs Intel modernas compatíveis com o Windows 10 ou o Windows 11. Faça verificações de suporte da CPU em tempo de execução para qualquer coisa além de SSE2 que você usar no PC, como AVX ou AVX2.
Opção do compilador /favor
A opção /favor controla as escolhas de otimização do compilador x64 para processadores AMD64 versus Intel 64. Para o desenvolvimento para XBOX, use /favor:AMD64.
Modelo de tratamento de exceções (/EHsc)
No código nativo x64, o tratamento de exceções não tem nenhum efeito direto no código do epílogo ou do prólogo da função. Enquanto o Windows x86 usava um esquema baseado em pilha que envolvia código adicional injetado nos módulos, a geração de código nativo x64 usa um esquema baseado em tabela para garantir que a pilha possa ser desenrolada corretamente durante o processamento de exceções. O esquema baseado em tabela usado pelo código nativo x64 também tem a vantagem de ser mais seguro, pois não está sujeito a ataques de estouro de buffer da pilha. Esse design tem várias implicações.
- O tratamento de exceções não afeta o número de instruções no código gerado. Enquanto esquemas baseados em pilha, como os usados no Windows x86, podem gerar uma penalidade de 5 a 10% no código, o tratamento de exceções nativo x64 gera apenas dados baseados em tabela associados ao executável, e não mais instruções. Mesmo desabilitar explicitamente o tratamento de exceções no código nativo x64, o que não recomendamos, economiza apenas uma pequena quantidade de dados auxiliares para o tratamento do C++ e não desabilita a geração dos dados de desenrolamento da pilha.
- Os blocos try/catch são baratos de usar. Um bloco try/catch no esquema baseado em pilha adiciona algum código adicional para rastreamento. No x64, isso apenas adiciona mais algumas entradas na tabela de desenrolamento.
- O processamento de exceções (ou seja, o lançamento real de uma exceção) requer algumas pesquisas adicionais em tabelas. A troca é que, embora os esquemas baseados em pilha possam lançar exceções mais rapidamente, eles fazem isso com uma penalidade em todos os caminhos de código. O esquema baseado em tabela é mais lento para “lançar”, mas não afeta os outros caminhos de código. Como as exceções não devem ser usadas como controle de fluxo normal e, na verdade, só devem ser disparadas em circunstâncias excepcionais, esse custo de desempenho adicional do processamento é insignificante em comparação com o desempenho geral do aplicativo.
HRESULT, em vez de tratamento de exceções, para retornar resultados de erro, portanto o nível de adoção do tratamento de exceções do C++ na base de código de um título fica totalmente a seu critério. As exceções não devem ser usadas para controle de fluxo, portanto geralmente o melhor uso é em cenários de “falha rápida”, o que pode simplificar a depuração e a codificação. Grande parte da Standard C++ Library pressupõe que o tratamento de exceções esteja habilitado para um tratamento de erros adequado.
Não é recomendável desabilitar explicitamente o tratamento de exceções, pois isso afeta negativamente a análise pós-falha e não melhora a geração de código. Não recomendamos o uso de /EHa, pois isso pode inibir o otimizador.
O operador
new sempre lança uma exceção do C++ quando uma alocação falha. Se você quiser usar uma versão de new que não lança exceções, precisará usar new (std::nothrow). Para obter mais informações, veja std::nothrow (cppreference.com).std::unique_ptr, std::shared_ptr e std::lock_guard. O uso de um ponteiro inteligente COM, como Microsoft::WRL::ComPtr, para lidar automaticamente com a contagem de referências COM é “seguro para exceções” e menos propenso a erros. Em geral, você deve preferir o uso de padrões de codificação do tipo “a aquisição de recursos é a inicialização” (RAII).
Por padrão, o código nativo x64 compilado com o VS 2019 usa uma implementação aprimorada do manipulador de exceções (
__CxxFrameHandler4, __GSHandlerCheck_EH4). Portanto, as bibliotecas estáticas compiladas com o VS 2019 não são compatíveis com o C/C++ Runtime do VS 2017. As bibliotecas estáticas compiladas com o VS 2017 são compatíveis com o VS 2019.- /EH (Exception handling model) (Microsoft Docs)
- x64 exception handling (Microsoft Docs)
- Making C++ Exception Handling Smaller On x64 (C++ Team Blog)
Biblioteca de tempo de execução (/MD, /MDd)
A escolha recomendada é usar a versão DLL multithread do Visual C/C++ Runtime. Isso minimiza o inchaço do código, evita possíveis problemas nas interações entre DLLs, simplifica a manutenção e é a opção recomendada para todas as plataformas da Microsoft.
Para o Microsoft Game Development Kit (GDK) no XBOX, isso significa vincular a ucrt.lib ou ucrtd.lib.
Tecnicamente, você pode usar a vinculação estática do CRT por meio de
/MT, /MTd usando libucrt.lib ou libucrtd.lib. O GDK não contém bibliotecas de extensão compatíveis com o CRT estático, portanto o suporte a esse cenário é limitado.Convenção de chamada (/Gd, /Gv)
A geração de código nativo para x64 usa uma convenção de chamada __fastcall simples e padrão, que pode passar os quatro primeiros parâmetros em registradores.
- Se o primeiro parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em RCX. Se for
floatoudouble, ele é passado em XMM0L. Caso contrário, ele é passado pela pilha. - Se o segundo parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em RDX. Se for
floatoudouble, ele é passado em XMM1L. Caso contrário, ele é passado pela pilha. - Se o terceiro parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em R8. Se for
floatoudouble, ele é passado em XMM2L. Caso contrário, ele é passado pela pilha. - Se o quarto parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em R9. Se for
floatoudouble, ele é passado em XMM3L. Caso contrário, ele é passado pela pilha. - Todos os outros parâmetros são passados pela pilha.
- Um valor de retorno que cabe em 64 bits é retornado em RAX. XMM0 é usado para retornar valores
float,double,__m128,__m128ie__m128d. Caso contrário, o chamador passa um ponteiro para a memória como argumento 0 em RCX, e RAX precisa ser retornado com o mesmo ponteiro.
__fastcall.
__cdecl, __stdcall e __thiscall são todos aliases de __fastcall no código nativo x64.Vector call
O Visual Studio dá suporte a uma convenção de chamada opcional conhecida como__vectorcall para a geração de código nativo x64.
- Se o primeiro parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em RCX. Se for
float,double,__m128,__m128iou__m128d, o parâmetro é passado em XMM0. Se for__m256,__m256iou__m256d, ele é passado em YMM0. Caso contrário, o primeiro parâmetro é passado pela pilha. - Se o segundo parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em RDX. Se for
float,double,__m128,__m128i,__m128d,__m256,__m256iou__m256d, o parâmetro é passado em XMM1/YMM1. Caso contrário, o segundo parâmetro é passado pela pilha. - Se o terceiro parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em R8. Se for
float,double,__m128,__m128i,__m128d,__m256,__m256iou__m256d, o parâmetro é passado em XMM2/YMM2. Caso contrário, o terceiro parâmetro é passado pela pilha. - Se o quarto parâmetro for um inteiro ou equivalente a um ponteiro, ele é passado em R9. Se for
float,double,__m128,__m128i,__m128d,__m256,__m256iou__m256d, o parâmetro é passado em XMM3/YMM3. Caso contrário, o quarto parâmetro é passado pela pilha. - Se o quinto parâmetro for
float,double,__m128,__m128i,__m128d,__m256,__m256iou__m256d, o parâmetro é passado em XMM4/YMM4. Caso contrário, o quinto parâmetro é passado pela pilha. - Se o sexto parâmetro for
float,double,__m128,__m128i,__m128d,__m256,__m256iou__m256d, o parâmetro é passado em XMM5/YMM5. Caso contrário, o sexto parâmetro é passado pela pilha. - Todos os outros parâmetros são passados pela pilha.
- Um valor de retorno que cabe em 64 bits é retornado em RAX. XMM0 é usado para retornar valores
float,double,__m128,__m128ie__m128d. YMM0 é usado para retornar valores__m256,__m256iou__m256d. Caso contrário, o chamador passa um ponteiro para a memória como argumento 0 em RCX, e RAX precisa ser retornado com o mesmo ponteiro.
__vectorcall também pode lidar com tipos de agregação de vetores homogêneos (HVA), que consistem em um ou mais membros do mesmo tipo de vetor ou de ponto flutuante, até quatro membros (ou seja, struct * { __m128 v[4]; } é um HVA).
Como parâmetro por valor, um HVA será passado em registrador se houver espaço suficiente disponível em XMM0/YMM0 - XMM5/YMM5 após a alocação dos outros parâmetros. Como valor de retorno, um HVA é retornado por meio de XMM0/YMM0 - XMM3/YMM3.
__vectorcall não dá suporte a funções vararg nem a construtores do C++.- __vectorcall (Microsoft Docs)
- Introducing ‘Vector Calling Convention’ (C++ Team Blog)
Otimização de programa inteiro (/GL, /Gw, /LTCG)
Enquanto as técnicas tradicionais de otimização do compilador podem otimizar funções e módulos, a otimização de programa inteiro, também conhecida como geração de código em tempo de vinculação (LTCG), executa otimizações entre módulos. Isso inclui alocação e agendamento de registradores aprimorados, com melhor conhecimento dos efeitos colaterais, propagação interprocedural de constantes/intervalos, inlining parcial e desvirtualização de chamadas de função em objetos, quando possível.
A LTCG também pode ser usada em um modo incremental para obter benefícios de desempenho do código durante a iteração de desenvolvimento. Para obter mais informações, veja Speeding up the Incremental Developer Build Scenario (C++ Team Blog).
Para fornecedores de middleware que distribuem bibliotecas C++ estáticas pré-compiladas, habilitar a WPO vincula a biblioteca a uma versão específica do conjunto de ferramentas do compilador. Nesse cenário, você deve distribuir as bibliotecas sem WPO. Essa recomendação não se aplica a DLLs nem a código compilado a partir do código-fonte.Para obter mais informações, veja /GL (Whole Program Optimization) (Microsoft Docs).
O Visual Studio 2022 (17.5) adicionou uma nova opção de conformidade,/Zc:checkGwOdr, relacionada a/Gw. Veja esta postagem de blog.
Otimização guiada por perfil
A otimização guiada por perfil (PGO) leva o processo de LTCG um passo adiante, em que a otimização de programa inteiro é controlada por rastreamentos de desempenho coletados em execuções anteriores do aplicativo. Isso melhora a qualidade das otimizações existentes, bem como as otimizações de layout de funções, layout de blocos e separação de código, para melhorar o conjunto de trabalho e a previsão de ramificações. Para obter mais informações, veja Profile-guided optimizations (Microsoft Docs).Opção do vinculador /OPT:REF,ICF
Essas opções eliminam conteúdo redundante nos vários módulos de objeto quando vinculados ao executável final. Normalmente, elas ficam desabilitadas em builds de depuração, mas devem estar presentes em builds de versão.
Para obter os melhores resultados, compile com a opção
/Gy (Enable Function-Level Linking).Opção do compilador /GS
Recomendamos o uso da verificação de buffer nas configurações de versão para todo o código. Nos casos em que há buffers específicos que estão protegidos contra ameaças de segurança, mas o desempenho parece afetado pela verificação, use __declspec(safebuffers) na função em vez de desabilitar /GS globalmente. Para código de maior risco, use #pragma strict_gs_check(on).
Para obter mais informações, veja /GS (Buffer Security Check) (Microsoft Docs).
Opção do compilador /homeparams
O uso dessa opção em builds otimizados pode aumentar muito a capacidade de depurar os builds de versão do seu aplicativo. Se usada em builds de produção, ela pode simplificar o processo de análise e depuração de despejos de falha. Isso adiciona uma pequena sobrecarga para armazenar parâmetros adicionais na pilha. Na maioria dos casos, isso não tem um efeito perceptível no desempenho.
Para obter mais informações, veja /homeparams (Copy Register Parameters to Stack) (Microsoft Docs).
Opção do compilador /Zc:inline
Essa opção aplica as regras mais rígidas do C++11 para a declaração de funções embutidas, que exigem que o corpo de todas as funções embutidas esteja presente na mesma unidade de compilação que a declaração e seu uso. Usar esse sinalizador pode melhorar os tempos de build e reduzir significativamente o tamanho dos arquivos .obj. Se as suas funções embutidas não estiverem em conformidade com o C++11, você receberá erros LNK2019 no momento da vinculação. Essa opção vem ativada por padrão ao compilar com o MSBuild, mas precisa ser adicionada explicitamente ao compilar usando a linha de comando, o CMake etc.
Para obter mais informações, veja /Zc:inline (Remove unreferenced COMDAT) (Microsoft Docs).
Opção do compilador /Zc:throwingNew
O padrão C++ e os modelos da Standard C++ Library exigem que o operador new lance uma exceção em vez de retornar nullptr quando uma alocação falha; você pode usar std::nothrow com new para forçar o comportamento de retornar nullptr. Há muito tempo, o compilador Visual C++ gera uma verificação de null após cada chamada a new, o que é desnecessário na presença do tratamento de exceções. Usando essa opção, as verificações extras são eliminadas.
Para obter mais informações, veja:
- /Zc:throwingNew (Assume operator new throws) (Microsoft Docs)
- New in VS 2015: /Zc:throwingNew (C++ Team Blog)
Opção do compilador /Zc:__cplusplus
Por motivos históricos, a macro __cplusplus no Visual C++ retornou “199711” por muito tempo. A partir do Visual Studio 2017 (atualização 15.7), essa nova opção faz o compilador Visual C++ retornar o valor padrão correto. Uma versão futura do compilador fará isso por padrão, portanto vale a pena ativá-la o quanto antes para resolver quaisquer problemas de conformidade remanescentes.
Para obter mais informações, veja:
- /Zc:__cplusplus (Enable updated __cplusplus macro) (Microsoft Docs)
- MSVC now correctly reports __cplusplus (C++ Team Blog)
Opção do compilador /volatile:iso
A palavra-chave volatile tem vários comportamentos estendidos específicos da Microsoft que não são realmente portáveis, nem mesmo entre gerações do Visual C++. Considere ativar essa opção e, em seguida, garantir que você não está usando volatile de forma inadequada no seu código.
Para obter mais informações, veja /volatile (volatile Keyword Interpretation) (Microsoft Docs).
Opção do compilador /permissive-
O Visual Studio 2017 introduziu uma nova opção de conformidade com o padrão para substituir a opção obsoleta /Za. Essa opção faz o compilador emitir erros e avisos ao usar comportamentos de extensão específicos da Microsoft que podem causar problemas ao portar para outros compiladores. O uso de /permissive- também pode melhorar os tempos de compilação.
Para obter mais informações, veja:
- /permissive- (Standards conformance) (Microsoft Docs)
- Give Visual C++ a Switch to Standard Conformance (C++ Team Blog)
A partir do Visual Studio 2017 (atualização 15.3), o uso de
/permissive- também habilita a pesquisa de nomes em duas fases. Alguns códigos de modelo C++ não serão compilados com a aplicação adequada do padrão, então você pode desabilitar seletivamente apenas essa parte usando /Zc:twoPhase-, em vez de desabilitar /permissive- completamente.Para obter mais informações, veja:- /Zc:twoPhase- (disable two-phase name lookup) (Microsoft Docs)
- Two-phase name lookup support comes to MSVC (C++ Team Blog)
Opção do compilador /Zc:preprocessor
O Visual Studio 2019 (16.6) inclui uma nova opção para habilitar o pré-processador em conformidade com o C99. Essa opção vem desativada por padrão, mas, se a portabilidade do código for uma preocupação, considere habilitá-la. Veja Announcing full support for a C/C++ conformant preprocessor in MSVC.
Opção do compilador /ZH:SHA_256
Tradicionalmente, os símbolos de depuração usam hash MD5. Para melhorar a segurança da cadeia de suprimentos, a recomendação é usar SHA-256. Observe que o Visual Studio 2022 usa /ZH:SHA_256 por padrão.
Essa opção tem suporte no clang/LLVM a partir da v16.
Opções do vinculador /NXCOMPAT e /SAFESEH
Essas duas opções são implícitas ao usar destinos nativos x64. A proteção no-execute (NX) é obrigatória para títulos XBOX, portanto você não pode usar /NXCOMPAT:NO.
Opção do vinculador /DYNAMICBASE
Essa opção habilita o uso da randomização do layout do espaço de endereço (ASLR) e vem ativada por padrão. Observe que ela é obrigatória para títulos XBOX, portanto você não pode usar /DYNAMICBASE:NO.
Opção do vinculador /Debug:FASTLINK
Para o Visual Studio 2019 (16.8) ou posterior, melhorias significativas de desempenho no vinculador fazem com que não recomendemos mais o uso de /Debug:FASTLINK.
Lembre-se de que, com
/Debug:FASTLINK, o pdb principal do seu projeto contém apenas links para os arquivos pdb espalhados pelo seu build. Se você quiser compartilhar ou armazenar os símbolos de um build /Debug:FASTLINK, poderá usar a ferramenta de linha de comando mspdbcmf.exe para gerar um arquivo pdb completo.Para obter mais informações, veja:- /DEBUG (Generate Debug Info) (Microsoft Docs)
- Faster C++ build cycle in VS 2017 with /Debug:fastlink (C++ Team Blog)
Bibliotecas
Para as plataformas Gaming.Xbox.XboxOne.x64 e Gaming.Xbox.Scarlett.x64, é importante vincular axgameplatform.lib. Essa é uma biblioteca ‘guarda-chuva’ que inclui todas as APIs Win32 com suporte no console. Não vincule a kernel32.lib, onecore.lib, onecoreuap.lib ou WindowsApps.lib. Misturar bibliotecas guarda-chuva não é recomendado e pode causar falhas na inicialização do processo.
Veja o Microsoft Docs para obter mais informações sobre bibliotecas ‘guarda-chuva’.
Opção do vinculador /NODEFAULTLIB:library
Recomendamos usar a opção do vinculador /NODEFAULTLIB com uma lista específica de nomes de bibliotecas comuns para garantir que bibliotecas sem suporte não sejam usadas no momento da vinculação por meio de #pragma comment(lib,).
Se uma biblioteca for listada explicitamente como entrada de vinculação, ela ainda será usada mesmo que esteja listada como uma biblioteca
/NODEFAULTLIB. A opção ignora apenas as referências implícitas.Bibliotecas do Visual C++ Runtime
O Visual Studio Developer Command Prompt define as variáveis de ambiente necessárias para localizar esses caminhos. O/LIBPATH adequado para Gaming.Xbox.*.x64 localizar as bibliotecas de importação do Visual C++ Runtime é %VCToolsInstallDir%lib\onecore\x64.
Bibliotecas de vínculo dinâmico (DLLs)
O Game OS para Gaming.Xbox.*.x64 não inclui as bibliotecas DLL do Visual C++ Runtime. Elas são incluídas no layout do título para que o jogo possa ser iniciado.-
Para Release, você precisará do conteúdo de
%VCToolsRedistDir%onecore\x64\Microsoft.VC14?.CRT. Se você tiver uma combinação de binários de Debug e Release no mesmo layout, inclua-os em todos os seus layouts. -
Para Debug, você precisará do conteúdo de
%VCToolsRedistDir%onecore\debug_nonredist\x64\Microsoft.VC14?.DebugCRT. -
Para Debug, você também precisará da versão de depuração de
ucrtbased.dll, que se encontra no Windows SDK:%WindowsSdkVerBinPath%x64\ucrt. A versão Release deucrtbase.dllestá incluída no Game OS.
Se você usar o OpenMP, também precisará do conteúdo de
Microsoft.VC14?.OpenMP e/ou Microsoft.VC14?.DebugOpenMP