0

I am working on a open source project (Blender) and have encountered the problem that many source code files like the file I am currently working on don't have the necessary header files #included. For example in the example file class float3 and class KernelGlobals do not have a definition anywhere in the file.

As Blender is an open source project I have all the source code that's needed. The IDE I'm using is Visual Studio 2022 Community Edition and I'm compiling with the compiler set to the C++17 standard.

What's worse is that there usually are multiple source code files defining the same identifier. For example Visual Studio shows 6 files defining class KernelGlobals.

When I then compile the code the Visual C++ compiler gives my an error for every class that doesn't have a definition, yet the whole build still somehow succeds.

I want to stress that I did not modify the files in any way. Everything is exactly the source code for the official Blender build.

  1. How does the build succed, even though it gives hundreds of errors due to missing definition?
  2. How does Visual C++ know which definition to use when there are multiple definitions available, as is the case with e.g. KernelGlobals?
  3. Is this behavior even described by the ISO C++ standard or is it just a Visual Studio thing?

The ouput from a succesful build is:

Build started...
1>------ Build started: Project: cycles_osl_shaders, Configuration: Release x64 ------
2>------ Build started: Project: cycles_kernel_osl, Configuration: Release x64 ------
3>------ Skipped Build: Project: RUN_TESTS, Configuration: Release x64 ------
3>Project not selected to build for this solution configuration 
4>------ Build started: Project: locales, Configuration: Release x64 ------
2>services.cpp
2>cycles_kernel_osl.vcxproj -> C:build_windows_x64_vc17_Release\lib\Release\cycles_kernel_osl.lib
5>------ Build started: Project: cycles_kernel, Configuration: Release x64 ------
5>kernel.cpp
5>cycles_kernel.vcxproj -> C:build_windows_x64_vc17_Release\lib\Release\cycles_kernel.lib
6>------ Build started: Project: blender, Configuration: Release x64 ------
6>   Creating library C:build_windows_x64_vc17_Release/bin/Release/blender.lib and object C:build_windows_x64_vc17_Release/bin/Release/blender.exp
6>blender.vcxproj -> C:build_windows_x64_vc17_Release\bin\Release\blender.exe
7>------ Skipped Build: Project: PACKAGE, Configuration: Release x64 ------
7>Project not selected to build for this solution configuration 
8>------ Skipped Build: Project: INSTALL, Configuration: Release x64 ------
8>Project not selected to build for this solution configuration 
========== Build: 5 succeeded, 0 failed, 156 up-to-date, 3 skipped ==========
Hoshinova
  • 1
  • 2
  • 2
    If it gives **errors**, the build did not succeed. – sweenish Oct 19 '22 at 18:05
  • 1
    Transitive includes. – Jesper Juhl Oct 19 '22 at 18:06
  • Nothing stops header X from including header Y. And usually nothing requires it either. – user4581301 Oct 19 '22 at 18:06
  • I only see one definition of `KernelGlobals` in that repo, [here](https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/intern/cycles/kernel/kernel_globals.h#L53). – Nelfeal Oct 19 '22 at 18:06
  • @JesperJuhl As far as I can tell there isn't a single `#include` statement in the whole file. – Hoshinova Oct 19 '22 at 18:09
  • 1
    Check your terminology: If you get a missing **definition**, that's usually a linker problem and you've forgotten to specify one or more libraries or object files that contain definitions, implementations, of identifiers declared in headers (or elsewhere). A missing **declaration** means the compiler can't find the identifier at all. Sometimes the compilation can continue because the compiler assumes whatever the identifier is to be an `int` for legacy reasons. – user4581301 Oct 19 '22 at 18:09
  • @sweenish that's exactly what I thought, but for some reason the build succeds despite having errors. – Hoshinova Oct 19 '22 at 18:10
  • @user4581301 neither the declaration nor the definition are included – Hoshinova Oct 19 '22 at 18:12
  • @Hoshinova -- "the build succeeds despite having errors" -- I don't know of any compiler that does that. The point of an error is that the code won't compile. What do you see that tells you that the build succeeded? – Pete Becker Oct 19 '22 at 18:13
  • We'll need to see a small sample program complete with the full build output. Get the output from Visual Studio's Output Tab. The Error list can lie. – user4581301 Oct 19 '22 at 18:17
  • @PeteBecker Visual Studio gives the message: `========== Build: 4 succeeded, 0 failed, 151 up-to-date, 0 skipped ==========`. Apart from that when I hit "Local Windows Debugger" it launches Blender after compiling. – Hoshinova Oct 19 '22 at 18:17
  • Note that the file that you linked to in your post is a header file and is not intended to be directly compiled, but included in something else that is compiled. – Avi Berger Oct 19 '22 at 18:21
  • @user4581301 I put the output in the question as it was too long for a comment. – Hoshinova Oct 19 '22 at 18:24
  • @AviBerger that would explain where the missing definitions come from, but given that the file is made up of primarily function definitions wouldn't that violate ODR? – Hoshinova Oct 19 '22 at 18:26
  • @Hoshinova Thank you and the question's the right place for it. Comments can be deleted at any time for any reason, and important details need to be permanent. Plus it's easier to find and format information when it's in the question body. – user4581301 Oct 19 '22 at 18:26
  • Looks like you might need to do a clean build. Too much stuff was omitted because it was previously built. – user4581301 Oct 19 '22 at 18:27
  • @user4581301 I would like to do that, but the output of a clean build is literally a few thousand lines long. Should I still do it, and if so where should I put it? – Hoshinova Oct 19 '22 at 18:30
  • Normally, yes it could lead to ODR issues, but it could depend on precisely how things are handled. I haven't sorted out just how this project is set up, it doesn't seem to be what I would consider the common, typical way of doing it. It seems to resemble, to at least some extent, a [unity build](https://stackoverflow.com/q/847974/631266) which I personally have never dealt with. – Avi Berger Oct 19 '22 at 18:38

1 Answers1

0

First of all, you don't compile header files. You compile translation units, usually made from source files (as in .cpp or .c or .cxx or whatever) that can include other files. The file you link to is a header file and isn't compiled by itself, it's included in other places.

For example, you can have the files A.h, B.h, and S.c where:
A.h defines a type A;
B.h uses the type A but does not include A.h (and does not forward-declare A);
S.c includes A.h and then B.h.
The result is that the translation unit made from S.c first contains the definition of A from A.h and then the uses of A from B.h.

Then, the One Definition Rule says that there must be only one definition of any variable, function or type in any single translation unit. However, there can be any number of declarations. In the repository you link to, there is only one definition of KernelGlobals, the rest are declarations. And even though there are function definitions in some of the header files, none are present multiple times in a translation unit.

Nelfeal
  • 12,593
  • 1
  • 20
  • 39
  • Thanks for your explanation! Is there a way to search for definitions of `KernelGlobals` as opposed to declarations? – Hoshinova Oct 19 '22 at 18:38
  • @Hoshinova Since you're using Visual Studio, I would assume a right-click on any of its declarations will give you the option to jump to the definition. Otherwise you can try searching for `struct KernelGlobals` or `class KernelGlobals`. – Nelfeal Oct 19 '22 at 18:43
  • It seems that Visual Studio's jump option confuses definitions and declaration, as it sometimes jumps to declarations instead of definitions, eventhough I explicitly want to jump to a definition. – Hoshinova Oct 19 '22 at 18:44