Rust: Vinculando com LLD

Criado em 17 fev. 2017  ·  94Comentários  ·  Fonte: rust-lang/rust

O LLVM 4.0 é enviado com LLD habilitado, embora AFAIK ainda não esteja pronto para produção em todas as plataformas. Eu acredito que temos uma atualização LLVM planejada em breve para resolver problemas de AVR / emscripten de qualquer maneira, então agora é a hora de começar a determinar o que podemos precisar fazer para suportá-lo, como isso afeta o desempenho do compilador / tamanho do binário / desempenho do tempo de execução em comparação com nosso vinculadores usuais e em quais plataformas podemos querer habilitá-lo por padrão.

Status atual (2020-04-24) resumido em https://github.com/rust-lang/rust/issues/39915#issuecomment -618726211

A-linkage C-feature-request I-compiletime T-compiler

Comentários muito úteis

Este bug é uma bagunça, então aqui está minha melhor chance de um rápido resumo da situação atual, para as pessoas que querem seguir em frente.

O que é lld

Um vinculador que faz parte do projeto llvm, o que é desejável por dois motivos:

  • é muito amigável para compilação cruzada (daí sua ênfase para alvos incorporados)
  • é muito rápido (geralmente é executado na metade do tempo que o Gold - a vinculação pode levar vários minutos para grandes projetos (rustc, servo, etc.) e a vinculação pode ser uma grande% da compilação com compilações incrementais, portanto, reduzir pela metade esse tempo de execução é um Grande negócio.)

Coisas que o Rust faz com o lld hoje

  • Rust atualmente envia sua própria cópia do lld na maioria das plataformas como um binário que ele chama de rust-lld
  • rust-lld é usado por padrão em muitos alvos bare-metal
  • rust-lld é usado por padrão para wasm
  • (?) você pode solicitar explicitamente que rust-lld seja usado usando "-C linker-flavour" (confuso sobre o que exatamente isso faz em plataformas não bare-metal, veja abaixo)

Problemas para usar rust-lld em mais lugares (por exemplo, desktop linux / mac / windows)

  • O back-end do macOS (Mach-O) para lld está quebrado e abandonado

    • uma reescrita do zero começou, mas ainda é cedo

  • Em plataformas linux / unix, você não deve invocar diretamente ld / lld. Você deve invocar o linker por meio do compilador c do sistema (ou seja, gcc), cuja responsabilidade é descobrir símbolos do sistema como crt1.o e fornecê-los ao ld. Isso significa que não podemos "apenas" usar rust-lld; devemos alimentá-lo em gcc / clang / qualquer. (não queremos implementar essa lógica de símbolo do sistema nós mesmos)

    • Em geral, você não pode fornecer o linker como um caminho, você deve injetá-lo no caminho de pesquisa do compilador C como "ld"

    • Como alternativa, você pode fazer a mesma coisa, mas injetá-lo como "ld.lld" e passar "-fuse-ld = lld"



      • Isso pode ser importante, aparentemente o lld faz a detecção de nomes binários no estilo clang para saber se está sendo executado como "ld" ou "ld.lld" (precisa ser investigado)


      • Infelizmente -fuse-ld = lld é apenas parte do GCC 9, portanto, podemos exigir a detecção de recurso / versão para usá-lo (o clang está com ele há muito tempo)



  • windows-msvc está aparentemente em boa forma e parece ter algum suporte limitado para usar rust-lld no back-end, mas não estou certo sobre o que precisa ser feito aqui.
  • windows-mingw parece estar mais ou menos no mesmo lugar que linux / unix, exceto que você está sujeito a obter um GCC antigo, e as coisas estão um pouco confusas porque pseudo-windows-linux não é exatamente uma configuração bem testada?

Além disso, em geral, lld é mais recente, não é o padrão para a maioria dos sistemas operacionais, bugs de compatibilidade aleatórios certamente surgirão se começarmos a usar isso em mais lugares.

Apresentei dois metabugs para esforços concentrados no uso de (rust-) lld por padrão em duas plataformas:

  • # 71515 - x64 Ubuntu 20.04 LTS (e mais amplamente todas as plataformas x64 ELF)
  • # 71520 - janelas x64 msvc

Todos 94 comentários

Veja também um PoC em # 36120.

LLD pode ser um candidato muito bom para destinos de MinGW, porque atualmente empacotamos um vinculador com eles de qualquer maneira e o vinculador de MinGW tem uma variedade de problemas que variam de falta de ASLR a nenhum suporte de bigobj. Se pudermos, de alguma forma, trazer junto as bibliotecas mingw necessárias durante a compilação cruzada e não apenas o direcionamento nativo (ao qual o pacote mingw do rustup está atualmente limitado), então isso permitiria a compilação cruzada da ferrugem do linux fora da caixa, o que seria uma grande melhoria sobre a situação existente em que as pessoas obtêm o MinGW de sua distro e depois encontram problemas porque as distros quase sempre usam um MinGW incompatível.

O LLD não é um bom candidato para almejar nativamente os alvos MSVC, devido a vários motivos, sendo o principal a falta de suporte para debuginfo. A compilação cruzada para destinos MSVC requer bibliotecas que não podem ser redistribuídas, portanto, não podemos oferecer suporte para isso fora da caixa de qualquer maneira.

O problema de rastreamento para atualizar para o LLVM 4.0 é https://github.com/rust-lang/rust/issues/37609 .

Para registro, o lld definitivamente não está pronto para destinos Solaris. Mas no Solaris, não há razão que eu conheça para usar lld em vez do ld nativo. Já vimos o que seria necessário para que o rust usasse o Solaris ld no Solaris em vez de usar o gcc para vinculação.

@binarycrusader Uma razão para usar lld é ao compilar para Solaris, não no Solaris.

PR rust-lang / rust # 40018 adiciona um sinalizador -Z linker-flavor a rustc para possibilitar o uso de LLD como um vinculador. Esse PR não incorpora LLD no rustc, mas permite experimentação fora da árvore com ele.

@binarycrusader ^ que pode ajudar em sua experiência de usar diretamente o ld do Solaris em vez do gcc.

Agora parece que estamos rodando no LLVM 4.0. @japaric , isso significa que o sinalizador de sabor do vinculador agora pode ser facilmente usado para comparar e contrastar o LLD com o vinculador do sistema?

@bstrie # 40018 pousou há algumas semanas. Desde que pousou, pode-se usar -Z linker-flavor=ld -C linker=ld.lld para usar um binário LLD externo como vinculador. Observe que, ao contrário do gcc, o LLD não sabe onde estão as bibliotecas do sistema, então você terá que passar o caminho de pesquisa da biblioteca para o vinculador usando -C link-args='-L ...' se estiver vinculando a qualquer biblioteca do sistema.

O que o LLVM 4.0 ajuda a fazer é fundir o LLD ao rustc. Com essa mudança, não exigiríamos um vinculador externo em alguns cenários, como vincular binários MUSL ou programas bare metal. Digo alguns cenários porque a maioria dos destinos requer vinculação às bibliotecas do sistema, onde você encontrará o problema do caminho de pesquisa da biblioteca que mencionei acima. Para esses alvos, o LLD não funcionará fora da caixa. Não está claro como e onde resolver esse problema e, sem uma solução para isso, não podemos mudar para o LLD para os alvos mais importantes (camada 1), o que reduz o apelo de incorporar o LLD ao rustc em primeiro lugar.

@japaric Quais são os argumentos contra a incorporação de caminhos de pesquisa (biblioteca relativa ao sysroot), bem como coisas como -lc -lpthread crt0.o , diretamente no rustc? Afinal, algum componente do conjunto de ferramentas precisa incorporá-los, pois não temos nenhum padrão para as plataformas a serem seguidas, e binutils não é uma boa fonte de ouro desse conhecimento.

A única desvantagem que consigo pensar é a situação em que o mesmo triplo teria diferentes caminhos de pesquisa em diferentes sabores de sistemas (o que provavelmente será exclusivo para triplos Linux / glibc, e especialmente ruim em plataformas com multilib). Nesse caso, acredito que o clang espia o nome do sistema operacional e codifica as convenções específicas do sistema operacional, o que parece ruim, mas provavelmente inevitável se alguém quiser distribuir um único binário que seja executado em qualquer Linux (e não precise do vinculador de sistema).

@ retep998 Dei uma olhada rápida em lld há alguns meses. Não consegui fazer a compilação cruzada (link cruzado?) Um .exe do Linux. Parece que o lld só oferece suporte a formatos nativos de plataforma.

Espero estar enganado.

Marcando isso como um bug de desempenho, já que de acordo com os benchmarks do LLD, ele parece superar o GNU ld por um fator de dez, e o desempenho da vinculação é um grande componente da velocidade do compilador atualmente.

Er, esqueci de vincular os benchmarks: https://lld.llvm.org/#performance

(Relevante hoje, já que o LLVM 5.0 acaba de ser lançado.)

Vincular com LLD é muito mais rápido do que bfd ou gold, mas duvido que usá-lo melhore significativamente o desempenho geral. Ainda assim, acho que essa questão é importante e deve ser uma prioridade.

@tpimh Na verdade, não tenho certeza se a tag I-slow deve representar bugs de desempenho de tempo de execução ou de desempenho de compilação, eu pretendia que fosse o último. E o IME, quando olho para o tempo decorrido, a vinculação de saída geralmente está nas três fases mais longas, significativamente mais longas do que a maioria, então mesmo cortar o tempo de vinculação pela metade provavelmente seria uma grande vitória (especialmente para coisas grandes como Servo e rustc).

@bstrie I-slow é para desempenho de tempo de execução ruim, I-compiletime é para desempenho do compilador da última vez que verifiquei

Boas notícias para qualquer pessoa interessada no obscuro tópico de links cruzados do Linux para o Windows. Eu disse antes que não era possível com lld, mas isso só é verdade para o sabor ld do lld. É possível para o tipo link.exe do lld (link-lld).

Especificamente para Rust, podemos fazer isso hoje com algumas alterações de código.

  1. Precisamos compilar um subconjunto muito pequeno de CRT do mingw-w64 em arquivos de objeto .o. Ou seja, algum thread de inicialização de armazenamento local. Também precisamos do chkstk.

  2. O lld não gosta das bibliotecas de importação usuais do MinGW. Em vez disso, precisamos construir nós mesmos os arquivos .def em arquivos .lib, usando lld-link ou llvm-dlltool

  3. Modifique lld para tratar IMPORT_NAME_NOPREFIX como
    IMPORT_NAME_UNDECORATE, porque mesmo com a etapa 2 os .libs não são perfeitos

  4. Modifique seh.rs de Rust para substituir TYPE_INFO_VTABLE por ptr :: null (). Obrigatório porque o símbolo ??_7type_info@@6B@ não está definido no MinGW. Em seguida, crie e instale o Rust.

  5. Use .cargo / config para especificar um script de wrapper personalizado como o vinculador.

  6. Nosso script de vinculador de wrapper deve invocar lld-link principalmente usando os parâmetros que são passados. No entanto, devemos fazer alguns ajustes:

    a) Corrija a caixa do nome do arquivo, por exemplo, altere AdvAPI32.Lib para advapi32.lib

    b) Modifique o arquivo .def que Rust gera para prefixar símbolos com um sublinhado extra

    c) Substituir o ponto de entrada (/ entrada). Necessário provavelmente devido a um problema de mutilação de nome.

    d) Anexe os arquivos de objeto mingw-crt que você compilou na etapa 1

  7. Construa seu projeto Rust usando xargo --target = i686-pc-windows-msvc

Seguir as etapas acima me permite compilar o código Rust. Posso até entrar em pânico usando o desenrolamento baseado em SEH do Rust.

@iainnicol Você está misturando o alvo msvc com bits MinGW, e é por isso que você tem que fazer todas aquelas modificações estranhas. Se você apenas copiar as bibliotecas de uma instalação VC ++ existente, poderá usar o lld-link normalmente sem todas essas modificações ou quaisquer bits do MinGW.

Mas eu não quero usar uma instalação VC ++ existente. Não há nenhuma maneira de obter um sem gastar algo como oito horas baixando e instalando lixo, muito menos para redistribuir.

As ferramentas de compilação autônomas são muito mais leves, a menos que já seja a que você está se referindo, caso em que talvez devêssemos nos esforçar para melhorar ou recriar o que o MinGW fez para que seja realmente compatível com o MSVC.

As ferramentas de construção autônomas são muito mais leves

Eu não percebi que a Microsoft os distribui. Você poderia criar um link para eles? Existe alguma maneira razoável de extrair o arquivo de instalação sem realmente executá-lo, ou seja, é um msi ou algo semelhante?

Aqui estão eles: http://landinghub.visualstudio.com/visual-cpp-build-tools

As versões de 2015 e 2017 são exes, mas você pode convencer o exe de 2017 a dar o que você deseja por meio deste: https://docs.microsoft.com/en-us/visualstudio/install/install-vs- rede de qualidade inconsistente

Se realmente quisermos fazer isso direito para o Windows, precisaríamos primeiro de https://github.com/rust-lang/rust/issues/30027 para eliminar a necessidade do SDK do Windows ou das bibliotecas de importação do MinGW. Em seguida, tudo o que nos restaria é substituir os bits CRT por nossas próprias versões puras do Rust (funções matemáticas / de memória, ponto de entrada, alguns outros bits de tempo de execução que o Rust precisa) e teríamos um conjunto de ferramentas Rust totalmente autocontido que pode crie binários do Windows! A desvantagem disso é que você não seria capaz de vincular estaticamente o código C / C ++ porque isso depende muito da vinculação no CRT apropriado de MinGW ou VC ++. Claro que todo o objetivo do Rust é reescrever tudo no Rust, então isso não é um grande problema.

Boas notícias para qualquer pessoa interessada no obscuro tópico de links cruzados do Linux para o Windows. Eu disse antes que não era possível com lld, mas isso só é verdade para o sabor ld do lld. É possível para o tipo link.exe do lld (link-lld).

Parece que agora também deve ser possível com o tipo ld: https://reviews.llvm.org/rL312926

O driver compatível com MinGW do novo lld é um invólucro para o vinculador de lld. Ele traduz internamente as opções do tipo Unix para opções do tipo Windows e, em seguida, chama o ponto de entrada do lld-link. Não tenho certeza se vocês querem usá-lo porque (exceto que o driver do wrapper está incompleto e não está pronto para uso) ele não parece facilitar as coisas, a menos que você já tenha Makefiles para MinGW.

Tenho uma pergunta (provavelmente boba) para vocês sobre compilação cruzada. No Windows, todos os símbolos dllimportados têm nomes DLL dos quais são importados. Se você não tiver nenhum arquivo de biblioteca MSVC, como saber de quais arquivos os símbolos importados são importados?

Tenho uma pergunta (provavelmente boba) para vocês sobre compilação cruzada. No Windows, todos os símbolos dllimportados têm nomes DLL dos quais são importados. Se você não tiver nenhum arquivo de biblioteca MSVC, como saber de quais arquivos os símbolos importados são importados?

Se você não tiver nenhuma biblioteca de importação, terá que criar bibliotecas de importação ou implementar https://github.com/rust-lang/rust/issues/30027 para que winapi faça todo o trabalho trabalho de especificar de qual DLL cada símbolo vem junto com zaniness como ordinais. Algo tem que especificar o mapeamento de símbolos em tempo de link para símbolos / ordinais em DLLs, sejam bibliotecas de importação ou anotações em seu código.

Depois de puxar https://reviews.llvm.org/rL311734 , estou quase capaz de inicializar o rustc usando lld no macOS. Parece haver um problema com os metadados dylib, que ainda preciso investigar.

Eu tenho um ramo que ressuscita https://github.com/rust-lang/rust/pull/36120; uma vez que precisamos dessa correção lld (muito recente), isso está bloqueado em https://github.com/rust-lang/rust/issues/43370.

@tamird : # 43370 foi fechado.

O LLD foi adicionado em https://github.com/rust-lang/rust/pull/48125 e agora está sendo fornecido com plataformas de nível 1 (mac, linux, windows). Você pode testá-lo com -Z linker-flavor para cada plataforma, embora seja improvável que funcione para a maioria das plataformas por padrão. Ele funciona, no entanto, por padrão no MSVC. Por exemplo:

$ RUSTFLAGS='-Z linker-flavor=lld-link' cargo build

reduziu o tempo de link do próprio Cargo de 2,5s para 1,5s, uma ótima melhoria!

@alexcrichton , quais são os próximos passos? O ideal seria que o LLD funcionasse por padrão em todas as plataformas (não tenho ideia de quanto trabalho isso levará) e, em seguida, gostaria de executar benchmarks de tempo de execução / compiletime para ver se faz sentido tornar o LLD o padrão em quaisquer plataformas. Especialmente com a compilação incremental, o desempenho da vinculação será mais importante do que nunca.

Especialmente com a compilação incremental, o desempenho da vinculação será mais importante do que nunca.

É uma pena que o desempenho de links ainda não seja importante o suficiente para que possamos fazer coisas como habilitar links incrementais em plataformas que o suportam. https://github.com/rust-lang/rust/issues/37543

@bstrie Suponho que essas sejam as próximas etapas, fazendo com que funcione em outras plataformas :)

Não tenho certeza do que isso acarreta, mas já funciona no MSVC, acho que está longe de funcionar no MinGW / Linux, e estamos bem próximos no OSX. Quanto ao suporte de arquitetura cruzada, também não tenho certeza. Não espero "estabilizá-lo" para outra coisa senão a plataforma wasm em um futuro próximo.

@alexcrichton Posso perguntar como você especificaria "estabilização"? Por que não seria possível "estabilizar" a vinculação com lld para os outros suportes de ferrugem das principais plataformas? (por exemplo, compilação cruzada de um executável do linux para macOS).

No momento, é uma dor de compilação cruzada, por exemplo, o trabalho necessário para compilar um executável para macOS (x86_64-apple-darwin) do Linux requer etapas não triviais como adquirir o xcode sdk e construir todo o conjunto de ferramentas.

@cynecx uma boa pergunta! Um sobre o qual não pensei muito. Acho, no entanto, que não queremos estabilizar de fato o LLD apenas porque o adicionamos para outra plataforma; isso vai exigir tempo e trabalho para acertar e expor bem.

por exemplo, o trabalho necessário para compilar um executável para macOS (x86_64-apple-darwin) do linux requer etapas não triviais, como adquirir o xcode sdk e construir todo o conjunto de ferramentas.

O LLD não ajudaria muito aqui, você ainda precisa do SDK do Xcode porque ele tem cabeçalhos que você não pode redistribuir (e dependendo do que você está construindo, você também precisará de outras ferramentas do SDK).

O que é realmente bom sobre o LLD agora ser integrado todas as noites é que você pode compilar facilmente projetos Rust puros do Windows para o Linux com RUSTFLAGS='-Z linker-flavor=ld.lld' cargo build --target x86_64-unknown-linux-musl . Excelente para escrever pequenas ferramentas para máquinas Linux nas quais você não pode simplesmente instalar o Rust.

Não espero "estabilizá-lo" para outra coisa senão a plataforma wasm em um futuro próximo.

Como @rkarp disse, um caso de uso muito comum visa x86_64-unknown-linux-musl (e eventualmente steed) para suportar cargas de trabalho Linux em contêineres. Esta é uma daquelas coisas que Go faz muito bem e onde parece que estamos muito perto de Rust ser capaz de fazer o mesmo. Em termos de uso real, aposto que o LLD para x86_64-unknown-linux-musl seria usado muito mais amplamente do que o wasm.

De forma mais geral, quando se trata de construção cruzada, não acho que uma abordagem "deve funcionar para todos os hosts e / ou todos os destinos" faça sentido. Acho que faz sentido estabilizar isso em uma base alvo por alvo, conforme os alvos começam a funcionar.

Em particular, eu adoraria ajudar com o esforço para obter o LLD para o destino x86_64-unknown-linux-musl estabilizado o mais rápido possível.

Meu projeto tem 37 caixas, e os links de construção cerca de 70 binários (muitos testes). Não cientificamente (olhando top ) pelo menos metade do tempo de construção, estamos apenas executando o ld. Espero que usar lld agilize muito nossas compilações. Estamos com o Rust estável e ainda não consegui fazer o lld 6.0 funcionar.

@briansmith , você testou o LLD para musl e seu caso de uso? Em teoria, tudo o que você precisa fazer para testá-lo é passar -Z linker-flavor=ld.lld , e se isso funcionar pareça plausível, poderíamos mudar os padrões!

@rocallahan só para confirmar, vocês estão usando o linker ouro atualmente, certo? (afaik é mais rápido do que o linker binutils padrão). Se -Z linker-flavor=ld.lld funcionar (e for mais rápido), talvez possamos tentar estabilizá-lo! Em que plataforma estava isso?

De forma não científica (olho no topo), pelo menos metade do tempo de construção, estamos apenas executando o ld.

Isso é para uma compilação de depuração BTW.

vocês estão usando o linker ouro atualmente, certo? (afaik é mais rápido do que o linker binutils padrão)

Não, esse é o vinculador do sistema Fedora, o vinculador GNU padrão.

Em que plataforma estava isso?

Fedora 27, laptop Skylake quad-core com SSD. Vou obter alguns números de desempenho.

Ah ok bom saber! As compilações de depuração provavelmente obterão o maior benefício no tempo de link do anão dividido (https://github.com/rust-lang/rust/issues/34651) em vez de melhorias no linker.

Para obter informações de tempo, no entanto, @rocallahan se você tiver uma chance de testar a mente com ld.gold e ld.lld ?

Certo. Devo também lembrar que o problema # 48762 é muito fácil de usar para acelerar o tempo de link de depuração do Linux. (Já estamos usando um script de linker hackeado que remove .debug_pubnames / .debug_pubtypes do executável.)

Dividir DWARF pode ser bom, mas também pode causar problemas para os usuários. Vou comentar nessa questão.

@briansmith , você testou o LLD para musl e seu caso de uso? Em teoria, tudo o que você precisa fazer para testá-lo é passar -Z linker-flavour = ld.lld, e se isso funcionar pareça plausível, poderíamos mudar os padrões!

OK, vou testar as coisas. Talvez inicialmente deva haver um meio-termo entre "padrão" e "apenas à noite", alguma forma de optar por usar LLD como fazemos com -Z , mas sem usar -Z para que funcione em compilações estáveis.

mas sem usar -Z para que funcione em compilações estáveis.

Você pode tentar RUSTC_BOOTSTRAP=1 RUSTFLAGS="-Z linker-flavor=foo" cargo build

Por favor, não vamos recomendar o sinalizador de bootstrap? Preocupo-me com o fato de que, se um número suficiente de projetos depender dele, as coisas se tornarão de fato estáveis, anulando o ponto de todo o mecanismo de estabilidade.

Desculpe = /

Como um ponto de dados, vincular a caixa rustc_trans no repositório Rust caiu de um tempo de link de 78s para um tempo de link de 1s em minha máquina local.

Meu desempenho resulta de fazer uma mudança de espaço em branco para uma caixa perto da parte inferior de nossa hierarquia de caixa. Laptop Skylake quad core, 16 GB de RAM, rustc 1.24.0, LLD 7.0.0, GNU ld 2.29-13. Usamos um script de vinculador personalizado que descarta .debug_pubnames e .debug_pubtypes ; O LLD usa caminhos de código bastante diferentes quando um script de vinculador está presente, de modo que pode afetar as coisas.

GNU ld:

real    2m39.138s
user    8m18.992s
sys 1m37.513s

LLD:

real    2m19.164s
user    6m4.477s
sys 0m56.858s

O ouro não funcionou, ele vomitou em nosso script de vinculação. Os resultados são bastante estáveis. O LLD não afeta muito o tempo de ponta a ponta, mas reduz significativamente o uso da CPU; Eu acho que isso significa que nossa construção não gasta muito tempo esperando o lds terminar, mas gasta muito tempo de CPU executando-os.

Veja # 50584 para um exemplo do mundo real onde mudar de GNU ld para lld faz com que uma carga de trabalho comum de "pequenas mudanças e reconstruções" seja executada mais de 2,5 vezes mais rápido.

Er https://github.com/rust-lang/rust/issues/50584#issuecomment -400918647 é mais apropriado aqui:


A próxima etapa para estabilizar o LLD seria obter um sinalizador, como -Z linker-flavour = lld, funcionando para todos os alvos (Windows + Mac + Linux). Ele faria tudo o que fosse necessário para funcionar nas várias plataformas.

Depois de fazer isso, podemos anunciar para a comunidade, pedindo feedback. Aqui podemos obter informações de tempo e relatórios de bug para enviar ao LLD. Se tudo correr bem (o que é meio duvidoso com um linker totalmente novo, mas nunca se sabe!), Podemos ativá-lo por padrão, caso contrário, podemos trabalhar para estabilizar a seleção de LLD e, em seguida, adicionar uma opção para Cargo. toml para que os projetos possam pelo menos optar por ele.

Mudamos para lld para alguns destinos: https://rust-embedded.github.io/blog/2018-08-2x-psa-cortex-m-breakage/

Eu acredito para wasm também?

Este problema abrange a vinculação com um binário lld externo e a vinculação com suporte a lld interno integrado ao próprio rustc? Ou apenas o primeiro?

Este problema abrange a vinculação com um binário lld externo e a vinculação com suporte a lld interno integrado ao próprio rustc? Ou apenas o primeiro?

Apenas o binário lld externo, IIUC.

@nnethercote Existe outro problema para rastrear o uso de um vinculador interno ou devo registrar um problema separado para isso?

Eu não tinha ouvido falar da ideia do linker interno antes. Não estou ciente de um PR para isso.

https://github.com/rust-lang/rust/pull/57514 preparou o terreno para usar o LLD para vincular o LLVM.

Talvez inicialmente deva haver um meio-termo entre "padrão" e "apenas à noite", alguma forma de optar por usar LLD como fazemos com -Z, mas sem usar -Z para que funcione em compilações estáveis.

https://github.com/rust-lang/rust/pull/56351 adicionou -C linker-flavor .

Não está claro o que esse problema pretende rastrear. Parece que seria melhor encerrar isso em favor de ter problemas específicos, por exemplo, "Link com LLD para alvos -msvc quando o conjunto de ferramentas da Microsoft não está disponível".

Para mim, esse problema é sobre como habilitar o LLD como o vinculador padrão para todos os destinos. Eu gostaria disso porque o LLD é extremamente rápido e o tempo de vinculação costuma ser um componente significativo do tempo de compilação, e a velocidade de compilação é um problema perene.

FWIW Eu registrei um bug para oferecer suporte a LLD no macOS no BMO. Aparentemente, isso é WONTFIX. A partir dos comentários lá, parece que não é tão simples quanto "LLD é extremamente rápido", já que os LLDs em plataformas diferentes são programas diferentes, e o do macOS está quebrado com o desenvolvimento paralisado.

Concordou com @briansmith que seria bom ter problemas dedicados para rastrear o status disso para diferentes alvos, embora, em vez de encerrarmos, pudéssemos transformar isso em um metabug. Se houver alguém que saiba mais sobre para quais alvos vale a pena abrir questões, sinta-se à vontade, pois estou muito longe do status de suporte do LLD.

A vinculação com o LLD está documentada em algum lugar? Eu tenho (no Linux) rustc -C linker-flavor=ld.lld hello.rs , mas não estou tendo sorte. Achei que o LLD foi distribuído com nossa cópia do LLVM, estou errado? Eu também tentei instalar o LLD via apt, mas rustc ainda está perplexo. Quais são as etapas que devem ser seguidas para testar o LLD com código Rust hoje?

@bstrie Além disso, você deve passar o argumento -C linker=rust-lld .

Deve funcionar com carga? Atualmente, recebo os seguintes erros ao tentar construir um projeto em branco na última construção noturna de ferrugem e carga.

$ RUSTFLAGS='-C linker=rust-lld' cargo build
   Compiling rust3 v0.1.0 (/home/carado/tmp/rust3)
error: linking with `rust-lld` failed: exit code: 1
  |
  = note: "rust-lld" "-flavor" "gnu" "-L" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.2ualxzb8lqn4ho3y.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.32vfyq64cfbzv618.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.4rbt3m5y8o8cl09t.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.ben0932xzwyt64v.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.fzsdnygvstiwzxo.rcgu.o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.x0rq6ifodcf11zi.rcgu.o" "-o" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55" "/home/carado/tmp/rust3/target/debug/deps/rust3-c4f8c40972021c55.1m259ox4uzrzk583.rcgu.o" "--gc-sections" "-pie" "-zrelro" "-znow" "-L" "/home/carado/tmp/rust3/target/debug/deps" "-L" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--start-group" "-Bstatic" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-44988553032616b2.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-607feef6be9150b2.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-a8dbf6d92401e34a.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-9a4716f5e8a3e722.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-988a64d96b043c6d.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-cadd6177b8c6d586.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-8f1d8efc92b45369.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-1e76014677816767.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-cc28bce38cb195d9.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-4123e9e89add689a.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4d259c17788c1fb5.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-9495dbda85bb8f16.rlib" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-793d0026c575805f.rlib" "--end-group" "/home/carado/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-33c3162edae6574e.rlib" "-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: rust-lld: error: unable to find library -ldl
          rust-lld: error: unable to find library -lrt
          rust-lld: error: unable to find library -lpthread
          rust-lld: error: unable to find library -lgcc_s
          rust-lld: error: unable to find library -lc
          rust-lld: error: unable to find library -lm
          rust-lld: error: unable to find library -lrt
          rust-lld: error: unable to find library -lpthread
          rust-lld: error: unable to find library -lutil
          rust-lld: error: unable to find library -lutil


error: aborting due to previous error

error: Could not compile `rust3`.

To learn more, run the command again with --verbose.

Estou recebendo os mesmos erros do carado. Gerenciado para "calçadeira" -L / usr / lib na invocação do vinculador, mas isso apenas encurta a lista de libs perdidas para -lgcc que não existe em nenhum lugar do sistema como libgcc (há um libgcc_s.a ) Suspeito que isso seja resultado de algum gnu-ismo, mas não consigo descobrir como consertá-lo.

@almindor tente RUSTFLAGS='-C linker=rust-lld -L /usr/lib -L /usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0' ou algo semelhante. O caminho dependerá da distribuição e da versão do compilador.

Meu comentário acima é a maneira correta de usar o LLD? Não consigo fazer funcionar, pois todo programa trava com SIGSEGV :

Reading symbols from target/debug/hello...
(gdb) show directories
Source directories searched: ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/etc:$cdir:$cwd
(gdb) r
Starting program: target/debug/hello 

Program received signal SIGSEGV, Segmentation fault.
core::ops::function::FnOnce::call_once{{vtable-shim}} () at /rustc/a7f28678bbf4e16893bb6a718e427504167a9494/src/libcore/ops/function.rs:231
(gdb) l
226     #[stable(feature = "fn_once_output", since = "1.12.0")]
227     type Output;
228 
229     /// Performs the call operation.
230     #[unstable(feature = "fn_traits", issue = "29625")]
231     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
232 }
233 
234 mod impls {
235     #[stable(feature = "rust1", since = "1.0.0")] 
(gdb) info reg
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x0                 0
rbp            0x0                 0x0
rsp            0x7fffffffddb0      0x7fffffffddb0
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
r13            0x0                 0
r14            0x0                 0
r15            0x0                 0
rip            0x7ffff7ffc000      0x7ffff7ffc000 <core::ops::function::FnOnce::call_once{{vtable-shim}}>
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) disassemble 
Dump of assembler code for function core::ops::function::FnOnce::call_once{{vtable-shim}}:
=> 0x00007ffff7ffc000 <+0>: mov    (%rdi),%rax
   0x00007ffff7ffc003 <+3>: mov    (%rax),%rdi
   0x00007ffff7ffc006 <+6>: jmpq   *0x11d4(%rip)        # 0x7ffff7ffd1e0
End of assembler dump.

Para qualquer um que acabe aqui, o encantamento mágico é RUSTFLAGS="-C link-arg=-fuse-ld=lld" cargo build se você tiver GCC 9 ou Clang como seu compilador. Alternativamente, -C linker=clang deve funcionar independentemente da versão do GCC, por isso pode ser preferível.

Para tornar isso permanente, você pode adicioná-lo a ~/.cargo/config ou .cargo/config em um projeto específico:

[build]
rustflags = ["-C", "linker=clang"]
# rustflags = ["-C", "link-arg=-fuse-ld=lld"]

@lnicola note que funciona apenas ao usar GCC 9 ou Clang como CC.

@bstrie você sabe qual é o status atual disso? Quais são os obstáculos para avançar com isso?

@ mati865 você conhece uma invocação alternativa para pessoas com um GCC mais antigo?

@lnicola todas as minhas plataformas têm Clang + GCC 9 e não investiguei como usá-lo com compiladores incompatíveis.

@jonhoo Não estou a par de nenhum trabalho nesta área, suponho que você gostaria de perguntar à equipe do compilador.

Não acho que posso marcar times, e também não quero causar barulho indevido para eles. Qual é a melhor maneira de fazer alguém de lá dar uma olhada rápida, você acha?

Triage; @rust-lang / compiler alguém sabe qual é o status atual desse problema?

Para qualquer um aqui que consegue fazer o LLD funcionar com o Rust, você pode incluir adicionalmente os detalhes sobre sua plataforma e as versões específicas de todos os compiladores que estão sendo usados? Ainda estou vendo pessoas na selva tendo problemas para fazê-lo funcionar, mesmo com os conselhos listados aqui.

O comando que postei acima funciona no Linux com GCC 9.2.0 e LLD 9.0.0. Acho que às vezes também funciona no Windows, mas vi alguém com um GCC 9 para Windows que não suportava -fuse = lld. No MacOS não vale a pena tentar, de acordo com alguns links postados aqui.

Para qualquer um aqui que consegue fazer o LLD funcionar com o Rust, você pode incluir adicionalmente os detalhes sobre sua plataforma e as versões específicas de todos os compiladores que estão sendo usados? Ainda estou vendo pessoas na selva tendo problemas para fazê-lo funcionar, mesmo com os conselhos listados aqui.

cat / etc / system-release
Fedora versão 30 (trinta)

cc - versão
cc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)

ld.lld --version
LLD 8.0.0 (compatível com linkers GNU)

Espero que isso ajude

mas eu vi alguém com um GCC 9 para Windows que não suportava -fuse = lld

@lnicola
As compilações do Windows GCC 9 suportam -fuse-ld=lld (a menos que tenham sido corrigidos para não suportá-lo, mas por que alguém faria isso?).
Suponho que o componente rust-mingw foi instalado e o vinculador não foi substituído em .cargo/config . Dessa forma, o rustc escolheu o GCC 6 que ele envia em vez do do sistema.

Outro problema no Windows é o sinalizador de linker codificado --enable-long-section-names que o LLD 9 e anteriores não suportam (há planos para oferecer suporte no futuro). Para contornar isso, você pode:

  • crie um invólucro que retire esta bandeira
  • patch LLD para aceitar este sinalizador como no-op
  • use compilações Rust com patch local que não usam este sinalizador

Outro problema no Windows é o sinalizador de vinculador codificado --enable-long-section-names, que o LLD 9 e anteriores não suportam (há planos para suportá-lo no futuro).

Esta parte foi corrigida por: https://github.com/rust-lang/rust/pull/66257
Os usuários do Windows-gnu ainda precisam fazer o trabalho manual para usar o compilador C que suporta -fuse-ld=lld .

@bstrie : Funciona com Stable e Nightly no Windows-MSVC, detalhes no primeiro post deste problema gamedev-wg: https://github.com/rust-gamedev/wg/issues/50

Outro ponto de dados: usando RUSTFLAGS="-C link-arg=-fuse-ld=lld" ao construir rustc si, o tempo de vinculação cai de 93s para 41s em minha rápida caixa Linux de 14 núcleos.

@nnethercote : Isso é diferente de definir linker=lld (por exemplo) na seção [target.x86_64-unknown-linux-gnu] de config.toml ?

@ Aaron1011 : Meu palpite é que as duas abordagens têm o mesmo efeito, mas eu não verifiquei isso sozinho.

@ Aaron1011 deve ser clang, consulte https://github.com/rust-lang/rust/issues/39915#issuecomment -538049306.

@ mati865
Você tentou construir rustc em x86_64-pc-windows-gnu com LLD como um vinculador?

Eu tentei hoje e o LLD trava no meio da construção e para de fazer qualquer trabalho ou reclama de unknown argument: --version-script=... .
O travamento também acontece se o LLD for usado para vincular apenas LLVM, com

[llvm]
use-linker = "lld"

Versões da ferramenta:

$ ld.lld --version
LLD 9.0.1 (https://github.com/msys2/MINGW-packages.git 5e3b8820ed9f04221affee4197e458aca2612e87) (compatible with GNU linkers)

$ gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

@petrochenkov sim, eu poderia construí-lo com alguns hacks:

Estou escrevendo algumas possibilidades futuras aqui. Embora alguns esforços de implementação sejam necessários, acho que eles ajudarão a resolver alguns pontos problemáticos de longa data no desenvolvimento do Rust:

  • Em vez de usar lld fornecido externo, crie e use-o como bibliotecas estáticas dentro do rustc. Isso permite que uma integração mais estreita se enferruje, melhora a experiência pronta para uso e abre possibilidades futuras.
  • Em vez de passar muitos nomes de caminho para lld como um comando de vinculador, use um sistema de arquivos virtual e passe esses dados de memória para memória em vez de usar IO de disco sempre que houver espaço de memória suficiente para fazer. Para projetos maiores, isso pode economizar centenas ou mesmo milhares de megabytes de E / S de disco e, assim, melhorar o tempo de compilação.

Em vez de passar muitos nomes de caminho para lld como um comando de vinculador, use um sistema de arquivos virtual e passe esses dados de memória para memória em vez de usar IO de disco sempre que houver espaço de memória suficiente para fazer. Para projetos maiores, isso pode economizar centenas ou mesmo milhares de megabytes de E / S de disco e, assim, melhorar o tempo de compilação.

Não é apenas uma questão de largura de banda IO. Em plataformas como o Windows, especialmente quando o Windows Defender está habilitado, cada arquivo com o qual deseja trabalhar adiciona uma penalidade de tempo bastante significativa, e o modelo de unidade codegen de Rust significa que as caixas são divididas em centenas de pequenos arquivos de objeto que podem rapidamente acumular uma grande quantidade de compilação Tempo.

Este bug é uma bagunça, então aqui está minha melhor chance de um rápido resumo da situação atual, para as pessoas que querem seguir em frente.

O que é lld

Um vinculador que faz parte do projeto llvm, o que é desejável por dois motivos:

  • é muito amigável para compilação cruzada (daí sua ênfase para alvos incorporados)
  • é muito rápido (geralmente é executado na metade do tempo que o Gold - a vinculação pode levar vários minutos para grandes projetos (rustc, servo, etc.) e a vinculação pode ser uma grande% da compilação com compilações incrementais, portanto, reduzir pela metade esse tempo de execução é um Grande negócio.)

Coisas que o Rust faz com o lld hoje

  • Rust atualmente envia sua própria cópia do lld na maioria das plataformas como um binário que ele chama de rust-lld
  • rust-lld é usado por padrão em muitos alvos bare-metal
  • rust-lld é usado por padrão para wasm
  • (?) você pode solicitar explicitamente que rust-lld seja usado usando "-C linker-flavour" (confuso sobre o que exatamente isso faz em plataformas não bare-metal, veja abaixo)

Problemas para usar rust-lld em mais lugares (por exemplo, desktop linux / mac / windows)

  • O back-end do macOS (Mach-O) para lld está quebrado e abandonado

    • uma reescrita do zero começou, mas ainda é cedo

  • Em plataformas linux / unix, você não deve invocar diretamente ld / lld. Você deve invocar o linker por meio do compilador c do sistema (ou seja, gcc), cuja responsabilidade é descobrir símbolos do sistema como crt1.o e fornecê-los ao ld. Isso significa que não podemos "apenas" usar rust-lld; devemos alimentá-lo em gcc / clang / qualquer. (não queremos implementar essa lógica de símbolo do sistema nós mesmos)

    • Em geral, você não pode fornecer o linker como um caminho, você deve injetá-lo no caminho de pesquisa do compilador C como "ld"

    • Como alternativa, você pode fazer a mesma coisa, mas injetá-lo como "ld.lld" e passar "-fuse-ld = lld"



      • Isso pode ser importante, aparentemente o lld faz a detecção de nomes binários no estilo clang para saber se está sendo executado como "ld" ou "ld.lld" (precisa ser investigado)


      • Infelizmente -fuse-ld = lld é apenas parte do GCC 9, portanto, podemos exigir a detecção de recurso / versão para usá-lo (o clang está com ele há muito tempo)



  • windows-msvc está aparentemente em boa forma e parece ter algum suporte limitado para usar rust-lld no back-end, mas não estou certo sobre o que precisa ser feito aqui.
  • windows-mingw parece estar mais ou menos no mesmo lugar que linux / unix, exceto que você está sujeito a obter um GCC antigo, e as coisas estão um pouco confusas porque pseudo-windows-linux não é exatamente uma configuração bem testada?

Além disso, em geral, lld é mais recente, não é o padrão para a maioria dos sistemas operacionais, bugs de compatibilidade aleatórios certamente surgirão se começarmos a usar isso em mais lugares.

Apresentei dois metabugs para esforços concentrados no uso de (rust-) lld por padrão em duas plataformas:

  • # 71515 - x64 Ubuntu 20.04 LTS (e mais amplamente todas as plataformas x64 ELF)
  • # 71520 - janelas x64 msvc

windows-msvc está aparentemente em boa forma e parece ter algum suporte limitado para usar rust-lld no back-end, mas não estou certo sobre o que precisa ser feito aqui.

LLD + windows-msvc está em muito bom estado. No momento, estou usando esta configuração para o desenvolvimento de rustc .

Todo o suporte necessário para lld-link está disponível no back-end de rustc , mas existem bugs como https://github.com/rust-lang/rust/issues/68647.

  • Isso pode ser importante, aparentemente o lld faz a detecção de nomes binários no estilo clang para saber se está sendo executado como "ld" ou "ld.lld" (precisa ser investigado)

sim, mas ld e ld.lld são o mesmo modo: https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-02-05/lld/tools/lld/lld. cpp (mesmo desde 8.0-2019-01-16)

  • Infelizmente -fuse-ld = lld é apenas parte do GCC 9, portanto, podemos exigir a detecção de recurso / versão para usá-lo (o clang está com ele há muito tempo)

uma vez que ld.lld é o mesmo que ld, e de acordo com https://patches-gcc.linaro.org/patch/11148/ a única alteração com -fuse-ld = lld é executar ld.lld em vez de ld, se usamos injeção PATH, deve estar bem. Eu acho que bloquear isso no gcc 9+ não é bom: o debian stable só tem 8.3, e o bullseye provavelmente não será lançado até 2021.

  • windows-mingw parece estar mais ou menos no mesmo lugar que linux / unix, exceto que você está sujeito a obter um GCC antigo, e as coisas estão um pouco confusas porque pseudo-windows-linux não é exatamente uma configuração bem testada?

mingw-w64 6.0.0, lançado em 2016-09-18, tem gcc 8.3.0, que não tem -fuse-ld = lld, mas ainda é razoavelmente novo. mingw-w64 7.0.0, lançado em 11/11/2019, tem gcc 9.3.0, que tem -fuse-ld = lld. Debian buster (estável) tem 6.0.0, bullseye (teste) tem 7.0.0. O Debian stretch (oldstable) tem apenas 5.0.1 com gcc 6.3.0, mas eu acho que seria razoável requerer o debian stable mais recente para suporte lld se houver problemas significativos com gcc 6.3.

Apresentei dois metabugs para esforços concentrados no uso de (rust-) lld por padrão em duas plataformas:

  • # 71515 - x64 Ubuntu 20.04 LTS (e mais amplamente todas as plataformas x64 ELF)
  • # 71520 - janelas x64 msvc

Sobre a porta macOS (Mach-O) do lld: parece funcionar, ou pelo menos, estar em uma forma significativamente melhor desde https://github.com/rust-lang/rust/issues/39915#issuecomment -618726211 foi escrito!

Usando este commit LLVM , eu construí lld e o defini como um linker específico do projeto para tokio-rs / tracing . Em seguida, construí o rastreamento em relação a nightly-x86_64-apple-darwin e executei todos os testes com êxito. Estou especialmente feliz com os tempos de compilação (depuração):

  • Com ld , um cargo build limpo levou 35 segundos.
  • Com lld , um cargo build limpo levou 20 segundos.

Observe que:

  • esses números de desempenho vieram de um MacBook Pro recente com 32 GB de RAM e um 8-Core i9, e
  • existem alguns problemas pendentes para lld e Mach-O.

@davidbarsky Cool! Por curiosidade, como esse desempenho se compara a zld ? (https://github.com/michaeleisel/zld)

Além disso, você considerou as térmicas? Os MBPs entram em aceleração térmica muito rapidamente, especialmente com o perfil de velocidade do ventilador padrão. Apenas esperar até que a parte inferior da máquina perto da dobradiça esteja fria ao toque antes de executar uma operação deve ajudar na consistência.

Eu só tal bug um, no Ubuntu 16 i686

Esta página foi útil?
0 / 5 - 0 avaliações