Pergunta

Eu acho que, se há um monte de aulas o tempo de compilação é aumentado dramaticamente quando eu uso um * .h e um arquivo * .cpp por classe. Eu já uso cabeçalhos pré-compilados e vinculação incremental, mas ainda a tempo de compilação é muito longa (sim eu uso boost;)

Então, eu vim com o seguinte truque:

  • definidos arquivos * .cpp como não compilable
  • definidos * .cxx arquivos como compilable
  • adicionado um arquivo * .cxx por aplicativo módulo e #included todos os arquivos * .cpp deste módulo nele.

Então, ao invés de 100+ unidades de tradução acabei com apenas 8 unidades de tradução. O tempo de compilação tornou-se 4-5 vezes mais curto.

As desvantagens são que você tem que incluir manualmente todos os arquivos .cpp * (mas não é realmente um pesadelo de manutenção, pois se você se esqueça de incluir algo que o vinculador irá lembrá-lo), e que algumas conveniências VS IDE não está trabalhando com neste esquema, por exemplo, Go To / Mover para Implementação etc.

Então a questão é, é ter lotes de unidades de tradução CPP realmente a única maneira verdadeira? É o meu truque um padrão conhecido, ou talvez eu estou faltando alguma coisa? Obrigado!

Foi útil?

Solução

O conceito é chamado construir a unidade

Outras dicas

Uma desvantagem significativa desta abordagem é causado por ter um obj arquivo para cada unidade de tradução.

Se você criar uma biblioteca estática para reutilização em outros projetos muitas vezes você vai enfrentar binários maiores nesses projetos se você tiver várias unidades de tradução enormes em vez de muitos pequenos porque o vinculador só incluirá os arquivos obj contendo as funções / variáveis realmente referenciado a partir de dentro do projeto usando a biblioteca.

Em caso de grandes unidades de tradução é mais provável que cada unidade é referenciado eo arquivo correspondente obj está incluído. binários maiores pode ser um problema em alguns casos. Também é possível que alguns ligadores são suficientes inteligente para incluir apenas as funções necessárias / variáveis, não os arquivos de toda obj.

Além disso, se o arquivo .obj é incluído e todas as variáveis ??globais são incluídos também, em seguida, seus construtores / destruidores serão chamados quando o programa é iniciado / parado o que certamente vai levar tempo.

Eu vi o que você faz em jogos de vídeo, uma vez que ajuda o compilador para fazer otimizações que de outra forma não poderia fazer, bem como guardar um monte de memória. Eu vi "construção uber" e "compilação em massa" referem-se a esta ideia. E se isso ajuda a acelerar a sua construção, por que não ..

Agregação de um número maior de arquivos de código fonte C ++ em um único arquivo é uma abordagem que foi mencionado algumas vezes recentemente, especialmente quando as pessoas estavam construindo grandes sistemas e puxando em arquivos de cabeçalho complicadas (que vai ser impulso, a seguir) .

Como você menciona VS, descobri que o número de incluir arquivos em um projeto e, especialmente, o tamanho do caminho de inclusão parece afetar Visual C ++ 's vezes compilação muito mais do que ele faz g ++' s compilação vezes. Este é especialmente o caso com muita inclui aninhada (novamente, boost faz isso) que sejam necessárias para encontrar todos os arquivos de inclusão exigidos pelo código-fonte de um grande número de pesquisas de arquivo. Combinando o código em um único meio de arquivo de origem que o compilador pode ser muito mais inteligente sobre encontrar disse que inclui, além disso, existem, obviamente, menos deles a ser encontrado como seria de esperar que os arquivos no mesmo subprojeto seria provável que incluem um muito semelhante conjunto de arquivos de cabeçalho.

Os "lotes de unidades de compilação" abordagem de desenvolvimento C ++ geralmente vem de um desejo de aulas dissociar e minimizar dependências entre as classes para que o compilador só tem de reconstruir o conjunto mínimo de arquivos no caso de você fazer qualquer alteração. Esta é geralmente uma boa abordagem, mas muitas vezes não é realmente viável em um subprojeto simplesmente porque os arquivos lá têm dependências entre si de modo que você vai acabar com bastante grandes reconstruções de qualquer maneira.

Eu não acho que a redução do número de unidades de compilação é uma boa idéia. Você está tentando resolver um problema com grande tempo de compilação, e essa abordagem parece ajudar com isso, mas o que você ganha, além disso:

  1. tempo de compilação aumentou durante o desenvolvimento. Normalmente desenvolvedor modificar alguns arquivos de uma vez, e compilação será provavelmente mais rápido por 3-4 arquivos pequenos, em seguida, para um arquivo muito grande.
  2. Como você mencionou, mais difícil de código de navegação, IMHO isso é extremamente importante.
  3. Você pode ter alguma interferência entre arquivos .cpp incluído em um arquivo .cxx:

    a. É prática comum para definir localmente no arquivo CPP (para compilações de depuração) macro novo para verificação de vazamento de memória. Infelizmente, isso não pode ser feito antes de incluir cabeçalhos usando posicionamento novo (como alguns STL e impulsionar cabeçalho fazer)

    b. É prática comum adicionar usando declarações em arquivos CPP. Com a sua abordagem pode levar a problemas com cabeçalhos, incluídos mais tarde

    c. conflitos de nome são mais provável

IMHO, muito mais limpo (mas maneira talvez mais caro) para acelerar o tempo de compilação é usar algum sistema de compilação distribuída. Eles são especialmente eficazes para limpar constrói.

Eu não sei se isso é relevante no seu caso, mas talvez você pode usar a declaração ao invés definição para reduzir o número de #include estou é que você tem que fazer. Além disso, talvez você possa usar o idioma pimpl para o mesmo fim. Isso poderia vir a reduzir o número de arquivos de origem que precisam ser recompilados cada vez e o número de cabeçalhos que têm de ser puxado.

unidades de tradução maiores e menos não tirar proveito de compilação paralela. Eu não sei o que compiladores e quais as plataformas que você está usando, mas a compilação em unidades de tradução múltiplas paralelas pode diminuir significativamente o tempo de construção de ...

Na sequência do sharptooths postar, eu tendem a examinar os executáveis ??resultantes em algum detalhe. Se forem diferentes, eu tendem a limitar a sua técnica para compilações de depuração e recorrer à configuração original do projeto para o principal compilação de lançamento. Ao verificar o executável, eu também olhar para o seu uso pegada de memória e recursos na inicialização e durante a execução.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top