How to fix this bazel project for kotlin? - kotlin

I want to be able to use bazel to organize a simple kotlin project.
I am using the templates as listed in rules_kotlin (https://github.com/bazelbuild/rules_kotlin)
This is my BUILD file
load("#io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
kt_jvm_library(
name = "redis-tools",
srcs = glob(["*.kt"]),
deps = [],
)
This is my WORKSPACE file
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
rules_kotlin_version = "legacy-1.3.0"
rules_kotlin_sha = "4fd769fb0db5d3c6240df8a9500515775101964eebdf85a3f9f0511130885fde"
http_archive(
name = "io_bazel_rules_kotlin",
urls = ["https://github.com/bazelbuild/rules_kotlin/archive/%s.zip" % rules_kotlin_version],
type = "zip",
strip_prefix = "rules_kotlin-%s" % rules_kotlin_version,
sha256 = rules_kotlin_sha,
)
load("#io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kotlin_repositories", "kt_register_toolchains")
kotlin_repositories() # if you want the default. Otherwise see custom kotlinc distribution below
kt_register_toolchains() # to use the default toolchain, otherwise see toolchains below
My kotlin file main.kt:
import java.util.Scanner
fun main(args: Array<String>) {
// Creates a reader instance which takes
// input from standard input - keyboard
val reader = Scanner(System.`in`)
print("Enter a number: ")
// nextInt() reads the next integer from the keyboard
var integer:Int = reader.nextInt()
// println() prints the following line to the output screen
println("You entered: $integer")
}
I use a very simple file to test my setup.
Without bazel, I can do these to build: kotlinc main.kt -include-runtime -d test.jar
then run it with java -jar test.jar
When I use bazel build ., bazel creates a few folders. I tried to run java -jar bazel-out/darwin-fastbuild/bin/redis-tools.jar but it failed.
$ java -jar bazel-out/darwin-fastbuild/bin/redis-tools.jar
no main manifest attribute, in bazel-out/darwin-fastbuild/bin/redis-tools.jar
Did I miss a target? How can I run the main.tk from the bazel output?

The jar you are trying to run is missing a manifest file which declares its main class.
For executing a binary, Bazel uses a shell script wrapper which includes the required jvm flags and its run-time dependencies.
Notice that you are using kt_jvm_library. This rule builds a shared dependency without the wrapper. To include a wrapper you should use the kt_jvm_binary rule. Then you can specify the main class by setting the main_class attribute.
Notice that you can use the bazel run :redis-tools to run the jar (use -s to see which script Bazel excuted)
You can also use bazel build :redis-tools_deploy.jar to build a "fat-jar" which will include the manifest.

Related

How to run main function Kotlin file on command-line with string array arguments

i'm trying to run one of .kt files that i have for my side project and I suddenly wanted run my *.kt file that has
fun main(args: Array<String>) {
...
}
on command-line tool. I did install kotlin compiler, set up the path. All I have to do is to figure out how to pass args parameter through command line and cannot find a way to do that.
I've looked through kotlin compiler options and how to run kotlin file on command-line and it did not help at all.
Thanks in advance.
Just type them after the command:
java -jar myjar.jar arg_one arg_two
//OR (After compiling to jars you can specify the main class to run)
kotlin -classpath myjar.jar MyKt 'arg_one' 'arg_two'
//OR
kotlin MyKt 'arg_one' 'arg_two'
Then:
val argOne = args[0] // "arg_one"
First you have to compile your file to a JAR:
kotlinc filename.kt -include-runtime -d output.jar
Then you can run that JAR with java:
java -jar output.jar argument0 argument1

Kotlin Script (.kts) - How to divide it into multiple files?

I have a Generator.kts file. When I execute it using:
kotlinc -script Generator.kts
everything works as expected.
However, now my script has grown and I need to separate that class into multiple files.
I did that but when I try to execute it again I get the following errors:
Generator.kts:8:23: error: unresolved reference: CSVReader
val csvData = CSVReader().readCSV()
^
Generator.kts:10:23: error: unresolved reference: Folders
val folders = Folders()
^
Generator.kts:14:9: error: unresolved reference: KeyStore
KeyStore().generateKeyStoreFile(
Basically it fails to find all of the classes I created (CSVReader.kt, Folders.kt and KeyStore.kt). All those classes are in the same folder (including Generator.kts).
How can I run a Kotlin script that uses multiple files?
You could either compile all your sub-scripts into an artifact and add it to the classpath
Or you could use a third party tool like kscript to include them on the fly into your master script.
#!/usr/bin/env kscript
#file:Include("utils.kt")
val robustMean = listOf(1.3, 42.3, 7.).median()
println(robustMean)
For details and examples see https://github.com/holgerbrandl/kscript#ease-prototyping-with-include
Disclaimer: I'm a contributor of kscript.

Usage: java cucumber.api.cli.Main [options] [ [FILE|DIR][:LINE[:LINE]*] ]+

I am getting this error while running my feature file
Usage: java cucumber [options] [ [FILE|DIR][:LINE[:LINE]*] ]+
Options:
-g, --glue PATH Where glue code (step definitions and hooks) is loaded from.
-f, --format FORMAT[:PATH_OR_URL] How to format results. Goes to STDOUT unless PATH_OR_URL is specified.
Built-in FORMAT types: junit, html, pretty, progress, json.
FORMAT can also be a fully qualified class name.
-t, --tags TAG_EXPRESSION Only run scenarios tagged with tags matching TAG_EXPRESSION.
-n, --name REGEXP Only run scenarios whose names match REGEXP.
-d, --[no-]-dry-run Skip execution of glue code.
-m, --[no-]-monochrome Don't colour terminal output.
-s, --[no-]-strict Treat undefined and pending steps as errors.
--snippets Snippet name: underscore, camelcase
--dotcucumber PATH_OR_URL Where to write out runtime information. PATH_OR_URL can be a file system
path or a URL.
-v, --version Print version.
-h, --help You're looking at it.
Exception in thread "main" cucumber.runtime.CucumberException: Unknown option: --plugin
at cucumber.runtime.RuntimeOptions.parse(RuntimeOptions.java:119)
at cucumber.runtime.RuntimeOptions.<init>(RuntimeOptions.java:50)
at cucumber.runtime.RuntimeOptions.<init>(RuntimeOptions.java:44)
at cucumber.api.cli.Main.run(Main.java:20)
at cucumber.api.cli.Main.main(Main.java:16)
my runner class
package cucumber;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith( value = Cucumber.class)
#CucumberOptions(dryRun = false, strict = true,
features="/STAF/src/main/java/CucumberFeature/GmailLoginLogout.feature/",
tags ={"~#/ReCall/src/SeleniumWithCucumber/FbTest.java"})
public class CucumberRunner {
}
my feature file
Feature: Gmail login Logout
Scenario: Login and Log out to Gmail
Given Open gmail
When Login with valide credential
Then Home page should come
my step defination
package StepDfination;
import org.openqa.selenium.WebDriver;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class GmailLoginLogout {
WebDriver driver;
#Given("^Open gmail$")
public void Open_gmail(){
System.out.println("gmailopened ");
}
#When("^Login with valide credential$")
public void Login_with_valide_credential(){
System.out.println("cridential entered");
}
#Then("^Home page should come$")
public void Home_page_should_come(){
System.out.println("in home page");
}
}
Use of CLI command to invoke it as a Java program would be
public static void main(String args[]) {
Main.main(new String[]{"-g", "StepDfination", "-t", "<your tag what you need to test", "/STAF/src/main/java/CucumberFeature/GmailLoginLogout.feature"});
}
As grasshopper suggested, if you need invoke it as TestNG, you need a runner class.
Note that your feature file location should be the last. Let me know if it helps!
It looks like you are trying to get started. Your steps will only report that they are executed. However, your approach seems very complicated and you are getting an error you don't understand. You have a problem with Gall's law.
I would suggest that you start from another angle. Start from something that works and then transform it into something that you want.
Clone the getting started project supplied by the Cucumber Team and then transform it in small steps to the example you really would like to have.
Try using "-p" instead of "--plugin".
I found out it by a similar error of mine. Hope this log would help.
Usage: java cucumber.api.cli.Main [options] [[[FILE|DIR][:LINE[:LINE]*] ]+ | #FILE ]
Options:
-g, --glue PATH Where glue code (step definitions, hooks
and plugins) are loaded from.
-p, --[add-]plugin PLUGIN[:PATH_OR_URL]
Register a plugin.
Built-in formatter PLUGIN types: junit,
html, pretty, progress, json, usage, rerun,
testng. Built-in summary PLUGIN types:
default_summary, null_summary. PLUGIN can
also be a fully qualified class name, allowing
registration of 3rd party plugins.
--add-plugin does not clobber plugins of that
type defined from a different source.
-f, --format FORMAT[:PATH_OR_URL] Deprecated. Use --plugin instead.
-t, --tags TAG_EXPRESSION Only run scenarios tagged with tags matching
TAG_EXPRESSION.
-n, --name REGEXP Only run scenarios whose names match REGEXP.
-d, --[no-]-dry-run Skip execution of glue code.
-m, --[no-]-monochrome Don't colour terminal output.
-s, --[no-]-strict Treat undefined and pending steps as errors.
--snippets [underscore|camelcase] Naming convention for generated snippets.
Defaults to underscore.
-v, --version Print version.
-h, --help You're looking at it.
--i18n LANG List keywords for in a particular language
Run with "--i18n help" to see all languages
--junit,OPTION[,OPTION]* Pass the OPTION(s) to the JUnit module.
Use --junit,-h or --junit,--help to print the
options of the JUnit module.
Feature path examples:
<path> Load the files with the extension ".feature"
for the directory <path>
and its sub directories.
<path>/<name>.feature Load the feature file <path>/<name>.feature
from the file system.
classpath:<path>/<name>.feature Load the feature file <path>/<name>.feature
from the classpath.
<path>/<name>.feature:3:9 Load the scenarios on line 3 and line 9 in
the file <path>/<name>.feature.
#<path>/<file> Parse <path>/<file> for feature paths generated
by the rerun formatter.

Trying to run Kotlin script in IntelliJ IDEA

I am learning Kotlin by doing Kotlin Koans int IntelliJ EduKotlin plugin (https://plugins.jetbrains.com/plugin/8186). While doing tasks and running them im this plugin is working, I am not able to create new Kotlin script and run it without this plugin.
Sample code in a file named Hello.kt:
fun hello() : String {
return "ok"
}
Then I create new run configuration derived from 'Kotlin script', set 'Working directory' to ProjectName/src folder (or ProjectName folder, same result) and IDE shows me a 'Could not find script file: Hello.kt' warning as in the screen below:
And indeed, while trying to run script I got following stacktrace:
"C:\Program Files\Java\jdk1.8.0_74\bin\java" -Dfile.encoding=windows-1250 -classpath C:\Users\myUser\.IdeaIC2016\config\plugins\Kotlin\kotlinc\lib\kotlin-compiler.jar;C:\Users\myUser\.IdeaIC2016\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;C:\Users\myUser\.IdeaIC2016\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar org.jetbrains.kotlin.cli.jvm.K2JVMCompiler -script Hello.kt
exception: java.lang.RuntimeException: Failed to evaluate script: kotlin.KotlinNullPointerException
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileScript(KotlinToJVMBytecodeCompiler.kt:263)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileAndExecuteScript(KotlinToJVMBytecodeCompiler.kt:212)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:181)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:49)
at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:181)
at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:138)
at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:57)
at org.jetbrains.kotlin.cli.common.CLICompiler.doMainNoExit(CLICompiler.java:248)
at org.jetbrains.kotlin.cli.common.CLICompiler.doMain(CLICompiler.java:238)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler$Companion.main(K2JVMCompiler.kt:248)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.main(K2JVMCompiler.kt)
Caused by: kotlin.KotlinNullPointerException
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileScript(KotlinToJVMBytecodeCompiler.kt:475)
... 10 more
Process finished with exit code 2
What more, the hello method is marked as never used. However, when I change file extension from .kt to .ktscript, then this method is marked as used, and the output from running code is following:
"C:\Program Files\Java\jdk1.8.0_74\bin\java" -Dfile.encoding=windows-1250 -classpath C:\Users\myUser\.IdeaIC2016\config\plugins\Kotlin\kotlinc\lib\kotlin-compiler.jar;C:\Users\myUser\.IdeaIC2016\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;C:\Users\myUser\.IdeaIC2016\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar org.jetbrains.kotlin.cli.jvm.K2JVMCompiler -script Hello.kt
error: source file or directory not found: Hello.kt
Process finished with exit code 1
So my question is: what am I missing when trying to create and run Kotlin code in a standalone Kotlin script in IntelliJ?
A standalone Kotlin script file needs to have a .kts extension. If you rename your file, you also need to make sure that your run configuration is updated to refer to the new name of the file.
Also, if you create any file (a regular Kotlin file or a .kts file) which only contains a function, running the script will not produce any output, because the function will not be called. To see some output, you need to call the function in your script:
fun hello(): String {
return "ok"
}
println(hello())
The stacktrace that you saw is a bug in Kotlin.

Sbt plugin for jruby

Is there a plugin for sbt available which automatically installs JRuby and adds some hooks to automatically run scripts at certain points (e.g. before compilation).
Background: For a (lift) project, I want to use sass, or more specifically, compass as a tool for generating the css. A Java or Scala clone of sass would not be enough, unfortunately.
Of course, It wouldn’t be a problem at all to just generate the css manually and then put both inside the repository and no-one ever needs to care about it.
On the other hand, to ease development on several systems, I’d rather have a clear dependency inside sbt which simply does the work.
Is there any way to achieve this?
Or generally: Is there a way to run JRuby scripts from inside Scala?
Edit Added maven-2 to the tags. Maybe there is a maven repo for JRuby which allows me to deliver and use it somehow.
While it's perhaps not the most elegant solution, you can always call external scripts using the Process support in SBT.
import sbt._
import Process._
class Project(info: ProjectInfo) extends DefaultProject(info) {
lazy val runSomething = task {
"ruby somescript.rb" ! log
None
}
}
There's a bit more info about the external process support available here: http://code.google.com/p/simple-build-tool/wiki/Process
Try my sbt plugin from github. It's very bare-bones for now, but it should download the jruby jar and allow you to call a .rb file before compiling.
The guts of the plugin are really simple:
import sbt._
object SbtJRuby extends Plugin {
object SbtJRubySettings {
lazy val settings = Seq(Keys.commands += jirb, tx, jrubyFile := file("fnord.rb"))
}
def jirb = Command.args("jirb", "<launch jirb>") { (state, args) =>
org.jruby.Main.main(List("-S", "jirb").toArray[String])
state
}
val jruby = TaskKey[Unit]("jruby", "run a jruby file")
val jrubyFile = SettingKey[File]("jruby-file", "path to file to run with JRuby")
val tx = jruby <<= (jrubyFile, Keys.baseDirectory) map { (f: File, b: File) =>
val rb = (b / f.toString).toString
// println("jruby with " + rb)
org.jruby.Main.main(List(rb).toArray[String])
}
}
Really all it's doing is calling the jruby jar file with the name of the rb file you've passed in. And of course adding jruby itself as a managed dependency:
libraryDependencies ++= Seq(
"org.jruby" % "jruby-complete" % "1.6.5"
)
It also adds a "jirb" command to the Scala console that puts you into a jirb session.