Skip to content

Commit

Permalink
Fix integration tests on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsmith committed Aug 13, 2023
1 parent c9030d2 commit cfede99
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 36 deletions.
3 changes: 3 additions & 0 deletions product/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ public static String findExecutable(String name) throws FileNotFoundException {
// PATH, but this is because it's listed in /etc/paths, which only affects
// shells, but not other apps like Android Studio and its Gradle subprocesses.
List<String> path = new ArrayList<>();
if (System.getProperty("os.name").toLowerCase().startsWith("mac")) {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.startsWith("mac")) {
final String ETC_PATHS = "/etc/paths";
try (BufferedReader reader = new BufferedReader(new FileReader(ETC_PATHS))) {
String line;
Expand All @@ -109,10 +110,19 @@ public static String findExecutable(String name) throws FileNotFoundException {
}
Collections.addAll(path, System.getenv("PATH").split(File.pathSeparator));

List<String> exts = new ArrayList<>();
exts.add("");
if (osName.startsWith("win")) {
exts.add(".exe");
exts.add(".bat");
}

for (String dir : path) {
file = new File(dir, name);
if (file.exists()) {
return file.toString();
for (String ext : exts) {
file = new File(dir, name + ext);
if (file.exists()) {
return file.toString();
}
}
}
throw new FileNotFoundException("Couldn't find '" + name + "' on PATH");
Expand Down
58 changes: 26 additions & 32 deletions product/runtime/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,18 @@ if (osName == null) {
throw new GradleException("unknown os.name: '$osNameProperty'")
}

def pyPlusVersion = "python$Common.DEFAULT_PYTHON_VERSION"
// filenames with dots require the ".exe" suffix with Exec tasks on Windows.
def pyPlusVersionExe = "$pyPlusVersion"
if (osName == "windows") {
pyPlusVersionExe += ".exe"
String hostPythonExe() {
return findExecutable("python$Common.DEFAULT_PYTHON_VERSION")
}
pyPlusVersionExe = findExecutable(pyPlusVersionExe)

String pythonHome
if (osName == "windows" && System.getenv("CI") != null) {
// All the tasks that use pythonHome require MSYS2 Python on Windows, but we don't
// install that in CI because we don't run any of those tasks. TODO: fix this by
// moving to the standard Windows Python builds.
pythonHome = "disabled/in/CI"
} else {
new ByteArrayOutputStream().withStream { output ->

String hostPythonHome() {
return new ByteArrayOutputStream().withStream { output ->
exec {
executable pyPlusVersionExe
executable hostPythonExe()
args "-c", "import sys; print(sys.base_prefix)"
standardOutput = output
}
pythonHome = output.toString().trim()
return output.toString().trim()
}
}

Expand Down Expand Up @@ -154,8 +144,8 @@ javadoc {
}
}

def cythonTask = { String name, Closure closure ->
tasks.register(name, Exec) {
TaskProvider cythonTask(String name, Closure closure) {
return tasks.register(name, Exec) {
group = "build"
configure(closure)

Expand All @@ -173,9 +163,10 @@ def cythonTask = { String name, Closure closure ->

doLast {
String[][] replacements = [
// All functions called directly by the JVM must be declared JNICALL JNIEXPORT. JNIEXPORT
// should be equivalent to Cython's "cdef public", but JNICALL does make a difference on
// some platforms including x86. So alter the generated C code to add it.
// All functions called directly by the JVM must be declared JNICALL
// JNIEXPORT. JNIEXPORT should be equivalent to Cython's "cdef public",
// but JNICALL does make a difference on some platforms including x86.
// So alter the generated C code to add it.
[/^__PYX_EXTERN_C (\w+)/,
'/* cythonTask altered */ __PYX_EXTERN_C JNIEXPORT $1 JNICALL'],

Expand Down Expand Up @@ -223,21 +214,21 @@ dependencies {
testImplementation 'org.hamcrest:hamcrest-library:2.2'
}

tasks.register("generateStaticProxy", Exec) {
def proxyTask = tasks.register("generateStaticProxy", Exec) {
group = "verification"
def outputDir = "$buildDir/static_proxy"
outputs.dir(outputDir)
outputs.upToDateWhen { false }
doFirst { delete outputDir }
environment "PYTHONPATH", "$projectDir/../gradle-plugin/src/main/python"
executable pyPlusVersionExe
executable hostPythonExe()
args "-m", "chaquopy.static_proxy"
args "--path", "$projectDir/src/test/python"
args "--java", outputDir
args("chaquopy.test.static_proxy.basic", "chaquopy.test.static_proxy.header",
"chaquopy.test.static_proxy.method")
}
sourceSets.test.java.srcDirs += generateStaticProxy.outputs
sourceSets.test.java.srcDir(proxyTask)

for (abi in ["host"] + Common.ABIS) {
def pyLibSuffix = ".so"
Expand Down Expand Up @@ -276,8 +267,8 @@ for (abi in ["host"] + Common.ABIS) {
javaIncludeSubdir = osName
}
args "-DCHAQUOPY_PYTHON_VERSION=$Common.DEFAULT_PYTHON_VERSION"
args "-DCHAQUOPY_LIB_DIRS=$pythonHome/lib"
args "-DCHAQUOPY_INCLUDE_PYTHON=$pythonHome/include"
args "-DCHAQUOPY_LIB_DIRS=${hostPythonHome()}/lib"
args "-DCHAQUOPY_INCLUDE_PYTHON=${hostPythonHome()}/include"
args ("-DCHAQUOPY_INCLUDE_JAVA=$javaHome/include;" +
"$javaHome/include/$javaIncludeSubdir")
} else {
Expand Down Expand Up @@ -352,7 +343,7 @@ for (abi in ["host"] + Common.ABIS) {
configure(hostConfig)
workingDir "$projectDir/src/test/python"
environment "JAVA_HOME", javaHome
executable pyPlusVersionExe
executable hostPythonExe()
args "-m", "unittest"
if (project.hasProperty("testPythonArgs")) {
args project.testPythonArgs.split(" ")
Expand All @@ -373,15 +364,18 @@ for (abi in ["host"] + Common.ABIS) {
group = "verification"
configure(hostConfig)
outputs.upToDateWhen { false }
environment "PYTHONHOME", pythonHome
environment "PYTHONHOME", hostPythonHome()
if (osName == "linux") {
// libchaquopy_java.so is linked against libpython, but that doesn't add
// the libpython symbols to the global scope, which is required in order to
// load native modules like ctypes. Loading libpython with
// System.loadLibrary doesn't help: presumably it uses RTLD_LOCAL on
// Linux. Altering chaquopy_java to call dlopen with RTLD_GLOBAL would be
// the proper solution, but let's do it the easy way for now. See #5695.
environment "LD_PRELOAD", "/usr/lib/x86_64-linux-gnu/lib${pyPlusVersion}.so"
environment(
"LD_PRELOAD",
"/usr/lib/x86_64-linux-gnu/libpython${Common.DEFAULT_PYTHON_VERSION}.so"
)
}
testClassesDirs = sourceSets.test.output.classesDirs
scanForTestClasses = false
Expand All @@ -407,7 +401,7 @@ for (abi in ["host"] + Common.ABIS) {
writer.println "export $key='${env.get(key)}'"
}
writer.println "export PATH=\"$cmakeBuildSubdir${File.pathSeparator}" + '$PATH"'
writer.println "winpty $pyPlusVersionExe " + '"$@"'
writer.println "winpty ${hostPythonExe()} " + '"$@"'
writer.close()
}
}
Expand All @@ -419,7 +413,7 @@ for (abi in ["host"] + Common.ABIS) {

// We call a specific Python executable rather than running `sphinx-build`,
// because Sphinx needs to be able to import the runtime module.
executable pyPlusVersionExe
executable hostPythonExe()
args "-m", "sphinx", "-v", "-b", "html", "docs/sphinx", "build/docs"
environment "JAVA_HOME", javaHome
}
Expand Down

0 comments on commit cfede99

Please sign in to comment.