Scope of the extra properties in Gradle? - properties

I have a Gradle script similar to this:
ext {
dir = null
}
task init << {
build()
}
task buildAll(type: Exec){
workingDir ext.dir
commandLine 'cmd', '/c', "echo %JAVA_HOME%"
}
def build(){
ext.dir = "asdf"
buildAll.execute()
}
When I run the script, I get:
groovy.lang.MissingPropertyException: Cannot get property 'dir' on extra properties extension as it does not exist
Whatever I tried, I couldn't get a task to read a property from "ext". It can be seen from methods (like "build()" in my example), but not from any other task except the default one ("init" in my example).
I understand that the "ext" properties should be accessible from anywhere inside the project, so what am I doing wrong?
UPDATE:
The workflow I'm trying to achieve (as asked by Opal):
I have several environments I need to build with one script. Each of these environments is listed in a CSV file with a line: <environment>,<version>.
Script then needs to do the following:
Delete existing directory
Checkout code from SVN into new directory (both directory and SVN url depend on environment and version)
Copy some settings files (paths depend on version)
Edit some of those settings files (values depend on environment and version)
Set some environment variables (JAVA_HOME, ANT_HOME...) (depends on version)
Run three build commands (${ANT_HOME}/bin/ant -f $checkedOutCodeDirectory/Build/build-all.xml target1, then target2 and target3)
This needs to be executed for each environment

Extra properties should be created via ext but referred via project instance without any instance at all so: project.dir or dir, so the first change to script will be:
ext {
dir = null
}
task init << {
build()
}
task buildAll(type: Exec){
workingDir dir // ext.dir -> dir
commandLine 'cmd', '/c', "echo %JAVA_HOME%"
}
def build(){
ext.dir = "asdf"
buildAll.execute()
}
Now, before any task or method is executed the script is read and parsed, sot the whole body of buildAll will be configured before any other part is run. Thus it will always fail, since dir property has no value. Proof:
ext {
dir = null
}
task init << {
build()
}
task buildAll(type: Exec){
workingDir dir ? dir : project.rootDir
commandLine 'cmd', '/c', "echo %JAVA_HOME%"
}
def build(){
ext.dir = "asdf"
buildAll.execute()
}

Related

readLine() doesn't wait for user input in Kotlin/Native

Here is a simple script
fun main() {
print("ready> ")
val input = readLine()
println("User input: $input")
}
When I run this program with gradle runReleaseExecutableMacos I expect that I'll see a ready> prompt and will have a possibility to type some chars. But this program finishes immediately with User input: null as a result.
Am I missing something?
To achieve the behavior you desire, you can run the executable file produced by the Gradle. It will have an extension *.kexe.
Also, you can extend your build.gradle file with additional parameter. you got to add something like this:
macosX64("macos") {
binaries {
executable {
runTask.standardInput = System.in
}
}
}

Gradle task: how to wait for the file operation to complete

Here's what I'm trying to do:
Copy archive (zip) from buildscript dependencies to the temp directory
Unzip archive to another directory within build
Here's task to copy archive (works)
task copyTpcds(type: Copy) {
file('build/zip').mkdirs()
from buildscript.configurations.classpath
include 'tpcds*'
into 'build/zip'
}
And the task to unzip and then delete archive
task extractTpcds(type: Copy) {
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when
into outDir
// now remove copied zip file
//zipFile.delete() // deletes file before the extractions completes?
}
Here are few scenarios:
If I put both tasks into build.gradle and try to run anything, even just gradle tasks then I get this error: Neither path nor baseDir may be null or empty string. path='null' basedir='C:\dev\code\td\pdo\tpcds-tpg' from this code in the task #2: file(names[0])
If I comment out code in the 2nd task, 1st task would run and copy zip file to build/zip
Now I can uncomment code in the 2nd task (except deletion) and execute gradle extractTpcds it will run and extract the archive
So it seems to me that
File operations are evaluated across all tasks regardless of which tasks is executed
If I have a code that copies the file with some follow up code that tries to operate on the file being copied then that code will not wait for copy process to complete and will fail because file is not there yet
I'm at loss on how to deal with this and would greatly appreciate your suggestions
The following works for me, using Gradle 2.12 (and assuming that the zip file resides in files):
buildscript {
configurations {
classpath
}
dependencies {
classpath files("files/tpcds.zip")
}
}
def copyFiles = { ->
ant.mkdir(dir: "build/zip")
buildscript.configurations.classpath.each { def thisFile ->
if (thisFile.name ==~ /tpcds.*/) {
ant.copy(file: thisFile.absolutePath, todir: "build/zip")
}
}
}
tasks.whenTaskAdded { task ->
if (task.name == "extractTpcds") {
copyFiles()
}
}
task copyTpcds << {
copyFiles()
}
task extractTpcds(type: Copy) {
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when
into outDir
// now remove copied zip file
//zipFile.delete() // deletes file before the extractions completes?
}
An issue with the original involves an impedance mismatch vis-a-vis the ICE rule: Initialization phase, Configuration phase, and Execution phase. In particular, the specification of the Copy task is in Configuration phase; typically, task dependencies are enforced (e.g. dependsOn) during the Execution phase. The extractTpcds task has a dependency on other code during the Configuration phase.
In my example, there are are 2 cases:
gradle copyTpcds will call the copyFiles method during Execution phase. The << means "do this stuff last [during the Execution phase]".
gradle tasks will trigger the code in whenTaskAdded, during Configuration phase, and call copyFiles. Similarly for gradle extractTpcds
An alternative to this is simply to use the AntBuilder in both tasks, and avoid Type: Copy completely, as shown here:
buildscript {
configurations {
classpath
}
dependencies {
classpath files("files/tpcds.zip")
}
}
task copyTpcds << {
ant.mkdir(dir: "build/zip")
buildscript.configurations.classpath.each { def thisFile ->
if (thisFile.name ==~ /tpcds.*/) {
ant.copy(file: thisFile.absolutePath, todir: "build/zip")
}
}
}
task extractTpcds(dependsOn: 'copyTpcds') << {
def outDir = "build/cmd/tpcds"
ant.mkdir(dir: outDir)
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
names.eachWithIndex { zipFile, index ->
if (index == 0) {
ant.unzip(src: zipFile, dest: outDir)
}
}
}
Something like this should work, but why do you need to delete the zip? chaining the tasks with dependsOn means you only need to run the second task and the copyTpcds will automatically run unless the inputs or outputs have changed (deleted)
task extractTpcds(type: Copy) {
dependsOn(copyTpcds) //make this execute after
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when
into outDir
// now remove copied zip file
doLast { zipFile.delete() }// deletes file after the extractions completes
}

Typescript build error (TS5007)

I've been trying to get typescript building via the build servers on visualstudio.com, and I've done the normal thing of bringing typescript into source control. But I'm getting the following issue:
VSTSC : error TS5007: Build:
Cannot resolvereferenced file:
'COMPUTE_PATHS_ONLY'.
[C:\a\src\Main\RecruitCloud\RecruitCloud.csproj]
I'm aware of the encoding issues, but in all the examples I've seen the culprit file has been named in the error message.
I'm starting to think this could be down to the number of typescript files I'm compiling in the project.
Any ideas?
This is a configuration option for the VsTsc task, the one that runs the compiler. It is used in the PreComputeCompileTypeScript target. The intention is to make the VsTsc task go through all the motions, except to run the compiler. That didn't pan out on your machine, it actually did run the compiler. Which then threw a fit since it can't find a file named COMPUTE_PATHS_ONLY.
The VsTsc task is stored in C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\TypeScript\TypeScript.Tasks.dll. Looking at the assembly with a decompiler:
protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
if (this.Configurations.Contains("--sourcemap"))
{
this.generateSourceMaps = true;
}
else
{
this.generateSourceMaps = false;
}
if (this.Configurations.Contains("--declaration"))
{
this.generateDeclarations = true;
}
else
{
this.generateDeclarations = false;
}
this.GenerateOutputPaths();
if (!responseFileCommands.Contains("COMPUTE_PATHS_ONLY"))
{
return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
return 0;
}
Note the !responseFileCommands.Contains() test to bypass the base.ExecuteTool() call.
All I can guess is that the method doesn't look like this on your machine. With the most likely cause that you have an outdated version of TypeScript.Tasks.dll. On my machine with VS2013 Update 4 installed it is dated Nov 11, 2014 with a size of 27816 bytes.
Your best bet would be to simply resave all the files in Unicode encoding. You can do it from a quick powershell script (Change files' encoding recursively on Windows?)
Get-ChildItem *.txt | ForEach-Object {
$content = $_ | Get-Content
Set-Content -PassThru $_.Fullname $content -Encoding UTF8 -Force}

Executing SQL files using Groovy in Gradle

I have a bunch of sql files which I want to execute in my gradle build. I came up with this.
def sqlDir = new File('src/main/resources/')
task testSql << {
sqlDir.eachDirRecurse() { dir ->
dir.eachFileMatch(~/.*\.sql$/) {
// sql.execute(it.text)
println it
}
}
}
I however, also want to exclude some files, and I can probably do that using if blocks and hardcoding filenames inside the code. Can someone give me a cleaner solution to exclude files?
As you pointed, there is a [fileTree] solution in Gradle
You can use it somehow like that. Please refer link to details.
def sqlDir = file 'src/main/resources/'
task testSql << {
fileTree(dir: sqlDir, include: "**.sql", exclude: ["somefilename.sql", "otherfilename.sql"]).each {
sql.execute(it.text)
}
}

Run a terminal/shell in a SlickEdit window?

I'd like to run a bash shell in a 'normal' document window in Slick Edit.
At a minimum I'd be content with running a command and having all output captured into a document window. Better would be the ability to interactively work with the shell in that window.
This is a bit crude, but it is what I use for launching external programs
(including bash scripts). When I used to work in Win+Cygwin I also had a wrapper around the bash script but I forget why I needed that.
but remember that you can always tie specific actions to your project
(build, compile, etc), you can always add your own as well Project->Properties->Tools->New. All those commands can execute in the process window
#include "slick.sh"
static _str mytmp='/tmp/myvstmp.txt'
_command git_annotate(_str filename='') name_info(',' VSARG2_MACRO )
{
if (filename=='') {
filename=p_buf_name;
}
curr_line=p_line;
delete_file(mytmp); // make sure we dont get old file
if( file_match(mytmp,'1')==mytmp ) {
message('Tmp file delete failed! ('mytmp') change permissions and if still failing - restart vs');
return 1
}
shell('/usr/bin/git blame -s 'filename' | sed "s#^\(.\{8\}\) [^)]*) #\1 #" >'mytmp, 'p');
if( file_match(mytmp,'1')!=mytmp ) {
message('Annotate failed');
return 1
}
status=edit('-w 'mytmp);
if (status) {
message('Error opening output file for display.');
return 1
}
goto_line(curr_line+1);
// keep disk clean
p_buf_flags |= VSBUFFLAG_THROW_AWAY_CHANGES;
name("* annotate output *" filename, false);
delete_file(mytmp);
}