0

The glfw3-library can be made to include vulkan using a definition before the include:

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

i want to do a similar thing, but for debug vs non-debug-mode. I tried the following:

main.cpp:

#define DEBUG_ENABLED
#include "someFile.hpp"

someFile.hpp:

#ifdef DEBUG_ENABLED
  std::vector<const char*> _debugExtensions = {
    VK_EXT_DEBUG_UTILS_EXTENSION_NAME
  };
#endif
#ifndef DEBUG_ENABLED
  std::vector<const char*> _debugExtensions = {};
#endif

I checked if that 'passing of definitions' across the header-files worked, by printing the size of the vector, but received zero which indicates that the compiler didn't consider the DEBUG_ENABLED to be defined inside the someFile.hpp.

I then looked on stackoverflow to see how i could react to the definitions of an extern file, and found this post:

Is it possible to use #define from other cpp file?

The accepted answer there claims that

Defines inside a source file aren't seen by other translation units. Implementation files are compiled separately.

My problem with this answer is that my experience tells me the contrary, as the included glfw mentioned above clearly reacted to the GLFW_INCLUDE_VULKAN definition i made.
How might one be able to achieve such behaviour (being able to react to definitions made in an extern source-file) ?

  • 1
    1. How is `VK_EXT_DEBUG_UTILS_EXTENSION_NAME` defined? 2. Can you show a [mcve] which will demonstrate which file (and how) did the size query? – Angew is no longer proud of SO Jul 23 '19 at 20:17
  • 1
    You probably want to define your constant on the compilers command line - like `-Dfoo`.. – Jesper Juhl Jul 23 '19 at 20:22
  • 1
    I suspect not all cpp that include `someFile.hpp`, directly or indirectly defines the same thing. – Guillaume Racicot Jul 23 '19 at 20:30
  • 3
    I think you're confusing translation unit with source file, they're not the same thing. A translation unit is a source file after all the `#includes` have been replaced with the included files (and other preprocessing has been completed). Incidentally your example should have worked, so I think there's some other issue with your code. – john Jul 23 '19 at 20:31
  • 1
    Also, try marking your global `constexpr` and use `std::array` instead of vector. that will make use of constant initialization so it's immune to the order of initialization problem. – Guillaume Racicot Jul 23 '19 at 20:32
  • @GuillaumeRacicot i guess that might be the problem. Trying to implement a "minimal reproducible example" , i now stumbled upon multiple-definition compiler-errors.. – LeonTheProfessional Jul 23 '19 at 20:39
  • @Angew it was a tough decision, but i decided to add the example you asked for in an answer, as it answers part of my question, and i felt that my findings might obscure the assumptions in my initial question. – LeonTheProfessional Jul 23 '19 at 21:20

1 Answers1

-1

I was asked to create a "minimal reproducable example".
This example showed that the problem really is a different one that i assumed.
The example was successfull in not reproducing the error, but it helps to answer a part of my initial question.

Don't consider this a good solution! This example is provided for clarification of cpp's behaviour, not as a solution to implement in a project!

main.cpp:

#define DEBUG_ENABLED
#include "someFile.hpp"

int main() {
    Test test = Test();
    test.doCount();

    return 0;
}

someFile.hpp

#pragma once

#include <vector>

class Test {
public:
    #ifdef DEBUG_ENABLED
        std::vector<const char*> _debugExtensions = {
            "one",
            "two"
        };
    #endif
    #ifndef DEBUG_ENABLED
        std::vector<const char*> _debugExtensions = {};
    #endif

    void doCount();
};

someFile.cpp:

#include <stdio.h>

#include "someFile.hpp"

void Test::doCount() {
    printf("count: %lu", _debugExtensions.size());    
}

compiling, and running this with:

g++ -g main.cpp someFile.cpp -o out
./out

shows that definitions indeed get preprocessor-directives in included header-files to react accordingly. The misbehaviour (as pointed out by comments) results from different includsions of the header, of which only a subset defines the DEBUG_ENABLED.

The example here is still prone to that problem!!

(credits to the people commenting)
For a solution there are multiple possibilities:

  1. define the constant in question using your compiler, like so:
g++ -DDEBUG_ENABLED
  1. make sure that the file(s) that have behaviour dependant on the definition of such a constant only get included from a single translation-unit, or that all translation-units are consistent regarding the definition of the constant. This pretty much rules out the possibility of keeping seperate .h(.hpp) and .cpp files.
  • 1
    Simple: once you include such a header file inconsistently in a program (i.e. once with the define, once without it), you have violated the One Definition Rule and as such your program is ill-formed (though no diagnostic required). In other words properties of valid C++ programs no longer apply to it, and it can thus do literally anything. That also includes working as expected in one example program and differently in a different program. – Angew is no longer proud of SO Jul 24 '19 at 08:16
  • 1
    This is not a good solution. You *have* to define `DEBUG_ENABLED` in each and every file that include your class, or in none at all. You are still hitting ODR violation. – Guillaume Racicot Jul 24 '19 at 12:42
  • @GuillaumeRacicot i know, i didn't provide this answer as a good solution, and i am aware of the problems, as i point out in my answer.. I still consider it to be answering part of my question, which was if definitions made in one file get consisted across includes. – LeonTheProfessional Jul 24 '19 at 16:47