Partilhar via


Arquivos de cabeçalho pré-compilados

Quando você cria um projeto no Visual Studio, um arquivo de cabeçalho pré-compilado nomeado pch.h é adicionado ao projeto. (No Visual Studio 2017 e anterior, o arquivo era chamado stdafx.h.) A finalidade do arquivo é acelerar o processo de build. Todos os arquivos de cabeçalho estáveis, por exemplo, cabeçalhos da Biblioteca Padrão, como <vector>, devem ser incluídos aqui. O cabeçalho pré-compilado é compilado somente quando ele, ou todos os arquivos que ele inclui, são modificados. Se você fizer alterações apenas no código-fonte do projeto, o build ignorará a compilação para o cabeçalho pré-compilado.

As opções do compilador para cabeçalhos pré-compilados são /Y. Nas páginas de propriedades do projeto, as opções estão localizadas em Propriedades de Configuração>C/C++>Cabeçalhos Pré-compilados. Você pode optar por não usar cabeçalhos pré-compilados e especificar o nome do arquivo de cabeçalho e o nome e o caminho do arquivo de saída.

Código pré-compilado personalizado

Para projetos grandes que levam um tempo significativo para serem compilados, convém considerar a criação de arquivos pré-compilados personalizados. Os compiladores C e C++ da Microsoft fornecem opções para pré-compilar qualquer código C ou C++, incluindo código embutido. Usando esse recurso de desempenho, é possível compilar um corpo de código estável, armazenar o estado compilado do código em um arquivo e, durante as compilações subsequentes, combinar o código pré-compilado com código que ainda está em desenvolvimento. Cada compilação subsequente é mais rápida, porque o código estável não precisa ser recompilado.

Quando pré-compilar o código-fonte

O código pré-compilado é útil durante o ciclo de desenvolvimento para reduzir o tempo de compilação, especialmente se:

  • Você sempre usa um corpo grande de código que é alterado com pouca frequência.

  • Seu programa é composto por vários módulos, todos os quais usam um conjunto padrão de arquivos de inclusão e as mesmas opções de compilação. Nesse caso, todos os arquivos de inclusão podem ser pré-compilados em um cabeçalho pré-compilado. Para obter mais informações sobre maneiras mais recentes de manipular arquivos de inclusão, consulte Comparar unidades de cabeçalho, módulos e cabeçalhos pré-compilados.

A primeira compilação (aquela que cria o arquivo de cabeçalho pré-compilado) leva um pouco mais de tempo do que as compilações subsequentes. As compilações subsequentes podem continuar mais rapidamente, incluindo o código pré-compilado.

Você pode pré-compilar programas C e C++. Na programação C++, é prática comum separar informações da interface de classe em arquivos de cabeçalho. Esses arquivos de cabeçalho podem ser incluídos posteriormente em programas que usam a classe. Ao pré-compilar esses cabeçalhos, você pode reduzir o tempo necessário para compilar um programa.

Observação

Embora você possa usar apenas um arquivo de cabeçalho pré-compilado (.pch) por arquivo de origem, você pode usar vários arquivos .pch em um projeto.

Duas escolhas para pré-compilar código

Você pode pré-compilar qualquer código C ou C++; você não está limitado a pré-compilar somente arquivos de cabeçalho.

A pré-compilação requer planejamento, mas oferece compilações muito mais rápidas se você pré-compilar código-fonte diferente de arquivos de cabeçalho simples.

Pré-compile o código quando você souber que seus arquivos de origem usam conjuntos comuns de arquivos de cabeçalho ou quando você desejar incluir código-fonte em sua pré-compilação.

As opções de cabeçalho pré-compilado são /Yc (criar arquivo de cabeçalho pré-compilado) e /Yu (usar arquivo de cabeçalho pré-compilado). Use /Yc para criar um cabeçalho pré-compilado. Quando usado com o pragma opcional hdrstop, /Yc permite pré-compilar arquivos de cabeçalho e código-fonte. Selecione /Yu para usar um cabeçalho pré-compilado existente na compilação existente. Você também pode usar /Fp com as opções /Yc e /Yu para fornecer um nome alternativo para o cabeçalho pré-compilado.

Os artigos de referência da opção do compilador para /Yu e /Yc discutem como acessar essa funcionalidade no ambiente de desenvolvimento.

Regras de consistência do cabeçalho pré-compilado

Como os arquivos PCH contêm informações sobre o ambiente do computador e informações de endereço de memória sobre o programa, você deve usar apenas um arquivo PCH no computador em que ele foi criado.

Regras de consistência para uso por arquivo de cabeçalhos pré-compilados

A opção do compilador /Yu permite que você especifique qual arquivo PCH usar.

Quando você usa um arquivo PCH, o compilador assume o mesmo ambiente de compilação que estava em vigor quando você criou o arquivo PCH, a menos que você especifique o contrário. O ambiente de compilação inclui as opções do compilador, pragmas e assim por diante. Se o compilador detectar uma inconsistência, ele emitirá um aviso e identificará a inconsistência sempre que possível. Esses avisos não indicam necessariamente um problema com o arquivo PCH; eles simplesmente avisam sobre possíveis conflitos. Os requisitos de consistência para arquivos PCH são descritos nas seções a seguir.

Consistência da opção do compilador

As seguintes opções do compilador podem disparar um aviso de inconsistência ao usar um arquivo PCH:

  • As macros criadas usando a opção Pré-processador (/D) precisam ser as mesmas entre a compilação que criou o arquivo PCH e a compilação atual. O estado das constantes definidas não é verificado, mas resultados imprevisíveis poderão ocorrer se essas macros forem alteradas.

  • Os arquivos PCH não funcionam com as opções /E e /EP.

  • Os arquivos PCH precisam ser criados usando a opção Gerar Informações de Navegação (/FR) ou a opção Excluir Variáveis Locais (/Fr) antes que as compilações subsequentes que usam o arquivo PCH possam usar essas opções.

Compatível com C 7.0 (/Z7)

Se essa opção estiver em vigor quando o arquivo PCH for criado, compilações posteriores que usam o arquivo PCH poderão usar as informações de depuração.

Se a opção C 7.0-Compatible (/Z7) não estiver em vigor quando o arquivo PCH for criado, compilações posteriores que usam o arquivo PCH e /Z7 disparam um aviso. As informações de depuração são colocadas no arquivo atual .obj e os símbolos locais definidos no arquivo PCH não estão disponíveis para o depurador.

Consistência de caminho de inclusão

Um arquivo PCH não contém informações sobre o caminho de inclusão de cabeçalho que estava em vigor quando ele foi criado. Quando você usa um arquivo PCH, o compilador sempre usa o caminho de inclusão de cabeçalho especificado na compilação atual.

Consistência do arquivo de origem

Quando você especifica a opção Usar Arquivo de Cabeçalho Pré-compilado (/Yu), o compilador ignora todas as diretivas de pré-processador (incluindo pragmas) que aparecem no código-fonte que será pré-compilado. A compilação especificada por essas diretivas de pré-processador precisa ser a mesma que a compilação usada para a opção Criar Arquivo de Cabeçalho Pré-compilado (/Yc).

Consistência de pragma

Pragmas processados durante a criação de um arquivo PCH geralmente afetam o arquivo com o qual o arquivo PCH é usado posteriormente. Os pragmas comment e message não afetam o restante da compilação.

Esses pragmas afetam apenas o código dentro do arquivo PCH; eles não afetam o código que usa o arquivo PCH posteriormente:

comment
linesize

message
page

pagesize
skip

subtitle
title

Esses pragmas são retidos como parte de um cabeçalho pré-compilado e afetam o restante de uma compilação que usa o cabeçalho pré-compilado:

alloc_text
auto_inline
check_stack
code_seg
data_seg

function
include_alias
init_seg
inline_depth

inline_recursion
intrinsic
optimize
pack

pointers_to_members
setlocale
vtordisp
warning

Regras de consistência para /Yc e /Yu

Quando você usa um cabeçalho pré-compilado criado usando /Yc ou /Yu, o compilador compara o ambiente de compilação atual com o que existia quando você criou o arquivo PCH. Especifique um ambiente consistente com o anterior (usando opções consistentes do compilador, pragmas e assim por diante) para a compilação atual. Se o compilador detectar uma inconsistência, ele emitirá um aviso e identificará a inconsistência sempre que possível. Esses avisos não indicam necessariamente um problema com o arquivo PCH; eles simplesmente avisam sobre possíveis conflitos. As seções a seguir explicam os requisitos de consistência para cabeçalhos pré-compilados.

Consistência da opção do compilador

Esta tabela lista as opções do compilador que podem disparar um aviso de inconsistência ao usar um cabeçalho pré-compilado:

Opção Nome Regra
/D Definir constantes e macros Precisam ser as mesmas entre a compilação que criou o cabeçalho pré-compilado e a compilação atual. O estado das constantes definidas não é verificado. No entanto, resultados imprevisíveis poderão ocorrer se os arquivos dependerem dos valores das constantes alteradas.
/E ou /EP Copiar a saída do pré-processador para a saída padrão Os cabeçalhos pré-compilados não funcionam com a opção /E ou /EP.
/Fr ou /FR Gerar informações do Navegador de Origem da Microsoft Para que as opções /Fr e /FR sejam válidas com a opção /Yu, elas também precisam estar em vigor quando o cabeçalho pré-compilado foi criado. As compilações subsequentes que usam o cabeçalho pré-compilado também geram informações do Navegador de Origem. As informações do navegador são colocadas em um arquivo .sbr e são referenciadas por outros arquivos da mesma maneira que as informações do CodeView. Você não pode substituir o posicionamento das informações do Navegador de Origem.
/GA, /GD, /GE, /Gw ou /GW Opções de protocolo do Windows Precisam ser as mesmas entre a compilação que criou o cabeçalho pré-compilado e a compilação atual. O compilador emitirá um aviso se essas opções forem diferentes.
/Zi Gerar informações completas de depuração Se essa opção estiver em vigor quando o cabeçalho pré-compilado for criado, as compilações subsequentes que usarem a pré-compilação poderão usar essas informações de depuração. Se /Zi não estiver em vigor quando o cabeçalho pré-compilado for criado, as compilações subsequentes que usarem a pré-compilação e a opção /Zi dispararão um aviso. As informações de depuração são colocadas no arquivo de objeto atual e os símbolos locais definidos no cabeçalho pré-compilado não estão disponíveis para o depurador.

Observação

A instalação de cabeçalho pré-compilado destina-se a ser usada somente em arquivos de origem C e C++.

Usando cabeçalhos pré-compilados em um projeto

As seções anteriores apresentam uma visão geral dos cabeçalhos pré-compilados: /Yc e /Yu, a opção /Fp e o pragma hdrstop. Esta seção descreve um método para usar as opções de cabeçalho pré-compilado manual em um projeto; ele termina com um makefile de exemplo e o código que ele gerencia.

Para outra abordagem sobre como usar as opções de cabeçalho pré-compilado manual em um projeto, estude um dos arquivos makefile localizados no diretório MFC\SRC criado durante a configuração padrão do Visual Studio. Esses makefiles adotarão uma abordagem semelhante à apresentada nesta seção. Eles usam mais macros do Utilitário de Manutenção de Programas (NMAKE) da Microsoft e oferecem maior controle do processo de build.

Arquivos PCH no processo de build

A base de código de um projeto de software geralmente está contida em vários arquivos de origem C ou C++, arquivos de objeto, bibliotecas e arquivos de cabeçalho. Normalmente, um makefile coordena a combinação desses elementos em um arquivo executável. A figura a seguir mostra a estrutura de um makefile que usa um arquivo de cabeçalho pré-compilado. Os nomes de macro NMAKE e os nomes de arquivo neste diagrama são consistentes com o código de exemplo encontrado em Makefile de exemplo para PCH e Código de exemplo para PCH.

A figura usa três dispositivos diagramáticos para mostrar o fluxo do processo de build. Retângulos nomeados representam cada arquivo ou macro; as três macros representam um ou mais arquivos. As áreas sombreadas representam cada ação de compilação ou vinculação. As setas mostram quais arquivos e macros são combinados durante o processo de compilação ou vinculação.

 The diagram is described in the text following the diagram.
Estrutura de um makefile que usa um arquivo de cabeçalho pré-compilado:

Diagram showing example inputs and outputs of a makefile that uses a precompiled header file.

O diagrama mostra '$(STABLEHDRS)' e '$(BOUNDRY)' alimentando CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp. A saída disso é $(STABLE. PCH). Em seguida, applib.cpp e $(UNSTABLEHDRS) e $(STABLE. PCH) alimentar em CL /c /w3 /Yu $(BOUNDRY) applib.cpp, que produz applib.obj. myapp.cpp, $(UNSTABLEHDR) e $(STABLE. PCH) alimentar em CL /c /w3 /Yu $(BOUNDRY) myapp.cpp, que produz myapp.obj. Finalmente, applib.obj e myapp.obj são combinados por LINK /NOD ONERROR:NOEXE $(OBJS), myapp, NUL, $(LIBS), NUL para produzir myapp.exe.

Começando na parte superior do diagrama, ambos STABLEHDRS e BOUNDRY são macros NMAKE nas quais você lista arquivos que provavelmente não precisam de recompilação. Esses arquivos serão compilados pela cadeia de caracteres de comando

CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp

somente se o arquivo de cabeçalho pré-compilado (STABLE.pch) não existir ou se você fizer alterações nos arquivos listados nas duas macros. Em ambos os casos, o arquivo de cabeçalho pré-compilado conterá código somente dos arquivos listados na macro STABLEHDRS. Liste o último arquivo que você deseja pré-compilado na macro BOUNDRY.

Os arquivos listados nessas macros podem ser arquivos de cabeçalho ou arquivos de origem C ou C++. (Não é possível usar apenas um arquivo PCH com fontes C e C++.) Você pode usar a macro hdrstop para interromper a pré-compilação em algum momento dentro do arquivo BOUNDRY. Para obter mais informações, consulte hdrstop.

Em seguida, no diagrama, APPLIB.obj representa o código de suporte usado em seu aplicativo final. Ele é criado com base em APPLIB.cpp, nos arquivos listados na macro UNSTABLEHDRS e no código pré-compilado do cabeçalho pré-compilado.

MYAPP.obj representa seu aplicativo final. Ele é criado com base em MYAPP.cpp, nos arquivos listados na macro UNSTABLEHDRS e no código pré-compilado do cabeçalho pré-compilado.

Por fim, o arquivo executável (MYAPP.EXE) é criado vinculando os arquivos listados na macro OBJS (APPLIB.obj e MYAPP.obj).

Makefile de exemplo para PCH

O makefile a seguir usa macros e uma estrutura de comando de fluxo de controle de !IF, !ELSE, !ENDIF para simplificar a adaptação dele ao seu projeto.

# Makefile : Illustrates the effective use of precompiled
#            headers in a project
# Usage:     NMAKE option
# option:    DEBUG=[0|1]
#            (DEBUG not defined is equivalent to DEBUG=0)
#
OBJS = myapp.obj applib.obj
# List all stable header files in the STABLEHDRS macro.
STABLEHDRS = stable.h another.h
# List the final header file to be precompiled here:
BOUNDRY = stable.h
# List header files under development here:
UNSTABLEHDRS = unstable.h
# List all compiler options common to both debug and final
# versions of your code here:
CLFLAGS = /c /W3
# List all linker options common to both debug and final
# versions of your code here:
LINKFLAGS = /nologo
!IF "$(DEBUG)" == "1"
CLFLAGS   = /D_DEBUG $(CLFLAGS) /Od /Zi
LINKFLAGS = $(LINKFLAGS) /COD
LIBS      = slibce
!ELSE
CLFLAGS   = $(CLFLAGS) /Oselg /Gs
LINKFLAGS = $(LINKFLAGS)
LIBS      = slibce
!ENDIF
myapp.exe: $(OBJS)
    link $(LINKFLAGS) @<<
$(OBJS), myapp, NUL, $(LIBS), NUL;
<<
# Compile myapp
myapp.obj  : myapp.cpp $(UNSTABLEHDRS)  stable.pch
    $(CPP) $(CLFLAGS) /Yu$(BOUNDRY)    myapp.cpp
# Compile applib
applib.obj : applib.cpp $(UNSTABLEHDRS) stable.pch
    $(CPP) $(CLFLAGS) /Yu$(BOUNDRY)    applib.cpp
# Compile headers
stable.pch : $(STABLEHDRS)
    $(CPP) $(CLFLAGS) /Yc$(BOUNDRY)    applib.cpp myapp.cpp

Além das macros STABLEHDRS, BOUNDRYe UNSTABLEHDRS mostradas na figura "Estrutura de um Makefile que usa um arquivo de cabeçalho pré-compilado" em Arquivos PCH no processo de build, esse makefile fornece uma macro CLFLAGS e uma macro LINKFLAGS. Você precisa usar essas macros para listar opções de compilador e vinculador que se aplicam independentemente de você compilar uma versão final ou de depuração do arquivo executável do aplicativo. Há também uma macro LIBS em que você lista as bibliotecas necessárias para o projeto.

O makefile também usa !IF, !ELSE e !ENDIF para detectar se você define ou não um símbolo DEBUG na linha de comando NMAKE:

NMAKE DEBUG=[1|0]

Esse recurso possibilita que você use o mesmo makefile durante o desenvolvimento e para as versões finais do programa. Use DEBUG=0 para as versões finais. As seguintes linhas de comando são equivalentes:

NMAKE
NMAKE DEBUG=0

Para obter mais informações sobre makefiles, confira Referência do NMAKE. Confira também as opções do compilador MSVC e as opções do vinculador MSVC.

Código de exemplo para PCH

Os arquivos de origem a seguir são usados no makefile descrito em Arquivos PCH no processo de build e em Makefile de exemplo para PCH. Os comentários contêm informações importantes.

Arquivo de origem ANOTHER.H:

// ANOTHER.H : Contains the interface to code that is not
//             likely to change.
//
#ifndef __ANOTHER_H
#define __ANOTHER_H
#include<iostream>
void savemoretime( void );
#endif // __ANOTHER_H

Arquivo de origem STABLE.H:

// STABLE.H : Contains the interface to code that is not likely
//            to change. List code that is likely to change
//            in the makefile's STABLEHDRS macro.
//
#ifndef __STABLE_H
#define __STABLE_H
#include<iostream>
void savetime( void );
#endif // __STABLE_H

Arquivo de origem UNSTABLE.H:

// UNSTABLE.H : Contains the interface to code that is
//              likely to change. As the code in a header
//              file becomes stable, remove the header file
//              from the makefile's UNSTABLEHDR macro and list
//              it in the STABLEHDRS macro.
//
#ifndef __UNSTABLE_H
#define __UNSTABLE_H
#include<iostream>
void notstable( void );
#endif // __UNSTABLE_H

Arquivo de origem APPLIB.CPP:

// APPLIB.CPP : This file contains the code that implements
//              the interface code declared in the header
//              files STABLE.H, ANOTHER.H, and UNSTABLE.H.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
using namespace std;
// The following code represents code that is deemed stable and
// not likely to change. The associated interface code is
// precompiled. In this example, the header files STABLE.H and
// ANOTHER.H are precompiled.
void savetime( void )
    { cout << "Why recompile stable code?\n"; }
void savemoretime( void )
    { cout << "Why, indeed?\n\n"; }
// The following code represents code that is still under
// development. The associated header file is not precompiled.
void notstable( void )
    { cout << "Unstable code requires"
            << " frequent recompilation.\n";
    }

Arquivo de origem MYAPP.CPP:

// MYAPP.CPP : Sample application
//             All precompiled code other than the file listed
//             in the makefile's BOUNDRY macro (stable.h in
//             this example) must be included before the file
//             listed in the BOUNDRY macro. Unstable code must
//             be included after the precompiled code.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
int main( void )
{
    savetime();
    savemoretime();
    notstable();
}

Confira também

Comparar unidades de cabeçalho, módulos e cabeçalhos pré-compilados
Referência de compilação C/C++
Opçõesdo compilador MSVC Visão geral dos módulos em C++
Tutorial: Importar a biblioteca padrão do C++ usando módulos
Guia Passo a passo: compilar e importar unidades de cabeçalho em seus projetos do Visual C++
Passo a passo: Importar bibliotecas STL como unidades de cabeçalho