How to detect the current OS from gradle

2019-02-02 19:09发布

问题:

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

Detecting the platform (Window or Linux) by groovy/grails :

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

Is there a better way?

回答1:

Actually, I looked at the gradle project and this looks a little cleaner as it uses ant's existing structure

import org.apache.tools.ant.taskdefs.condition.Os
task checkWin() << {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        println "*** WINDOWS "
    }
}

I found this in the following gradle branch and it seems to work nicely gradle/gradle-core/branches/RB-0.3/build.gradle



回答2:

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 Summer'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 sense that if it returns true with one particular params it is not necesserily means that it returns false for any other param. 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))
    }   
}

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 doc for org.gradle.nativeplatform.platform.OperatingSystem interface. It 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 implementation also gives us a hint that we should us 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 not to mess up in case something will change in future.



回答3:

One can differ the build environment in between Linux, Unix, Windows and OSX - while the Gradle nativeplatform.platform.OperatingSystem differs the target environment (incl. FreeBSD and Solaris), instead.

String osName = org.gradle.internal.os.OperatingSystem.current().getName();
String osVersion = org.gradle.internal.os.OperatingSystem.current().getVersion();
println "*** $osName $osVersion was detected."

if (org.gradle.internal.os.OperatingSystem.current().isLinux()) {
    // consider Linux.
} else if (org.gradle.internal.os.OperatingSystem.current().isUnix()) {
    // consider UNIX.
} else if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
    // consider Windows.
} else if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
    // consider OSX.
} else {
    // unknown OS.
}


回答4:

Gradle doesn't provide a public API for detecting the operating system. Hence the os. system properties are your best bet.



回答5:

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 work 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 Arch:

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.

Edit2:

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


标签: gradle