Como detectar o sistema operacional atual do Gradle

98

Eu encontrei esta resposta sobre como fazer isso com o Groovy:

Detectando a plataforma (Windows ou Linux) por Groovy / Grails :

if (System.properties['os.name'].toLowerCase().contains('windows')) {
    println "it's Windows"
} else {
    println "it's not Windows"
}

Existe uma maneira melhor?

Daniel Sperry
fonte
é o que eu uso, sem a toLowerCase().contains()parte, pois só preciso do nome.
Kevin Welker
Você também pode obter a versão do sistema operacional, comSystem.getProperty('os.arch')
Kevin Welker
13
"WINDOWS".toLowerCase()depende da localidade e retornará wındows(observe o i sem ponto) em máquinas nas quais a localidade é turco. Use em toLowerCase(Locale.ROOT)vez disso para estar do lado seguro.
Matthias Braun

Respostas:

125

Na verdade, eu olhei para o projeto Gradle, e ele parece um pouco mais limpo, pois usa a estrutura existente do Ant :

import org.apache.tools.ant.taskdefs.condition.Os

task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        println "*** Windows "
    }
}

Eu encontrei isso no seguinte branch do Gradle e parece funcionar bem. gradle / gradle-core / branches / RB-0.3 / build.gradle

Peter Kahn
fonte
7
esteja avisado, Os.isFamily (Os.FAMILY_UNIX) retornará verdadeiro tanto para unix quanto para mac (enquanto Os.isFamily (Os.FAMILY_MAC) também é válido
shabunc
3
Tenha cuidado, este é realmente o sistema operacional e não diz nada sobre o shell que o gradle foi iniciado (por exemplo, pode ser Mingw, Cygwin ou outro shell bash). Portanto, tome cuidado se você usar isso para ler variáveis ​​de ambiente, elas podem não ser o que você espera.
Estani
2
@shabunc tem uma solução melhor usando org.gradle.internal.os.OperatingSystem
Peter Kahn
task checkWin() << {por que você precisa disso? você pode simplesmente escreverif (Os.isFamily(Os.FAMILY_WINDOWS)) { println "*** WINDOWS " }
user25
também é melhor usar org.gradle.internal.os.OperatingSysteme if (OperatingSystem.current() == OperatingSystem.WINDOWS)(se falamos sobre Gradle, por que não usar suas próprias implementações)
usuário25
67

Atualização de meados de 2020 : Ainda incubando:

OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem; 

Atualização do início de 2019 : current()removida.

org.gradle.nativeplatform.platform.OperatingSystem.getDisplayName()

org.gradle.nativeplatform.platform.OperatingSystem.isLinux()

Tenha em mente que ainda está incubando .

Atualização de meados de 2018 : assim como foi mencionado nos comentários, agora esta classe mudou para um pacote diferente, portanto, deve-se usarorg.gradle.nativeplatform.platform.OperatingSystem.current()


Em meados de 2015, a resposta de Peter Kahn ainda é válida. A ativação do perfil com base no ambiente ainda é algo relativamente mais fácil no Maven. Mas tenha em mente que isso org.apache.tools.ant.taskdefs.condition.Os.isFamilynão é exclusivo no sentido de que se retornar verdadeiro com um parâmetro específico, não significa necessariamente que retornará falso para qualquer outro parâmetro. Por exemplo:

import org.apache.tools.ant.taskdefs.condition.Os
task detect {
    doLast {
        println(Os.isFamily(Os.FAMILY_WINDOWS))
        println(Os.isFamily(Os.FAMILY_MAC))
        println(Os.isFamily(Os.FAMILY_UNIX))
    }
}

Ele retornará verdadeiro para Os.FAMILY_MACe Os.FAMILY_UNIXno MacOS. Normalmente não é algo que você precisa em scripts de construção.

No entanto, existe outra maneira de fazer isso usando a API Gradle 2+, a saber:

import org.gradle.internal.os.OperatingSystem;

task detect {
    doLast {
        println(OperatingSystem.current().isMacOsX())
        println(OperatingSystem.current().isLinux())
    }
}

Verifique a documentação da interface org.gradle.nativeplatform.platform.OperatingSystem . Vale ressaltar que esta interface é marcada com anotação de incubação , ou seja, "o recurso está em andamento e pode ser alterado a qualquer momento". O namespace "interno" na implementação também nos dá uma dica de que devemos usá-lo sabendo que isso pode mudar.

Mas pessoalmente, eu escolheria essa solução. É só que é melhor escrever uma classe de wrapper para não bagunçar caso algo mude no futuro.

Shabunc
fonte
8
Isso mudou? O uso do Gradle 2.5 OperatingSystemnão parece ter .current()
ocorrido
6
preste atenção ao pacote interno:org.gradle.internal.os.OperatingSystem.current()
Brian
@danblack, como você obtém uma instância de OperatingSystemsem current()?
TWiStErRob
1
Encontrado um OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem:; gostaria que houvesse um público @PeterNiederwieser
TWiStErRob
Como Mac OS, Windows e Linux não são os únicos sistemas operacionais, seria bom se z / OS fosse incluído. Embora seja difícil, fazer a escolha de não ser nenhum dos outros pode funcionar.
John Czukkermann
18

Pode-se diferenciar o ambiente de construção entre Linux, Unix, Windows e OS X - enquanto o Gradle nativeplatform.platform.OperatingSystem diferencia o ambiente de destino (incl. FreeBSD e Solaris ).

import org.gradle.internal.os.OperatingSystem

String osName = OperatingSystem.current().getName();
String osVersion = OperatingSystem.current().getVersion();
println "*** $osName $osVersion was detected."

if (OperatingSystem.current().isLinux()) {
    // Consider Linux.
} else if (OperatingSystem.current().isUnix()) {
    // Consider UNIX.
} else if (OperatingSystem.current().isWindows()) {
    // Consider Windows.
} else if (OperatingSystem.current().isMacOsX()) {
    // Consider OS X.
} else {
    // Unknown OS.
}

Também se pode usar uma tarefa Ant ( fonte ):

import org.apache.tools.ant.taskdefs.condition.Os

task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        // Consider Windows.
    }
}
Martin Zeitler
fonte
7

O Gradle não fornece uma API pública para detectar o sistema operacional. Portanto, as os.propriedades do sistema são sua melhor aposta.

Peter Niederwieser
fonte
7

Ou você pode definir osName como uma string ...

import org.gradle.internal.os.OperatingSystem

switch (OperatingSystem.current()) {
    case OperatingSystem.LINUX:
        project.ext.osName = "Linux";
        break;
    case OperatingSystem.MAC_OS:
        project.ext.osName = "macOS";
        break;
    case OperatingSystem.WINDOWS:
        project.ext.osName = "Windows";
        break;
}

... e usá-lo mais tarde - para incluir uma biblioteca nativa, por exemplo:

run {
    systemProperty "java.library.path", "lib/$osName"
}

Mas isso não mudaria nada, já que OperatingSystem funciona exatamente como seu código:

public static OperatingSystem forName(String os) {
    String osName = os.toLowerCase();
    if (osName.contains("Windows")) {
        return WINDOWS;
    } else if (osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx")) {
        return MAC_OS;
    } else if (osName.contains("sunos") || osName.contains("solaris")) {
        return SOLARIS;
    } else if (osName.contains("linux")) {
        return LINUX;
    } else if (osName.contains("freebsd")) {
        return FREE_BSD;
    } else {
        // Not strictly true
        return UNIX;
    }
}

Fonte: https://github.com/gradle/gradle/blob/master/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java

Editar:

Você pode fazer o mesmo para a arquitetura:

project.ext.osArch = OperatingSystem.current().getArch();
if ("x86".equals(project.ext.osArch)) {
    project.ext.osArch = "i386";
}

e:

run {
    systemProperty "java.library.path", "lib/$osName/$osArch"
}

Esteja ciente de que getArch () retornará:

  • "ppc" no PowerPC
  • "amd64" em 64b
  • "i386" OU "x86" em 32b.

getArch () retornará "x86" no Solaris ou "i386" para qualquer outra plataforma.

Editar 2:

Ou, se quiser evitar qualquer importação, pode simplesmente fazer você mesmo:

def getOsName(project) {
    final String osName = System.getProperty("os.name").toLowerCase();

    if (osName.contains("linux")) {
        return ("linux");
    } else if (osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx")) {
        return ("macos");
    } else if (osName.contains("windows")) {
        return ("windows");
    } else if (osName.contains("sunos") || osName.contains("solaris")) {
        return ("solaris");
    } else if (osName.contains("freebsd")) {
        return ("freebsd");
    }
    return ("unix");
}

def getOsArch(project) {
    final String osArch = System.getProperty("os.arch");

    if ("x86".equals(osArch)) {
        return ("i386");
    }
    else if ("x86_64".equals(osArch)) {
        return ("amd64");
    }
    else if ("powerpc".equals(osArch)) {
        return ("ppc");
    }
    return (osArch);
}
Tirz
fonte
4

Não gosto de detectar o sistema operacional no Gradle por meio de propriedades ou uma tarefa Ant, e a OperatingSystemclasse não contém mais o current()método.

Portanto, na minha opinião, a maneira mais limpa de detectar o sistema operacional seria:

Importar DefaultNativePlatform:

import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform

Em seguida, use DefaultNativePlatformem sua tarefa:

if (DefaultNativePlatform.getCurrentOperatingSystem().isWindows()) {
   println 'Windows'
}

Lembre-se de que esse método não é ideal, pois usa a API interna do Gradle.

Ele foi testado com Gradle 4.10.

Ruslan Pilin
fonte