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?


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


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.


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

7

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


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

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.