Groovy scripts no longer work under Cygwin? - groovy

In older versions of Groovy, I could run Groovy as a shell script under Cygwin, following their own instructions for doing so:
$ cat ~/bin/hiworld
#!/usr/bin/env groovy
println("Hello world")
This worked. However, under (at least) Groovy 2.3.2 and 2.3.3, I'm seeing this instead:
$ hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
My best stab in the dark: "env" launches scripts via an absolute path (e.g. "groovy /home/myacct/bin/hiworld"), and newer versions of Groovy have been, un, 'improved' so that Groovy no longer understands how to handle this.
Indeed, I can produce the same error by doing that:
$ groovy ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
So I'm not sure how Groovy is (a) resolving that to a windows-style path, and then (b) failing to understand it's a windows-style path.
I can "fix" this, then, by running it thusly:
$ groovy $(cygpath -w ~/bin/hiworld)
Hello world
... but, c'mon, that's a completely insane way of having users launch a utility script. (Or I could write a "front" script, with just that line, to launch another script, of course. But then, for what I'm trying to ultimately accomplish, I might as well just give up on Groovy and distribute a runnable JAR with an associated launching script.)
So has Groovy simply dropped support for Cygwin? Or is it really possible that they've gone at least two releases without testing their own recommended way of running a script under one of the most popular environments?
If not, what am I missing or doing wrong?
Update: I thought it would be helpful to back up some of the things I'm suggesting here.
First, I want note Cygwin clearly is (or was) at least somewhat supported: groovyStart, for example, has considerable code in it supporting the Cygwin platform (seemingly as much as, say Mac OSX). As noted, it apparently worked fine under previous versions.
Currently, the last example resolves, under groovyStart, to this:
'/cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/java' -classpath C:/cygwin64/home/myacct/opt/groovy-2.3.3/lib/groovy-2.3.3.jar -Dscript.name=/home/myacct/opt/groovy-2.3.3/bin/groovy -Dprogram.name=groovy -Dgroovy.starter.conf=C:/cygwin64/home/myacct/opt/groovy-2.3.3/conf/groovy-starter.conf -Dgroovy.home=C:/cygwin64/home/myacct/opt/groovy-2.3.3 '-Dtools.jar=C:/Program Files/Java/jdk1.7.0_51/lib/tools.jar' org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf C:/cygwin64/home/myacct/opt/groovy-2.3.3/conf/groovy-starter.conf --classpath . C:/cygwin64/home/myacct/bin/hiworld
Just to clarify, there's no problem invoking the JDK itself -- runs that part of the command runs just fine. The part which is broken is the very last argument: if I change
C:/cygwin64/home/myacct/bin/hiworld
to
file:///C:/cygwin64/home/myacct/bin/hiworld
... it works again. This agrees with my assertion above that "groovy" (the script) is indeed correctly converting from Cygwin/UNIX-style paths to a native Windows path, but the underlying process -- running in Windows Java -- is actually confused by having been a windows path! Apparently it was expecting a URL.
Update 2: Below, Warren makes the excellent suggestion of trying to use GVM. Sadly, this still produces the same error:
$ which groovy
/home/myacct/.gvm/groovy/current/bin/groovy
$ hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
$ sh $(which groovy) ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
Adding the "-x" flag to the previous command shows that Groovy is still using my Windows JVM (which isn't wrong, just noting) and is now referencing the GVM-installed libraries (shown here reformatted slightly for readability):
'/cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/java' \
-classpath C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/lib/groovy-2.3.3.jar \
-Dscript.name=/home/C400334/.gvm/groovy/current/bin/groovy \
-Dprogram.name=groovy \
-Dgroovy.starter.conf=C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/conf/groovy-starter.conf \
-Dgroovy.home=C:/cygwin64/home/myacct/.gvm/groovy/2.3.3 \
'-Dtools.jar=C:/Program Files/Java/jdk1.7.0_51/lib/tools.jar' \
org.codehaus.groovy.tools.GroovyStarter \
--main groovy.ui.GroovyMain \
--conf C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/conf/groovy-starter.conf \
--classpath . \
C:/cygwin64/home/myacct/bin/hiworld
As before, adding a "file:///" before the final argument seems to resolve the problem.
So I'm wondering perhaps if we're using a different version of the JVM or something?
Update 3: Upgrading to jdk1.7.0_60 (tried both 64- and 32-bit versions) but that didn't seem to make a difference. Java 6 exhibits the same problem, but also adds a complaint about missing NioGroovyMethods.

I'm not sure how Groovy is (a) resolving that to a windows-style path
The startGroovy script has specific code in it to detect Cygwin and use cygpath as necessary.
I discovered this by installing Groovy via GVM, the approved way of getting Groovy for Unixy platforms. (You do not want to use the native Windows distribution of Groovy in this case!)
The only tricky thing was figuring out how to set JAVA_HOME. Here, it needed to be:
$ export JAVA_HOME='/cygdrive/c/Program Files (x86)/Java/jre7'
If you're on a 64-bit version of Windows and have a 32-bit JRE installed as I do, this should also work for you. Otherwise, you may have to adjust the path.
Once I got gvm install groovy to succeed, your hiworld example worked fine here if I ran it as ./hiworld. This was with the 32-bit version of Cygwin with Java 1.7.0_55.
However, when I put it in the PATH and ran it as hiworld, as you are doing, this passed a fully-qualified path to the groovy wrapper script (e.g. /home/wyoung/bin/hiworld) instead of a relative path, which caused the startGroovy script to run the path through cygpath -m, which turns that into something like C:/cygwin64/home/wyoung/bin/hiworld. Oracle's JRE can't cope with forward slashes in local paths. It blindly assumes that forward slashes on Windows means it's a URL of some kind, so C: gets treated as the URL scheme, or "protocol" as they put it.
I don't know if this is a regression in Java or in the startGroovy script. Although you could pass a file:// URL here as you discovered, you can also pass a "proper" Windows path with backslashes instead of forward slashes. You get that from cygpath with the -w switch instead of -m. You have to be a lot more careful about avoiding accidental backslash escaping in this case, which may explain the regression.

Just hit the same problem and changed the exec call in the startGroovy script to the following (note the last two lines):
exec "$JAVACMD" $JAVA_OPTS \
-classpath "$STARTER_CLASSPATH" \
-Dscript.name="$SCRIPT_PATH" \
-Dprogram.name="$PROGNAME" \
-Dgroovy.starter.conf="$GROOVY_CONF" \
-Dgroovy.home="$GROOVY_HOME" \
-Dtools.jar="$TOOLS_JAR" \
$STARTER_MAIN_CLASS \
--main $CLASS \
--conf "$GROOVY_CONF" \
--classpath "$CP" \
"$(cygpath -w $1)" \
"${#:2}"
... that way the script being called is altered to a windows path with backslashes as suggested above, and then not interpreted as a URL it seems. Nasty hack, but at least I was able to execute my script again :)

Not sure if anyone still interests in this. But shortly I commented the above answer, I found a solution for this.
Update the "startGroovy" script with the following two changes:
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
ROOTDIRS="/c$SEP$ROOTDIRS" ## <<<< ADD THIS LINE;assuming cygwin on c: drv
and also replace the --mixed with --windows:
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
if [ $CHECK -ne 0 ] ; then
### change the --mixed to --windows here
patched=`cygpath --path --ignore --windows "$arg"`
else
patched="$arg"
fi
and it should work.

Related

Wine + Cygwin garbles argv

I'm trying to compile a program (sbcl to be precise) under Wine + MinGW/Cygwin environment. I've fixed plethora of different quirks, but now I'm stuck on the fact that this environment breaks command line arguments in weird way. The problem is that build shellscript contains the lines
./src/runtime/sbcl --core output/cold-sbcl.core \
--lose-on-corruption $SBCL_MAKE_TARGET_2_OPTIONS --no-sysinit --no-userinit \
--eval '(sb-fasl::!warm-load "src/cold/warm.lisp")' --quit
...but within the running sbcl process the last command line argument appears as (sb-fasl;!warm-load "src/cold/warm.lisp"), which is, of course, syntactically incorrect and the build fails.
I've performed some tests with different versions of wine (I've tried versions 6.0, 6.12 and 6.15) and win32 bash (I've tried a plenty of those, including busybox for windows, currently stuck with the one from old MSYS-20111123.zip from here since it does not exhibit FAST_CWD bug that is currently not fixed). It appears that every time the command line contains both double colon and forward slash, some part of the environment changes double colon to semicolon. I'm not sure where to look for that behaviour to circumvent it - is that shell escaping, or exec syscall behaviour? Could it be that this behaviour is hardcoded into exec function in msvcrt.dll?

(Node.js) --grpc_out: protoc-gen-grpc: %1 is not a valid Win32 application

I want to compile my .proto file into stubs, but when entering the command:
`protoc -I=. ./protos/dummy.proto
--js_out=import_style=commonjs,binary:./server --grpc_out=./server --plugin=protoc-gen-grpc=which grpc_tools_node_protoc_plugin
I got the following error :
--grpc_out: protoc-gen-grpc: %1 is not a valid Win32 application.
Thigs I have installed :
Windows 10
npm install -g grpc-tools
npm install google-protobuf
protoc
NOTE: I noticed there are a few similar questions already, but I didn't find one for Node.js, also the already asked questions all have different solutions.
On Windows, I messed around with the grpc-tools for Node a bit and came across some issues. I installed the tools (and the TS plugin) via npm install grpc-tools grpc_tools_node_protoc_ts --save-dev to my local node_modules/.bin folder. Thanks to this post, I can provide these solutions. This was my original shell script
#!/usr/bin/env bash
PROTO_DIR="./src/grpc/proto"
PROTOC_GEN_TS_PATH="./node_modules/.bin/protoc-gen-ts"
GRPC_TOOLS_NODE_PROTOC_PLUGIN="./node_modules/.bin/grpc_tools_node_protoc_plugin"
GRPC_TOOLS_NODE_PROTOC="./node_modules/.bin/grpc_tools_node_protoc"
# Generate JS and corresponding TS d.ts codes for each .proto file using the grpc-tools for Node.
$GRPC_TOOLS_NODE_PROTOC \
--plugin=protoc-gen-grpc="$GRPC_TOOLS_NODE_PROTOC_PLUGIN" \
--plugin=protoc-gen-ts="$PROTOC_GEN_TS_PATH" \
--js_out=import_style=commonjs,binary:"$PROTO_DIR" \
--ts_out="$PROTO_DIR" \
--grpc_out="$PROTO_DIR" \
-I "$PROTO_DIR" \
"$PROTO_DIR"/*.proto
If you just provide the plugin by its name, e.g. --plugin=protoc-gen-grpc=./node_modules/.bin/grpc_tools_node_protoc_plugin, Windows will complain about an invalid Win32 application. You can solve this issue by adding the .cmd extension:
--plugin=protoc-gen-grpc=./node_modules/.bin/grpc_tools_node_protoc_plugin.cmd
Unfortunately, the following issue '.' Not an internal or external command, or a runnable program or batch file arises, which indicates that Windows cannot resolve the relative path to the plugin. Therefore, you have to provide the absolute path, e.g.
--plugin=protoc-gen-grpc=C:/.../<project-dir>/node_modules/.bin/grpc_tools_node_protoc_plugin.cmd
Now the real magic happens:
Because of a simple typo (I typed --plugin=proto-gen-grpc instead of --plugin=protoc-gen-grpc), I figured out that, if you have grpc-tools and additional plugins installed in your local Node environment, you can simply omit --plugin.
It seems that grpc_tools_node_protoc will automatically lookup the executables required to generate the code specified by the output flags --grpc_out, --js_out or --ts_out in ./node_modules/.bin/.
Therefore, I updated the following LOC in my script
$GRPC_TOOLS_NODE_PROTOC \
--js_out=import_style=commonjs,binary:"$PROTO_DIR" \
--ts_out="$PROTO_DIR" \
--grpc_out="$PROTO_DIR" \
-I "$PROTO_DIR" \
"$PROTO_DIR"/*.proto
Maybe, others could share their experience and more clarifications to this issue.
You can solve this issue by adding the .cmd extension:
--plugin=protoc-gen-grpc=./node_modules/.bin/grpc_tools_node_protoc_plugin.cmd
And the following issue '.' Not an internal or external command, or a runnable program or batch file, you can solve replacing the '.' by '%cd%':
--plugin=protoc-gen-grpc=%cd%/node_modules/.bin/grpc_tools_node_protoc_plugin.cmd
SIMPLE SOLUTION :
For me the "which" command was pointing to the wrong path so I removed it and replaced it with an absolute path to the plugin instead. It looks like this :
protoc -I=. ./protos/dummy.proto
--js_out=import_style=commonjs,binary:./server --grpc_out=./server --plugin=protoc-gen-grpc=C:\Users\myUser\AppData\Roaming\npm\node_modules\grpc-tools\bin\grpc_node_plugin.exe
Explanation :
I am not sure why this error (--grpc_out: protoc-gen-grpc: %1 is not a valid Win32 application) was happening, but I have an theory... The "which" command pointed to the folder and not to the .exe file. How do I know this? When I try to only run the command (in the terminal)
which grpc_tools_node_protoc_plugin
It returns the folder
/c/Users/myUser/AppData/Roaming/npm/grpc_tools_node_protoc_plugin
As grpc-tools has been installed globally (-g flag per OP), setting the plugin path beforehand works.
GRPC_TOOLS_PLUGIN="$HOME/AppData/Roaming/npm/grpc_tools_node_protoc_plugin.cmd" && \
protoc -I=. ./protos/*.proto \
--js_out=import_style=commonjs,binary:./server \
--grpc_out=./server \
--plugin=protoc-gen-grpc=$GRPC_TOOLS_PLUGIN
Thanks to both answers before me for pointers!
Tested and found to be working on Windows 10 Pro and Git Bash.
This piece of code worked for me.
protoc --js_out=import_style=commonjs,binary:./server ./proto/dummy.proto

Running xjc command for Java 11-works in git bash but not cygwin

Interesting issue. I'm working on a Java 11 upgrade and ran into a problem running XJC locally. As XJC is no longer part of the JDK I've downloaded our own XJC and the needed jaxb libraries. However, when I run it locally via Cygwin it errors stating that it 'Could not find or load main class com.sun.tools.xjc.XJCFacade'. After some debugging I pulled out the command being run which produces the error, but with a minor change it works in Git Bash. I'm trying to figure out why it works in Git Bash but not Cygwin (in Windows, as it works on my Linux VM), to maybe gain some insight into what to fix.
XJC works successfully on Linux VM (so I know the script is valid)
Command (listed below) works with Git Bash on Windows 10 with Java 11
Commands (listed further below) FAIL in Cygwin on Windows 10 with Java 11
Working Git command
/c/Programs/Amazon_Corretto/jdk11.0.5_10/bin/java -cp /c/Programs/jaxb-ri/lib/jaxb-xjc.jar:/c/Programs/jaxb-ri/lib/jakarta.xml.bind-api.jar:/c/Programs/jaxb-ri/lib/jaxb-impl.jar:/c/Programs/jaxb-ri/lib/jaxb-jxc.jar:/c/Programs/jaxb-ri/lib/jakarta.activation.jar com.sun.tools.xjc.XJCFacade -xmlschema /c/Development/Project_Folder/path/to/some/code/filename.xsd -d /c/Development/Project_Folder/path/to/some/code
Failed attempts with Cygwin
/cygdrive/c/Programs/Amazon_Corretto/jdk11.0.5_10/bin/java -cp /c/Programs/jaxb-ri/lib/jaxb-xjc.jar:/c/Programs/jaxb-ri/lib/jakarta.xml.bind-api.jar:/c/Programs/jaxb-ri/lib/jaxb-impl.jar:/c/Programs/jaxb-ri/lib/jaxb-jxc.jar:/c/Programs/jaxb-ri/lib/jakarta.activation.jar com.sun.tools.xjc.XJCFacade -xmlschema /c/Development/Project_Folder/path/to/some/code/filename.xsd -d /c/Development/Project_Folder/path/to/some/code
/cygdrive/c/Programs/Amazon_Corretto/jdk11.0.5_10/bin/java -cp /cygdrive/c/Programs/jaxb-ri/lib/jaxb-xjc.jar:/cygdrive/c/Programs/jaxb-ri/lib/jakarta.xml.bind-api.jar:/cygdrive/c/Programs/jaxb-ri/lib/jaxb-impl.jar:/cygdrive/c/Programs/jaxb-ri/lib/jaxb-jxc.jar:/cygdrive/c/Programs/jaxb-ri/lib/jakarta.activation.jar com.sun.tools.xjc.XJCFacade -xmlschema /cygdrive/c/Development/Project_Folder/path/to/some/code/filename.xsd -d /cygdrive/c/Development/Project_Folder/path/to/some/code
/cygdrive/c/Programs/Amazon_Corretto/jdk11.0.5_10/bin/java -cp /c/Programs/jaxb-ri/lib/jaxb-xjc.jar:/c/Programs/jaxb-ri/lib/jakarta.xml.bind-api.jar:/c/Programs/jaxb-ri/lib/jaxb-impl.jar:/c/Programs/jaxb-ri/lib/jaxb-jxc.jar:/c/Programs/jaxb-ri/lib/jakarta.activation.jar com.sun.tools.xjc.XJCFacade -xmlschema /cygdrive/c/Development/Project_Folder/path/to/some/code/filename.xsd -d /cygdrive/c/Development/Project_Folder/path/to/some/code
So I have identified the issue being the pathing format.
After alot of trial and error and some brainstorming I figured out the path for the jar files must be in Windows format with a semi-colon delimiter. Somehow during my trials I ended up using a Windows path with ':' delimiter, and later when I correctly used both Windows format and semi-colon delimiter I was using the 'cygpath -w' which is not needed.
So
"java -cp "C:\Program File\Path\jaxb-xjc.jar;C:\Program File\Path\jaxb-impl.jar..." com.sun.tools.xjc.XJCFacade.

Why isn't Coq recognizing compiled libraries?

I'm trying to get Coq working as a plugin for Sublime Text 3 on MacOS. I have everything working save for code that requires import statements.
The exact same code works perfectly when run in CoqIDE (which runs Coqc version 8.9), but when I try to run from Coqc verion 8.8 (homebrew install), when I reach my statement:
From LF Require Export Basics.
it throws the error:
Cannot find a physical path bound to logical path matching suffix <> and prefix LF.
When I remove From LF I get:
Basics.vo contains library LF.Basics and not library Basics
which indicates (at least to me) that the libraries are, indeed, compiling and making correctly, and something else is wrong.
Here are the commands that I run:
coq_makefile -f _CoqProject -o CoqMakefile
make -f CoqMakefile -B
My _CoqProject looks like this:
-R . LF
Basics.v
Induction.v
Anyone have any ideas or any experience with this?

Why doesn't SBT 0.7.7 work correctly on my Linux system? (case details inside)

First of all, I'd like to ask to correct my question title if something better comes into your mind.
Let's take a Lift REST web service example from the Simply Lift book by David Pollak here.
If I open a Windows (Windows XP SP3, all the updates, Oracle JDK 7) console inside the directory and run "sbt" (sbt.bat), everything works just fine. But in case I try to do the same (but using "./sbt") in Linux (XUbuntu 11.10, OpenJDK 6, OpenJDK 7, Oracle JDK 7 (tried all of them)), SBT returns (instead of going to SBT console mode) immediately as it has done it's job. This means that may the command be just ./sbt it returns about immediately (after finishing the automatic project maintenance), or be it ./sbt jetty-run - it just starts the web server and shuts it down immediately.
Moreover, a web service I've developed for a project of mine compiles and works ok on Windows, but can't be compiled (using ./sbt compile) on Linux (by the same version of SBT). The error is "source file '/.../src/main/scala/code/lib/FooBar.scala;src/main/scala/bootstrap/liftweb/Boot.scala' could not be found", where "FooBar.scala" is an object where I do all the serves (directly called from Boot.scala).
Any ideas of what can be the reason and how to fix it?
UPDATE: The reason of the first problem (SBT returning to shell instead of offering SBT console) seems to be the file was checked out on Windows and had CR+LF instead of just LF line ending. The solution of source files not being found was in just using clean command to recompile from scratch.
The reason of the first problem (SBT returning to shell instead of offering SBT console) seems to be the file was checked out on Windows and had CR+LF instead of just LF line ending. The solution of source files not being found was in just using clean command to recompile from scratch.
First what happens when you simply type:
java -jar sbt-launch.jar
directly from the command line in the folder where the sbt-launch.jar is placed ?. If the sbt-launch.jar is in the same folder as the sbt script then you can edit the script to look like this:
#!/bin/sh
test -f ~/.sbtconfig && . ~/.sbtconfig
java -Xmx512M ${SBT_OPTS} -jar dirname $0/sbt-launch.jar "$#"
The dirname $0 construct returns the full path of the sbt script folder without the filename of the script. Using the $SBT_OPTS variable allows you to experiment with the various JVM options, like:
SBT_OPTS="-Xss2M -XX:+CMSClassUnloadingEnabled"
Although I would wait with these options as they are likely not the problem here (however be sure to add CMSClassUnloadingEnable later when SBT is working as it ensures that Scala class definitions generated dynamically when running SBT gets unloaded when they are unused, thus preventing memory errors - see more info here):
Also consider using one of
-Djline.terminal=scala.tools.jline.UnixTerminal
or even
-Djline.terminal=jline.UnsupportedTerminal
in your SBT_OPTS.
Finally what happens if you try a never version of SBT ? (you could try running the SBT 0.11 version of the lift example found here https://github.com/lacy/lift-quickstart).
Replace your Linux script by:
#!/bin/bash
java -Xmx512M -jar `dirname $0`/sbt-launch.jar "$#"
On your settings:
Your script sets Xss (the Thread stack size). In Linux you sometimes need to change (via ulimit) the settings for stack per thread (ulimit -s) as you may have conflicts at SO level which may be triggering the "kill" on your threads. Unless you have a very important reason to set this flag just remove it and let the JVM manage this.
It may also be you wanted to put Xms instead of Xss, although then 2M would make this flag irrelevant (heap too small to be practical)
The flag -XX:+CMSClassUnloadingEnabled allows GC to sweep the Perm space. It shouldn't be necessary for sbt. As you can read here the PermGen options will only pospone PermGen issues, so if you have problems with PermGen when running Jetty, just add a bigger PermGen via -XX:MaxPermSize

Resources