Jak wykryć aktualny system operacyjny z Gradle

99

Znalazłem tę odpowiedź, jak to zrobić z Groovym:

Wykrywanie platformy (Windows lub Linux) przez Groovy / Grails :

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

Czy jest lepszy sposób?

Daniel Sperry
źródło
tego używam, bez toLowerCase().contains()części, ponieważ potrzebuję tylko nazwy.
Kevin Welker
Możesz także pobrać wersję systemu operacyjnego zSystem.getProperty('os.arch')
Kevin Welker
13
"WINDOWS".toLowerCase()jest zależne od ustawień regionalnych i powróci wındows(zwróć uwagę na bez kropki i) na komputerach, na których język jest turecki. toLowerCase(Locale.ROOT)Zamiast tego użyj, aby być po bezpiecznej stronie.
Matthias Braun

Odpowiedzi:

128

Właściwie przyjrzałem się projektowi Gradle i wygląda to trochę czyściej, ponieważ wykorzystuje istniejącą strukturę Anta :

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

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

Znalazłem to w następującej gałęzi Gradle i wydaje się, że działa dobrze. gradle / gradle-core / branches / RB-0.3 / build.gradle

Peter Kahn
źródło
8
uważaj, Os.isFamily (Os.FAMILY_UNIX) zwróci wartość true zarówno dla unixa, jak i mac (podczas gdy Os.isFamily (Os.FAMILY_MAC) jest również poprawna
shabunc
3
Uważaj, to jest rzeczywiście system operacyjny i nie mówi nic o uruchomieniu powłoki (np. Może to być Mingw, Cygwin lub inna powłoka bash). Więc bądź ostrożny, jeśli użyjesz tego do odczytu zmiennych środowiskowych, mogą nie być tym, czego oczekujesz.
estani
2
@shabunc ma lepsze rozwiązanie za pomocą org.gradle.internal.os.OperatingSystem
Peter Kahn
task checkWin() << {a po co ci to? możesz po prostu napisaćif (Os.isFamily(Os.FAMILY_WINDOWS)) { println "*** WINDOWS " }
user25
też lepiej jest używać org.gradle.internal.os.OperatingSystemi if (OperatingSystem.current() == OperatingSystem.WINDOWS)(jeśli mówimy o Gradle, dlaczego nie użyć własnych implementacji)
user25
70

Aktualizacja z połowy 2020 r . : Nadal inkubacja:

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

Aktualizacja z początku 2019 r . : current()usunięta.

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

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

Pamiętaj, że nadal się inkubuje .

Aktualizacja z połowy 2018 r . : tak jak wspomniano w komentarzach, teraz ta klasa została przeniesiona do innego pakietu, więc należy użyćorg.gradle.nativeplatform.platform.OperatingSystem.current()


Od połowy 2015 roku odpowiedź Petera Kahna jest nadal aktualna. Aktywacja profilu oparta na środowisku jest nadal czymś stosunkowo łatwiejszym w Maven. Należy jednak pamiętać, że org.apache.tools.ant.taskdefs.condition.Os.isFamilynie jest to wykluczające w tym sensie, że jeśli zwraca prawdę z jednym określonym parametrem, niekoniecznie oznacza, że ​​zwraca fałsz dla dowolnego innego parametru. Na przykład:

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

Zwróci prawdę zarówno na MacOS, jak Os.FAMILY_MACi Os.FAMILY_UNIXna MacOS. Zwykle nie jest to coś, czego potrzebujesz w skryptach kompilacji.

Jest jednak inny sposób osiągnięcia tego za pomocą Gradle 2+ API, a mianowicie:

import org.gradle.internal.os.OperatingSystem;

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

Sprawdź dokumentację interfejsu org.gradle.nativeplatform.platform.OperatingSystem . Warto wspomnieć, że ten interfejs jest oznaczony inkubacją adnotacją , czyli „funkcja jest obecnie w toku i może ulec zmianie w dowolnym momencie”. „Wewnętrzna” przestrzeń nazw w implementacji również daje nam wskazówkę, że powinniśmy z niej korzystać, wiedząc, że może się to zmienić.

Ale osobiście wybrałbym to rozwiązanie. Po prostu lepiej jest napisać klasę opakowującą, aby nie zepsuć na wypadek, gdyby coś się zmieniło w przyszłości.

shabunc
źródło
8
Czy to się zmieniło? Używanie Gradle 2.5 OperatingSystemnie wydaje się mieć.current()
Ross Drew
6
uwaga na pakiet wewnętrzny:org.gradle.internal.os.OperatingSystem.current()
Brian
@danblack jak uzyskać instancję OperatingSystembez current()?
TWiStErRob
1
Znaleziono jeden OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem:; Szkoda, że ​​nie było publicznego @PeterNiederwieser
TWiStErRob
Ponieważ Mac OS, Windows i Linux nie są jedynymi systemami operacyjnymi, byłoby miło, gdyby dołączono z / OS. Chociaż jest to trudne, dokonanie wyboru nie będącego żadnym z pozostałych może się udać.
John Czukkermann
18

Można rozróżnić środowisko kompilacji na Linux, Unix, Windows i OS X - podczas gdy Gradle nativeplatform.platform.OperatingSystem rozróżnia środowisko docelowe (w tym FreeBSD i 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.
}

Można również użyć zadania Ant ( źródło ):

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

task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        // Consider Windows.
    }
}
Martin Zeitler
źródło
7

Gradle nie udostępnia publicznego interfejsu API do wykrywania systemu operacyjnego. Dlatego os.właściwości systemu są najlepszym rozwiązaniem.

Peter Niederwieser
źródło
7

Lub możesz zdefiniować osName jako ciąg ...

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

... i użyj go później - aby dołączyć bibliotekę natywną, na przykład:

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

Ale to niczego by nie zmieniło, ponieważ OperatingSystem działa dokładnie tak, jak twój kod:

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

Źródło: https://github.com/gradle/gradle/blob/master/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java

Edytować:

Możesz zrobić to samo dla architektury:

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

i:

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

Pamiętaj tylko, że funkcja getArch () zwróci:

  • „ppc” na PowerPC
  • „amd64” na 64b
  • „i386” LUB „x86” na 32b.

getArch () zwróci „x86” w systemie Solaris lub „i386” na dowolnej innej platformie.

Edycja 2:

Jeśli chcesz uniknąć importu, możesz po prostu zrobić to sam:

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
źródło
O architekturę nie pytano - a odkrywanie koła na nowo to bezcelowy wysiłek. Może to być osobiste preferencje, ale większość programistów użyłaby importu, gdy tylko można użyć importu (używając frameworka, ale nie używając go, może powstać tylko zduplikowany kod).
Martin Zeitler
4

Nie podoba mi się wykrywanie systemu operacyjnego w Gradle za pomocą właściwości lub zadania Ant, a OperatingSystemklasa nie zawiera już current()metody.

Moim zdaniem najczystszym sposobem na wykrycie systemu operacyjnego byłoby:

Importuj DefaultNativePlatform:

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

Następnie użyj DefaultNativePlatformw swoim zadaniu:

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

Należy pamiętać, że ta metoda nie jest idealna, ponieważ korzysta z wewnętrznego interfejsu API Gradle.

Został przetestowany z Gradle 4.10.

Rusłan Pilin
źródło