3

I guess this is not possible (yet) but not sure. I need to do conditional compilation based on current date. Something like:

#if (__CURRENT_YEAR < 2016)
...
#endif

I need to exclude something from project after some months and be sure that this will not be forgotten (in future releases).

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
i486
  • 6,491
  • 4
  • 24
  • 41
  • 3
    You may want to take a look at this SO post : http://stackoverflow.com/a/16472369/949297 – Nicolas Riousset Sep 09 '15 at 14:10
  • 8
    I would go for fixing that in the buildsystem, let it determine the date (using an appropriate shell function), and generate a define injected via `-D` option. – πάντα ῥεῖ Sep 09 '15 at 14:12
  • I agree. But it is relatively complex and indirect solution. My question was to check whether I have omitted something from today's preprocessor features. – i486 Sep 09 '15 at 14:14
  • 3
    "I need to exclude something from project after some months and be sure that this will not be forgotten" The solution to this isn't C programming but version control. Create a branch of your current version, where you can keep the "extra stuff", then in the trunk, remove the "extra stuff". – Lundin Sep 09 '15 at 14:24
  • 1
    @Lundin Who will "remove the extra stuff"? Person. The same person can change `#define _TEMP_PART 1` to `0`. What is the difference? I want to do this automatically in future compilations. PS: The question is partially theoretical. I can implement this as πάντα ῥεῖ says if necessary. – i486 Sep 09 '15 at 14:36
  • 2
    @i486 To obfuscate your program with date-based pre-processor goo just because you worry about the human memory is a poor argument. The human who writes the obscure pre-processor goo is far more likely to fail than the human who selects the release version. Anyway, the whole point with version control is that you set up routines that the humans have to follow. Upon release you would probably create a "tag", which forces you to consider where to get that tag from, the branch or the trunk. Which in turn forces you to consider why you made a branch in the first place. Ah, the extra stuff. – Lundin Sep 09 '15 at 14:41
  • 1
    If your goal is to prevent forgetting about it in future versions, why use the year at all? Presumably you already have a version number somewhere (let's say 2.8 currently), so why not use something like `#define REMIND_ON_NEXT_VERSION (VER_MAJOR > 2 || VER_MAJOR == 2 && VER_MINOR > 8)` – MooseBoys Sep 09 '15 at 14:49
  • 1
    I concur that it is better to fix this in the build system. What if some time in 2017 you need to build a copy of a 2015 version of the project? But I think it would be *even better* to use an issue tracking system to remember that after the end of 2015 you want to cut out the affected code. Then you can always build whatever version you check out from your version-control system without jumping through any extra hoops. – John Bollinger Sep 09 '15 at 14:57

2 Answers2

6

In your Makefile add

CFLAGS += -DYEAR=$(shell date +%g)

Then in your C source:

#if (YEAR < 16)
....
#endif
qrdl
  • 34,062
  • 14
  • 56
  • 86
  • I think you want [`+%Y`](http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/) instead of `+%g`. – MooseBoys Sep 09 '15 at 14:54
  • @MooseBoys Did you check `+%g` first? – qrdl Sep 09 '15 at 14:58
  • FWIW, in CMakeLists.txt that'd be `string( TIMESTAMP YEAR "%Y" )` and `add_definitions( -DYEAR=${YEAR} )` for the same effect (four-digit year, though). ;-) – DevSolar Sep 09 '15 at 15:00
  • Before you use %Y, check that your source code control system does not substitute it with something else after you've checked in the file – cup Sep 09 '15 at 15:20
  • @qrdl The doc page says `+%g` is the 2-digit *week* number. – MooseBoys Sep 09 '15 at 15:22
  • @MooseBoys I don't know which doc you are referring to - I use `man` – qrdl Sep 09 '15 at 16:30
  • @qrdl According to [this page](http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/), `%g` gets the year based on the week number. So for example, in 2016, on Jan 1 through Jan 3, `%g` will still return `15` since it will be week 53 of 2015 until Jan 4 (weeks are defined to start on Monday). `%y` should return `16` beginning Jan 1. – MooseBoys Sep 09 '15 at 17:12
  • @cup: If it does, trash it and use something else. I've never heard of a version control software touching something as innocous as `%Y`, and would consider it broken beyond repair, especially considering e.g. `printf()` using those `%d` and `%s` things all day. – DevSolar Sep 10 '15 at 08:48
  • You'd better not use SCCS then. It is not %y but %y%. So if you have something like %y%m%d%h, the %y% and %d% will be substituted. – cup Sep 10 '15 at 10:55
0

Something like this isn't possible with the C preprocessor, but could be solved at a higher level via your build system. You could build some scripting that would auto-generate a header at build time that contains something like:

#define __CURRENT_YEAR 2015

This header would then be included by your code that is date-sensitive. Depending upon the implementation of your build system, you could do this automatically at each build or if a year change is detected.

Jason R
  • 11,159
  • 6
  • 50
  • 81
  • 2
    @BrianMcFarland: But `__DATE__` is a string constant, not usable in preprocessor expressions, so I'm not sure how it could solve the OP's problem. It's possible I'm not seeing something, though. – Jason R Sep 09 '15 at 14:10
  • Ok, but how to get year or month from `__DATE__`? `__DATE__` is useful to put current date in compilation. – i486 Sep 09 '15 at 14:11
  • @JasonR _"... not usable in preprocessor expressions ..."_ Well, look at the linked Q&A from the 1st comment. – πάντα ῥεῖ Sep 09 '15 at 14:13
  • @πάνταῥεῖ: As I said, you can't use constant strings in preprocessor `#if` expressions. Give the solutions on that page a try and you'll see that they aren't suitable for the OP's desired application. Those pages just define macros that are expanded upon later use. If you use them in other contexts (e.g. initializing string variables), the approach works fine. However, the preprocessor doesn't support strings within `#if` expressions. – Jason R Sep 09 '15 at 14:21
  • 1
    @πάνταῥεῖ The A in question uses `__DATE__` only in expansions. – molbdnilo Sep 09 '15 at 14:24
  • Correct on "should be solved at a higher level via your build system" (as qrdl's answer showcases). Needlessly complicated in the suggested solution though (as qrdl's answer showcases). – DevSolar Sep 09 '15 at 14:55
  • You _can_ generate a C++ constant expression and use that in a `std::enable_if::type main(int, char**)` – MSalters Sep 09 '15 at 14:56
  • 1
    @JasonR: I thought you could extract the year & convert, i.e. `__DATE__[7]*1000`, but this doesn't compile, so you were right. If you make an edit, I can un-downvote if you care. – Brian McFarland Sep 09 '15 at 15:31