- Os aplicativos do macOS têm componentes mais complexos do que programas de linha de comando, e recursos de interface como janelas e menus são gerenciados em uma estrutura separada
- No Classic Mac OS, o código executável e os recursos eram armazenados no resource fork do arquivo, mas a partir do Mac OS X isso mudou para a estrutura de bundle
- O bundle do app é organizado em torno do diretório Contents, com subpastas como MacOS, Resources e Frameworks, além de arquivos essenciais como Info.plist
- Depois, foram adicionados assinatura de código, recibos da App Store e notarização, evoluindo para uma estrutura que reforça segurança e integridade
- Essa estrutura autossuficiente do app bundle se tornou a base central para simplificar instalação, atualização e remoção, além de aumentar a segurança e a eficiência de manutenção
Estrutura de apps no Classic Mac OS
- Nas primeiras versões do Mac OS, recursos de UI como janelas e menus eram separados do executável e armazenados no resource fork
- Como exemplo, os recursos do QuarkXPress 4.11 aparecem no ResEdit
- O código executável ficava incluído no recurso CODE, e as informações de type e creator também eram armazenadas para que o Finder pudesse reconhecê-lo
Estrutura de bundle no Mac OS X
- O Mac OS X adotou a estrutura de bundle herdada do NeXTSTEP
- Um app é um diretório com a extensão
.app e inclui internamente a pasta Contents
- A pasta MacOS contém o executável do app GUI e ferramentas de linha de comando
- A pasta Resources armazena arquivos de recurso, como o ícone do app e componentes da GUI
- Alguns apps incluem a pasta Frameworks e incorporam dylib (bibliotecas dinâmicas)
- O arquivo Info.plist é obrigatório e define o nome do executável, ícone, versão mínima do macOS, tipos de documento, número de versão e mais
- O arquivo PkgInfo preserva as informações de type/creator do Classic Mac OS, mas não é obrigatório
- Ao iniciar um app, o launchd inicia o código executável, enquanto LaunchServices e RunningBoard executam o procedimento de inicialização com base nas informações do Info.plist
Segurança e extensões no macOS
- A partir do Mac OS X 10.5 Leopard (2007), foi introduzida a assinatura de código (Code Signature), adicionando a pasta _CodeSignature
- O arquivo CodeResources inclui o hash do diretório de código (CDHash) para verificar a integridade do app
- Apps distribuídos pela App Store incluem o recibo da loja na pasta _MASReceipt
- Após 2018, foi introduzida a notarização, permitindo que um ticket emitido pela Apple seja stapled ao bundle por meio do arquivo CodeResources
- Bundles de apps modernos incluem internamente componentes que antes eram instalados em pastas do sistema
- Pasta Library: LaunchDaemons, LoginItems etc.
- Pasta XPCServices: serviços executáveis separados usados pelo app
- Pastas Plugins / Extensions: recursos de extensão do app e App Intents
- Alguns apps também incluem o arquivo version.plist
Vantagens do app bundle
- Ao integrar todos os componentes dentro do bundle, a instalação, atualização e remoção ficam mais simples
- Reduz-se a chance de componentes ausentes, e a segurança é reforçada por meio de proteção por assinatura e notarização
- Apps da App Store ainda incluem recibos e tickets de notarização para garantir confiabilidade adicional
- Não há diferença estrutural entre as arquiteturas Intel e Arm; o executável Mach-O é armazenado como um binário universal (fat) que inclui código para ambas as plataformas
- No mesmo arquivo, também ficam presentes as assinaturas de cada arquitetura
Visão geral visual da estrutura do app
- No diagrama, o amarelo-claro indica componentes obrigatórios ou presentes em quase todos os apps
- O verde indica itens presentes apenas em apps distribuídos pela App Store, e o azul representa o ticket opcional de notarização
- Além disso, podem ser incluídos elementos adicionais como workflows do Automator e scripts
- De forma geral, os apps do macOS evoluíram para uma estrutura autossuficiente e centrada em segurança
1 comentários
Comentário no Hacker News
A parte marcada em azul é o notarisation ticket (ticket de notarização), mas na prática isso não é opcional
Um app não notarizado é inconveniente demais para o usuário, então no fim você precisa pagar a taxa de registro de desenvolvedor da Apple de US$ 99 por ano
Se for só para compilar e executar para uso pessoal, tudo bem, mas se for para distribuição o macOS mostra alertas que fazem o app parecer quebrado
Antes dava para executar com clique direito, mas agora é preciso até entrar nos ajustes do sistema para permitir
Dá para ver capturas de tela relacionadas na documentação de suporte da Apple e nas notícias para desenvolvedores
Eu gosto da filosofia de segurança da Apple, mas acho que o sistema de notarização para apps fora da App Store prejudica todas as partes envolvidas
Na prática, não consegui encontrar casos em que a notarização tenha impedido um problema de segurança
Eu achava a notarização do macOS chata, mas quando fui fazer distribuição no Windows vi que era ainda pior
Para ganhar a confiança do Windows Defender, você precisa comprar um certificado, e tanto empresas quanto pessoas físicas têm de passar por uma verificação de identidade profunda
Também é preciso assinar com token de hardware, então só uma pessoa pode publicar releases
Além disso, a autoridade certificadora pode bloquear sua chave de forma arbitrária, então seria terrível ficar travado justamente quando você precisa lançar um patch de segurança
Nesse aspecto, o ecossistema do macOS parece muito melhor
Estou desenvolvendo uma linguagem de programação que compila para várias plataformas, e assinatura e notarização não combinam em nada com esse processo
Esse tipo de sistema de assinatura é apenas um mecanismo de controle e corre o risco de abuso, como no caso da Epic
Se não for possível executar binários não assinados de forma razoável, considero a plataforma fechada e não dou suporte
Plataformas fechadas como iOS e Android podem ser parcialmente substituídas por PWA
Mas minha confiança de que o Google continuará permitindo executar apps autoassinados enfraqueceu
Só conheço dois casos em que a Apple revogou certificados de apps fora da App Store
Um foi o Research App do Facebook, o outro foi o Screenwise Meter do Google
Ambos eram apps com características de spyware voltados para adolescentes, e a revogação dos certificados acabou paralisando até ferramentas internas
Depois disso, parece que o Screenwise Meter voltou para a App Store
Artigos relacionados: Wired, EFF
Cerca de metade da pasta de apps no meu Mac não é notarizada e, na prática, não há grande problema
Depois da notarização, o stapled ticket (ticket anexado) é opcional
Se você não anexar o ticket, o usuário precisa verificar o status da notarização com conexão à internet
Ao desenvolver o AppBundler.jl, tenho várias reclamações sobre a estrutura dos apps no macOS
A exigência da estrutura da pasta Frameworks parece limpa visualmente, mas na prática empacotar tudo é trabalhoso, então estou contornando isso com uma pasta Libraries
O maior problema é a assinatura de código — parece um desperdício ter de assinar todos os binários
É difícil entender por que tornar isso tão complicado quando daria para reunir os hashes dos arquivos e assinar uma vez só
Além disso, o fato de os entitlements ficarem só no binário launcher também é ineficiente
Como os critérios de notarização ficam mais rígidos com o tempo, é possível que mais tarde o app de repente deixe de passar
Entrei no Apple Developer Program para tentar assinar e notarizar um app Tauri, mas estou falhando há 3 semanas
Como não tenho Mac, tentei via GitHub Actions, mas dizem que a primeira notarização costuma demorar
Já gastei quase US$ 100 só com GitHub e a notarização ainda não saiu
A equipe de suporte da Apple se recusou a ajudar porque eu não tenho Mac e uso Tauri
O processo de autenticação da API de notarização também é nível pesadelo — eu precisava gerar um JWT em PKCS8, mas quase não havia documentação, então tive de escrever meu próprio programa em Node
Foi a pior experiência de desenvolvedor (DX) que já tive até agora
Disseram que tentar resolver isso sem hardware da Apple é perda de tempo
Ao ver a primeira captura de tela do sistema operacional, meu coração afundou
Antes era uma UI prática e limpa, mas hoje em dia só desperdiça espaço com cantos arredondados e ícones com cara de bolha
Ainda assim, a qualidade do hardware do Mac é tão boa que não consigo migrar para um ThinkPad
Cantos arredondados são, na verdade, um recurso melhor para a visão humana
Há estudos de que cantos retos causam fadiga visual
Texto relacionado: Round Rects Are Everywhere
Eu também não gosto muito do macOS atual, mas essa captura de tela também não é perfeita
Há linhas demais e falta cor, então o olhar se dispersa
Pessoalmente, acho que a Aqua UI da era Leopard tinha um bom equilíbrio entre densidade de informação e profundidade visual
Em proporção de pixels, a UI antiga na verdade ocupava mais espaço
Considerando resolução 5K, o MacBook Pro moderno é mais eficiente
Os Macs clássicos também já tinham alguns cantos levemente arredondados
Referência: Infinite Mac
Computadores não são só para trabalho, mas também ferramentas para diversão
Ainda assim, parece que as UIs de hoje se afastaram demais da praticidade
A maior parte da tela é informação inútil tipo 101101, então é difícil chamar isso de prático
Está errado dizer que no macOS quem executa ferramentas de linha de comando é o launchd
Na prática, como em outros sistemas UNIX, elas são executadas pelo shell com fork/spawn
O sistema de bundles do NeXTSTEP inspirou o design dos arquivos JAR do Java
No Mac OS clássico, apps de Power Mac tinham o código PPC armazenado no data fork
O mesmo valia para binários CFM-68K, e quem usava recursos CODE eram só os códigos 68K mais antigos
Tenho boas lembranças da época em que mexíamos nos apps com o velho ResEdit
Uma explosão de burocracia como no último diagrama não é um bom sinal
Fico com ainda menos motivos para “fazer upgrade” para o macOS 26
A estrutura atual é o “padrão” do macOS, mas não é a única forma
Se você configurar bem o RPATH, dá para colocar bibliotecas em subpastas arbitrárias e ainda passar na notarização
Por exemplo, o caminho AppName.App/Contents/Libraries também funciona
Mas esse método quase não tem vantagem prática, e entre uns 100 apps no meu sistema nenhum usa pasta /Libraries
Em vez de .dylib, você obrigatoriamente tem de usar o formato .framework, e essa é uma regra não documentada
Na submissão isso pode ser detectado automaticamente e levar à rejeição