Cara mendeteksi OS saat ini dari Gradle

99

Saya menemukan jawaban ini tentang cara melakukannya dengan Groovy:

Mendeteksi platform (Window atau Linux) oleh Groovy / Grails :

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

Apakah ada cara yang lebih baik?

Daniel Sperry
sumber
itulah yang saya gunakan, tanpa toLowerCase().contains()bagian, karena saya hanya butuh nama.
Kevin Welker
Anda juga bisa mendapatkan versi OS, denganSystem.getProperty('os.arch')
Kevin Welker
13
"WINDOWS".toLowerCase()bergantung pada lokal dan akan kembali wındows(perhatikan i dotless) pada mesin yang lokalnya adalah Turki. Gunakan toLowerCase(Locale.ROOT)sebagai gantinya untuk berada di sisi yang aman.
Matthias Braun

Jawaban:

128

Sebenarnya, saya melihat proyek Gradle, dan ini terlihat sedikit lebih bersih karena menggunakan struktur Ant yang ada:

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

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

Saya menemukan ini di cabang Gradle berikut, dan tampaknya berfungsi dengan baik. gradle / gradle-core / Branches / RB-0.3 / build.gradle

Peter Kahn
sumber
8
berhati-hatilah, Os.isFamily (Os.FAMILY_UNIX) akan mengembalikan true baik untuk unix dan mac (sementara Os.isFamily (Os.FAMILY_MAC) juga valid
shabunc
3
Berhati-hatilah karena ini memang OS dan tidak menjelaskan apa pun tentang shell gradle yang dimulai (misalnya, mungkin Mingw, Cygwin, atau bash shell lainnya). Jadi berhati-hatilah jika Anda menggunakannya untuk membaca variabel lingkungan, mereka mungkin bukan yang Anda harapkan.
estani
2
@shabunc memiliki solusi yang lebih baik menggunakan org.gradle.internal.os.OperatingSystem
Peter Kahn
task checkWin() << {kenapa kamu membutuhkannya Anda bisa menulisif (Os.isFamily(Os.FAMILY_WINDOWS)) { println "*** WINDOWS " }
pengguna25
juga lebih baik menggunakan org.gradle.internal.os.OperatingSystemdan if (OperatingSystem.current() == OperatingSystem.WINDOWS)(jika kita berbicara tentang Gradle mengapa tidak menggunakan implementasinya sendiri)
user25
70

Pembaruan Pertengahan 2020 : Masih dalam inkubasi:

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

Pembaruan Awal 2019 : current()dihapus.

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

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

Perlu diingat bahwa itu masih dalam proses inkubasi .

Pembaruan Pertengahan 2018 : seperti yang disebutkan di komentar, sekarang kelas ini dipindahkan ke paket yang berbeda, jadi harus digunakanorg.gradle.nativeplatform.platform.OperatingSystem.current()


Sampai pertengahan 2015, jawaban Peter Kahn masih berlaku. Aktivasi profil berbasis lingkungan masih merupakan sesuatu yang relatif lebih mudah dilakukan di Maven. Namun perlu diingat bahwa org.apache.tools.ant.taskdefs.condition.Os.isFamilytidak eksklusif dalam arti bahwa jika mengembalikan nilai benar dengan satu parameter tertentu, itu tidak berarti bahwa ia mengembalikan salah untuk parameter lainnya. Misalnya:

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

Ini akan mengembalikan true baik untuk Os.FAMILY_MACdan Os.FAMILY_UNIXdi MacOS. Biasanya itu bukan sesuatu yang Anda butuhkan dalam skrip build.

Ada cara lain untuk mencapai ini menggunakan Gradle 2+ API, yaitu:

import org.gradle.internal.os.OperatingSystem;

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

Lihat dokumentasi untuk antarmuka org.gradle.nativeplatform.platform.OperatingSystem . Perlu disebutkan bahwa antarmuka ini ditandai dengan anotasi inkubasi , yaitu, "fitur saat ini sedang dalam proses dan dapat berubah kapan saja". Namespace "internal" dalam implementasi juga memberi kita petunjuk bahwa kita harus menggunakan ini dengan kesadaran bahwa ini bisa berubah.

Tetapi secara pribadi saya akan menggunakan solusi ini. Hanya saja lebih baik menulis kelas pembungkus agar tidak mengacaukan jika sesuatu akan berubah di masa depan.

shabunc
sumber
8
Apakah sudah berubah? Menggunakan Gradle 2.5 OperatingSystemsepertinya tidak harus.current()
Ross Drew
6
keberatan paket internal:org.gradle.internal.os.OperatingSystem.current()
Brian
@danblack bagaimana Anda mendapatkan contoh OperatingSystemtanpa current()?
TWiStErRob
1
Ditemukan satu OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem:; berharap ada yang publik @PeterNiederwieser
TWiStErRob
Karena Mac OS, Windows dan Linux bukan satu-satunya sistem operasi, alangkah baiknya jika z / OS disertakan. Meskipun dalam keadaan darurat, membuat pilihan sebagai tidak menjadi salah satu dari yang lain bisa berhasil.
John Czukkermann
18

Orang dapat membedakan lingkungan build di antara Linux, Unix, Windows, dan OS X - sedangkan Gradle nativeplatform.platform.OperatingSystem membedakan lingkungan target (termasuk FreeBSD dan 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.
}

Seseorang juga dapat menggunakan tugas Ant ( sumber ):

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

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

Gradle tidak menyediakan API publik untuk mendeteksi sistem operasi. Karenanya os.properti sistem adalah pilihan terbaik Anda.

Peter Niederwieser
sumber
7

Atau Anda dapat mendefinisikan osName sebagai 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;
}

... dan gunakan nanti - untuk menyertakan perpustakaan asli misalnya:

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

Tetapi itu tidak akan mengubah apa pun karena OperatingSystem bekerja persis seperti kode Anda:

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

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

Edit:

Anda dapat melakukan hal yang sama untuk arsitektur:

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

dan:

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

Ketahuilah bahwa getArch () akan mengembalikan:

  • "ppc" di PowerPC
  • "amd64" di 64b
  • "i386" ATAU "x86" pada 32b.

getArch () akan mengembalikan "x86" pada Solaris atau "i386" untuk platform lain.

Edit 2:

Atau jika Anda ingin menghindari impor apa pun, Anda dapat melakukannya sendiri:

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
sumber
Arsitekturnya tidak pernah diminta - dan menemukan kembali roda adalah upaya yang sia-sia. Ini mungkin merupakan preferensi pribadi, tetapi sebagian besar pemrogram akan menggunakan impor, setiap kali impor dapat digunakan (menggunakan kerangka kerja, tetapi tidak menggunakannya, hanya dapat menghasilkan kode duplikat).
Martin Zeitler
4

Saya tidak suka mendeteksi OS di Gradle melalui properti atau tugas Ant, dan OperatingSystemkelas tersebut tidak lagi berisi current()metode tersebut.

Jadi, menurut saya, cara terbersih untuk mendeteksi OS adalah:

Impor DefaultNativePlatform:

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

Kemudian gunakan DefaultNativePlatformdalam tugas Anda:

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

Ingatlah bahwa metode ini tidak ideal karena menggunakan API internal Gradle.

Itu telah diuji dengan Gradle 4.10.

Ruslan Pilin
sumber