Bug 2370 – Version statement enhancement: versioned identifiers
Status
RESOLVED
Resolution
INVALID
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2008-09-22T21:18:26Z
Last change time
2019-08-20T11:28:08Z
Assigned to
No Owner
Creator
Sergey Gromov
Comments
Comment #0 by snake.scaly — 2008-09-22T21:18:26Z
I propose version identifiers to have a numeric value and to add the following version statement syntax:
VersionCondition:
version ( Identifier, Integer )
This version condition is satisfied when the Identifier's value is equal or greater than the Integer. This way, the code in
version (D_Version, 2)
{
...
}
will be compiled only when the compiler version is 2 or greater. The version specification syntax can be
VersionSpecification:
version = Identifier ( Integer ) ;
Comment #1 by jarrett.billingsley — 2008-09-22T22:27:15Z
Please please please. It seems odd that such an obvious use of preprocessor macros for versioning was not carried forward into D.
Comment #2 by benoit — 2008-09-23T03:41:06Z
This would have helped me a lot in the past.
Comment #3 by shro8822 — 2008-09-23T13:34:31Z
Vote += Lots
Comment #4 by bruno.do.medeiros+deebugz — 2008-10-03T10:04:53Z
Like I said in the original thread, isn't it enough to have:
version(D_Version_2OrAbove) { ...
?
Or just
version(D_Version1) {
...
} else {
//version 2 or above here...
}
?
It doesn't seem this feature is justified.
Comment #5 by snake.scaly — 2008-10-03T10:53:09Z
(In reply to comment #4)
> Like I said in the original thread, isn't it enough to have:
> version(D_Version_2OrAbove) { ...
> ?
> Or just
> version(D_Version1) {
> ...
> } else {
> //version 2 or above here...
> }
> ?
> It doesn't seem this feature is justified.
Imagine I've got MyLib v.21. There was nice API introduced in v.17 and I have a special cased code which should work from version 17 on. In my approach:
module myapp;
import mylib;
version(MyLib, 17)
{
NiftyMyLibCall();
}
else
{
...lots of code...
}
module mylib;
version = MyLib(21);
In your approach I'm either going to have 21 version statements in mylib which is tedious, error-prone and is hardly automated, or I must have 5 version clauses in my source which all mix in the same piece of code
and I must add new version clause every time a new version of lib is published.
Comment #6 by bruno.do.medeiros+deebugz — 2008-10-03T11:31:19Z
If you add a specific feature in a given version, it's best (clearer) to add a:
version = NiftyMyLibCallAvailable;
and then use:
version(NiftyMyLibCallAvailable)
{
NiftyMyLibCall();
}
instead of version numbers.
In any case, when releasing a new version:
Your approach:
* go to the 'version = MyLibVersion(20);' statement
* change it to 'version = MyLibVersion(21);'
My approach:
* go to the 'version = MyLibVersion20OrAbove;' statement
* add a 'version = MyLibVersion21OrAbove;' statement
How is my approach any more tedious, error-prone, or less automated? They are both one line changes you have to make (mine has an extra copy&paste), and they are both dead easy to make. My approach may end up with more code written, but that's hardly ever more error-prone, since that code is not supposed to change or be maintained (one doesn't usually downgrade the version number of a lib).
Comment #7 by snake.scaly — 2008-10-03T15:46:25Z
(In reply to comment #6)
> If you add a specific feature in a given version, it's best (clearer) to add a:
> version = NiftyMyLibCallAvailable;
> and then use:
> version(NiftyMyLibCallAvailable)
> {
> NiftyMyLibCall();
> }
> instead of version numbers.
Is there *any* library around that has a version/#define for every single interface and every single change in that interface? I don't think so, it's just not feasible.
> In any case, when releasing a new version:
> Your approach:
> * go to the 'version = MyLibVersion(20);' statement
> * change it to 'version = MyLibVersion(21);'
>
> My approach:
> * go to the 'version = MyLibVersion20OrAbove;' statement
> * add a 'version = MyLibVersion21OrAbove;' statement
>
> How is my approach any more tedious, error-prone, or less automated? They are
> both one line changes you have to make (mine has an extra copy&paste), and they
> are both dead easy to make. My approach may end up with more code written, but
> that's hardly ever more error-prone, since that code is not supposed to change
> or be maintained (one doesn't usually downgrade the version number of a lib).
A version number in one particular place can be replaced by a script, or by a version control system. It's significantly harder to add a line automatically.
Though adding a line for every version is definitely much better than adding a version statement for every interface change.
Comment #8 by shro8822 — 2008-10-03T15:55:46Z
Several of the comments seem to be forgetting that "version = bob" in an imported file has no effect on "version(bob)" statements in the importing file.
importer.d:
import imported;
version(bob) { pragma(msg,"bob"); }
else { pragma(msg,"!bob"); }
imported.d:
version = bob;
output:
!bob
Comment #9 by snake.scaly — 2008-10-03T16:10:25Z
(In reply to comment #8)
> Several of the comments seem to be forgetting that "version = bob" in an
> imported file has no effect on "version(bob)" statements in the importing file.
You're right. This is a very strange and undocumented behavior. Well, this adds more value to my proposal: writing 21 version statements in command line is... well, tedious.
Comment #10 by dfj1esp02 — 2008-10-09T07:06:52Z
(In reply to comment #0)
why do you think that code working for d2 will work for d3?
Comment #11 by snake.scaly — 2008-10-09T07:22:19Z
(In reply to comment #10)
> (In reply to comment #0)
> why do you think that code working for d2 will work for d3?
It's my best guess that D3 will likely support D2 way of doing things rather than D1, if at all. If I'm wrong I'll fix my version statement to support whatever D3 requires. But if I'm right I won't be needing to change anything.
Note that D version is only an example. This sort of version compatibility is required when you need to support multiple versions of a library or a host application. If I write a plug-in for 3dsmax that must support versions 8, 9, 2008, 2009 and as many future versions as possible, and I know that a particular API is only available from 9 onwards, I put its use under version(max,9) and hope that 2010 will support it as well.
Comment #12 by bruno.do.medeiros+deebugz — 2008-10-15T09:57:56Z
(In reply to comment #7)
> (In reply to comment #6)
> > If you add a specific feature in a given version, it's best (clearer) to add a:
> > version = NiftyMyLibCallAvailable;
> > and then use:
> > version(NiftyMyLibCallAvailable)
> > {
> > NiftyMyLibCall();
> > }
> > instead of version numbers.
> Is there *any* library around that has a version/#define for every single
> interface and every single change in that interface? I don't think so, it's
> just not feasible.
I've seen the equivalent, in Java. Namely in Eclipse, where the API is managed through the use of interfaces. Whenever new functionality is added, they don't changed the existing interface, but add a new one, with a name like IFooExtension4 Example:
http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextViewerExtension7.html
There are dozens of interfaces like that. (although few reach as many as a 7th version)
(In reply to comment #8)
> Several of the comments seem to be forgetting that "version = bob" in an
> imported file has no effect on "version(bob)" statements in the importing file.
Dang, forgot about that indeed.
(In reply to comment #9)
> (In reply to comment #8)
> > Several of the comments seem to be forgetting that "version = bob" in an
> > imported file has no effect on "version(bob)" statements in the importing file.
> You're right. This is a very strange and undocumented behavior. Well, this
> adds more value to my proposal: writing 21 version statements in command line
> is... well, tedious.
If you use a proper build tool, editor, or IDE (which you obviously should), you should only have to write these statements *once*, which hardly counts as tedious or even significant.
Comment #13 by bruno.do.medeiros+deebugz — 2008-10-15T10:12:36Z
(In reply to comment #8)
> Several of the comments seem to be forgetting that "version = bob" in an
> imported file has no effect on "version(bob)" statements in the importing file.
>
In fact, I think this fact alone shows that D's version statement mechanism should not be used for version management of user libraries, but only runtime related aspects (the platform/CPU, the compiler, the D version, etc.)
For user libraries, I would suggestion using (manifest) constants to define the lib version, and users of you library could use static if to perform tasks depending on the existing version (including compile-time duck typing like code). Example:
static if(OpenGL.VersionMajor == 2) {
...
static if(is(com.foo.MyLib.myXptoFunc)) { // check if myXptoFunc is available
...
Comment #14 by razvan.nitu1305 — 2019-08-20T11:28:08Z