Project

General

Profile

Actions

Feature #2671

closed

Print version number

Added by Junxiao Shi about 9 years ago. Updated about 9 years ago.

Status:
Closed
Priority:
High
Assignee:
Start date:
Due date:
% Done:

100%

Estimated time:
1.50 h

Description

In all tools, print the version number upon -V command line option.

All tools in ndn-tools repository should be given the same version number during a build.


Related issues 1 (0 open1 closed)

Blocks ndn-tools - Feature #2749: Derive version from git repository and elsewhereClosedEric Newberry

Actions
Actions #1

Updated by Junxiao Shi about 9 years ago

  • Description updated (diff)
Actions #2

Updated by Junxiao Shi about 9 years ago

I looked at NFD version processing in wscript.

The code there isn't clean enough: there are too many details that unnecessarily inflates the main wscript.

I plan to:

  1. write a bash script to
    1. derive version number from git describe, VERSION file, or hard-coded
    2. save version to VERSION file
  2. declare a Waf Task to invoke the bash script, and then subst the output into the code file containing version number
Actions #3

Updated by Junxiao Shi about 9 years ago

Another issue with NFD version processing is: the version number is declared as a preprocessor macro in a header included by every program.

In an incremental build (on developer workstation), this requires re-compiling every program object whenever version changes.

I plan to put the macro in a .cpp, so that a version change only requires re-linking of every program, and slightly saves compilation time.

The public API would be:

namespace ndn_tools_version {

const std::string BUILD;

void
print(const std::string& programName);

} // namespace ndn_tools_version

When a program sees '-V' command line option, it should call ndn_tools_version::print("ndnping") which prints to stdout:

ndnping 0.1.0
Actions #4

Updated by Alex Afanasyev about 9 years ago

I disagree with note-2. There is no reason in introducing additional script to generate version, if python (wscript) can do it as easy.

For note-3, I would simply define method to get std::string that contains a version number. "print" function is not general enough:

namespace ndn {
namespace tools {

std::string
getVersion();

} // namespace tools
} // namespace ndn


...

std::cout << "programName " << tools::getVersion() << std::endl;
Actions #5

Updated by Junxiao Shi about 9 years ago

I disagree with note-2. There is no reason in introducing additional script to generate version, if python (wscript) can do it as easy.

The Python code to collect version number has 50 lines. A bash script can do the same in 20 lines or less.

Actions #6

Updated by Alex Afanasyev about 9 years ago

That script had a few different considerations, besides just generating VERSION from git. And I guess it can be simplified, if necessary. Having dependency on python is enough and I don't want to introduce another (unnecessary) dependency on bash/sh.

Actions #7

Updated by Junxiao Shi about 9 years ago

  • Estimated time changed from 2.00 h to 1.50 h

In this Feature, I'll just define the getVersion method according to note-4, and print version in all existing tools.

This is the minimal necessity to allow other issues to proceed.

Deriving the version from git describe or other places will be split to another Feature.

Actions #8

Updated by Junxiao Shi about 9 years ago

  • Status changed from New to Code review
  • % Done changed from 0 to 100
Actions #9

Updated by Junxiao Shi about 9 years ago

  • Blocks Feature #2749: Derive version from git repository and elsewhere added
Actions #10

Updated by Davide Pesavento about 9 years ago

Alex Afanasyev wrote:

For note-3, I would simply define method to get std::string that contains a version number. "print" function is not general enough:

A function that returns the version string seems overkill to me.

A pattern I've seen used elsewhere is to declare an extern constant in the header and define the value in the cpp. Yet another way is a constexpr function that returns a char const * const, but I'm not sure you can define it out-of-line (and defining it inline kinda defeats the purpose).

Actions #11

Updated by Junxiao Shi about 9 years ago

note-3 suggested using a constant. @Alex please explain why you want a function instead of a constant.

Actions #12

Updated by Alex Afanasyev about 9 years ago

Constants (if it is not simple char*) may have issues with initialization. At least in the past, I had problems with them (order static constants are initialized/deleted is undetermined).

A function serves the same goal. If use of extern constant is safe, then I have no strong opinion on which way to go.

Actions #13

Updated by Davide Pesavento about 9 years ago

Alex Afanasyev wrote:

Constants (if it is not simple char*) may have issues with initialization. At least in the past, I had problems with them (order static constants are initialized/deleted is undetermined).

That's the so called "static init order fiasco". I'm proposing extern linkage here, not static. Moreover, this constant can be a simple char const * const, no need for a std::string.

Actions #14

Updated by Junxiao Shi about 9 years ago

commit:7bab1f75e168a84b17d6ce5fd6ea4a4e48a6b15a declares extern const std::string VERSION.

I disagree with char const* const because a string is semantically correct, and there's no reason to use a C type.

Actions #15

Updated by Davide Pesavento about 9 years ago

Junxiao Shi wrote:

I disagree with char const* const because a string is semantically correct, and there's no reason to use a C type.

Uh? so we cannot use char or int or double because they're "C types" now?

Actions #16

Updated by Junxiao Shi about 9 years ago

I prefer to use std::string because it's semantically correct.
If you insist on const char[], please give a technical reason.

I won't change without being convinced with a valid reason.

Actions #17

Updated by Davide Pesavento about 9 years ago

An std::string requires dynamic initialization, i.e. code is executed before running the main() function every time the program is loaded. A simple const char[] is statically initialized and exists as a constant in the ELF file (.rodata section IIRC) therefore it doesn't require any code to be executed before main().

Actions #18

Updated by Junxiao Shi about 9 years ago

I'll test whether it's constructed even when not used. If so, I could change.

Also, what's wrong with const std::string& getVersion()?
Using a function is also semantically correct.
Simply "overkill" is not a valid reason.

Actions #19

Updated by Davide Pesavento about 9 years ago

I don't know what you mean by semantically correct. Keeping things as simple as they can be is a very valid reason in my opinion.

Btw, you haven't mentioned a single drawback of const char[] so far, so it seems to me that it's the best approach from a purely technical point of view.

Actions #20

Updated by Junxiao Shi about 9 years ago

  • Status changed from Code review to In Progress
  • % Done changed from 100 to 50

I have confirmed the claim in note-17 with the following snippet:

// g++ -std=c++0x x.cpp $(pkg-config --cflags --libs libndn-cxx)
#include <iostream>

class A
{
public:
  A()
  {
    std::cout << "A ctor" << std::endl;
  }
};

static const A a;

int
main()
{
  return 0;
}

I'll make changes accordingly.

Actions #21

Updated by Junxiao Shi about 9 years ago

  • Status changed from In Progress to Code review
  • % Done changed from 50 to 100
Actions #22

Updated by Junxiao Shi about 9 years ago

  • Status changed from Code review to Closed
Actions

Also available in: Atom PDF