0

I want to make sure resource image files that I pass to my gui are actually there during compile time. something like

load_image(static_assert(!(std::filesystem::exists(pathToFile)), "Resource file " + std::string(pathToFile) + " does not exist"));

This seems to require std::filesystem::path to be constexpr. Is this possible or can I only do this through build tools?

The goal of this would be to catch simple mistakes at compile time before it leaves our desks and goes through the QA process.

A number of people pointed out that the files may have moved on the users system after distribution. this is both untrue and misses the point. It's an arcade game. we have full control over the whole system. the program and resources get baked into an OS and the user has no access to files to move anything. It misses the point by assuming I'm relying on this to prevent run time errors. I am not. I am attempting to prevent one type of error as early as possible. it is not meant to be the only way in which we attempt to prevent errors.

Aaron
  • 81
  • 2
  • 9
  • 6
    No, you can't do that. Sounds very much like a xy-problem. – πάντα ῥεῖ Apr 13 '23 at 21:38
  • `static_assert` is a compile time construct. The file might be present during compilation, but you can still delete it afterwards – 463035818_is_not_an_ai Apr 13 '23 at 21:40
  • 2
    Why would you want to test if a file exists at compile time? It could be gone two ms after you test, it could be created one ms before you test. What is the point of this test? – Jesper Juhl Apr 13 '23 at 21:42
  • 3
    I think the motivation is pretty clear from the question. The files are resource files that are meant to be there and this is a sanity check to catch a missing file earlier than runtime. If a TOCTTOU happens to occur for some reason (when the resource file presumably isn't supposed to be deleted during or after a build anyway), big deal, that one freak occurrence will be caught at runtime instead of earlier. – chris Apr 13 '23 at 21:47
  • We have an executable build step and a data processing step. If the code build succeeds then the data verification/cook uses a manifest file to validate that all required resources exist and where necessary converts assets from whatever source format to the binary format the program requires. You might consider something like that. – Retired Ninja Apr 13 '23 at 21:51
  • 4
    @chris: "*The files are resource files that are meant to be there and this is a sanity check to catch a missing file earlier than runtime.*" "earlier than runtime" makes absolutely no sense. The executable may be running on an entirely different machine. Or it could just be run 3 weeks after compilation. This only makes sense if you're only ever going to run the program instantly after compiling it. If the program needs that file to exist when it is run, then it needs to check this *when it is run*, not when it is *compiled*. – Nicol Bolas Apr 13 '23 at 21:53
  • 1
    @chris is correct. it is a sanity check. later in the build process an OS image is created and everything needed to run this stand alone process is merged into that image (think arcade game). sure it's possible a file was deleted in between but it's a sanity check to make sure you aren't making a simple mistake that might get past QA or just plain not find out about right away – Aaron Apr 13 '23 at 21:58
  • Nothing in-language. Maybe the output of a directory listing massaged into a bunch of strings fed into grep or a similar? – user4581301 Apr 13 '23 at 22:02
  • @NicolBolas the executable can't be running on a different machine it's an arcade game we build the entire os image and put our program in there. the user can not modify files on the machine. – Aaron Apr 13 '23 at 22:06
  • 1
    @NicolBolas, The way I make sense of it is that there are two checks, one unnecessary check early on as an easy mistake catcher and one later doing the final validity test (that would be making sure input succeeds rather than an existence check). You can remove the first one entirely without breaking things, but having a redundant check earlier in the process saves you some time whenever it catches something earlier. And specifically in this context, the files have extra "lifetime" expectations that make the earlier check more likely to be useful than it would otherwise be. – chris Apr 13 '23 at 22:07
  • 2
    @Aaron: "*later in the build process*" Then that should be part of the build system, not the language you're building the application in. After all, it's the build system that requires it, not C++. – Nicol Bolas Apr 13 '23 at 22:09
  • @NicolBolas that would make sense, but then how would I make sure that every usage of a file system path in the code is matched against something in the build system that checks to make sure that file is there during the build? – Aaron Apr 13 '23 at 22:10
  • 1
    @Aaron You have some construct in the C++ code that the build system detects and checks for in a pre-compile step. This is not particularly uncommon. I have some code that has special macros that both affect the code and cause the build system to run particular pre-compile checks because they access an immutable data base that must have corresponding entries for the code to work. – David Schwartz Apr 14 '23 at 02:29
  • The problem isn't so much you have redundant checks. The problem is you are torturing the language to do something entirely outside its intent. Like Nicol Bolas said, this is something belonging squarely in build systems. – Passer By Apr 14 '23 at 03:19
  • 2
    This looks to be a perfectly valid and answerable question. In fact, there already is at least one answer to the question in the comments (by Nicol Bolas). Note that an answer explaining why something is not possible (or even shouldn't be done) is a valid answer. Voting to reopen. – cigien Apr 14 '23 at 14:18
  • 1
    You may consider abusing `__has_include` for this purpose, if you're feeling slightly chaotic. – ildjarn Apr 15 '23 at 20:03
  • @ildjarn oh my that looks fun! – Aaron Apr 20 '23 at 13:37

1 Answers1

1

The warning and caveats mentioned in the comments not withstanding, if I really needed to check for the existence of a file using the compiler, I would abuse the preprocessor and try something like the following:

#if __has_include("path/to/resource/file")
#error "Resource file not found"
#endif

Again, I am not sure this is a good idea, but I think it will work.

Edit

As pointed out by @user17732522 in the comments, __has_include is part of C++17.

RandomBits
  • 4,194
  • 1
  • 17
  • 30