如何从Gradle检测当前操作系统

xu3bshqb  于 2022-12-13  发布在  其他
关注(0)|答案(8)|浏览(294)

I found this answer about how to do it with Groovy:

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

Is there a better way?

2jcobegt

2jcobegt1#

实际上,我查看了Gradle项目,它看起来更简洁,因为它使用了Ant's现有结构:

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

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

我在下面的Gradle分支中找到了这个,它似乎工作得很好。gradle/gradle-core/branches/RB-0.3/build.gradle

falq053o

falq053o2#

Mid 2020 Update: Still incubating:

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

Early 2019 Update: current() removed.
org.gradle.nativeplatform.platform.OperatingSystem.getDisplayName()
org.gradle.nativeplatform.platform.OperatingSystem.isLinux()

Keep in mind that it's still incubating though.

Mid 2018 Update: just like it was mentioned in comments, now this class moved to a different package, so one should use org.gradle.nativeplatform.platform.OperatingSystem.current()

As of mid 2015, Peter Kahn's answer is still valid. Environment-based profile activation is still something done relatively easier in Maven. But keep in mind that org.apache.tools.ant.taskdefs.condition.Os.isFamily is not exclusive in the sense that if it returns true with one particular parameter it is not necessarily means that it returns false for any other parameter. For instance:

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

It will return true both for Os.FAMILY_MAC and Os.FAMILY_UNIX on MacOS. Usually it is not something you need in build scripts.
There is though another way to achieve this using Gradle 2+ API, namely:

import org.gradle.internal.os.OperatingSystem;

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

Check out the documentation for the org.gradle.nativeplatform.platform.OperatingSystem interface. It is worth to mention that this interface is marked with incubating annotation, that is, "the feature is currently a work-in-progress and may change at any time". The "internal" namespace in the implementation also gives us a hint that we should use this knowing that this can change.
But personally I'd go with this solution. It's just that it's better to write a wrapper class so as not to mess up in case something will change in the future.

tktrz96b

tktrz96b3#

人们可以区分Linux、Unix、Windows和OS X之间的构建环境-而Gradle nativeplatform.platform.OperatingSystem则区分目标环境(包括FreeBSDSolaris)。

import org.gradle.internal.os.OperatingSystem
OperatingSystem os = OperatingSystem.current();

println "*** Building on ${os.familyName} / ${os.name} / ${os.version} / ${System.getProperty("os.arch")}."

println "*** Building on ${os.toString()}."

if (os.isLinux()) {
    // Consider Linux.
} else if (os.isUnix()) {
    // Consider UNIX.
} else if (os.isWindows()) {
    // Consider Windows.
} else if (os.isMacOsX()) {
    // Consider OS X.
} else {
    // Unknown OS.
}

也可以使用Ant任务(source):

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

task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        // Consider Windows.
    }
}
bweufnob

bweufnob4#

Or you can define osName as a 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;
}

... and use it later - to include a native library for example:

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

But it wouldn't change anything since OperatingSystem works exactly like your code:

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

Source: https://github.com/gradle/gradle/blob/master/subprojects/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java
Edit:
You can do the same for the architecture:

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

and:

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

Just be aware that getArch() will return:

  • "ppc" on PowerPC
  • "amd64" on 64b
  • "i386" OR "x86" on 32b.
  • getArch() will return "x86" on Solaris or "i386" for any other platform.*

Edit 2:
Or if you want to avoid any import, you can simply do it yourself:

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

mbzjlibv5#

Gradle不提供用于检测操作系统的公共API,因此os.系统属性是您的最佳选择。

2nbm6dog

2nbm6dog6#

我不喜欢通过属性或Ant任务在Gradle中检测操作系统,并且OperatingSystem类不再包含current()方法。
因此,在我看来,检测操作系统的最干净的方法是:
导入默认本机平台:

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

然后在任务中使用DefaultNativePlatform

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

请注意,这种方法并不理想,因为它使用的是Gradle内部API。
使用Gradle 4.10对其进行了测试。

jvidinwx

jvidinwx7#

在没有任何导入的情况下,我从System类中获得了这些值,如下所示:

def osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH)
def osArch = System.getProperty("os.arch").toLowerCase(Locale.ENGLISH)
def osVersion = System.getProperty("os.version").toLowerCase(Locale.ENGLISH)
kadbb459

kadbb4598#

根据@shabunc的回答,你的一些选择是:

  1. org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
  2. org.apache.tools.ant.taskdefs.condition.Os
  3. org.gradle.nativeplatform.platform.OperatingSystem
  4. org.gradle.internal.os.OperatingSystem
    3号和4号基本上是相同的接口,其中OperatingSystem.current()实际上是OperatingSystem.isCurrent()(因为Groovy)。
    2号是一个可行的选择,但不是优雅的IMHO。
    因此,这是你可以如何使用选项1(作为一个例子,没有包括在内):
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform

def os = DefaultNativePlatform.currentOperatingSystem
def arch = DefaultNativePlatform.currentArchitecture
def version = "1.0.0"

switch (true) {
    case os.windows && arch.i386:
        implementation "com.example:example-win32-x86:${version}"
        break
    case os.windows && arch.amd64:
        implementation "com.example:example-win32-x86-amd64:${version}"
        break
    case os.macOsX && arch.amd64:
        implementation "com.example:example-darwin-x86-amd64:${version}"
        break
    case os.linux && arch.i386:
        implementation "com.example:example-linux-x86:${version}"
        break
    case os.linux && arch.amd64:
        implementation "com.example:example-linux-x86-amd64:${version}"
        break
    default:
        println "No suitable driver found for " + 
                "current OS (${os.displayName}) and " + 
                "architecture (${arch.displayName})"
}

相关问题