Cómo detectar el sistema operativo actual de Gradle

98

Encontré esta respuesta sobre cómo hacerlo con Groovy:

Detectando la plataforma (Windows o Linux) por Groovy / Grails :

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

¿Existe una forma mejor?

Daniel Sperry
fuente
eso es lo que uso, sin la toLowerCase().contains()pieza, ya que solo necesito el nombre.
Kevin Welker
También puede obtener la versión del sistema operativo, conSystem.getProperty('os.arch')
Kevin Welker
13
"WINDOWS".toLowerCase()depende de la configuración regional y volverá wındows(observe la i sin puntos) en las máquinas donde la configuración regional es turca. Úselo en su toLowerCase(Locale.ROOT)lugar para estar seguro.
Matthias Braun

Respuestas:

125

En realidad, miré el proyecto Gradle, y este se ve un poco más limpio ya que usa la estructura existente de Ant :

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

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

Encontré esto en la siguiente rama de Gradle y parece funcionar bien. gradle / gradle-core / branch / RB-0.3 / build.gradle

Peter Kahn
fuente
7
Tenga cuidado, Os.isFamily (Os.FAMILY_UNIX) devolverá verdadero tanto para unix como para mac (mientras que Os.isFamily (Os.FAMILY_MAC) también es válido
shabunc
3
Tenga cuidado, este es de hecho el sistema operativo y no dice nada sobre el shell gradle que se inició (por ejemplo, podría ser Mingw, Cygwin u otro shell bash). Así que tenga cuidado si lo usa para leer variables de entorno, es posible que no sean lo que espera.
Estani
2
@shabunc tiene una mejor solución usando org.gradle.internal.os.OperatingSystem
Peter Kahn
task checkWin() << {¿Por qué lo necesitas? simplemente puede escribirif (Os.isFamily(Os.FAMILY_WINDOWS)) { println "*** WINDOWS " }
user25
También es mejor usar org.gradle.internal.os.OperatingSystemy if (OperatingSystem.current() == OperatingSystem.WINDOWS)(si hablamos de Gradle, ¿por qué no usar sus propias implementaciones)?
user25
67

Actualización de mediados de 2020 : Todavía incubando:

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

Actualización de principios de 2019 :current() eliminada.

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

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

Sin embargo, tenga en cuenta que todavía está incubando .

Actualización de mediados de 2018 : tal como se mencionó en los comentarios, ahora esta clase se movió a un paquete diferente, por lo que se debe usarorg.gradle.nativeplatform.platform.OperatingSystem.current()


A mediados de 2015, la respuesta de Peter Kahn sigue siendo válida. La activación del perfil basada en el entorno sigue siendo algo relativamente más fácil en Maven. Pero tenga en cuenta que org.apache.tools.ant.taskdefs.condition.Os.isFamilyno es exclusivo en el sentido de que si devuelve verdadero con un parámetro en particular, no necesariamente significa que devuelve falso para cualquier otro parámetro. Por ejemplo:

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))
    }
}

Se volverá cierto tanto para Os.FAMILY_MACy Os.FAMILY_UNIXen MacOS. Por lo general, no es algo que necesite en los scripts de compilación.

Sin embargo, hay otra forma de lograr esto usando Gradle 2+ API, a saber:

import org.gradle.internal.os.OperatingSystem;

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

Consulte la documentación de la interfaz org.gradle.nativeplatform.platform.OperatingSystem . Vale la pena mencionar que esta interfaz está marcada con una anotación de incubación , es decir, "la característica es actualmente un trabajo en progreso y puede cambiar en cualquier momento". El espacio de nombres "interno" en la implementación también nos da una pista de que debemos usar esto sabiendo que esto puede cambiar.

Pero personalmente iría con esta solución. Es solo que es mejor escribir una clase contenedora para no estropear en caso de que algo cambie en el futuro.

shabunc
fuente
8
¿Ha cambiado? Usar Gradle 2.5 OperatingSystemno parece tenerlo.current()
Ross Drew
6
cuidado con el paquete interno:org.gradle.internal.os.OperatingSystem.current()
Brian
@danblack ¿cómo se obtiene una instancia de OperatingSystemsin current()?
TWiStErRob
1
Encontrado uno: OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem; Ojalá hubiera uno público @PeterNiederwieser
TWiStErRob
Dado que Mac OS, Windows y Linux no son los únicos sistemas operativos, sería bueno que se incluyera z / OS. Aunque en un apuro, tomar la decisión de no ser ninguno de los otros podría funcionar.
John Czukkermann
18

Se puede diferenciar el entorno de compilación entre Linux, Unix, Windows y OS X, mientras que Gradle nativeplatform.platform.OperatingSystem diferencia el entorno de destino (incluidos FreeBSD y 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.
}

También se puede usar una tarea Ant ( fuente ):

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

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

Gradle no proporciona una API pública para detectar el sistema operativo. Por lo tanto, las os.propiedades del sistema son su mejor opción.

Peter Niederwieser
fuente
7

O puede definir osName como una cadena ...

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;
}

... y utilícelo más tarde, para incluir una biblioteca nativa, por ejemplo:

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

Pero no cambiaría nada ya que OperatingSystem funciona exactamente como tu 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;
    }
}

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

Editar:

Puedes hacer lo mismo con la arquitectura:

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

y:

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

Solo tenga en cuenta que getArch () devolverá:

  • "ppc" en PowerPC
  • "amd64" en 64b
  • "i386" O "x86" en 32b.

getArch () devolverá "x86" en Solaris o "i386" para cualquier otra plataforma.

Edición 2:

O si desea evitar cualquier importación, simplemente puede hacerlo usted mismo:

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
fuente
4

No me gusta detectar el sistema operativo en Gradle a través de propiedades o una tarea Ant, y la OperatingSystemclase ya no contiene el current()método.

Entonces, en mi opinión, la forma más limpia de detectar el sistema operativo sería:

Importar DefaultNativePlatform:

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

Luego use DefaultNativePlatformen su tarea:

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

Tenga en cuenta que este método no es ideal, ya que utiliza la API interna de Gradle.

Fue probado con Gradle 4.10.

Ruslan Pilin
fuente