New #ifver/#ifnver preprocessor directive for version checks

Discussion among members of the development team.

Moderator: Forum Moderators

Post Reply
User avatar
Iris
Site Administrator
Posts: 6797
Joined: November 14th, 2006, 5:54 pm
Location: Chile
Contact:

New #ifver/#ifnver preprocessor directive for version checks

Post by Iris »

Hi there!

After pondering for a while the consequences of the extended 1.9.x development cycle for UMC developers like me, I decided to give the implementation of some basic preprocessor-level version checking a shot. It turned out to be significantly easier to implement than I originally thought.

The idea is to allow UMC coders to include code in their add-ons that is expanded according to the outcome of comparing a specified Wesnoth version with the actual version number of the game build that’s running the preprocessor, like follows:

Code: Select all

[event]
    name=start
#ifver >= 1.9.8
    [message]
        speaker=narrator
        message= _ "I’m on Wesnoth 1.9.8 or later!"
    [/message]
#else
#ifver == 1.9.7
    [message]
        speaker=narrator
        message= _ "I’m on Wesnoth 1.9.7, and I’ll include some workaround code for bug #9001!"
    [/message]
#endif
#endif
As you can see, it’s very similar in essence to using #ifdef MACRO or #ifhave path/to/file, except that version strings are compared using C-like operators (<, <=, >, >=, ==, !=).

The following patch adds the necessary code to the preprocessor module to implement these directives. You may apply it with patch -p1 < ifver_patch.diff on the top source dir if you want to test. It should apply cleanly against trunk as of [rev]48971[/rev].
ifver_patch.diff
(3.39 KiB) Downloaded 1312 times
However, I figured that before committing this to trunk I’d ask for opinions on whether this is really the most useful way to provide this functionality. It might be feasible to compare an arbitrary macro against a version number, instead of comparing always against the engine version. This could be useful for add-ons that use eras, for example, to warn the user if he/she tries to run them with buggy/outdated era versions.

Misuse of that option could lead to suboptimal scenarios, for example if a large multiline preprocessor macro’s contents are checked instead of a plain single-line string.

Nonetheless, considering this option I committed a change in [rev]48971[/rev] that defines a special WESNOTH_VERSION macro with Wesnoth’s version number as its contents that can already be used by plain WML or Lua code for other runtime conditionals. As a bonus, it might possibly be used to check for the existence of the #ifver/#ifnver directive without crashing if the latter is finished and committed before 1.9.5 is released.

In that case, the previous example would turn into the fragment below:

Code: Select all

[event]
    name=start
#ifver WESNOTH_VERSION >= 1.9.8
    [message]
        speaker=narrator
        message= _ "I’m on Wesnoth 1.9.8 or later!"
    [/message]
#else
#ifver WESNOTH_VERSION == 1.9.7
    [message]
        speaker=narrator
        message= _ "I’m on Wesnoth 1.9.7, and I’ll include some workaround code for bug #9001!"
    [/message]
#endif
#endif
Additionally, I’m not sure if C-like operators (which feel natural to me as I write code mainly in Perl, C++ and PHP) is what this functionality should use, at least in the equal/not equal case, which could use “eq” and “ne” instead, or as an alternative.


EDIT (2): Added WML sample for the alternative proposal.
EDIT (3): No, the final patch won’t have so much code duplication.
EDIT (4): VERSION renamed to WESNOTH_VERSION in [rev]48975[/rev].
Author of the unofficial UtBS sequels Invasion from the Unknown and After the Storm.
User avatar
zookeeper
WML Wizard
Posts: 9742
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Re: New #ifver/#ifnver preprocessor directive for version ch

Post by zookeeper »

Proper version checking finally made possible? Awesome.

However, does this work on major branch versions? That is, will "#ifver < 1.10" be true on 1.9.8, or do I need to use "#ifdef < 1.10.0"?
Max
Posts: 1449
Joined: April 13th, 2008, 12:41 am

Re: New #ifver/#ifnver preprocessor directive for version ch

Post by Max »

this is indeed awesome^^
the comparison is smart enough to handle major/minor/rev combinations. even things like +svn are considered.

if you could add a IFVER_AVAILABLE symbol this could even be used for combining 1.8/1.9 branches of umc.
User avatar
Iris
Site Administrator
Posts: 6797
Joined: November 14th, 2006, 5:54 pm
Location: Chile
Contact:

Re: New #ifver/#ifnver preprocessor directive for version ch

Post by Iris »

Max wrote:if you could add a IFVER_AVAILABLE symbol this could even be used for combining 1.8/1.9 branches of umc.
#ifdef WESNOTH_VERSION can be used to that effect now.

I have just committed the implementation of #ifver and #ifnver in [rev]48984[/rev] based on the second proposal in the OP. They are also now documented in the wiki.

Code: Select all

#ifver WESNOTH_VERSION >= 1.9.7+svn
    [message]
        speaker=narrator
        message= _ "I’m on Wesnoth 1.9.7+svn, 1.9.8 or later!"
    [/message]
#else
#ifver WESNOTH_VERSION == 1.9.7
    [message]
        speaker=narrator
        message= _ "I’m on Wesnoth 1.9.7, and I’ll include some workaround code for bug #9001!"
    [/message]
#endif
#endif
Defining and publishing custom version numbers for eras and other types of add-ons should theoretically be as easy as providing a custom version define like follows:

Code: Select all

#define ERA_OF_FAIL_VERSION
    0.4.1a
#enddef
The current caveats:
  1. The define that is to be compared should consist entirely of plain text. If it contains code inclusions ({}) or preprocessor directives, those will not be resolved, and will be taken literally instead. This is for the sake of simplicity in the initial implementation, and if someone else thinks they can provide a patch to do complete expansion in this context safely, be my guest.
  2. The define may not have arguments for the same reasons.
Point (1) should not be a problem in any case I can imagine at the moment, other than the following:

Code: Select all

#define ALIAS_OF_WESNOTH_VERSION
    # Silliness ensues...
    {WESNOTH_VERSION}
#enddef
Version numbers are supposed to be plain old constant data defined directly by the content author, after all.
Author of the unofficial UtBS sequels Invasion from the Unknown and After the Storm.
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: New #ifver/#ifnver preprocessor directive for version ch

Post by Anonymissimus »

How does this feature cope with mp content ?
For #ifhave I asked silene:
silene wrote:...only the host preprocesses the scenario; it is then sent to all the other clients through the server. So only the host is actually testing #ifhave.
So I guess for #ifver it's similar, the result of the #ifver evaluation is sent to the other clients, meaning that they can be sent wml which is invalid for their BfW version. This must be mentioned in the documentation as it's done for #ifhave:
note: For a multiplayer game, the #ifhave directive works only for the host, not for the other clients.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
User avatar
Iris
Site Administrator
Posts: 6797
Joined: November 14th, 2006, 5:54 pm
Location: Chile
Contact:

Re: New #ifver/#ifnver preprocessor directive for version ch

Post by Iris »

I believe it’s fairly obvious that the same applies to anything that’s controlled by the preprocessor, but if you feel that’s a necessary addition to the documentation, be my guest.
Author of the unofficial UtBS sequels Invasion from the Unknown and After the Storm.
Post Reply