So erkennen Sie das aktuelle Betriebssystem in Gradle

98

Ich habe diese Antwort gefunden, wie es mit Groovy geht:

Erkennen der Plattform (Windows oder Linux) durch Groovy / Grails :

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

Gibt es einen besseren Weg?

Daniel Sperry
quelle
Das ist es, was ich ohne das toLowerCase().contains()Teil benutze, da ich nur den Namen brauche.
Kevin Welker
Sie können auch die OS-Version erhalten, mitSystem.getProperty('os.arch')
Kevin Welker
13
"WINDOWS".toLowerCase()ist vom Gebietsschema abhängig und wird wındowsauf Computern mit türkischem Gebietsschema zurückgegeben (beachten Sie das punktlose i). Verwenden Sie toLowerCase(Locale.ROOT)stattdessen, um auf der sicheren Seite zu sein.
Matthias Braun

Antworten:

125

Eigentlich habe ich mir das Gradle-Projekt angesehen, und das sieht ein wenig sauberer aus, da es die vorhandene Struktur von Ant verwendet:

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

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

Ich habe dies im folgenden Gradle-Zweig gefunden, und es scheint gut zu funktionieren. Gradle / Gradle-Core / Zweige / RB-0.3 / build.gradle

Peter Kahn
quelle
7
Seien Sie gewarnt, Os.isFamily (Os.FAMILY_UNIX) gibt sowohl für Unix als auch für Mac true zurück (während Os.isFamily (Os.FAMILY_MAC) ebenfalls gültig ist
shabunc
3
Seien Sie vorsichtig, dies ist in der Tat das Betriebssystem und sagt nichts über den Start des Shell-Gradles aus (z. B. Mingw, Cygwin oder eine andere Bash-Shell). Seien Sie also vorsichtig, wenn Sie das zum Lesen von Umgebungsvariablen verwenden, da diese möglicherweise nicht Ihren Erwartungen entsprechen.
Estani
2
@ Shabunc hat eine bessere Lösung mit org.gradle.internal.os.OperatingSystem
Peter Kahn
task checkWin() << {Wieso brauchst du es? Sie können einfach schreibenif (Os.isFamily(Os.FAMILY_WINDOWS)) { println "*** WINDOWS " }
user25
Es ist auch besser zu verwenden org.gradle.internal.os.OperatingSystemund if (OperatingSystem.current() == OperatingSystem.WINDOWS)(wenn wir über Gradle sprechen, warum nicht ihre eigenen Implementierungen verwenden)
user25
67

Mitte 2020 Update : Noch inkubiert:

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

Anfang 2019 Update : current()entfernt.

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

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

Denken Sie daran, dass es immer noch inkubiert .

Mitte 2018 Update : Genau wie in den Kommentaren erwähnt, wurde diese Klasse jetzt in ein anderes Paket verschoben, daher sollte man es verwendenorg.gradle.nativeplatform.platform.OperatingSystem.current()


Ab Mitte 2015 ist die Antwort von Peter Kahn noch gültig. Die umgebungsbasierte Profilaktivierung ist in Maven immer noch relativ einfach. Beachten Sie jedoch, dass dies org.apache.tools.ant.taskdefs.condition.Os.isFamilynicht in dem Sinne exklusiv ist, dass wenn es mit einem bestimmten Parameter true zurückgibt, dies nicht unbedingt bedeutet, dass es für jeden anderen Parameter false zurückgibt. Zum Beispiel:

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

Es wird sowohl für Os.FAMILY_MACals auch Os.FAMILY_UNIXunter MacOS true zurückgeben . Normalerweise benötigen Sie dies nicht für Build-Skripte.

Es gibt jedoch eine andere Möglichkeit, dies mithilfe der Gradle 2+ -API zu erreichen:

import org.gradle.internal.os.OperatingSystem;

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

Lesen Sie die Dokumentation zur Schnittstelle org.gradle.nativeplatform.platform.OperatingSystem . Es ist erwähnenswert, dass diese Schnittstelle mit Inkubationsanmerkungen gekennzeichnet ist, dh "Die Funktion ist derzeit in Arbeit und kann jederzeit geändert werden". Der "interne" Namespace in der Implementierung gibt uns auch einen Hinweis, dass wir diesen verwenden sollten, da wir wissen, dass sich dies ändern kann.

Aber ich persönlich würde mich für diese Lösung entscheiden. Es ist nur besser, eine Wrapper-Klasse zu schreiben, um nicht durcheinander zu kommen, falls sich in Zukunft etwas ändern sollte.

shabunc
quelle
8
Hat es sich geändert? Die Verwendung von Gradle 2.5 OperatingSystemscheint nicht zu haben.current()
Ross Drew
6
Beachten Sie das interne Paket:org.gradle.internal.os.OperatingSystem.current()
Brian
@danblack wie bekommt man eine Instanz von OperatingSystemohne current()?
TWiStErRob
1
Gefunden : OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem; Ich wünschte, es gäbe eine öffentliche @PeterNiederwieser
TWiStErRob
Da Mac OS, Windows und Linux nicht die einzigen Betriebssysteme sind, wäre es schön, wenn z / OS enthalten wäre. Obwohl zur Not, könnte es funktionieren, die Wahl zu treffen, keiner der anderen zu sein.
John Czukkermann
17

Man kann die Build- Umgebung zwischen Linux, Unix, Windows und OS X unterscheiden - während das Gradle nativeplatform.platform.OperatingSystem die Zielumgebung (inkl. FreeBSD und Solaris ) unterscheidet.

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

Man kann auch eine Ant-Aufgabe ( Quelle ) verwenden:

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

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

Gradle bietet keine öffentliche API zum Erkennen des Betriebssystems. Daher sind die os.Systemeigenschaften die beste Wahl.

Peter Niederwieser
quelle
7

Oder Sie können osName als Zeichenfolge definieren ...

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

... und später verwenden - um beispielsweise eine native Bibliothek einzuschließen:

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

Aber es würde nichts ändern, da OperatingSystem genau wie Ihr Code funktioniert:

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

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

Bearbeiten:

Sie können dasselbe für die Architektur tun:

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

und:

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

Beachten Sie jedoch, dass getArch () Folgendes zurückgibt:

  • "ppc" auf PowerPC
  • "amd64" auf 64b
  • "i386" ODER "x86" auf 32b.

getArch () gibt "x86" unter Solaris oder "i386" für jede andere Plattform zurück.

Bearbeiten 2:

Oder wenn Sie einen Import vermeiden möchten, können Sie dies einfach selbst tun:

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

Ich mag es nicht, das Betriebssystem in Gradle anhand von Eigenschaften oder einer Ant-Aufgabe zu erkennen, und die OperatingSystemKlasse enthält die current()Methode nicht mehr .

Meiner Meinung nach wäre der sauberste Weg, das Betriebssystem zu erkennen, also:

DefaultNativePlatform importieren:

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

Dann verwenden Sie DefaultNativePlatformin Ihrer Aufgabe:

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

Beachten Sie, dass diese Methode nicht ideal ist, da sie die interne Gradle-API verwendet.

Es wurde mit Gradle 4.10 getestet.

Ruslan Pilin
quelle