How to pass command line arguments to a task? - command-line-arguments

How do I pass command line arguments to a nimble task? For example, say I have the task
task mytask, "my task":
echo &"my task {args}"
When I run
nimble mytask --foo --bar
I would like nimble to output
mytask --foo --bar
or something like that.

from nimble documentation (i.e. github's README.md):
Tasks support two kinds of flags: nimble <compflags> task <runflags>. Compile flags are those specified before the task name and are forwarded to the Nim compiler that runs the .nimble task. This enables setting --define:xxx values that can be checked with when defined(xxx) in the task, and other compiler flags that are applicable in Nimscript mode. Run flags are those after the task name and are available as command-line arguments to the task. They can be accessed per usual from commandLineParams: seq[string].
commandLineParams is available in std/os. For your example:
import std / [os, strformat]
task mytask, "my task":
echo &"my task {commandLineParams()}"
Update:
Setting up a new nimble project with the above code added and running:
nimble mytask --foo --bar
you will actually find that it prints a nim sequence with ALL arguments and not only the runtime flags. For example on Windows and anonymizing specific folder names:
my task #["e", "--hints:off", "--verbosity:0", "--colors:on", "XXX\\nimblecache-0\\test_nimble_2483249703\\test_nimble.nims", "XXY\\test_nimble\\test_nimble.nimble", "XXZ\\nimble_23136.out", "mytask", "--foo", "--bar"]
So in order to get only --foo and --bar you need to select arguments after mytask
Note: we probably should fix nimble docs about that.

Passing just the right arguments:
proc forward_args(task_name: string): seq[string] =
let args = command_line_params()
let arg_start = args.find(task_name) + 1
return args[arg_start..^1]
task dev, "Start the project in dev mode":
const params = forward_args("dev").join(" ")
exec &"nimble run {bin[0]} {params} --silent"

Related

Why does Gradle's javaexec behave differently from running Java directly?

I am trying to integrate the generation of REST-API client code via the openapi-generator through Gradle. Using the openapi-generator-gradle-plugin at first, I found some bugs that make it impossible to achieve what I want, so I thought I might just download the JAR of the openapi-generator-cli in order to define a Gradle task with javaExec that will execute the generator for me.
The task looks is defined as:
build.gradle.kts
task("generate") {
javaexec {
main = "-jar"
args = listOf(
"$rootDir\\openapi-generator-cli.jar",
"generate",
"--skip-validate-spec",
"-g kotlin",
"-i $rootDir\\spec\\api.yml",
"-o $rootDir\\lib",
"-c $rootDir\\generate-kotlin.json"
)
}
}
However, when running the generate task, execution fails with
C:\work\kotlin\myapi\generate-kotlin.json (The filename, directory name, or volume label syntax is incorrect)
This is where things get strange, as I can see no issue with the path to the file in question.
I then activated debugging output for the task to see the actual command executed by Gradle. It is (formatted for readability):
C:\Program Files\Java\jdk1.8.0_202\bin\java.exe ^
-Dfile.encoding=windows-1252 ^
-Duser.country=DE ^
-Duser.language=de ^
-Duser.variant ^
-jar C:\work\kotlin\myapi\openapi-generator-cli.jar generate ^
--skip-validate-spec ^
-g kotlin ^
-i C:\work\kotlin\myapi\spec\api.yml ^
-o C:\work\kotlin\myapi\lib ^
-c C:\work\kotlin\myapi\generate-kotlin.json
To me, everything looks perfectly fine in that command. To test, I copy-pasted it to a CMD and it ran right away without any errors.
Despite the question being a bit centered around openapi-generator, as I can run the command perfectly fine manually, I assume this to be a problem with Gradle and would really like to know why it is receiving this error when the command it runs has no issues whatsoever?
I really don't want to write command-line scripts for people to execute when I could let Gradle do what I want to do.

Capistrano 2 - Pass array arguments to a Rake task

I am trying to write a Rake task in my deploy.rb that gets passed an array of arguments. I will run it through capistrano.
Assuming a task like the following:
desc "my task"
task :mytask, [:arguments] => :environment do |t, args|
puts 'hello'
end
When I try running cap mytask['arg1 arg2 arg3'], I get the following:
the task `mytask["arg1 arg2 arg3"]' does not exist
Any ideas? I have a task defined like this that I run locally with no problems, but defining tasks like this be run using cap does not work.
NOTE: running cap mytask without the arguments part works. This is obviously not what I want.
Rake tasks are defined by a string and called via Rake::Task["name"] internally . If cap treats your array as part of the task name string it will not work.
As 'mytask' != 'mytask["arg1 arg2 arg3"]'

Pass command line arguments to gradle

To start Java program, I can pass arguments like:
java Main arg1 arg2 arg3
What are the good ways to do that in gradle command line:
gradle startProgram arg1 arg2 arg3
And this is in build.gradle:
task startProgram(dependsOn: 'classes', type: JavaExec) {
main = 'Main'
classpath = sourceSets.main.runtimeClasspath
systemProperties = System.properties
}
Best way is to use java system properties (-D switch) but these are more 'global'. Instead You can use simple properties (-P switch) and get the passed values using instance of Project class.

Controlling Gradle task execution

In my build.gradle script, I have a lot of tasks, each depending on zero or more other tasks.
There are three 'main' tasks which can be called: moduleInstallation, backupFiles and restoreFiles.
Here's the question: I would like to be able to tell Gradle which tasks to execute and which don't need to execute. For example, when calling moduleInstallation, I want all depending tasks to execute (regardless of their UP-TO-DATE flag), but not the restore tasks. I've tried altering the phase in which the tasks get executed (e.g. config phase, execution phase,...) and a couple of other things, but all tasks just keep getting executed.
A solution I've thought of was just stating in the main tasks that, when this main task is called (f.e. moduleInstallation), we set the UP-TO-DATE flag of all non-related tasks to false, so they don't get executed. Is that possible?
EDIT: Here's an example:
When moduleInstallation is called (which depends on backupFiles), restoreFiles (which depends on restoreFromDate) is executed too.
First main action
task moduleInstallation << {
println "Hello from moduleInstallation"
}
task backupFiles {
doLast {
println "Hello from backupFiles"
}
}
Second main action
task restoreFiles {
println "Hello from restoreFiles"
}
task restoreFromDate {
println "Hello from restoreFromDate"
}
Dependencies:
moduleInstallation.dependsOn backupFiles
restoreFiles.dependsOn restoreFromDate
So when I type gradle moduleInstallation in the terminal, I get the following output:
Hello from restoreFromDate
Hello from restoreFiles
Hello from backupFiles
Hello from moduleInstallation
The second snippet has to use doLast (or its << shortcut) like the first snippet. Otherwise, the code is configuration code and will always be evaluated, no matter which tasks are eventually going to be executed. In other words, it's not the restoreFiles and restoreFromDate tasks that are being executed here (as one can tell from the bits of command line output that you don't show), but (only) their configuration code.
To better understand what's going on here (which is crucial for understanding Gradle), I recommend to study the Build Lifecycle chapter in the Gradle User Guide.

What is the difference between these task definition syntaxes in gradle?

A)
task build << {
description = "Build task."
ant.echo('build')
}
B)
task build {
description = "Build task."
ant.echo('build')
}
I notice that with type B, the code within the task seems to be executed when typing gradle -t - ant echoes out 'build' even when just listing all the various available tasks. The description is also actually displayed with type B. However, with type A no code is executed when listing out the available tasks, and the description is not displayed when executing gradle -t. The docs don't seem to go into the difference between these two syntaxes (that I've found), only that you can define a task either way.
The first syntax defines a task, and provides some code to be executed when the task executes. The second syntax defines a task, and provides some code to be executed straight away to configure the task. For example:
task build << { println 'this executes when build task is executed' }
task build { println 'this executes when the build script is executed' }
In fact, the first syntax is equivalent to:
task build { doLast { println 'this executes when build task is executed' } }
So, in your example above, for syntax A the description does not show up in gradle -t because the code which sets the description is not executed until the task executed, which does not happen when you run gradle -t.
For syntax B the code that does the ant.echo() is run for every invocation of gradle, including gradle -t
To provide both an action to execute and a description for the task you can do either of:
task build(description: 'some description') << { some code }
task build { description = 'some description'; doLast { some code } }

Resources