O que torna um programa (em uma linguagem como C ++) multiplataforma ou não?

8

Eu tenho uma experiência de programação bastante básica com Java e tentei C ++ e Python. Embora faça sentido para Java, os programas básicos que escrevi em C ++ foram bem executados no Windows e no OS X. Consegui enviar o arquivo de origem para o outro computador, compilar e executar. Os programas são bastante básicos, principalmente coisas básicas orientadas a objetos que venho fazendo para tentar aprender C ++.

Obviamente, porém, você não pode simplesmente compilar qualquer programa C ++ em qualquer máquina e fazê-lo funcionar bem. Em que ponto isso acontece? Em que nível de complexidade a plataforma começa a importar e o programa não é executado apenas em lugar algum? É quando você usa bibliotecas específicas da plataforma? Um programa poderia ser criado em várias plataformas em C ++ usando apenas bibliotecas de várias plataformas?

Eu tenho tentado descobrir isso sozinho, mas tudo o que eu descobri passa por cima da minha cabeça ou simplesmente não responde à pergunta, muito do que aparece são emuladores ou pessoas perguntando quais idiomas são multiplataforma.

Chris
fonte
2
Bibliotecas específicas de plataforma, extensões de compilador fora do padrão, qualquer confiança em como os bits são realmente dispostos na memória e qualquer outra forma de comportamento indefinido / não especificado são os motivos típicos que conheço para que o código se torne específico da plataforma. Se você evitar tudo isso, sim, o C ++ é bastante portátil por padrão.
Ixrec
"Um programa poderia ser criado em várias plataformas em C ++ usando apenas bibliotecas de várias plataformas?" Isto é principalmente verdade. Você também precisa compilar (criar os binários) para cada plataforma, porque o código de máquina compilado é específico da arquitetura.
rwong
1
Você pode usar estruturas Qt ou POCO .
Basile Starynkevitch

Respostas:

6

Existe uma linha muito clara na areia entre plataformas e monoplataforma:

Um programa usa apenas as APIs expostas pela Biblioteca Padrão em que é construído?

Se você direcionar uma implementação padrão, qualquer plataforma que implemente esse padrão deverá, em teoria, compilar e executar seu programa corretamente. Existem muitas exceções, mas, em geral, se você evitar truques inteligentes, poderá evitar muitas dessas exceções.

A razão pela qual esse problema surge especificamente com o C ++ é que, durante muito tempo, a Biblioteca Padrão do C ++ não incluiu muitos módulos úteis para programas não triviais. Concorrência e GUI são os dois maiores. Isso significava que um programa criado usando apenas a Biblioteca Padrão C ++ não poderia ter muitos dos recursos que esperamos do software moderno.

Como escrevemos software de plataforma cruzada que não suporta a Biblioteca Padrão?

Você menciona "bibliotecas de plataforma cruzada", que na prática são normalmente chamadas de "estruturas" ou "kits de ferramentas" com base em seu escopo. A maneira de escrever software em C ++ que é multiplataforma é direcionar não apenas a Biblioteca Padrão, mas uma estrutura que se baseia nas plataformas de destino.

Essencialmente, você acaba externalizando os bits específicos da plataforma para outra biblioteca. Por exemplo, wxWidgets é uma estrutura popular. Você pode usar suas classes para construir uma GUI e funcionalidade relacionada (por exemplo, caixas de diálogo padrão para selecionar arquivos). Nos bastidores, ele usa compilação condicional para implementar a GUI usando a GUI nativa para cada plataforma. Mas, como usuário da biblioteca, nada disso importa para você.


Nota histórica: aqui em 2015 os compiladores e bibliotecas C ++ são, na maioria das vezes, realmente bons. Volte alguns anos, e isso não é verdade. O C ++ não possuía um padrão oficial até 1998, muitos anos após sua criação. Os fornecedores demoraram muito tempo a atualizar seus compiladores e bibliotecas para implementar o padrão corretamente. As extensões específicas do fornecedor abundavam (e ainda estão por aí, na verdade). Alguns compiladores tinham cabeçalhos e funcionalidade fora do padrão. A portabilidade do código era praticamente inexistente. A reputação do C ++ em termos de portabilidade ainda sofre.


fonte
5

Em que nível de complexidade a plataforma começa a importar e o programa não é executado apenas em lugar algum?

Basicamente, qualquer coisa não trivial. Se você escrever um programa não trivial, acabará acidentalmente, dependendo de uma maneira específica do compilador de ordenar sobrecargas, pesquisar nomes e outras coisas complexas. Além disso, praticamente todos os programas não triviais dependem de um comportamento específico da plataforma não-padrão, porque o padrão realmente não fornece nada, exceto alguns contêineres.

No entanto, programas não triviais podem variar bastante na facilidade com que são portados para outra plataforma. Se você programou bem e seguiu as regras, poderá portar com bastante facilidade e bônus se puder abstrair as peças em uma biblioteca (que talvez já tenha sido fornecida para você, por exemplo, Boost.Filesystem).

Os programas geralmente se tornam muito difíceis de portar entre plataformas se eles executam tarefas inerentemente específicas da plataforma, por exemplo, gravar dados em disco com certas garantias de atomicidade / consistência ou, se você era um idiota e andava fazendo coisas estúpidas que eram nunca o que você deveria ter feito em primeiro lugar, como transmitir entre ints e ponteiros.

DeadMG
fonte
2
Certamente isso exagera o caso? Eu sei que códigos C ++ mais esotéricos podem ser executados em vários bugs do compilador em compiladores antigos ou de qualidade inferior, mas qualquer compilador razoavelmente compatível com os padrões deve lidar com coisas como sobrecarga e pesquisa de nome da mesma forma. A biblioteca Standard fornece E / S e (começando com C ++ 11) threading, e o suporte ao sistema de arquivos está sendo padronizado.
Josh Kelley #
@ JoshKelley: Isso é basicamente nada comparado ao que a maioria dos programas exige. Além disso, alguns compiladores muito comuns, como o MSVC, implementam sobrecarga, SFINAE e pesquisa de nomes de maneira diferente, com diferentes resultados observáveis.
DeadMG
1

Em termos muito simples, o que torna um programa multiplataforma é sua capacidade de pegar as fontes de um ambiente, compilá-las em outro e fazer com que o produto final funcione conforme o esperado.

Em termos menos simples, é haver sobreposição total entre o que o programa espera estar disponível e o que os ambientes de destino fornecem. Depois de fazer qualquer coisa que faça a sobreposição menor que 100%, como o uso de uma biblioteca específica do ambiente ou um recurso de linguagem com comportamento indefinido, você vincula seu programa aos ambientes que podem fornecer os recursos não sobrepostos.

("Plataforma" é um pouco de uma palavra mole. As pessoas podem falar sobre Windows e Unix como plataformas ou Linux, OS X, BSD e Solaris como plataformas, embora todas sejam nominalmente Unix. Execute qualquer uma das opções acima em diferentes as arquiteturas de hardware e as coisas ficam ainda mais nebulosas. Dito isso, vou começar a usar a palavra.)

Felizmente, existem padrões para facilitar esse problema:

Línguas. Você está escrevendo C ++, que foi padronizado pela ISO em 1998. Qualquer programa que você escreva em conformidade com esse padrão pode ser compilado e executado com os resultados esperados em qualquer plataforma com um compilador e tempo de execução em conformidade. Não há limite para o tamanho ou sofisticação do programa, desde que não se desvie do padrão. Se um programa que atenda ao padrão não for executado conforme o esperado em uma determinada plataforma, a implementação do idioma nessa plataforma se tornará suspeita. Muitos idiomas têm suítes de teste cuidadosamente projetadas que podem ser usadas para verificar a conformidade.

O Java recebe uma menção especial porque não apenas padroniza uma linguagem, como também padroniza o código do objeto, o que torna seus programas executáveis ​​em qualquer lugar sem recompilação. Isso é feito empurrando o ponto de conformidade para baixo em uma camada adicional em uma máquina virtual personalizada da plataforma (ou mesmo hardware) capaz de executar o código do objeto.

APIs. As chamadas que você faz para que seu programa faça certas coisas também podem ser padronizadas. Assim como os idiomas, essas APIs e as bibliotecas que os implementam podem ser configuradas para se comportarem conforme os chamadores esperam, usando uma implementação subjacente adequada para uma plataforma específica. Uma dessas APIs são os padrões POSIX do IEEE , que surgiram como uma maneira de conter a fragmentação que estava acontecendo no Unix durante a década de 1980. (Eu estava na época; esse aspecto não era divertido.) Ao definir chamadas e comportamento padrão, os fornecedores de sistemas podiam dar a seus clientes a confiança de que a migração para o sistema operacional não implicaria uma quantidade enorme de trabalho, como ocorreu no passado. O POSIX foi amplamente adotado e ainda é amplamente utilizado quase 30 anos depois.

Eu fiz vários projetos que aderiram aos padrões de maneira servil porque eu sabia que eles teriam que ser executados em várias plataformas. O que obtive pelos meus problemas foi um código que funcionava em todos os lugares que eu planejava executá-lo e me surpreendeu agradavelmente em alguns que não tinha.

Blrfl
fonte
0

Basicamente, quando você 'toca' coisas fora do seu programa. Um caso específico (não me atrevo a dizer o único caso) é quando você usa bibliotecas relacionadas ao sistema operacional. Coisas como usar memória compartilhada entre processo e imprimir coisas sofisticadas no console. No primeiro caso, você acessa um pedaço de memória sendo tratado pelo sistema operacional; no segundo, a tela também é controlada pelo sistema operacional.

A execução de uma GUI depende do SO, mas existem bibliotecas de GUI criadas para serem multiplataforma, portanto você não precisa se preocupar com isso. Pelo menos em teoria.

É difícil criar algo não trivial para ser multiplataforma. A novidade é que, se você usar as bibliotecas corretas e fazer testes adequados, não será difícil tornar o software portátil, pelo menos se o código não for muito grande. Quão grande é muito grande depende do tamanho da sua equipe, experiência em programação e assim por diante.

cauchy
fonte