Sou relativamente novo em C ++, portanto, não tenho certeza de como devo lidar melhor com pequenas dependências (por exemplo, uma linguagem de script ou um Analisador JSON / YAML / XML).
Devo criar projetos separados e vinculá-los como biblioteca estática ou há desvantagens em colocar os arquivos .h / .cpp no meu projeto principal?
O último parece muito mais fácil, porque passei várias horas lidando com bibliotecas incompatíveis (configuração diferente do compilador ao criar a biblioteca), mas não quero começar a aprender C ++ da maneira errada.
Se for preferível mantê-los como bibliotecas separadas, como manteria os sinalizadores de compilação em sincronia para que os arquivos .lib / .a sejam vinculados com êxito ao meu aplicativo?
(Atualmente, estou trabalhando com o MSVC 2015, mas o objetivo é compilar no Mac OS X e iOS usando XCode / clang, para que eu tenha que lidar com pelo menos três tipos diferentes de bibliotecas (Win x86, Mac x64, ARM) )
Respostas:
TLDR;
Você deve adicionar a fonte? SIM X
deve adicionar a fonte? DEPENDE
Aí vem o porquê ...
Naquela época, o tempo de compilação era um problema que os projetos ainda menores tinham. Compilar suas fontes e nunca se preocupar com os resultados do compilador de cache foi definitivamente atraente para alguns. Esse é um ponto para as bibliotecas irrelevantes para você.
Outro importante é o controle de versão. Você realmente precisa versão cada biblioteca separadamente? Executar testes contra cada um? Distribuí-lo entre muitos membros da equipe? As bibliotecas são ótimas, e conveniente para se movimentar, mas, novamente, parece que você também não se importa com isso.
O ponto final aqui é que é uma sobrecarga adicional, e soltar os arquivos de origem é mais fácil no seu caso, o que dá um ponto muito forte para soltar as fontes em vez de usar bibliotecas. Como você notou, depois de fazer uma única alteração na configuração do compilador, você deve perseguir todas as dependências caso contrário.
Eu sei tudo isso por experiência própria:
Para projetos Swift, definitivamente uso estruturas (bibliotecas) e vinculo-as a elas, pois é fácil de configurar usando o Xcode. Também preciso muito da versão, testes e dissociação, por isso.
Para projetos Mono (C #), para o Unity, comecei com a abordagem descolada de dividir o projeto em bibliotecas, compilei e testei cada um, o que foi ótimo ... mas depois que eu coloquei as bibliotecas no Unity, todos os tipos de problemas aconteceram , da versão hackeada do Mono Unity, para simplesmente o comportamento às vezes diferente que o código exibe ao alterar plataformas. Não ter um único IDE aqui para gerenciar todas as bibliotecas foi uma verdadeira dor; portanto, colocar toda a fonte no Unity foi uma grande vitória para a produtividade.
Finalmente, o mais relevante para você, um projeto de jogo em C ++ em que trabalhei. Um mecanismo de jogo, cliente em tempo real da rede, cliente HTTP da rede, IA e uma loja de persistência foram escritos para este jogo, apenas no lado do cliente. Pelo que eu optei? Bibliotecas CLion +. Mesmo usando bibliotecas, não parecia que eu estava. Todas as fontes estavam no projeto CLion IDE e, ao compor o CMakeLists, fui capaz de acionar todas as compilações e vinculá-las em um único toque.
Como conclusão , eu diria que usar bibliotecas é uma solução à prova de futuro, mas também uma otimização prematura, se não for necessária. Tanto quanto pude constatar da sua situação, alternar do MSVC para o Xcode será uma dor se você tiver vários alvos de compilação. Portanto, basta inseri-lo e manter o máximo de isolamento possível para quando for o momento em que você possa precisar usar bibliotecas.
PS: Estou tendo um dilema semelhante hoje em dia com o docker. Devo compor? Devo apenas executar localmente? .. etc Também o Elixir, pois permite criar aplicativos dentro do mesmo aplicativo. Devo fazer isso? Ou separar o aplicativo nos chamados microsserviços? ... etc. Não há bala de prata, sempre meça, como YMMV.
fonte
A vinculação com bibliotecas C ++ exige muita trabalheira e exige muito conhecimento e esforço para fazê-lo corretamente. Pode ser intimidante para os alunos de C ++.
Muitas vezes, os autores / mantenedores de uma biblioteca C ++ específica têm isso em mente e recomendam uma maneira ou de outra.
Em outras palavras, se os autores / mantenedores pretenderem que a biblioteca seja incluída por cabeçalhos (apenas * .h e .hpp) ou por fonte ( .h * ou .c ), isso teria sido dito claramente no leia-me ou documentação.
As bibliotecas projetadas e mantidas para serem multiplataforma (e compatíveis com vários fornecedores e ambientes do compilador C ++) geralmente terão um sistema de makefile ou um sistema de configuração de compilação (como CMake). Esses sistemas são usados para gerar calços de cabeçalho que atenuam as diferenças de plataforma e para gerar scripts que chamarão o compilador e o vinculador nos arquivos de origem, usando as opções de linha de comando apropriadas e na sequência correta. Dependendo da plataforma e configuração, esses sistemas de construção podem incluir ou excluir determinados cabeçalhos ou arquivos de origem, ou podem definir ou indefinir certos símbolos do pré-processador.
É possível ir contra a recomendação dos autores / mantenedores, mas isso sempre exige um esforço extenso de transferência. A quantidade de trabalho necessária para esse esforço de portabilidade pode ser comparável à portabilidade para um ambiente C ++ diferente.
Como o Visual C ++ usa seu próprio sistema de compilação com base em um arquivo de descrição do projeto (parcialmente baseado em XML), é bem diferente do sistema de compilação baseado em script usado no Linux. A abordagem usada pelo CMake é que o CMake faça as definições de configuração e emita toda a estrutura do projeto do Visual C ++, com as opções de configuração inseridas nos arquivos * .vcxproj.
Se surgirem problemas durante a vinculação do C ++ ao Visual C ++, as configurações de compilação nos arquivos * .vcxproj podem ser modificadas usando a GUI do Visual Studio (usando o diálogo das páginas de propriedades do projeto). Isso pressupõe que você compreenda completamente os significados e as consequências de uma dúzia de configurações importantes de compilação e vinculação de C ++.
Agora vem a parte mais estúpida do uso do Visual C ++: se você estiver usando uma dúzia de bibliotecas de terceiros diferentes, alterar as configurações de compilação para todas significa entrar em cada arquivo * .vcxproj e repetir a mesma alteração na GUI por uma dúzia vezes. Um aborrecimento, mas pode ser feito, se você souber como fazê-lo corretamente.
A maioria dos alunos do Visual C ++ aprende essas configurações da maneira mais difícil, observando os erros do compilador e vinculador do Visual C ++, identificados pelo código de erro. Por exemplo, pode-se consultar o LNK2005, com o significado superficial de "O símbolo do símbolo foi definido mais de uma vez", mas com o entendimento de que a definição duplicada não surge de um erro de programação descuidado, mas poderia ter acontecido por causa de alguns conflitos ou aplicações incorretas de opções de compilação e vinculação.
Para fornecer uma resposta mais específica e útil à sua situação, será necessário conhecer os nomes das bibliotecas que você pretende usar, bem como os erros de vinculação ou outras dificuldades que encontrar. Você pode encontrar respostas existentes para essas perguntas nos painéis de discussão da respectiva biblioteca. Essas perguntas tendem a ser marcadas com "problemas de vinculação", "janelas" e "C ++ visual".
Um guia iniciante para especialista sobre esse assunto é possível, mas será específico do projeto. Diferentes preferências escolhidas por diferentes projetos exigirão uma reescrita completa do guia.
fonte
Eu diria que sim, desde que seja mais fácil. Existem muitos benefícios:
Isso resultará em um código mais rápido e melhor, especialmente se você ativar a Otimização do tempo de link.
Seu IDE vai gostar mais, por exemplo, permitirá que você pule para a implementação (.cpp) do código da biblioteca, em vez de apenas para a interface (.h), que é extremamente útil quando se trabalha com código mal documentado (por exemplo, mais código).
Geralmente, você pode adicionar a dependência como um sub-módulo git, que é uma maneira um pouco invasiva, mas realmente muito boa de ter dependências (de qualquer maneira para C ++, que praticamente não possui sistemas de construção sãos). Isso facilita muito a atualização da biblioteca e o teste de versões diferentes.
Você não precisa se preocupar com a compilação de uma dependência com o MSVC ++ 2013, enquanto estiver usando 2017, por exemplo. Ou compartilhado vs estático MSVCRT.
Você pode criar facilmente no modo de depuração e entrar na biblioteca.
A única razão pela qual acho que você não gostaria de fazer isso é se a biblioteca é grande e possui um sistema de compilação complexo que você não deseja replicar no seu, por exemplo, Boost ou LLVM. Mas para bibliotecas simples, na verdade, não há desvantagem.
Como exemplo, eu uso o libusb em alguns projetos e preciso dar suporte ao Windows. O libusb usa ferramentas automáticas, que são uma piada de um sistema de compilação e, de qualquer maneira, não funcionam no Windows. Eles fornecem binários pré-compilados, mas são criados com o MSVC ++ 2013 e não funcionarão com 2017. A solução mais fácil de longe foi apenas adicionar todos os arquivos .c e .h relevantes ao meu projeto.
fonte
.o
arquivos que foram compilados,-flto
mas esses não são realmente uma biblioteca estática - para Clang, eles são arquivos de código de bits LLVM. E obviamente não funcionará se você usar bibliotecas estáticas fornecidas por outra pessoa.