fix handling spaces in folder names (ros/catkin#375)

include(CMakeParseArguments)

macro(rosunit_initialize_tests)
@[if DEVELSPACE]@
  # find binary and scripts in develspace
  find_program(ROSUNIT_EXE rosunit
    PATHS "@(PROJECT_SOURCE_DIR)/scripts"
    NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
  if(NOT ROSUNIT_EXE)
    message(FATAL_ERROR "'rosunit' not found")
  endif()
  set(ROSUNIT_SCRIPTS_DIR @(PROJECT_SOURCE_DIR)/scripts)
@[else]@
  # find binary and scripts in installspace
  find_program(ROSUNIT_EXE rosunit
    PATHS "@(CMAKE_INSTALL_PREFIX)/bin"
    NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
  if(NOT ROSUNIT_EXE)
    message(FATAL_ERROR "'rosunit' not found")
  endif()
  set(ROSUNIT_SCRIPTS_DIR @(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts)
@[end if]@
endmacro()

rosunit_initialize_tests()

function(add_pyunit file)

  message(WARNING "add_pyunit() is deprecated.  For Python tests, use catkin_add_nosetests() instead.")

  # Look for optional TIMEOUT argument, #2645
  cmake_parse_arguments(_pyunit "" "TIMEOUT;WORKING_DIRECTORY" "" ${ARGN})
  if(NOT _pyunit_TIMEOUT)
    set(_pyunit_TIMEOUT 60.0)
  endif()

  # Check that the file exists, #1621
  set(_file_name _file_name-NOTFOUND)
  if(IS_ABSOLUTE ${file})
    set(_file_name ${file})
  else()
    find_file(_file_name ${file}
              PATHS ${CMAKE_CURRENT_SOURCE_DIR}
              NO_DEFAULT_PATH
              NO_CMAKE_FIND_ROOT_PATH)  # for cross-compilation.  thanks jeremy.
    if(NOT _file_name)
      message(FATAL_ERROR "Can't find pyunit file \"${file}\"")
    endif()
  endif()

  # We look for ROS_TEST_COVERAGE=1
  # to indicate that coverage reports are being requested.
  if("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1")
    set(_covarg "--cov")
  else()
    set(_covarg)
  endif()

  # Create a legal test name, in case the target name has slashes in it
  string(REPLACE "/" "_" _testname ${file})
  # We use rostest to call the executable to get process control, #1629
  set(cmd "${ROSUNIT_EXE} --name=${_testname} --time-limit=${_pyunit_TIMEOUT} --package=${PROJECT_NAME} -- ${_file_name} ${_covarg}")
  catkin_run_tests_target("rosunit" ${_testname} "rosunit-${_testname}.xml" COMMAND ${cmd} WORKING_DIRECTORY ${_pyunit_WORKING_DIRECTORY})
endfunction()

include(CMakeParseArguments)

macro(rosunit_initialize_tests)
@[if DEVELSPACE]@
  # find binary and scripts in develspace
  find_program(ROSUNIT_EXE rosunit
    PATHS @(PROJECT_SOURCE_DIR)/scripts
    NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
  if(NOT ROSUNIT_EXE)
    message(FATAL_ERROR "'rosunit' not found")
  endif()
  set(ROSUNIT_SCRIPTS_DIR @(PROJECT_SOURCE_DIR)/scripts)
@[else]@
  # find binary and scripts in installspace
  find_program(ROSUNIT_EXE rosunit
    PATHS @(CMAKE_INSTALL_PREFIX)/bin
    NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
  if(NOT ROSUNIT_EXE)
    message(FATAL_ERROR "'rosunit' not found")
  endif()
  set(ROSUNIT_SCRIPTS_DIR @(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts)
@[end if]@
endmacro()

rosunit_initialize_tests()

function(add_pyunit file)

  message(WARNING "add_pyunit() is deprecated.  For Python tests, use catkin_add_nosetests() instead.")

  # Look for optional TIMEOUT argument, #2645
  cmake_parse_arguments(_pyunit "" "TIMEOUT;WORKING_DIRECTORY" "" ${ARGN})
  if(NOT _pyunit_TIMEOUT)
    set(_pyunit_TIMEOUT 60.0)
  endif()

  # Check that the file exists, #1621
  set(_file_name _file_name-NOTFOUND)
  if(IS_ABSOLUTE ${file})
    set(_file_name ${file})
  else()
    find_file(_file_name ${file}
              PATHS ${CMAKE_CURRENT_SOURCE_DIR}
              NO_DEFAULT_PATH
              NO_CMAKE_FIND_ROOT_PATH)  # for cross-compilation.  thanks jeremy.
    if(NOT _file_name)
      message(FATAL_ERROR "Can't find pyunit file \"${file}\"")
    endif()
  endif()

  # We look for ROS_TEST_COVERAGE=1
  # to indicate that coverage reports are being requested.
  if("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1")
    set(_covarg "--cov")
  else()
    set(_covarg)
  endif()

  # Create a legal test name, in case the target name has slashes in it
  string(REPLACE "/" "_" _testname ${file})
  # We use rostest to call the executable to get process control, #1629
  set(cmd "${ROSUNIT_EXE} --name=${_testname} --time-limit=${_pyunit_TIMEOUT} --package=${PROJECT_NAME} -- ${_file_name} ${_covarg}")
  catkin_run_tests_target("rosunit" ${_testname} "rosunit-${_testname}.xml" COMMAND ${cmd} WORKING_DIRECTORY ${_pyunit_WORKING_DIRECTORY})
endfunction()


Added default constructors

Added default constructors

package @(package_name).@(subfolder);

import org.ros2.rcljava.common.JNIUtils;
import org.ros2.rcljava.common.RCLJavaProxy;
import org.ros2.rcljava.interfaces.MessageDefinition;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@[for field in spec.fields]@
@[    if not field.type.is_primitive_type()]@
import @(field.type.pkg_name).msg.@(field.type.type);
@[    end if]@
@[end for]@

public final class @(type_name) implements MessageDefinition {

  private static final Logger logger = LoggerFactory.getLogger(@(type_name).class);

  static {
    java.lang.String typesupportIdentifier = RCLJavaProxy.getTypesupportIdentifier();
    if (typesupportIdentifier == null) {
      logger.debug("Typesupport identifier can't be found");
    } else {
      try {
        JNIUtils.loadLibrary(@(type_name).class, typesupportIdentifier);
      } catch (UnsatisfiedLinkError ule) {
        logger.error("Native code library failed to load.\n" + ule);
        System.exit(1);
      }
    }
  }

  public static native long getDestructor();
  public static native long getFromJavaConverter();
  public static native long getToJavaConverter();
  public static native long getTypeSupport();

  public long getDestructorInstance() {
    return @(type_name).getDestructor();
  }

  public long getFromJavaConverterInstance() {
    return @(type_name).getFromJavaConverter();
  }

  public long getToJavaConverterInstance() {
    return @(type_name).getToJavaConverter();
  }

  public long getTypeSupportInstance() {
    return @(type_name).getTypeSupport();
  }

@[for constant in spec.constants]@
    public static final @(get_builtin_java_type(constant.type)) @(constant.name) = @(constant_value_to_java(constant.type, constant.value));
@[end for]@

@[for field in spec.fields]@

@[    if field.type.is_array]@
@[        if field.default_value is not None]@
  private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name) = java.util.Arrays.asList(new @(get_java_type(field.type, use_primitives=False))[] @(value_to_java(field.type, field.default_value)));
@[        else]@
  private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name);
@[        end if]@

  public final void set@(convert_lower_case_underscore_to_camel_case(field.name))(final java.util.Collection<@(get_java_type(field.type, use_primitives=False))> @(field.name)) {
@[        if field.type.array_size]@
@[            if field.type.is_upper_bound]@
    if(@(field.name).size() > @(field.type.array_size)) {
        throw new IllegalArgumentException("List too big, maximum size allowed: @(field.type.array_size)");
@[            else]@
    if(@(field.name).size() != @(field.type.array_size)) {
        throw new IllegalArgumentException("Invalid size for fixed array, must be exactly: @(field.type.array_size)");
@[            end if]@
    }
@[        end if]@
    if (@(field.name) != null) {
      this.@(field.name) = new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>(@(field.name));
    }
  }

@[        if field.type.is_primitive_type()]@
  public final void set@(convert_lower_case_underscore_to_camel_case(field.name))(final @(get_java_type(field.type, use_primitives=True))[] @(field.name)) {
    java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name)_tmp = new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>();
    for(@(get_java_type(field.type, use_primitives=True)) @(field.name)_value : @(field.name)) {
      @(field.name)_tmp.add(@(field.name)_value);
    }
    set@(convert_lower_case_underscore_to_camel_case(field.name))(@(field.name)_tmp);
  }
@[        end if]@

  public final java.util.List<@(get_java_type(field.type, use_primitives=False))> get@(convert_lower_case_underscore_to_camel_case(field.name))() {
    if (this.@(field.name) == null) {
      return null;
    }
    return new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>(this.@(field.name));
  }
@[    else]@
@[        if field.default_value is not None]@
  private @(get_java_type(field.type)) @(field.name) = @(value_to_java(field.type, field.default_value));
@[        else]@
@[            if field.type.type == 'string']@
  private @(get_java_type(field.type)) @(field.name) = "";
@[            elif field.type.is_primitive_type()]@
  private @(get_java_type(field.type)) @(field.name);
@[            else]@
  private @(get_java_type(field.type)) @(field.name) = new @(get_java_type(field.type))();
@[            end if]@
@[        end if]@

  public void set@(convert_lower_case_underscore_to_camel_case(field.name))(final @(get_java_type(field.type)) @(field.name)) {
@[        if field.type.string_upper_bound]@
    if(@(field.name).length() > @(field.type.string_upper_bound)) {
        throw new IllegalArgumentException("String too long, maximum size allowed: @(field.type.string_upper_bound)");
    }
@[        end if]@

    this.@(field.name) = @(field.name);
  }

  public @(get_java_type(field.type)) get@(convert_lower_case_underscore_to_camel_case(field.name))() {
    return this.@(field.name);
  }
@[    end if]@
@[end for]@
}

package @(package_name).@(subfolder);

import org.ros2.rcljava.common.JNIUtils;
import org.ros2.rcljava.common.RCLJavaProxy;
import org.ros2.rcljava.interfaces.MessageDefinition;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@[for field in spec.fields]@
@[    if not field.type.is_primitive_type()]@
import @(field.type.pkg_name).msg.@(field.type.type);
@[    end if]@
@[end for]@

public final class @(type_name) implements MessageDefinition {

  private static final Logger logger = LoggerFactory.getLogger(@(type_name).class);

  static {
    java.lang.String typesupportIdentifier = RCLJavaProxy.getTypesupportIdentifier();
    if (typesupportIdentifier == null) {
      logger.debug("Typesupport identifier can't be found");
    } else {
      try {
        JNIUtils.loadLibrary(@(type_name).class, typesupportIdentifier);
      } catch (UnsatisfiedLinkError ule) {
        logger.error("Native code library failed to load.\n" + ule);
        System.exit(1);
      }
    }
  }

  public static native long getDestructor();
  public static native long getFromJavaConverter();
  public static native long getToJavaConverter();
  public static native long getTypeSupport();

  public long getDestructorInstance() {
    return @(type_name).getDestructor();
  }

  public long getFromJavaConverterInstance() {
    return @(type_name).getFromJavaConverter();
  }

  public long getToJavaConverterInstance() {
    return @(type_name).getToJavaConverter();
  }

  public long getTypeSupportInstance() {
    return @(type_name).getTypeSupport();
  }

@[for constant in spec.constants]@
    public static final @(get_builtin_java_type(constant.type)) @(constant.name) = @(constant_value_to_java(constant.type, constant.value));
@[end for]@

@[for field in spec.fields]@

@[    if field.type.is_array]@
@[        if field.default_value is not None]@
  private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name) = java.util.Arrays.asList(new @(get_java_type(field.type, use_primitives=False))[] @(value_to_java(field.type, field.default_value)));
@[        else]@
  private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name);
@[        end if]@

  public final void set@(convert_lower_case_underscore_to_camel_case(field.name))(final java.util.Collection<@(get_java_type(field.type, use_primitives=False))> @(field.name)) {
@[        if field.type.array_size]@
@[            if field.type.is_upper_bound]@
    if(@(field.name).size() > @(field.type.array_size)) {
        throw new IllegalArgumentException("List too big, maximum size allowed: @(field.type.array_size)");
@[            else]@
    if(@(field.name).size() != @(field.type.array_size)) {
        throw new IllegalArgumentException("Invalid size for fixed array, must be exactly: @(field.type.array_size)");
@[            end if]@
    }
@[        end if]@
    if (@(field.name) != null) {
      this.@(field.name) = new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>(@(field.name));
    }
  }

  public final java.util.List<@(get_java_type(field.type, use_primitives=False))> get@(convert_lower_case_underscore_to_camel_case(field.name))() {
    if (this.@(field.name) == null) {
      return null;
    }
    return new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>(this.@(field.name));
  }
@[    else]@
@[        if field.default_value is not None]@
  private @(get_java_type(field.type)) @(field.name) = @(value_to_java(field.type, field.default_value));
@[        else]@
@[            if field.type.type == 'string']@
  private @(get_java_type(field.type)) @(field.name) = "";
@[            else]@
  private @(get_java_type(field.type)) @(field.name);
@[            end if]@
@[        end if]@

  public void set@(convert_lower_case_underscore_to_camel_case(field.name))(final @(get_java_type(field.type)) @(field.name)) {
@[        if field.type.string_upper_bound]@
    if(@(field.name).length() > @(field.type.string_upper_bound)) {
        throw new IllegalArgumentException("String too long, maximum size allowed: @(field.type.string_upper_bound)");
    }
@[        end if]@

    this.@(field.name) = @(field.name);
  }

  public @(get_java_type(field.type)) get@(convert_lower_case_underscore_to_camel_case(field.name))() {
    return this.@(field.name);
  }
@[    end if]@
@[end for]@
}


remove explicit dependencies, will be installed with rosdep

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    source:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images/create_ros2_source_image.Dockerfile.em
        entrypoint_name: docker_images/ros2_source_entrypoint.sh
        template_packages:
            - docker_templates
        upstream_packages:
            - bash-completion
            - git
            - libasio-dev
            - libtinyxml2-dev
            - wget
        ros2_repo_packages:
            - python3-catkin-pkg-modules
            - python3-vcstool
        pip3_install:
            - argcomplete
            - flake8
            - flake8-blind-except
            - flake8-builtins
            - flake8-class-newline
            - flake8-comprehensions
            - flake8-deprecated
            - flake8-docstrings
            - flake8-import-order
            - flake8-quotes
            - pytest-repeat
            - pytest-rerunfailures
        ws: /root/ros2_ws
        colcon_args:
            - build
            - --cmake-args
                -DSECURITY=ON --no-warn-unused-cli
            - --symlink-install
        vcs:
            ros2:
                repos: https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    source:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images/create_ros2_source_image.Dockerfile.em
        entrypoint_name: docker_images/ros2_source_entrypoint.sh
        template_packages:
            - docker_templates
        upstream_packages:
            - bash-completion
            - build-essential
            - clang-format
            - cmake
            - cppcheck
            - git
            - libasio-dev
            - libassimp-dev
            - libcurl4-openssl-dev
            - libeigen3-dev
            - libfreetype6-dev
            - libgles2-mesa-dev
            - libglu1-mesa
            - libopencv-dev
            - libpoco-dev
            - libqt5core5a
            - libqt5gui5
            - libqt5opengl5
            - libqt5widgets5
            - libssl-dev
            - libtinyxml-dev
            - libtinyxml2-dev
            - libxaw7-dev
            - libxrandr-dev
            - openssl
            - pydocstyle
            - pyflakes
            - python3-coverage
            - python3-dev
            - python3-empy
            - python3-mock
            - python3-nose
            - python3-pep8
            - python3-pyparsing
            - python3-pytest
            - python3-pytest-cov
            - python3-pytest-runner
            - python3-setuptools
            - python3-yaml
            - qtbase5-dev
            - wget
        ros2_repo_packages:
            - libopensplice67
            - python3-catkin-pkg-modules
            - python3-vcstool
        pip3_install:
            - argcomplete
            - flake8
            - flake8-blind-except
            - flake8-builtins
            - flake8-class-newline
            - flake8-comprehensions
            - flake8-deprecated
            - flake8-docstrings
            - flake8-import-order
            - flake8-quotes
            - pytest-repeat
            - pytest-rerunfailures
        ws: /root/ros2_ws
        colcon_args:
            - build
            - --cmake-args
                -DSECURITY=ON --no-warn-unused-cli
            - --symlink-install
        vcs:
            ros2:
                repos: https://raw.githubusercontent.com/ros2/ros2/master/ros2.repos


cleanups

cleanups

#!/bin/sh

@[if DEVELSPACE]@
export THOR_SCRIPTS=@(PROJECT_SOURCE_DIR)/scripts
@[else]@
export THOR_SCRIPTS=@(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts
@[end if]@
export THOR_ROOT=$(cd "@(CMAKE_SOURCE_DIR)/../../.."; pwd)

# include THOR_scripts hooks
#if [ -d $THOR_SCRIPTS ]; then
#  . $THOR_SCRIPTS/functions.sh
#  . $THOR_SCRIPTS/robot.sh ""

#  _THOR_include "$THOR_SCRIPTS/setup.d/*.sh"
#  _THOR_include "$THOR_SCRIPTS/$HOSTNAME/setup.d/*.sh"

#  if [ -r "$THOR_SCRIPTS/$HOSTNAME/setup.sh" ]; then
#      echo "Including $THOR_SCRIPTS/$HOSTNAME/setup.sh..." >&2
#      . "$THOR_SCRIPTS/$HOSTNAME/setup.sh"
#  fi
#fi

# export additional ROS_PACKAGE_PATH for indigo
if [ "$ROS_DISTRO" = "indigo" ]; then
    export ROS_BOOST_LIB_DIR_NAME=/usr/lib/x86_64-linux-gnu
    export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:$ROS_WORKSPACE/../external
fi

# export some variables
export PATH=$THOR_SCRIPTS/helper:$PATH
export ROS_WORKSPACE=$THOR_ROOT/src
export THOR_MOTION_HOSTNAME="thor-motion"
export THOR_PERCEPTION_HOSTNAME="thor-perception"
export THOR_ONBOARD_HOSTNAME="thor-motion" #need to be thor-motion because on same machine
export ROBOT_HOSTNAMES="thor-motion thor-perception thor-onboard"
export ROBOT_USER="thor"

# adding ssh keys
if [ -d "$THOR_ROOT/.ssh/" ] && [ "$(ls -A $THOR_ROOT/.ssh/)" ]; then
    #echo "Adding ssh keys from '$THOR_ROOT/.ssh/':"
    for f in $THOR_ROOT/.ssh/*; do
        ssh-add $f
    done
fi

#!/bin/sh

@[if DEVELSPACE]@
export THOR_SCRIPTS=@(PROJECT_SOURCE_DIR)/scripts
@[else]@
export THOR_SCRIPTS=@(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts
@[end if]@
export THOR_ROOT=$(cd "@(CMAKE_SOURCE_DIR)/../../.."; pwd)

# set THOR_* environment variables
alias l_vt_hand='. l_vt_hand'
alias r_vt_hand='. r_vt_hand'
alias l_thor_mang_hand='. l_thor_mang_hand'
alias r_thor_mang_hand='. r_thor_mang_hand'

# include THOR_scripts hooks
#if [ -d $THOR_SCRIPTS ]; then
#  . $THOR_SCRIPTS/functions.sh
#  . $THOR_SCRIPTS/robot.sh ""

#  _THOR_include "$THOR_SCRIPTS/setup.d/*.sh"
#  _THOR_include "$THOR_SCRIPTS/$HOSTNAME/setup.d/*.sh"

#  if [ -r "$THOR_SCRIPTS/$HOSTNAME/setup.sh" ]; then
#      echo "Including $THOR_SCRIPTS/$HOSTNAME/setup.sh..." >&2
#      . "$THOR_SCRIPTS/$HOSTNAME/setup.sh"
#  fi
#fi

# export additional ROS_PACKAGE_PATH for indigo
if [ "$ROS_DISTRO" = "indigo" ]; then
    export ROS_BOOST_LIB_DIR_NAME=/usr/lib/x86_64-linux-gnu
    export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:$ROS_WORKSPACE/../external
fi

# export some variables
export PATH=$THOR_SCRIPTS/helper:$PATH
export ROS_WORKSPACE=$THOR_ROOT/src
export THOR_MOTION_HOSTNAME="thor-motion"
export THOR_PERCEPTION_HOSTNAME="thor-perception"
export THOR_ONBOARD_HOSTNAME="thor-motion" #need to be thor-motion because on same machine
export ROBOT_HOSTNAMES="thor-motion thor-perception thor-onboard"
export ROBOT_USER="thor"
export THOR_ROBOT_TYPE="thor_mang_hands"
export LEFT_HAND_TYPE="l_vt_hand"
export RIGHT_HAND_TYPE="r_vt_hand"
export THOR_DESCRIPTION_PACKAGE="thor_mang_tud_description"

# adding ssh keys
if [ -d "$THOR_ROOT/.ssh/" ] && [ "$(ls -A $THOR_ROOT/.ssh/)" ]; then
    #echo "Adding ssh keys from '$THOR_ROOT/.ssh/':"
    for f in $THOR_ROOT/.ssh/*; do
        ssh-add $f
    done
fi


don't set CMD in source template

don't set CMD in source template

Signed-off-by: Mikael Arguedas <a16f295d1139a1392bb19262902c32cf3e999ce4@gmail.com>

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@

ARG FROM_IMAGE=osrf/ros2:devel
FROM $FROM_IMAGE
@{
template_dependencies = [
    'wget',
]
packages_to_install = []
if 'upstream_packages' in locals():
    packages_to_install = upstream_packages
if 'ros2_repo_packages' in locals():
    if ros2_repo_packages:
        packages_to_install = packages_to_install + list(set(ros2_repo_packages) - set(packages_to_install))
}@
@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=packages_to_install,
))@
@
@[if 'pip3_install' in locals()]@
@[  if pip3_install]@

# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@
ARG ROS_DISTRO=@ros2_distro
ENV ROS_DISTRO=$ROS_DISTRO

@
@[if 'rosdep' in locals()]@
@[  if 'rosdistro_index_url' in rosdep]@
ENV ROSDISTRO_INDEX_URL @(rosdep['rosdistro_index_url'])
RUN rosdep update

@[  end if]@
@[end if]@
@
WORKDIR $ROS2_WS
@[if 'vcs' in locals()]@
@[  if vcs]@

@(TEMPLATE(
    'snippet/vcs_import.Dockerfile.em',
    vcs=vcs,
    ws='src',
))@

@[  end if]@
@[end if]@
@
@[if 'rosdep' in locals()]@
@[  if 'install' in rosdep]@
@(TEMPLATE(
    'snippet/install_rosdep_dependencies.Dockerfile.em',
    install_args=rosdep['install'],
))@

@[  end if]@
@[else]@
RUN rosdep update &&\
    rosdep install -y \
    --from-paths src \
    --ignore-src

@[end if]@
@[if 'colcon_args' in locals()]@
@[  if colcon_args]@
# build source
RUN colcon \
    @(' \\\n    '.join(colcon_args))@

@[  end if]@
@[end if]@

ARG RUN_TESTS
ARG FAIL_ON_TEST_FAILURE
RUN if [ ! -z "$RUN_TESTS" ]; then \
        colcon test; \
        if [ ! -z "$FAIL_ON_TEST_FAILURE" ]; then \
            colcon test-result; \
        else \
            colcon test-result || true; \
        fi \
    fi
@
@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@

# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@

ARG FROM_IMAGE=osrf/ros2:devel
FROM $FROM_IMAGE
@{
template_dependencies = [
    'wget',
]
packages_to_install = []
if 'upstream_packages' in locals():
    packages_to_install = upstream_packages
if 'ros2_repo_packages' in locals():
    if ros2_repo_packages:
        packages_to_install = packages_to_install + list(set(ros2_repo_packages) - set(packages_to_install))
}@
@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=packages_to_install,
))@
@
@[if 'pip3_install' in locals()]@
@[  if pip3_install]@

# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@
ARG ROS_DISTRO=@ros2_distro
ENV ROS_DISTRO=$ROS_DISTRO

@
@[if 'rosdep' in locals()]@
@[  if 'rosdistro_index_url' in rosdep]@
ENV ROSDISTRO_INDEX_URL @(rosdep['rosdistro_index_url'])
RUN rosdep update

@[  end if]@
@[end if]@
@
WORKDIR $ROS2_WS
@[if 'vcs' in locals()]@
@[  if vcs]@

@(TEMPLATE(
    'snippet/vcs_import.Dockerfile.em',
    vcs=vcs,
    ws='src',
))@

@[  end if]@
@[end if]@
@
@[if 'rosdep' in locals()]@
@[  if 'install' in rosdep]@
@(TEMPLATE(
    'snippet/install_rosdep_dependencies.Dockerfile.em',
    install_args=rosdep['install'],
))@

@[  end if]@
@[else]@
RUN rosdep update &&\
    rosdep install -y \
    --from-paths src \
    --ignore-src

@[end if]@
@[if 'colcon_args' in locals()]@
@[  if colcon_args]@
# build source
RUN colcon \
    @(' \\\n    '.join(colcon_args))@

@[  end if]@
@[end if]@

ARG RUN_TESTS
ARG FAIL_ON_TEST_FAILURE
RUN if [ ! -z "$RUN_TESTS" ]; then \
        colcon test; \
        if [ ! -z "$FAIL_ON_TEST_FAILURE" ]; then \
            colcon test-result; \
        else \
            colcon test-result || true; \
        fi \
    fi

@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]


remove rosdistro_index_url from images.yaml

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    source:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/source/create_ros_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/source/ros_entrypoint.sh
        template_packages:
            - docker_templates
        upstream_packages:
            - bash-completion
            - git
            - libasio-dev
            - libtinyxml2-dev
            - wget
        ros2_repo_packages:
            - python3-catkin-pkg-modules
            - python3-rosdep
            - python3-vcstool
        pip3_install:
            - argcomplete
            - flake8
            - flake8-blind-except
            - flake8-builtins
            - flake8-class-newline
            - flake8-comprehensions
            - flake8-deprecated
            - flake8-docstrings
            - flake8-import-order
            - flake8-quotes
            - pytest-repeat
            - pytest-rerunfailures
        ws: /root/ros2_ws
        colcon_args:
            - build
            - --cmake-args
                -DSECURITY=ON --no-warn-unused-cli
            - --symlink-install
        rosdep:
            install:
                - --from-paths src
                - --ignore-src
                - --rosdistro bouncy
                - --skip-keys "console_bridge fastcdr fastrtps libopensplice67 rti-connext-dds-5.3.1 urdfdom_headers"
        vcs:
            ros2:
                repos: https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    source:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/source/create_ros_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/source/ros_entrypoint.sh
        template_packages:
            - docker_templates
        upstream_packages:
            - bash-completion
            - git
            - libasio-dev
            - libtinyxml2-dev
            - wget
        ros2_repo_packages:
            - python3-catkin-pkg-modules
            - python3-rosdep
            - python3-vcstool
        pip3_install:
            - argcomplete
            - flake8
            - flake8-blind-except
            - flake8-builtins
            - flake8-class-newline
            - flake8-comprehensions
            - flake8-deprecated
            - flake8-docstrings
            - flake8-import-order
            - flake8-quotes
            - pytest-repeat
            - pytest-rerunfailures
        ws: /root/ros2_ws
        colcon_args:
            - build
            - --cmake-args
                -DSECURITY=ON --no-warn-unused-cli
            - --symlink-install
        rosdep:
            rosdistro_index_url: https://raw.githubusercontent.com/ros2/rosdistro/ros2/index.yaml
            install:
                - --from-paths src
                - --ignore-src
                - --rosdistro bouncy
                - --skip-keys "console_bridge fastcdr fastrtps libopensplice67 rti-connext-dds-5.3.1 urdfdom_headers"
        vcs:
            ros2:
                repos: https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos


Add in-package message generation macro.

# vim: set ft=cmake :
@[if DEVELSPACE]@
# location of scripts in develspace
set(GENGO_BIN_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts")
@[else]@
# location of scripts in installspace
set(GENGO_BIN_DIR "${gengo_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)")
@[end if]@

set(GENMSG_GO_BIN ${GENGO_BIN_DIR}/gen_go.py)
set(GENSRV_GO_BIN ${GENGO_BIN_DIR}/gen_go.py)

execute_process(COMMAND go env GOARCH OUTPUT_VARIABLE ROSGO_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND go env GOOS OUTPUT_VARIABLE ROSGO_OS OUTPUT_STRIP_TRAILING_WHITESPACE)

# Generate .msg -> .go
# The generated .go files should be added ALL_GEN_OUTPUT_FILES_go
macro(_generate_msg_go ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})
  #Create input and output filenames
  get_filename_component(MSG_SHORT_NAME ${ARG_MSG} NAME_WE)

  set(MSG_GENERATED_NAME ${MSG_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${MSG_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENMSG_GO_BIN} ${ARG_MSG} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${GENMSG_GO_BIN} ${ARG_MSG}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from MSG ${ARG_PKG}/${MSG_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})

endmacro()

#todo, these macros are practically equal. Check for input file extension instead
macro(_generate_srv_go ARG_PKG ARG_SRV ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})

  #Create input and output filenames
  get_filename_component(SRV_SHORT_NAME ${ARG_SRV} NAME_WE)

  set(SRV_GENERATED_NAME ${SRV_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${SRV_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENSRV_GO_BIN} ${ARG_SRV} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENSRV_GO_BIN} ${ARG_SRV}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from SRV ${ARG_PKG}/${SRV_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})
endmacro()

macro(_generate_module_go ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES)
  # Nothing to do
endmacro()

macro(rosgo_generate_message_in_package _package)
    set(pkg ${_package})
    execute_process(COMMAND ${CATKIN_ENV} rosmsg packages -s
                    OUTPUT_VARIABLE rosmsg_output
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REPLACE " " ";" msg_pkg_list ${rosmsg_output})
    set(iflags "")
    foreach(msg_pkg ${msg_pkg_list})
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${msg_pkg}
                        OUTPUT_VARIABLE msg_pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        list(APPEND iflags "-I${msg_pkg}:${msg_pkg_path}/msg")
    endforeach()

    # Find msg directory
    execute_process(COMMAND ${CATKIN_ENV} rospack find ${pkg}
                    OUTPUT_VARIABLE pkg_path
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(gen_output_files "")

    #message(STATUS pkg_path=${pkg_path})
    set(msg_dir ${pkg_path}/msg)
    #message(STATUS msg_dir=${msg_dir})
    file(GLOB msg_files "${msg_dir}/*.msg")
    #message(STATUS msg_files=${msg_files})

    foreach(msg ${msg_files})
        file(MAKE_DIRECTORY ${PROJECT_SOURCE_DIR}/src/${pkg})
        get_filename_component(msg_name ${msg} NAME_WE)
        set(output_file ${PROJECT_SOURCE_DIR}/src/${pkg}/${msg_name}.go)
        add_custom_command(OUTPUT ${output_file}
            COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
            ${msg} ${iflags} -p ${pkg} -o ${PROJECT_SOURCE_DIR}/src/${pkg}
            )
        list(APPEND gen_output_files ${output_file})
    endforeach()

    set(srv_dir ${pkg_path}/srv)
    #message(STATUS srv_dir=${srv_dir})
    file(GLOB srv_files "${srv_dir}/*.srv")
    #message(STATUS srv_files=${srv_files})
    foreach(srv ${srv_files})
        file(MAKE_DIRECTORY ${PROJECT_SOURCE_DIR}/src/${pkg})
        get_filename_component(srv_name ${srv} NAME_WE)
        set(output_files "")
        list(APPEND output_files ${PROJECT_SOURCE_DIR}/src/${pkg}/${srv_name}.go)
        list(APPEND output_files ${PROJECT_SOURCE_DIR}/src/${pkg}/${srv_name}Request.go)
        list(APPEND output_files ${PROJECT_SOURCE_DIR}/src/${pkg}/${srv_name}Response.go)
        add_custom_command(OUTPUT ${output_files}
            COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
            ${srv} ${iflags} -p ${pkg} -o ${PROJECT_SOURCE_DIR}/src/${pkg}
            )
        list(APPEND gen_output_files ${output_files})
    endforeach()
    add_custom_target(rosgo_generate_${pkg}_in_${PROJECT_NAME} ALL DEPENDS ${gen_output_files})
endmacro()

# Generate
macro(rosgo_force_generate_messages)
    set(ROSGO_SRC_DIR ${CATKIN_DEVEL_PREFIX}/go/src)
    execute_process(COMMAND ${CATKIN_ENV} rosmsg packages -s
                    OUTPUT_VARIABLE rosmsg_output
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REPLACE " " ";" msg_pkg_list ${rosmsg_output})
    set(iflags "")
    foreach(msg_pkg ${msg_pkg_list})
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${msg_pkg}
                        OUTPUT_VARIABLE msg_pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        list(APPEND iflags "-I${msg_pkg}:${msg_pkg_path}/msg")
    endforeach()
    set(all_gen_output_files "")
    foreach(pkg ${ARGV})
        # Find msg directory
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${pkg}
                        OUTPUT_VARIABLE pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        set(gen_output_files "")

        #message(STATUS pkg_path=${pkg_path})
        set(msg_dir ${pkg_path}/msg)
        #message(STATUS msg_dir=${msg_dir})
        file(GLOB msg_files "${msg_dir}/*.msg")
        #message(STATUS msg_files=${msg_files})

        foreach(msg ${msg_files})
            file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
            get_filename_component(msg_name ${msg} NAME_WE)
            set(output_file ${ROSGO_SRC_DIR}/${pkg}/${msg_name}.go)
            add_custom_command(OUTPUT ${output_file}
                COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                ${msg} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                )
            list(APPEND gen_output_files ${output_file})
        endforeach()

        set(srv_dir ${pkg_path}/srv)
        #message(STATUS srv_dir=${srv_dir})
        file(GLOB srv_files "${srv_dir}/*.srv")
        #message(STATUS srv_files=${srv_files})
        foreach(srv ${srv_files})
            file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
            get_filename_component(srv_name ${srv} NAME_WE)
            set(output_files "")
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}.go)
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Request.go)
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Response.go)
            add_custom_command(OUTPUT ${output_files}
                COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                ${srv} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                )
            list(APPEND gen_output_files ${output_files})
        endforeach()

        install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/go/src/${pkg}
                DESTINATION ${CMAKE_INSTALL_PREFIX}/go/src/
                PATTERN "*.go")

        list(APPEND all_gen_output_files ${gen_output_files})
    endforeach()
    foreach(pkg ${ARGV})
        set(msg_lib ${CATKIN_DEVEL_PREFIX}/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/${pkg}.a)
        add_custom_command(OUTPUT ${msg_lib}
            COMMAND env GOPATH=${CATKIN_DEVEL_PREFIX}/go go install ${pkg}
            DEPENDS ${all_gen_output_files}
            )
        add_custom_target(rosgo_genmsg_for_${pkg} ALL DEPENDS ${msg_lib})

        install(FILES ${msg_lib}
            DESTINATION ${CMAKE_INSTALL_PREFIX}/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/)
    endforeach()
endmacro()

set(gengo_INSTALL_DIR go/src)

# vim: set ft=cmake :
@[if DEVELSPACE]@
# location of scripts in develspace
set(GENGO_BIN_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts")
@[else]@
# location of scripts in installspace
set(GENGO_BIN_DIR "${gengo_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)")
@[end if]@

set(GENMSG_GO_BIN ${GENGO_BIN_DIR}/gen_go.py)
set(GENSRV_GO_BIN ${GENGO_BIN_DIR}/gen_go.py)

execute_process(COMMAND go env GOARCH OUTPUT_VARIABLE ROSGO_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND go env GOOS OUTPUT_VARIABLE ROSGO_OS OUTPUT_STRIP_TRAILING_WHITESPACE)

# Generate .msg -> .go
# The generated .go files should be added ALL_GEN_OUTPUT_FILES_go
macro(_generate_msg_go ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})
  #Create input and output filenames
  get_filename_component(MSG_SHORT_NAME ${ARG_MSG} NAME_WE)

  set(MSG_GENERATED_NAME ${MSG_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${MSG_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENMSG_GO_BIN} ${ARG_MSG} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${GENMSG_GO_BIN} ${ARG_MSG}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from MSG ${ARG_PKG}/${MSG_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})

endmacro()

#todo, these macros are practically equal. Check for input file extension instead
macro(_generate_srv_go ARG_PKG ARG_SRV ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})

  #Create input and output filenames
  get_filename_component(SRV_SHORT_NAME ${ARG_SRV} NAME_WE)

  set(SRV_GENERATED_NAME ${SRV_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${SRV_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENSRV_GO_BIN} ${ARG_SRV} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENSRV_GO_BIN} ${ARG_SRV}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from SRV ${ARG_PKG}/${SRV_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})
endmacro()

macro(_generate_module_go ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES)
  # Nothing to do
endmacro()

# Generate
macro(rosgo_force_generate_messages)
    set(ROSGO_SRC_DIR ${CATKIN_DEVEL_PREFIX}/go/src)
    execute_process(COMMAND ${CATKIN_ENV} rosmsg packages -s
                    OUTPUT_VARIABLE rosmsg_output
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REPLACE " " ";" msg_pkg_list ${rosmsg_output})
    set(iflags "")
    foreach(msg_pkg ${msg_pkg_list})
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${msg_pkg}
                        OUTPUT_VARIABLE msg_pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        list(APPEND iflags "-I${msg_pkg}:${msg_pkg_path}/msg")
    endforeach()
    set(all_gen_output_files "")
    foreach(pkg ${ARGV})
        # Find msg directory
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${pkg}
                        OUTPUT_VARIABLE pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        set(gen_output_files "")

        #message(STATUS pkg_path=${pkg_path})
        set(msg_dir ${pkg_path}/msg)
        #message(STATUS msg_dir=${msg_dir})
        file(GLOB msg_files "${msg_dir}/*.msg")
        #message(STATUS msg_files=${msg_files})

        foreach(msg ${msg_files})
            file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
            get_filename_component(msg_name ${msg} NAME_WE)
            set(output_file ${ROSGO_SRC_DIR}/${pkg}/${msg_name}.go)
            add_custom_command(OUTPUT ${output_file}
                COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                ${msg} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                )
            list(APPEND gen_output_files ${output_file})
        endforeach()

        set(srv_dir ${pkg_path}/srv)
        #message(STATUS srv_dir=${srv_dir})
        file(GLOB srv_files "${srv_dir}/*.srv")
        #message(STATUS srv_files=${srv_files})
        foreach(srv ${srv_files})
            file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
            get_filename_component(srv_name ${srv} NAME_WE)
            set(output_files "")
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}.go)
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Request.go)
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Response.go)
            add_custom_command(OUTPUT ${output_files}
                COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                ${srv} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                )
            list(APPEND gen_output_files ${output_files})
        endforeach()

        install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/go/src/${pkg}
                DESTINATION ${CMAKE_INSTALL_PREFIX}/go/src/
                PATTERN "*.go")

        list(APPEND all_gen_output_files ${gen_output_files})
    endforeach()
    foreach(pkg ${ARGV})
        set(msg_lib ${CATKIN_DEVEL_PREFIX}/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/${pkg}.a)
        add_custom_command(OUTPUT ${msg_lib}
            COMMAND env GOPATH=${CATKIN_DEVEL_PREFIX}/go go install ${pkg}
            DEPENDS ${all_gen_output_files}
            )
        add_custom_target(rosgo_genmsg_for_${pkg} ALL DEPENDS ${msg_lib})

        install(FILES ${msg_lib}
            DESTINATION ${CMAKE_INSTALL_PREFIX}/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/)
    endforeach()
endmacro()

set(gengo_INSTALL_DIR go/src)