-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ament_cmake_gen_version_h package #198
Conversation
32537ba
to
a26d191
Compare
ament_cmake_version/package.xml
Outdated
<package format="2"> | ||
<name>ament_cmake_version</name> | ||
<version>0.0.1</version> | ||
<description>Version header file generator</description> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make this a bit more descriptive, e.g.:
Generate a C header containing the version number of the package
ament_cmake_version/package.xml
Outdated
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> | ||
<package format="2"> | ||
<name>ament_cmake_version</name> | ||
<version>0.0.1</version> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version number must match the version from the other packages in this repo.
ament_cmake_version/CMakeLists.txt
Outdated
@@ -0,0 +1,17 @@ | |||
cmake_minimum_required(VERSION 3.10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a need to require 3.10? If not maybe relaxing it to at least 3.7
would be good to have the option to backport it to Dashing.
ament_cmake_version/CMakeLists.txt
Outdated
if(BUILD_TESTING) | ||
find_package(ament_cmake_lint_cmake REQUIRED) | ||
ament_lint_cmake(${CMAKE_CURRENT_SOURCE_DIR}) | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This package can't use the ament_cmake_lint_cmake
package since that would create a cyclic dependency. (It also doesn't declare that dependency in its manifest which would probable expose the cycle.)
set(${PROJECT_NAME}_VERSION_FILE_NAME ${TMP_INCLUDE_DIR}/version.h) | ||
set(NEED_TO_CREATE_VERSION_FILE FALSE) | ||
|
||
# retrieve verson information from <package>.xml file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling: verson
set(NEED_TO_CREATE_VERSION_FILE TRUE) | ||
else() | ||
string(REGEX MATCH "^#define[ \t]+${PROJECT_NAME}_VERSION_STR[ \t]+\"([0-9]+\.[0-9]+\.[0-9]+)\"" "" dummy ${VERSION_FILE_STRINGS}) | ||
if(NOT (${CMAKE_MATCH_1} STREQUAL ${${PROJECT_NAME}_VERSION})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: no need for the inner parenthesis.
message(STATUS "Create new version file for version ${${PROJECT_NAME}_VERSION}") | ||
file(MAKE_DIRECTORY ${TMP_INCLUDE_DIR}) | ||
# create the version.h file | ||
configure_file("resource/version.h.in" ${${PROJECT_NAME}_VERSION_FILE_NAME} NEWLINE_STYLE UNIX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the template file resource/version.h.in
isn't part of this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not not and it should be provided by each project in accordance to the project's requirements. I provided an example of such file in ament_cmake_version.cmake
file:
################################################################################
# Example of a template file for `rcutils` project:
# // Copyright 2015 Open Source Robotics Foundation, Inc.
# //
# // Licensed under the Apache License, Version 2.0 (the "License");
# // you may not use this file except in compliance with the License.
# // You may obtain a copy of the License at
# //
# // http://www.apache.org/licenses/LICENSE-2.0
# //
# // Unless required by applicable law or agreed to in writing, software
# // distributed under the License is distributed on an "AS IS" BASIS,
# // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# // See the License for the specific language governing permissions and
# // limitations under the License.
#
# #ifndef RCUTILS__VERSION_H_
# #define RCUTILS__VERSION_H_
#
# /// \def RCUTILS_VERSION_MAJOR
# /// Defines RCUTILS major version number
# #define RCUTILS_VERSION_MAJOR (@rcutils_VERSION_MAJOR@)
#
# /// \def RCUTILS_VERSION_MINOR
# /// Defines RCUTILS minor version number
# #define RCUTILS_VERSION_MINOR (@rcutils_VERSION_MINOR@)
#
# /// \def RCUTILS_VERSION_PATCH
# /// Defines RCUTILS version patch number
# #define RCUTILS_VERSION_PATCH (@rcutils_VERSION_PATCH@)
#
# /// \def RCUTILS_VERSION_STR
# /// Defines RCUTILS version string
# #define RCUTILS_VERSION_STR "@rcutils_VERSION@"
#
# #endif // RCUTILS__VERSION_H_"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't a default template be more convenient for the user? It seems that this file would be identical in the majority of packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
# create the version.h file | ||
configure_file("resource/version.h.in" ${${PROJECT_NAME}_VERSION_FILE_NAME} NEWLINE_STYLE UNIX) | ||
else() | ||
message(STATUS "Skip version file creation") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: 2 space indentation.
message(STATUS "Create new version file for version ${${PROJECT_NAME}_VERSION}") | ||
file(MAKE_DIRECTORY ${TMP_INCLUDE_DIR}) | ||
# create the version.h file | ||
configure_file("resource/version.h.in" ${${PROJECT_NAME}_VERSION_FILE_NAME} NEWLINE_STYLE UNIX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should the newline style be enforced to UNIX
even when running this on Windows?
else() | ||
# if the version file does not exist, create it | ||
set(NEED_TO_CREATE_VERSION_FILE TRUE) | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't the logic be shorted if NEED_TO_CREATE_VERSION_FILE
would be initialized with TRUE
and only if the file is already present and the expected version string is in the file be changed to FALSE
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
240a842
to
aeb5b09
Compare
@dirk-thomas, I have addressed your findings. Please see the changes. |
|
||
/// \def ${PROJECT_NAME_UPPER}_VERSION_STR | ||
/// Defines ${PROJECT_NAME_UPPER} version string | ||
#define ${PROJECT_NAME_UPPER}_VERSION_STR "${VERSION_STR}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add add ${PROJECT_NAME_UPPER}_VERSION_GTE(major, minor, patch)
macro as defined in https://github.com/ros2/rmw_cyclonedds/pull/51/files#diff-d03c99cafce317e1a93de46e787e0235R64?
/// \def ${PROJECT_NAME_UPPER}_VERSION_GTE
/// Defines a macro to check whether the version of ${PROJECT_NAME_UPPER} is greater than or equal to
/// the given version triple.
#define ${PROJECT_NAME_UPPER}_VERSION_GTE(major, minor, patch) ( \
(major < ${PROJECT_NAME_UPPER}_VERSION_MAJOR) ? true \
: (major > ${PROJECT_NAME_UPPER}_VERSION_MAJOR) ? false \
: (minor < ${PROJECT_NAME_UPPER}_VERSION_MINOR) ? true \
: (minor > ${PROJECT_NAME_UPPER}_VERSION_MINOR) ? false \
: (patch < ${PROJECT_NAME_UPPER}_VERSION_PATCH) ? true \
: (patch > ${PROJECT_NAME_UPPER}_VERSION_PATCH) ? false \
: true)
I could use such a macro already for rosidl_generator_cpp
, to compile my ROS 2 code conditionally depending on the version of rosidl. rosidl_generator_cpp::MessageInitialization
and other types have been moved to namespace rosidl_runtime_cpp
in version 0.9.0, and I do not see another way to use a non-default message initialization flag such that it works in dashing, eloquent and foxy.
For this specific case it would be convenient to have a
using MessageInitialization = rosidl_runtime_cpp::MessageInitialization;
declaration within the generated message structs, but that is an issue for https://github.com/ros2/rosidl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been silent for a good while. Any chance you'd bring this back to life @serge-nikulin? |
@hidmic, I got an impression that the maintainers are not interested in this feature. As you can see, I did not get a reply to my review request to @dirk-thomas two years ago: #198 (comment) |
I do see. It's been a long while. If you rebase I think this might be useful to some people. @clalancette @wjwwood for feedback. |
@hidmic, I'll wait for a maintainers' support for this issue. I'm curious why they did not do a similar feature long ago. It's the first product where I have to look up executables' |
I am the maintainer :)
Priorities. Though I vaguely recall some resistance to allowing version-based conditional compilation. I'm onboard with the idea but I cannot commit time to it right now. Thus my question. |
@hidmic , great! I'm going for a two-week vacation starting Sept 17th and I'll do it during that time. I hope you will help me to finish this one. |
53733c8
to
d8d5ed1
Compare
Signed-off-by: Serge Nikulin <serge@safeai.ai>
Signed-off-by: Serge Nikulin <serge@safeai.ai>
d8d5ed1
to
1b110bd
Compare
@hidmic, I rebased and everything checks out OK. Pease review. |
endif() | ||
|
||
# Find myself so I can use my own cmake instalation folder `ament_cmake_gen_version_h_DIR` | ||
# I can't rely on a pervious find_package call because it could be a direct call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# I can't rely on a pervious find_package call because it could be a direct call | |
# I can't rely on a previous find_package call because it could be a direct call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, fixed
# I can't rely on a previous find_package call because it could be a direct call | ||
find_package(ament_cmake_gen_version_h REQUIRED) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin direct call? If this .cmake
file is simply included, there may not even be an installed config module to look for in the CMAKE_PREFIX_PATH
.
I'm inclined to drop this and instead document how to make proper use of this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic, The find_package
call provides me with $ament_cmake_gen_version_h_DIR
variable so I can have access to my template file ${ament_cmake_gen_version_h_DIR}/version.h.in
. That's the only reliable way to do it, AFAIK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. My point is, the only scenario I can think of where a downstream package wouldn't have had to call find_package(ament_cmake_gen_version_h)
first is when ament_cmake_gen_version_h
is included into another, outer project. In that case, find_package(ament_cmake_gen_version_h)
will fail anyways. The outer project has to set that directory for you.
|
||
install( | ||
DIRECTORY ${TMP_INCLUDE_DIR} | ||
DESTINATION include) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin I'm somewhat inclined towards generating the file and letting the caller decide if and where to install it (as if it was an OUTPUT of add_custom_command
).
I'd be OK with optionally delegating the installation though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic, I decided to parametrize pretty much everything. How do the following optional parameters look to you?
If you are OK, I'll proceed with them and also create some unit tests for different scenarios.
# :param DO_NOT_INSTALL: whether to autmatically install the generated version file into DESTINATION include
# :type DO_NOT_INSTALL: BOOL
# :default value DO_NOT_INSTALL: FALSE
# :param PRJ_NAME: project name to use
# :type PRJ_NAME: string
# :default value PRJ_NAME: ${PROJECT_NAME}
# :param INCLUDE_DIR: path to the include folder where the file will be generated
# ${INCLUDE_DIR} folder will be added to the include paths
# the file will be placed into ${INCLUDE_DIR}/${PRJ_NAME} folder according to ROS2 standard
# :type INCLUDE_DIR: string
# :default value INCLUDE_DIR: ${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_gen_version_h/include
# :param VERSION_FILE_NAME: file name of the generated header file
# :type VERSION_FILE_NAME: string
# :default value VERSION_FILE_NAME: version.h
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin may I suggest a NO_INSTALL
option instead of a DO_NOT_INSTALL
one-value argument? Also, what use case do you have in mind for PRJ_NAME
? Why would you want to change it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with both points. Please review again.
9e26d46
to
db13b3c
Compare
Signed-off-by: Serge Nikulin <serge@safeai.ai>
Signed-off-by: Serge Nikulin <serge@safeai.ai>
db13b3c
to
9269c03
Compare
@hidmic, it seems I can't add a self/unit test section to the project. The following code is silently ignored by if(BUILD_TESTING)
find_package(ament_cmake_gmock REQUIRED)
find_package(ament_cmake_gtest REQUIRED)
find_package(ament_cmake_uncrustify REQUIRED)
find_package(ament_cmake_copyright REQUIRED)
find_package(ament_cmake_cpplint REQUIRED)
find_package(ament_cmake_lint_cmake REQUIRED)
ament_add_gtest(test_${PROJECT_NAME}
test1.cpp
)
ament_uncrustify(${LINT_DIRECTORIES})
ament_copyright(${LINT_DIRECTORIES})
ament_cpplint(${LINT_DIRECTORIES})
ament_lint_cmake(${CMAKE_CURRENT_SOURCE_DIR})
endif() |
|
Signed-off-by: Serge Nikulin <serge@safeai.ai>
31a3d10
to
610d7a1
Compare
@hidmic, please review. |
|
||
find_package(ament_cmake_core REQUIRED) | ||
|
||
ament_package(CONFIG_EXTRAS "ament_cmake_gen_version_h-extras.cmake") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin this line should be (conventionally) the last.
@@ -0,0 +1,50 @@ | |||
cmake_minimum_required(VERSION 3.5) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin nit: extra blank line
include (cmake/ament_cmake_gen_version_h.cmake) | ||
find_package(ament_cmake_gtest REQUIRED) | ||
|
||
ament_cmake_gen_version_h(NO_INSTALL TRUE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin hmm, options do not need a literal boolean argument -- their presence (or absence) is the boolean.
test/test_version1_h.cpp | ||
test/test_version2_h.cpp | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin nit: extra blank line
<buildtool_depend>ament_package</buildtool_depend> | ||
|
||
<buildtool_export_depend>ament_cmake_core</buildtool_export_depend> | ||
<test_depend>ament_cmake_gtest</test_depend> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin consider adding ament_lint_common
linters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic, ament_lint
repo depends on amen_cmake
and does not exist during amen_cmake
build. Nevertheless, on my PC I did run all the linters "out of order" and fixed all violations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point.
I did run all the linters "out of order" and fixed all violations.
Much appreciated.
# :type VERSION_PATCH: string | ||
# :default value VERSION_PATCH: VERSION_PATCH from the package.xml file | ||
|
||
################################################################################ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin nit: follow the docblock format that is used for other functions and macros in this repository.
cmake_minimum_required(VERSION 3.5) | ||
|
||
project(ament_cmake_gen_version_h) | ||
include(CTest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin nit: let's move this right next to the BUILD_TESTING
clause.
9101e13
to
94b9c26
Compare
Signed-off-by: Serge Nikulin <serge@safeai.ai>
94b9c26
to
4e75764
Compare
@hidmic, I addressed all your findings, please review again |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this LGTM but for one observation. Once that's addressed, I'll run CI.
@wjwwood @clalancette any last minute concerns about this?
message(STATUS "Skip version file creation") | ||
endif() | ||
|
||
if(NOT ARG_DO_NOT_INSTALL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serge-nikulin should this be
if(NOT ARG_DO_NOT_INSTALL) | |
if(NOT ARG_NOT_INSTALL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic, Oops. Fixed.
Signed-off-by: Serge Nikulin <serge@safeai.ai>
No objections from me. |
Alright, going in then. Thank you for your contribution @serge-nikulin ! |
@hidmic, now somebody should call this function from some ROS2 package like |
or possibly from every project that installs headers. |
See ros2/rcutils#175 (comment) for details