Hello,
I am using one of the recent nightly builds of gradle, and I am trying to create a plugin for transforming yacc grammars to C/C++ source code. In the build.gradle file, I would like to be able to have something like:
model {
components {
mylibrary(NativeLibrarySpec) {
binaries.all {
cppCompiler.args Config.includePaths(project,"mylibrary")
}
sources {
cpp {
source {
include '**/*.cc'
}
yacc {
source { include '**/*.y' }
}
}
}
}
}
but I am having trouble figuring out how to register the LanguageSourceSet factory from the plugin class. I think DefaultPolymorphicDomainObjectContainer is looking for a registered factory for YaccLanguageSourceSet when the ‘yacc’ name is encountered. The error I get is:
Cannot create a LanguageSourceSet named ‘yacc’ because this container does not support creating elements by name alone. Please specify which subtype of LanguageSourceSet to create. Known subtypes are: CppSourceSet, JvmResourceSet, YaccLanguageSourceSet
I have used the Scala plugin as a model for how to structure the plugin et al. but right now I am just trying to figure out how to have a plugin which gets a SourceSet from the build.gradle file on a per-cpp-library basis. FWIW my plugin code is below. I know the JVM compilation model is wrong for YACC, but the scala plugin seemed to be well ordered and I am really just trying to get a ‘*.y’ SourceSet where I can (1) pass it through bison and then (2) add the output to the C/C++ SourceSet.
I have a lot of these transformational plugins to do, e.g. XML to C++, XML to LaTeX, etc. so I am really trying to do it right.
Thanks very much for any advice or tips Darrell
class YaccLanguagePlugin implements Plugin<Project> {
def void apply(Project project) {
project.getPluginManager().apply(ComponentModelBasePlugin.class);
project.getPluginManager().apply(JvmResourcesPlugin.class);
}
/**
* Model rules.
*/
@SuppressWarnings("UnusedDeclaration")
static class Rules extends RuleSource {
@Model
YaccToolChain yaccToolChain(ServiceRegistry serviceRegistry) {
return serviceRegistry.get(YaccToolChain.class);
}
@LanguageType
void registerLanguage(LanguageTypeBuilder<YaccLanguageSourceSet> builder) {
builder.setLanguageName("yacc");
builder.defaultImplementation(DefaultYaccLanguageSourceSet.class);
}
@Mutate
void registerLanguageTransform(LanguageTransformContainer languages, ServiceRegistry serviceRegistry) {
languages.add(new Yacc());
}
}
private static class Yacc implements LanguageTransform<YaccLanguageSourceSet, JvmByteCode> {
public Class<YaccLanguageSourceSet> getSourceSetType() {
return YaccLanguageSourceSet.class;
}
public Map<String, Class<?>> getBinaryTools() {
return Collections.emptyMap();
}
public Class<JvmByteCode> getOutputType() {
return JvmByteCode.class;
}
public SourceTransformTaskConfig getTransformTask() {
return new SourceTransformTaskConfig() {
public String getTaskPrefix() {
return "compile";
}
public Class<? extends DefaultTask> getTaskType() {
return PlatformYaccCompile.class;
}
public void configureTask(Task task, BinarySpec binarySpec, LanguageSourceSet sourceSet) {
PlatformYaccCompile compile = (PlatformYaccCompile) task;
YaccLanguageSourceSet yaccSourceSet = (YaccLanguageSourceSet) sourceSet;
JvmBinarySpec binary = (JvmBinarySpec) binarySpec;
JavaPlatform javaPlatform = binary.getTargetPlatform();
// TODO RG resolve the yacc platform from the binary
compile.setPlatform(new DefaultYaccPlatform("2.10.4"));
File analysisFile = new File(task.getTemporaryDir(), String.format("compilerAnalysis/%s.analysis", task.getName()));
compile.getYaccCompileOptions().getIncrementalOptions().setAnalysisFile(analysisFile);
compile.setDescription(String.format("Compiles %s.", yaccSourceSet));
compile.setDestinationDir(binary.getClassesDir());
compile.setSource(yaccSourceSet.getSource());
compile.setClasspath(yaccSourceSet.getCompileClasspath().getFiles());
compile.setTargetCompatibility(javaPlatform.getTargetCompatibility().toString());
compile.setSourceCompatibility(javaPlatform.getTargetCompatibility().toString());
compile.dependsOn(yaccSourceSet);
binary.getTasks().getJar().dependsOn(compile);
}
};
}
public boolean applyToBinary(BinarySpec binary) {
return binary instanceof JvmBinarySpec;
}
}
}