Qt 5.1.1: O aplicativo falhou ao iniciar porque o plugin da plataforma "windows" está ausente


124

Edit: Algumas pessoas começaram a marcar minha pergunta como duplicada. Não esqueça que muitas perguntas semelhantes existiram quando eu fiz essa (veja, por exemplo, a lista abaixo). No entanto, nenhuma dessas respostas resolveu meu problema . Após uma longa pesquisa, encontrei um comentário que havia sido ignorado por todos os usuários, apontando para a biblioteca ausente. Agora, muitos meses depois, o comentário foi alterado para uma resposta. No entanto, quando respondi a essa pergunta por mim mesma, pretendia ajudar outras pessoas fornecendo diretamente a solução. Isso não deve ser esquecido, e até agora minha resposta ajudou muitas pessoas. Portanto, minha pergunta definitivamente não é uma duplicata. A propósito: A resposta aceita no link fornecido na parte superior não resolve o problema !


Sim, usei a pesquisa:

Falha ao carregar o plugin da plataforma "windows". As plataformas disponíveis são: Erro

Implantando o aplicativo Qt C ++ do erro qwindows.dll do Visual Studio

falha ao carregar o plugin da plataforma "windows" As plataformas disponíveis são: windows, minimal

No entanto, no meu caso, o problema ainda persiste. Estou usando o Qt 5.1.1 com o Visual Studio 2012 e desenvolvi meu aplicativo no Windows 7 com o Qt Creator 2.8.1. O aplicativo é compilado no modo "Release" e pode ser executado se iniciado diretamente com o Qt Creator.

No entanto, ao iniciar a pasta "release", recebo a seguinte mensagem:

Este aplicativo falhou ao iniciar porque não foi possível encontrar ou carregar o plugin da plataforma Qt "windows". Os plugins de plataforma disponíveis são: mínimo, fora da tela, janelas.

A estrutura de pastas fica assim:

release
+ gui.exe
+ icudt51.dll
+ icuin51.dll
+ icuuc51.dll
+ libGLESv2.dll
+ Qt5Core.dll
+ Qt5Gui.dll
+ Qt5Widgets.dll
+ platforms

Plataformas é a pasta copiada diretamente das plataformas Qt \ Qt5.1.1 \ 5.1.1 \ msvc2012 \ plugins \ incluindo, por exemplo, qwindows.dll. Não importa se eu o renomeio para "plataforma", como outros usuários fizeram. Qt ainda não está encontrando as "janelas de plug-in de plataforma", onde está meu erro?


5
Eu tive um problema semelhante. Windows 8.1 Qt 5.3.1 MinGW 32, vinculação dinâmica. Resolvido copiando a DLL da pasta Qt para ../MyApp/platforms/qwindows.dll. Nota: não há dir "plugins" no caminho
Dmitriy


Para problemas similares, use a ferramenta Depends, que mostra dependências de DLL e problemas resultantes deles. Você pode usar essa ferramenta para análise estática de um arquivo exe ou dll, mas também para mostrar a inicialização de um aplicativo com DLLs carregadas dinamicamente.
Flovdis 23/03/19

Use windeployQt
CrippledTable

Respostas:


64

Ok, como postado aqui https://stackoverflow.com/a/17271172/1458552 sem muita atenção por outros usuários:

O libEGL.dll estava ausente! Mesmo que isso não tenha sido relatado ao tentar iniciar o aplicativo (todas as outras * .dlls como Qt5Gui.dll foram relatadas).


2
No meu caso: Qt \ Qt5.1.1 \ 5.1.1 \ msvc2012 \ bin (é claro, dependendo da sua versão do Visual Studio)
Anonymous

8
como você sabia que a dll ausente era libEGL?
user1493046

4
VOCÊ ME SALVOU HORAS! Teve este mesmo problema no Qt 5.3.1
tarabyte

4
@ user1493046 Consegui reproduzir isso usando depende e seu modo de criação de perfil (F7). Depois que o aplicativo foi iniciado e mostrou o erro, o libEGL.dll apareceu na lista de dependências.
lapis

17
A adição de libEGL.dll não funcionou. No entanto, definindo a seguinte variável de ambiente trabalhou para mim: QT_QPA_PLATFORM_PLUGIN_PATH =% QTDIR% \ plugins \ plataformas \
arsalank2

36

Criei um diretório de plataformas próximo ao local do meu exe e coloquei o qwindows.dll dentro, mas ainda recebi o erro "Falha ao carregar o plugin da plataforma" windows ". As plataformas disponíveis são: windows".

Eu havia copiado o qwindows.dll das plataformas C: \ Qt \ Qt5.1.1 \ Tools \ QtCreator \ bin \ plugins \, que não é o local certo. Olhei para o log de depuração em execução no Qt Creator e descobri que meu aplicativo estava procurando nas plataformas C: \ Qt \ Qt5.1.1 \ 5.1.1 \ mingw48_32 \ plugins \ quando executado no depurador.

Quando copiei das plataformas C: \ Qt \ Qt5.1.1 \ 5.1.1 \ mingw48_32 \ plugins \, tudo funcionou bem.


38
A definição da seguinte variável de ambiente funcionou para mim: QT_QPA_PLATFORM_PLUGIN_PATH =% QTDIR% \ plugins \ platform \
arsalank2

24

Provavelmente, a versão está ausente de uma biblioteca / plugin ou a biblioteca está no diretório errado e / ou no diretório errado.

Resposta pretendida do Qt: use windeployqt . veja o último parágrafo para explicação

Resposta manual:

Crie uma pasta chamada "plataformas" no mesmo diretório que o arquivo application.exe. Copie e cole o qwindows.dll, encontrado na / bin do compilador que você usou para liberar seu aplicativo, na pasta "plataformas". Como mágica, funciona. Se o arquivo .dll não estiver lá, verifique os plugins / plataformas / (com os plugins / no mesmo diretório que bin /) <- comentário de PfunnyGuy.

Parece que um problema comum é que a DLL foi retirada da lixeira do compilador errada. Certifique-se de copiar o qwindows.dll do mesmo compilador usado para lançar o aplicativo.

O Qt vem com aplicativos de console de plataforma que adicionam todas as dependências (incluindo qwindows.dll e libEGL.dll) à pasta do executável implantado. Esta é a maneira pretendida de implantar seu aplicativo, para que você não perca nenhuma biblioteca (que é o principal problema com todas essas respostas). O aplicativo para Windows é chamado windeployqt . Provavelmente, há um aplicativo de console de implantação para cada sistema operacional.


1
Isto é o que eu precisava: Observe que o qwindows.dll não está no bin / da instalação da sua plataforma Qt, mas nos plugins / plataformas /, com plugins / no mesmo diretório que bin /
PfunnyGuy

1
Obrigado! Em resumo, os arquivos são: Qt5Core.dll, Qt5Gui.dll, Qt5Widgets.dll e YourApp.exe no diretório principal, e platform \ qwindows.dll e platform \ libEGL.dll no subdiretório.
Pierre

1
windeployqt é a resposta correta. Eu usei e copiei tudo o que era necessário ao lado do .exe. Ele remove as conjecturas de saber qual dll é necessária e que não é
H. Al-Amri

14

Definir a QT_QPA_PLATFORM_PLUGIN_PATHvariável de ambiente para% QTDIR% \ plugins \ platform \ funcionou para mim .

Também foi mencionado aqui e aqui .


3
Embora essa resposta possa fazê-lo funcionar em sua máquina atual, não ajuda outras pessoas que estão tentando implantar seus programas em outras máquinas e precisa identificar especificamente quais bibliotecas estão faltando / necessárias.
RTbecard

1
em 2017, isso funcionou para mim. Não implantarei nenhum aplicativo! Com o Qt creator, basta Abrir \ Novo arquivo ou projeto ... \ Qt Widgets Application, depois Executar e ele trava com a mesma mensagem. Definir esta var me ajuda.
Phiber

Apenas copie a pasta plugins em algum lugar ao lado da sua "distro" improvisada e aponte o env var para ela - deve funcionar (não é necessário usar "QTDIR") :)
mlvljr

9

Eu me deparei com isso e nenhuma das respostas que consegui encontrar me corrigiu.

Meu colega possui o Qt (5.6.0) instalado em sua máquina em: C: \ Qt \ Qt5.6.0 \ 5.6 \ msvc2015 \ plugins
Tenho o Qt (5.6.2) instalado no mesmo local.

Aprendi com este post: http://www.tripleboot.org/?p=536 , que o Qt5Core.dll possui um local para os plug-ins escritos quando o Qt é instalado pela primeira vez. Como os diretórios do meu colega e do meu Qt eram os mesmos, mas uma versão diferente do Qt foi instalada, é necessário um arquivo qwindows.dll diferente. Quando executei um exe implantado por ele, ele usaria o meu arquivo C: \ Qt \ Qt5.6.0 \ 5.6 \ msvc2015 \ plugins \ platform \ qwindows.dll em vez daquele localizado ao lado do executável na subpasta. \ Platform.

Para contornar isso, adicionei a seguinte linha de código ao aplicativo, que parece forçá-lo a procurar, ao lado do exe, a subpasta 'plataformas' antes de procurar o caminho no Qt5Core.dll.

QCoreApplication::addLibraryPath(".");

Adicionei a linha acima ao método principal antes da chamada do QApplication assim:

int main( int argc, char *argv[] )
{
    QCoreApplication::addLibraryPath(".");
    QApplication app( argc, argv );
    ...
    return app.exec();
}

1
Este funcionou para mim ... mas observe que você pode precisar qwindowsd.dllno diretório `plataformas` se estiver em uma situação em que esteja compartilhando versões de depuração com seus colegas ...
HostileFork diz que não confia em SE

Este funcionou para mim porque, com a menção de qwindowsd.dll, eu sabia que meu aplicativo foi compilado no modo de depuração e instalei as bibliotecas Qtxxxd.dll, mas estava usando qwindows.dll na pasta da plataforma.
Gustavo Rodríguez

6

criar dir platforms e copiar qwindows.dllpara ele, platformse app.exeestão no mesmo dir

cd app_dir mkdir platforms xcopy qwindows.dll platforms\qwindows.dll

Estrutura de pastas + app.exe + platforms\qwindows.dll


É mencionado na pergunta que "Plataformas é a pasta copiada diretamente das plataformas Qt \ Qt5.1.1 \ 5.1.1 \ msvc2012 \ plugins \ incluindo, por exemplo, qwindows.dll."
parasietje

aplicativo @parasietje está procurando qwindows.dllno diretório platforms. Postei isso porque eu o corrigi. Você está fazendo um teste antes do voto negativo?
KunMing Xie

Sua resposta não responde à pergunta original. Sua resposta sugere algo que o pôster original já tentou.
parasietje 23/03

3

Encontrei outra solução. Crie qt.conf na pasta do aplicativo da seguinte maneira:

[Paths]
Prefix = .

E, em seguida, copie a pasta plugins na pasta do aplicativo e funcionará para mim.


Ok, estou em um ambiente minGW, CMake, Qt 5.12, onde a aplicação da ferramenta windeploy não é possível. A pasta de plataformas estava lá, mas não funcionou. Substituí-lo por um da Qt-lib também não ajudou. Corrigido usando seu truque (depois de copiar a pasta). Obrigado!
Marcel Petrick

2

A maioria dessas respostas contém informações boas (corretas), mas no meu caso, ainda havia algo faltando.

Meu aplicativo é criado como uma biblioteca (dll) e chamado por um aplicativo não-Qt. Eu costumava windeployqt.execonfigurar as DLLs do Qt, plataformas, plugins etc. no diretório de instalação, mas ele ainda não conseguia encontrar a plataforma. Após algumas experiências, percebi que o diretório de trabalho do aplicativo estava definido para uma pasta diferente. Então, peguei o diretório em que a dll "vivia" usando GetModuleHandleExAe adicionei esse diretório ao caminho da biblioteca Qt em tempo de execução usando

QCoreApplication::addLibraryPath(<result of GetModuleHandleExA>);

Isso funcionou para mim.


2

Para mim, a solução foi corrigir o PATH variável. Ele tinha Anaconda3 \ Library \ bin como um dos primeiros caminhos. Este diretório contém algumas bibliotecas Qt, mas não todas. Aparentemente, isso é um problema. Mover C: \ Programas \ Qt \ 5.12.3 \ msvc2017_64 \ bin para a frente PATHresolveu o problema para mim.


1

Eu tive esse problema ao usar QT 5.6, Anaconda 4.3.23, python 3.5.2 e pyinstaller 3.3. Eu criei um programa python com uma interface desenvolvida usando o QTcreator, mas tive que implantá-lo em outros computadores, portanto, precisava criar um executável usando o pyinstaller.

Descobri que o problema foi resolvido no meu computador se eu definir as seguintes variáveis ​​de ambiente:

QT_QPA_PLATFORM_PLUGIN_PATH:% QTDIR% \ plugins \ platform \

QTDIR: C: \ Miniconda3 \ pkgs \ qt-5.6.2-vc14_3 \ Biblioteca

Mas esta solução só funcionou no meu PC que tinha o conda e o qt instalados nessas pastas.

Para resolver isso e fazer o executável funcionar em qualquer computador, tive que editar o ".spec" (arquivo gerado pela primeira vez pelo pyinstaller) para incluir a seguinte linha:

datas = [('C: \ Miniconda3 \ pkgs \ qt-5.6.2-vc14_3 \ Biblioteca \ plugins \ plataformas * .dll', 'plataformas'),]

Esta solução é baseada nas respostas de Jim G. e CrippledTable


1

Eu tive o mesmo problema e o resolvi aplicando várias coisas. O primeiro, se for um programa que você fez com o Qt.

Na pasta (no meu caso) de "C: \ Qt \ Qt5.10.0 \ 5.10.0 \ msvc2017_64 \ plugins", você encontra outras pastas, uma delas é "plataformas". Essa pasta "plataformas" será copiada ao lado do seu executável .exe. Agora, se você receber o erro 0xc000007d é que não copiou a versão anterior, pois pode ser 32 bits ou 64.

Se você continuar com os erros é que falta mais bibliotecas. Com o programa "Dependency Walker", você pode detectar algumas das pastas ausentes. Certamente isso indicará que você precisa de um .dll da NVIDIA e informa a localização.

Outra maneira, em vez de usar o "Dependency Walker", é copiar toda a DLL da pasta "C: \ Windows \ System32" ao lado do arquivo executável. Execute o seu .exe e, se tudo carregar bem, para que você não tenha espaço ocupado nas bibliotecas DLL que não precisa nem use, use o programa .exe com todas as suas opções e, sem fechar o .exe, você apagará todo o arquivo. DLL que você acabou de copiar ao lado do .exe, portanto, se esses arquivos .dll estiverem sendo usados ​​pelo seu programa, o sistema não permitirá que você apague, apenas remova aqueles que não são necessários.

Espero que esta solução atenda você.

Lembre-se de que se o seu sistema operacional tiver 64 bits, as bibliotecas estarão na pasta System32 e se o sistema operacional tiver 32 bits, elas também estarão na pasta System32. Isso acontece para que não haja problemas de compatibilidade com programas de 32 bits em um computador de 64 bits. A pasta SysWOW64 contém os arquivos de 32 bits como um backup.


Funciona, mas é mais como uma solução temporária. É possível fazer algo para que você não precise copiar a pasta de plataformas?
Oleg Yablokov 6/07

0

Para uma plataforma MinGW e se você estiver compilando um destino de Depuração por um CMakeLists.txt feito à mão, ad hoc, será necessário adicionar o qwindows.dll ao diretório da plataforma. O executável windeployqt funciona bem, mas parece que, por algum motivo estranho, o CMake build também precisa da variante de release. Em resumo, será melhor ter o qwindows.dll e o qwindowsd.dll no diretório da plataforma. Não notei o mesmo resultado estranho ao importar o projeto CMake no QtCreator e depois executar o procedimento de compilação. Compilando na linha de comando, o projeto CMake parece acionar a dependência qwindows.dll, se a correta para o destino Debug estiver definida (qwindowsd.dll)


0

Use este arquivo em lotes: RunWithQt.bat

@echo off
set QTDIR=C:\Qt\Qt5.1.1\5.1.1\msvc2012\bin
set QT_QPA_PLATFORM_PLUGIN_PATH=%QTDIR%\plugins\platforms\
start %1
  • para usá-lo, arraste o arquivo gui.exe e solte-o no RunWithQt.bat no explorer,
  • ou ligue RunWithQt gui.exeda linha de comando

0

Se você tiver o Anaconda instalado, recomendo que você o desinstale e tente instalar o pacote python da fonte, corrigi o problema dessa maneira


0

O aplicativo qtbase / bin / windeployqt.exe implanta automaticamente seu aplicativo. Se você iniciar um prompt com as variáveis ​​de ambiente definidas corretamente, ele será implantado no diretório atual. Você encontra um exemplo de script:

@echo off
set QTDIR=E:\QT\5110\vc2017

set INCLUDE=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\ATLMFC\include;S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\include;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\ucrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\cppwinrt

set LIB=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\ATLMFC\lib\x86;S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\lib\x86;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\lib\um\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.14393.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.14393.0\um\x86;

set LIBPATH=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\ATLMFC\lib\x86;S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\lib\x86;S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\lib\x86\store\references;C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17134.0;C:\ProgramFiles (x86)\Windows Kits\10\References\10.0.17134.0;C:\Windows\Microsoft.NET\Framework\v4.0.30319;

Path=%QTDIR%\qtbase\bin;%PATH%
set VCIDEInstallDir=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\
set VCINSTALLDIR=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\
set VCToolsInstallDir=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\
set VisualStudioVersion=15.0
set VS100COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools\
set VS110COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\
set VS120COMNTOOLS=S:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\
set VS150COMNTOOLS=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\
set VS80COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\Tools\
set VS90COMNTOOLS=c:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\
set VSINSTALLDIR=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
set VSSDK110Install=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\
set VSSDK150INSTALL=S:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VSSDK
set WindowsLibPath=C:\Program Files (x86)\Windows Kits\10\UnionMetadata;C:\Program Files (x86)\Windows Kits\10\References
set WindowsSdkBinPath=C:\Program Files (x86)\Windows Kits\10\bin\
set WindowsSdkDir=C:\Program Files (x86)\Windows Kits\10\
set WindowsSDKLibVersion=10.0.14393.0\
set WindowsSdkVerBinPath=C:\Program Files (x86)\Windows Kits\10\bin\10.0.14393.0\
set WindowsSDKVersion=10.0.14393.0\
set WindowsSDK_ExecutablePath_x64=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\x64\
set WindowsSDK_ExecutablePath_x86=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\

mkdir C:\VCProjects\Application\Build\VS2017_QT5_11_32-Release\setup
cd C:\VCProjects\Application\Build\VS2017_QT5_11_32-Release\setup
copy /Y ..\Release\application.exe .
windeployqt application.exe
pause

0

Digamos que você queria ter alguns CGAL-Demos portáteis. Portanto, você teria uma pasta "CGAL" e, nela, uma subpasta chamada "lib": todas as DLLs de suporte (comuns) para todos os programas na pasta CGAL aqui. No nosso exemplo, este seria o Dll-Download : basta descompactar o diretório "lib". Quanto mais você rola na página de demos , mais impressionante é o conteúdo. No meu caso, a demonstração do poliedro parecia certa. Se isso for executado em meu notebook com mais de 10 anos de idade, estou impressionado. Então, criei uma pasta "demo" no diretório "CGAL", ao lado de "lib". Agora crie um arquivo .cmd nessa pasta. Chamei o meu de "Polyhedron.cmd". Portanto, temos uma estrutura de diretórios como esta:

 CGAL - the bag for all the goodies
  lib - all libraries for all CGAL-packages
 demo - all the demos I'm interested in
[...] - certainly some other collections, several apps per folder...
Polyhedron.cmd - and a little script for every Qt-exe to make it truly portable.

Neste pequeno exemplo, "Polyhedron.cmd" contém o seguinte texto:

@echo off
set "me=%~dp0"
set PATH=%me%lib
set "QT_PLUGIN_PATH=%me%lib\plugins"
start /b "CGAL Polyhedron Demo" "%me%demo\polyhedron\polyhedron_3.exe"

Todos os scripts podem ser iguais, exceto a última linha, obviamente. A única ressalva é: a "Janela DOS" permanece aberta enquanto você usar o programa atual. Feche a janela do shell e você também mata o * .exe. Onde quer que você copie a pasta "CGAL", uma vez que a escrita estranha "% ~ dp0" representa o caminho completo para o arquivo * .cmd que iniciamos, com a sequência "\". Portanto, "% me% lib" é sempre o caminho completo para a biblioteca real ("CGAL \ lib" no meu caso). As próximas 2 linhas informam ao Qt onde estão seus arquivos de "tempo de execução". Esse será pelo menos o arquivo "qwindows.dll" para os programas Windows-Qt mais qualquer número de * .dlls. Se bem me lembro, a biblioteca DLL (pelo menos quando o baixei) tinha um pequeno "bug", pois contém o diretório "plataformas" com o qwindows.dll. para "plugins". Se um aplicativo Qt, qualquer aplicativo Qt, não encontrar "qwindows.dll", não poderá encontrar "janelas". E espera-o em um diretório chamado "plataformas" no diretório "plug-ins", que deve ser informado pelo SO em execução ... e se o "QT_PLUGIN_PATH" não estiver exatamente apontando para todas as DLLs auxiliares que você necessário, alguns programas Qt ainda serão executados sem probs. E alguns reclamam da falta de * .dlls que você nunca ouviu falar ...


0

Para quem vem da versão 5.14.0 do QT, levei dois dias para encontrar esta declaração de bug:

windeployqt não funciona para MinGW QTBUG-80763 Será corrigido no 5.14.1

https://wiki.qt.io/Qt_5.14.0_Known_Issues

Então esteja ciente. Usar o windeployqt withMinGW fornecerá o mesmo erro indicado aqui.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.