Copy Task after Linking

I am trying to perform a copy of the build artifacts after performing the linking for Native Executables. Attached is an excerpt from my build.gradle

	components {
		all {
			binaries.withType(SharedLibraryBinarySpec) {
				buildable = false 
			}
			binaries.withType(NativeExecutableBinarySpec) {
				tasks.withType(LinkExecutable) {		
					doFirst {
						outputFile = file("$buildDir/exe/${baseName}/${baseName}.o")
					}
					doLast {
						copy {
							from ("$buildDir/exe/${baseName}/")
							into "./objs_exe/exe/"
							include "*.o"
						}
					}
				}
			}
		}
	}

I would like to rename my linked executable and then copy it to another location. However, I get the error as

Attempt to modify a closed view of model element ‘components’ of type ‘ComponentSpecContainer’ given to rule model.components

This is a multi-project build and the above code is part of the root project’s build.gradle. The doFirst closure works without any issues. Also, I have applied the c plugin

Thanks Ganesh for providing a good example. However, when I tried your code, I didn’t get the same behavior. Everything succeeds as you would have expected. Could you provide a bit more context? If you could also provide a build scan, it would help a lot with the debugging.

If you would let me comment a bit on your code example, I would prefer changing the output file for the linked file through the NativeExecutableBinarySpec as oppose to using the outputFile property on LinkExecutable task. It cleaner this way. I would also be careful adding doLast action on typed task like LinkExecutable for transforming the output. In your case, I don’t see any problem but in order case, such as modifying the binary, the task can become forever out-of-date which will force the linking of the binary at every build. Depending what you are linking, this can be a significant performance hit.

Don’t hesitate to ask more question.

Daniel

Hi Daniel,

Thank you for the reply. The above code works fine when I have it inside the sub-project’s build.gradle but fails with the above error on the root project’s build.gradle. That is why I feel it is weird. I will try and share the build scan as soon as I can. But does Gradle provide a neat way of copying over the executables at the end of a link phase?What I thought would be nice was to make the Link Executable task dependOn a custom task of type Copy. But it raises the same error as the one above. I basically need to copy the generated artifact (in my case its a partially linked “.o” file) into another location. And i need this as a common behaviour for all my sub-projects.

Hi Ganesh,

In order to create post link task, you have to jam them between the binary lifecycle task (a task named the same way as the binary and that does nothing) and the LinkExecutable task. Basically, your copy task will dependsOn the linker task and the lifecycle task (named after your binary) dependsOn your copy task. This will ensure the linker has done it’s part before copying and that every time the binary is built, it will execute your copy task.

If you want to have a visual representation of your task to see what I’m talking about, I suggest having a look at the visteg plugin. It will enable you to create a picture of your task graph for a specific Gradle runs. Sometimes it helps to see your task layout.

Don’t hesitate to ask more questions,

Daniel