diff --git a/.gitignore b/.gitignore index 7c3fce7f..3318135e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ bin *.iml .idea local.properties +/.nb-gradle/ \ No newline at end of file diff --git a/buildscript.gradle b/buildscript.gradle index f2e146aa..9ca2fbb9 100644 --- a/buildscript.gradle +++ b/buildscript.gradle @@ -38,9 +38,6 @@ rootProject.buildscript { url rosMavenRepository } } - maven { - url "https://github.com/rosjava/rosjava_mvn_repo/raw/master" - } jcenter() } dependencies { diff --git a/gradle_plugins/src/main/groovy/org/ros/gradle_plugins/CatkinPlugin.groovy b/gradle_plugins/src/main/groovy/org/ros/gradle_plugins/CatkinPlugin.groovy index 5ef5bf21..56f3f996 100644 --- a/gradle_plugins/src/main/groovy/org/ros/gradle_plugins/CatkinPlugin.groovy +++ b/gradle_plugins/src/main/groovy/org/ros/gradle_plugins/CatkinPlugin.groovy @@ -58,17 +58,21 @@ class CatkinPlugin implements Plugin { } setTasks() } - def void setTasks() { - project.task('catkinPackageInfo') << { - println("CatkinPlugin is happy, you should be too.") - println("Catkin Workspaces........." + project.catkin.workspaces) - println("Catkin Packages") - project.catkin.packages.each { pkg -> - print pkg.value.toString() - } - } - } + + def void setTasks() { + project.task('catkinPackageInfo') << { + println("CatkinPlugin is happy, you should be too.") + println("Catkin Workspaces........." + project.catkin.workspaces) + println("Catkin Packages") + project.catkin.packages.each { pkg -> + print pkg.value.toString() + } + } + } + } + + class CatkinPluginExtension { CatkinPackage pkg List workspaces @@ -90,8 +94,7 @@ class CatkinPackages { void generate() { if (pkgs.size() == 0) { workspaces.each { workspace -> - def manifestTree = project.fileTree(dir: workspace, - include: "**/package.xml") + def manifestTree = project.fileTree(dir: workspace, include: "**/package.xml") manifestTree.each { file -> def pkg = new CatkinPackage(project, file) if(this.pkgs.containsKey(pkg.name)) { @@ -146,7 +149,7 @@ class CatkinPackages { generateSourcesTask.description = "Generate sources for " + pkg.name generateSourcesTask.outputs.dir(project.file(generatedSourcesDir)) /* generateSourcesTask.args = new ArrayList([generatedSourcesDir, pkg.name]) */ - generateSourcesTask.args = new ArrayList([generatedSourcesDir, '--package-path=' + pkg.directory, pkg.name]) + generateSourcesTask.args = new ArrayList(['--output-path', generatedSourcesDir, '--package-path', pkg.directory, '--package-names', pkg.name]) generateSourcesTask.classpath = project.configurations.runtime generateSourcesTask.main = "org.ros.internal.message.GenerateInterfaces" project.tasks.compileJava.source generateSourcesTask.outputs.files diff --git a/message_generation/build.gradle b/message_generation/build.gradle index 98680066..070bf43a 100644 --- a/message_generation/build.gradle +++ b/message_generation/build.gradle @@ -34,6 +34,7 @@ dependencies { compile 'org.apache.commons:com.springsource.org.apache.commons.io:1.4.0' compile 'commons-pool:commons-pool:1.6' compile 'org.apache.commons:com.springsource.org.apache.commons.lang:2.4.0' + compile group: 'args4j', name: 'args4j', version: '2.0.16' compile project(':gradle_plugins') testCompile 'junit:junit:4.8.2' } diff --git a/message_generation/src/main/java/org/ros/internal/message/GenerateInterfaces.java b/message_generation/src/main/java/org/ros/internal/message/GenerateInterfaces.java index 64a16c89..d3e40752 100644 --- a/message_generation/src/main/java/org/ros/internal/message/GenerateInterfaces.java +++ b/message_generation/src/main/java/org/ros/internal/message/GenerateInterfaces.java @@ -13,7 +13,6 @@ * License for the specific language governing permissions and limitations under * the License. */ - package org.ros.internal.message; import com.google.common.collect.Lists; @@ -29,154 +28,192 @@ import org.ros.message.MessageFactory; import org.ros.message.MessageIdentifier; +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.Option; + import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.ListIterator; +import org.kohsuke.args4j.spi.StringArrayOptionHandler; /** * @author damonkohler@google.com (Damon Kohler) */ public class GenerateInterfaces { - private final TopicDefinitionFileProvider topicDefinitionFileProvider; - private final ServiceDefinitionFileProvider serviceDefinitionFileProvider; - private final MessageDefinitionProviderChain messageDefinitionProviderChain; - private final MessageFactory messageFactory; - static private final String ROS_PACKAGE_PATH = "ROS_PACKAGE_PATH"; - - public GenerateInterfaces() { - messageDefinitionProviderChain = new MessageDefinitionProviderChain(); - topicDefinitionFileProvider = new TopicDefinitionFileProvider(); - messageDefinitionProviderChain.addMessageDefinitionProvider(topicDefinitionFileProvider); - serviceDefinitionFileProvider = new ServiceDefinitionFileProvider(); - messageDefinitionProviderChain.addMessageDefinitionProvider(serviceDefinitionFileProvider); - messageFactory = new DefaultMessageFactory(messageDefinitionProviderChain); - } - - /** - * @param packages - * a list of packages containing the topic types to generate - * interfaces for - * @param outputDirectory - * the directory to write the generated interfaces to - * @throws IOException - */ - private void writeTopicInterfaces(File outputDirectory, Collection packages) - throws IOException { - Collection topicTypes = Sets.newHashSet(); - if (packages.size() == 0) { - packages = topicDefinitionFileProvider.getPackages(); - } - for (String pkg : packages) { - Collection messageIdentifiers = - topicDefinitionFileProvider.getMessageIdentifiersByPackage(pkg); - if (messageIdentifiers != null) { - topicTypes.addAll(messageIdentifiers); - } - } - for (MessageIdentifier topicType : topicTypes) { - String definition = messageDefinitionProviderChain.get(topicType.getType()); - MessageDeclaration messageDeclaration = new MessageDeclaration(topicType, definition); - writeInterface(messageDeclaration, outputDirectory, true); - } - } - - /** - * @param packages - * a list of packages containing the topic types to generate - * interfaces for - * @param outputDirectory - * the directory to write the generated interfaces to - * @throws IOException - */ - private void writeServiceInterfaces(File outputDirectory, Collection packages) - throws IOException { - Collection serviceTypes = Sets.newHashSet(); - if (packages.size() == 0) { - packages = serviceDefinitionFileProvider.getPackages(); - } - for (String pkg : packages) { - Collection messageIdentifiers = - serviceDefinitionFileProvider.getMessageIdentifiersByPackage(pkg); - if (messageIdentifiers != null) { - serviceTypes.addAll(messageIdentifiers); - } - } - for (MessageIdentifier serviceType : serviceTypes) { - String definition = messageDefinitionProviderChain.get(serviceType.getType()); - MessageDeclaration serviceDeclaration = - MessageDeclaration.of(serviceType.getType(), definition); - writeInterface(serviceDeclaration, outputDirectory, false); - List requestAndResponse = MessageDefinitionTupleParser.parse(definition, 2); - MessageDeclaration requestDeclaration = - MessageDeclaration.of(serviceType.getType() + "Request", requestAndResponse.get(0)); - MessageDeclaration responseDeclaration = - MessageDeclaration.of(serviceType.getType() + "Response", requestAndResponse.get(1)); - writeInterface(requestDeclaration, outputDirectory, true); - writeInterface(responseDeclaration, outputDirectory, true); - } - } - - private void writeInterface(MessageDeclaration messageDeclaration, File outputDirectory, - boolean addConstantsAndMethods) { - MessageInterfaceBuilder builder = new MessageInterfaceBuilder(); - builder.setPackageName(messageDeclaration.getPackage()); - builder.setInterfaceName(messageDeclaration.getName()); - builder.setMessageDeclaration(messageDeclaration); - builder.setAddConstantsAndMethods(addConstantsAndMethods); - try { - String content; - content = builder.build(messageFactory); - File file = new File(outputDirectory, messageDeclaration.getType() + ".java"); - FileUtils.writeStringToFile(file, content); - } catch (Exception e) { - System.out.printf("Failed to generate interface for %s.\n", messageDeclaration.getType()); - e.printStackTrace(); + private final TopicDefinitionFileProvider topicDefinitionFileProvider = new TopicDefinitionFileProvider(); + private final ServiceDefinitionFileProvider serviceDefinitionFileProvider = new ServiceDefinitionFileProvider(); + private final MessageDefinitionProviderChain messageDefinitionProviderChain = new MessageDefinitionProviderChain(); + private final MessageFactory messageFactory; + + static private final String ROS_PACKAGE_PATH = "ROS_PACKAGE_PATH"; + + @Option(name = "-p", aliases = {"--package-path"}, metaVar = "PATH", + usage = "path to packages, default is env(" + ROS_PACKAGE_PATH + ")") + private String packagePath = System.getenv(ROS_PACKAGE_PATH); + @Option(name = "-o", aliases = {"--output-path"}, metaVar = "DIRECTORY", usage = "output path, default is .") + private File outputPath = new File("."); + @Option(name = "-n", aliases = {"--package-names"}, handler = StringArrayOptionHandler.class, + usage = "names of the packages") + private String[] packageNames; + @Option(name = "--help", usage = "show help output") + private boolean help = false; + + public GenerateInterfaces(String[] args) { + + messageDefinitionProviderChain.addMessageDefinitionProvider(topicDefinitionFileProvider); + messageDefinitionProviderChain.addMessageDefinitionProvider(serviceDefinitionFileProvider); + messageFactory = new DefaultMessageFactory(messageDefinitionProviderChain); + + CmdLineParser parser = new CmdLineParser(this); + + try { + parser.setUsageWidth(80); + parser.parseArgument(args); + } catch (CmdLineException e) { + System.err.println(e.getMessage()); + System.out.println("GenerateInterfaces [options...] arguments..."); + parser.printUsage(System.err); + System.err.println(); + return; + } + + if (help) { + System.out.println("GenerateInterfaces [options...] arguments..."); + parser.printUsage(System.out); + System.out.println(); + return; + } + + Collection packagePaths = Lists.newArrayList(); + for (String path : packagePath.split(File.pathSeparator)) { + File packageDirectory = new File(path); + if (packageDirectory.exists()) { + packagePaths.add(packageDirectory); + } + } + + List arguments = Lists.newArrayList(packageNames); + this.generate(outputPath, arguments, packagePaths); + } - } - public void generate(File outputDirectory, Collection packages, - Collection packagePath) { - for (File directory : packagePath) { - topicDefinitionFileProvider.addDirectory(directory); - serviceDefinitionFileProvider.addDirectory(directory); + /** + * @param packages a list of packages containing the topic types to generate interfaces for + * @param outputDirectory the directory to write the generated interfaces to + * @throws IOException + */ + private void writeTopicInterfaces(File outputDirectory, Collection packages) + throws IOException { + Collection topicTypes = Sets.newHashSet(); + + if (packages.isEmpty()) { + packages = topicDefinitionFileProvider.getPackages(); + System.out.println("no pkg given, generate all"); + } + for (String pkg : packages) { + Collection messageIdentifiers + = topicDefinitionFileProvider.getMessageIdentifiersByPackage(pkg); + if (messageIdentifiers != null) { + topicTypes.addAll(messageIdentifiers); + } + } + for (MessageIdentifier topicType : topicTypes) { + String definition = messageDefinitionProviderChain.get(topicType.getType()); + MessageDeclaration messageDeclaration = new MessageDeclaration(topicType, definition); + writeInterface(messageDeclaration, outputDirectory, true); + } } - topicDefinitionFileProvider.update(); - serviceDefinitionFileProvider.update(); - try { - writeTopicInterfaces(outputDirectory, packages); - writeServiceInterfaces(outputDirectory, packages); - } catch (IOException e) { - throw new RosMessageRuntimeException(e); + + /** + * @param packages a list of packages containing the topic types to generate interfaces for + * @param outputDirectory the directory to write the generated interfaces to + * @throws IOException + */ + private void writeServiceInterfaces(File outputDirectory, Collection packages) + throws IOException { + Collection serviceTypes = Sets.newHashSet(); + if (packages.isEmpty()) { + packages = serviceDefinitionFileProvider.getPackages(); + } + for (String pkg : packages) { + Collection messageIdentifiers + = serviceDefinitionFileProvider.getMessageIdentifiersByPackage(pkg); + if (messageIdentifiers != null) { + serviceTypes.addAll(messageIdentifiers); + } + } + for (MessageIdentifier serviceType : serviceTypes) { + String definition = messageDefinitionProviderChain.get(serviceType.getType()); + MessageDeclaration serviceDeclaration + = MessageDeclaration.of(serviceType.getType(), definition); + writeInterface(serviceDeclaration, outputDirectory, false); + List requestAndResponse = MessageDefinitionTupleParser.parse(definition, 2); + MessageDeclaration requestDeclaration + = MessageDeclaration.of(serviceType.getType() + "Request", requestAndResponse.get(0)); + MessageDeclaration responseDeclaration + = MessageDeclaration.of(serviceType.getType() + "Response", requestAndResponse.get(1)); + writeInterface(requestDeclaration, outputDirectory, true); + writeInterface(responseDeclaration, outputDirectory, true); + } } - } - public static void main(String[] args) { - List arguments = Lists.newArrayList(args); - if (arguments.size() == 0) { - arguments.add("."); + private void writeInterface(MessageDeclaration messageDeclaration, File outputDirectory, + boolean addConstantsAndMethods) { + MessageInterfaceBuilder builder = new MessageInterfaceBuilder(); + builder.setPackageName(messageDeclaration.getPackage()); + builder.setInterfaceName(messageDeclaration.getName()); + builder.setMessageDeclaration(messageDeclaration); + builder.setAddConstantsAndMethods(addConstantsAndMethods); + try { + String content; + content = builder.build(messageFactory); + File file = new File(outputDirectory, messageDeclaration.getType() + ".java"); + FileUtils.writeStringToFile(file, content); + System.out.println("Generate Interface for " + messageDeclaration.getType()); + } catch (Exception e) { + System.out.printf("Failed to generate interface for %s.\n", messageDeclaration.getType()); + e.printStackTrace(); + } } - String rosPackagePath = System.getenv(ROS_PACKAGE_PATH); - // Overwrite with a supplied package path if specified (--package-path=) - for (ListIterator iter = arguments.listIterator(); iter.hasNext(); ) { - String arg = iter.next(); - if (arg.contains("--package-path=")) { - rosPackagePath = arg.replace("--package-path=", ""); - iter.remove(); - break; - } + + private void generate(File outputDirectory, Collection packages, Collection packagePath) { + for (File directory : packagePath) { + topicDefinitionFileProvider.addDirectory(directory); + serviceDefinitionFileProvider.addDirectory(directory); + } + + if (packages.size() == 1 && packagePath.size() == 1) { + String pkg = (String) packages.toArray()[0]; + File pkgp = (File) packagePath.toArray()[0]; + System.out.println("single pkg generate, force pkg to " + pkg + " , with path:" + pkgp.getPath()); + topicDefinitionFileProvider.updateOnePKG(pkg); + serviceDefinitionFileProvider.updateOnePKG(pkg); + + } else { + topicDefinitionFileProvider.update(); + serviceDefinitionFileProvider.update(); + } + + for(String pkg : packages) { + boolean empty = topicDefinitionFileProvider.getMessageIdentifiersByPackage(pkg).isEmpty(); + empty &= serviceDefinitionFileProvider.getMessageIdentifiersByPackage(pkg).isEmpty(); + if(empty) System.err.println("No Interfaces found for pkg: " + pkg); + } + + try { + writeTopicInterfaces(outputDirectory, packages); + writeServiceInterfaces(outputDirectory, packages); + } catch (IOException e) { + throw new RosMessageRuntimeException(e); + } } - Collection packagePath = Lists.newArrayList(); - for (String path : rosPackagePath.split(File.pathSeparator)) { - File packageDirectory = new File(path); - if (packageDirectory.exists()) { - packagePath.add(packageDirectory); - } + + public static void main(String[] args) { + + GenerateInterfaces generateInterfaces = new GenerateInterfaces(args); } - GenerateInterfaces generateInterfaces = new GenerateInterfaces(); - File outputDirectory = new File(arguments.remove(0)); - generateInterfaces.generate(outputDirectory, arguments, packagePath); - } } diff --git a/message_generation/src/main/java/org/ros/internal/message/definition/MessageDefinitionFileProvider.java b/message_generation/src/main/java/org/ros/internal/message/definition/MessageDefinitionFileProvider.java index 4aa03891..45eaa958 100644 --- a/message_generation/src/main/java/org/ros/internal/message/definition/MessageDefinitionFileProvider.java +++ b/message_generation/src/main/java/org/ros/internal/message/definition/MessageDefinitionFileProvider.java @@ -25,8 +25,10 @@ import org.ros.message.MessageIdentifier; import java.io.File; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -63,7 +65,7 @@ private static MessageIdentifier fileToMessageIdentifier(File file) { private void addDefinition(File file, String definition) { MessageIdentifier topicType = fileToMessageIdentifier(file); if (definitions.containsKey(topicType.getType())) { - // First definition wins. + System.err.println("multiple defs"); return; } definitions.put(topicType.getType(), definition); @@ -72,18 +74,41 @@ private void addDefinition(File file, String definition) { } messageIdentifiers.get(topicType.getPackage()).add(topicType); } + + private void addDefinition(File file, String definition, String fixedPkg) { + MessageIdentifier topicType = fileToMessageIdentifier(file); + topicType.setPackage(fixedPkg); + if (definitions.containsKey(topicType.getType())) { + System.err.println("multiple defs"); + return; + } + definitions.put(topicType.getType(), definition); + if (!messageIdentifiers.containsKey(fixedPkg)) { + messageIdentifiers.put(fixedPkg, new HashSet()); + } + messageIdentifiers.get(fixedPkg).add(topicType); + } /** * Updates the topic definition cache. * * @see StringFileProvider#update() */ - public void update() { - stringFileProvider.update(); - for (Entry entry : stringFileProvider.getStrings().entrySet()) { - addDefinition(entry.getKey(), entry.getValue()); + public void update() { + stringFileProvider.update(); + for (Entry entry : stringFileProvider.getStrings().entrySet()) { + //System.out.println("have definition: " + entry.getKey() + " : " + entry.getValue()); + addDefinition(entry.getKey(), entry.getValue()); + } + } + + public void updateOnePKG(String pkgname) { + stringFileProvider.update(); + for (Entry entry : stringFileProvider.getStrings().entrySet()) { + // System.out.println("have definition: " + entry.getKey() + " : " + entry.getValue()); + addDefinition(entry.getKey(), entry.getValue(), pkgname); + } } - } /** * @see StringFileProvider#addDirectory(File) @@ -99,7 +124,7 @@ public Collection getPackages() { @Override public Collection getMessageIdentifiersByPackage(String pkg) { - return messageIdentifiers.get(pkg); + return messageIdentifiers.getOrDefault(pkg, new ArrayList()); } @Override diff --git a/message_generation/src/main/java/org/ros/message/MessageIdentifier.java b/message_generation/src/main/java/org/ros/message/MessageIdentifier.java index 9895c39e..4d64d7fe 100644 --- a/message_generation/src/main/java/org/ros/message/MessageIdentifier.java +++ b/message_generation/src/main/java/org/ros/message/MessageIdentifier.java @@ -74,6 +74,11 @@ private void splitType() { pkg = packageAndName[0]; name = packageAndName[1]; } + + + public void setPackage(String pkg) { + this.pkg = pkg; + } public String getPackage() { if (pkg == null) {