finatronics (finatronics) wrote in cprogramming,


I'm trying to figure out how to get the original path to a header file as a string in my program for version-control purposes...

I've tried using the predefined __FILE__ macro, but it's only giving me the filename itself "fileInfo.h" and none of the path info. Most important, actually, is the folder name the file is contained within, I don't even care about the filename!

As a quick method for version control, I tend to keep my versions separated by duplicating the folder of the previous version and modifying the folder name to contain the version number and a quick overview of the changes... for instance /Cprojects/FlyingRabbits/123-flyHigher/ contains version 123 of the FlyingRabbits project and what makes it different is that the rabbits fly higher in 123 than in 122... I'm open to suggestions of other methods of version control, but I don't want to have to learn CVS or something, this method has worked perfectly fine for my needs for 5 years and doesn't require any additional software or time-consuming editing of versionInfo.txt documents... The only problem is that I keep forgetting which version numbers are on which microcontrollers, and reading them with a chip reader and having to compare checksums with all my backups is getting to be a pain... Ideally I want to store "FlyingRabbits/123" in the program memory, so I can easily tell what it is using a chip reader...

The odd thing is, I can find a whole bunch of sites claiming that __FILE__ is supposed to be the entire path, but it's obviously not in my case. I'm using [avr-]gcc version 4.1.2

Ideas? Thanks!
  • Post a new comment


    default userpic
This comment is not going to answer your question. Sorry about that.

(However, I can confirm that the gcc 4.1.3 package for gutsy does replace __FILE__ with the full filepath).

Anyway, I don't mean to be a contrarian biatch, but learning CVS (or something more modern) is probably going to be less intellectually taxing, and more useful, than solving this problem the way you want to.

I'd recommend the tool Mercurial in your case ... it's extremely easy to use and doesn't require a server setup. Trust me, it's a total no-brainer (assuming you're on an OS that packages it or something similar).

Thanks for the suggestion!

It's not that I'm unintellectually-capable, nor is it that I don't want to learn something new. It's that I don't want to have to run yet-another-program every time I want to do something I can simply do now using right-click copy-paste, and a few quick keystrokes to enter the new version number and changes. The same could be done just as easily with cp -r, but I have what I consider a pretty healthy balance of mousing and command line-ing around in my life. Maybe I should just write a script to enter that info into main.c after copying the project directory... or maybe that's just as easy as using Mercurial or CVS? I'm not yet convinced, but I suppose it wouldn't hurt to read about them. Unless, of course, the time spent reading excedes the amount of time it would take total for me to retype the version number in each main.c over the next two years ;p

Oh, and I'm using Windows (yay!), so no prepackaged version managers ;)
Heh, that was me...

Thanks again. Maybe it's time I finally install that not-so-new-anymore 160GB hard drive in my laptop and load linux like I've been planning for almost a year...
No problem.

First of all, on Windows there's always cygwin, which from memory has a Mercurial package. Bit of a pain to install but you can keep everything else the same.

Secondly, Linux is far easier to install and set up than it ever used to be. I'm an Ubuntu user and these days it seems far quicker and somewhat easier to install / configure a new machine with Linux than it is with XP.

Mercurial version control goes something like this:
hg init (creates a local sekrit directory to store tracking information for the current tree)
  (edit files)
hg commit -m "some log message describing what I've been doing"
  (edit files ... oh shit screwed up)
hg revert *filename* (reverts files you've screwed up)
  (edit files ... oh shit when did this last work?)
hg log *filename* (displays all commits/messages to this file since you initialised the local repo)
hg update -r *revision number* (reverts tree to older revision)
And if you and someone you know are working on the same thing you can push changesets between each other's repositories with minimal fuss.

I recall version control being moderately intimidating when I first started using CVS years and years ago, but trust me it is a great way to stop shooting yourself in the foot (and then wasting all that time on reconstructive surgery).

If you switch to Linux, and I think it's much better environment for s/w dev, you may want to try Cervisia, a graphical front end to CVS.

It's that I don't want to have to run yet-another-program every time I want to do something I can simply do now using right-click copy-paste, and a few quick keystrokes to enter the new version number and changes.

This could even be a satisfactory argument for your short-term, current-project context, but in the mid-to-long term learning and using a version control system has benefits you may not realize you're missing. CVS, SVN, etc, are not just additional tools; they're ubiquitous tools that enable a wide variety of approaches to writing code that are inaccessible to you right now. The feature set that you're looking for at this moment is just a small part of what you will ultimately end up enjoying; may as well learn one of these necessary tools ASAP so you can begin reaping the benefits sooner rather than later.

Services such as CVSDude offer free cvs and svn; Windows utilities like Tortoise make using version control easy. These tools want to make friends with you and are easy to get. You don't need to learn to run your own server or install Linux. Install Tortoise, use someone else's SVN server, and get started right away. Life can be better than this.

__FILE__ is defined as “The presumed name of the current source file (a character string literal)”; there is no guarantee available that it's the full path and traditionally it is often not. Those sites are incorrect.

The best option for getting a revision identifier into the code is an auto-generated source file with a string constant or a macro definition.

Proper revision control systems aren't that hard to learn and are a considerable improvement over the lots-of-copies system.

I guess the text you found that confused you was “This is the path by which the preprocessor opened the file, not the short name specified in `#include' or as the input file name argument.” from the GNU C manual. This doesn't mean that it gives absolute paths, it means that it uses the name that was passed to fopen(). So you get to see the result of searching the include path, but not the effect of prepending the current directory.

Deleted comment

In GCC it does what the manual says it does, which is not the same as “the path it was passed”. Your example doesn't show this because it's not complete.

In general, it's implementation defined (the specification being rather vague).

__DATE__ and __TIME__ are also available almost everywhere, if you just want a string in the binary.

After that I'd seriously recommend creating some kind of real build program that embeds an actual version into your code (POSIX sh, make, python/scons, whatever).