General problem with error LNK2005 already defined in cpp.obj

Hey everybody,
I am working with UE for a few month now and already archieved some good results. I have a basic understanding of how things work in C++ but I am not a hard core programmer.
So now my problem I had to deal with a couple of times:
Sometimes in my project I need to include some headers in each other like this:

headerOne.h
#include “headerTwo.h”
headerTwo.h
#include “headerOne.h”

Normaly no problem thanks to
#pragma once
#ifndef HEADERONE_H
#define HEADERONE_H

#endif DBG_HEADERONE_H
Same for headerTwo.h

This worked quiet well, when I had two “empty” classes in which there was defined a value of the typ of the other class. But now several times I needed to do this with actor classes defined like this:

#include “GameFramework/Actor.h”
#include “SomeActor.generated.h”

UCLASS()
class SOMEPROJECT_API ASomeActor : public AActor
{
GENERATED_BODY()

But if I try to deal with it like in the example above, I get “error : UCLASS inside this preprocessor block will be skipped”
Just #pragma once does not work and with out UCLASS it also worked in another case. But now I need the Tick event and there fore UCLASS().

Is this an issue of UE or maybe Visual Studio (I am using Community 2017) or am I just stupid?

Can anybody help me please?

Thanks Robbi
(please excuse mistakes in my english)

Just use #pragma once. It does what the #ifndef/#define stuff does automatically. When you use #ifdef/#ifndef inside UE4 C++ code it confuses UBT – though UBT has its own defines that you can use in the preprocessor.

When compiling code, visual studio will analyze it. If there are no usages of a dll or your code, even if it is included, it will completely ignore it.

Since you said that your classes are empty right now I can assume just that. The solution would be to reference it elsewhere in code. Even if you don’t utilize it, VS will see that and not ignore your code.

At first thanks for your fast answer, but as alredy discribed above #pragma once alone does not work. Can you please tell me which defines in UBT you are talking about? I also added a more specific example to my question.

Ok mabee I need to give more detail. I did something similar to this:
HeaderA:
#pragma once
#ifndef HEADERA_H
#define HEADERA_H

#include “HeaderB.h”
class AHeaderB; // let the compiler know, that it exists

class AHeaderA
{
public:
AHeaderA();
private:
AHeaderB *valueB;
}
#endif HEADERA_H
and opposite for HeaderB. I do not think I have to write it our :wink:
So this works fine but just WITH #ifndef. Just #pragma once gives me error LNK2005. Confusing.
Also works if I set valueB to const, but thats no solution.

Again thanks to everyone who tries to help. Robbi

At Jin_VE
Why ever I can not reply to your answer anymore (mybee because the question is resolved) I will do it here:
Thank you so much for your time and have a nice weekend :slight_smile:

Well, yes it does work. Here’s what it does: pragma once - Wikipedia

You need to remove these lines:

#ifndef HEADERONE_H
#define HEADERONE_H

and the #endif at the end too.

Those are not UBT defines. That is why it isn’t compiling. There are defines that can be used but you shouldn’t worry about those now.

At least, I’m pretty sure that’s what you’re seeing. UProperty wrapped by Marco(#if) doesn't work - Blueprint - Epic Developer Community Forums

If it’s not then maybe show the full class definition. And use the “code block” format so it’s readable.

Here’s another related post Unable to bind delegate (function might not be marked as a UFUNCTION) - Programming & Scripting - Epic Developer Community Forums

You are defining settingTest in the header and it is being included in multiple .cpp files so they all have their own instance and the names are conflicting. In general, with UE4 you should avoid using global variables. You should put ‘global’ things in the GameMode, GameState, PlayerState, or one of a few other places.

That said, to get what you have to compile:

In the .h file, change it to extern int settingTest;

In one of the .cpp files, use int settingTest = 0;

Ok, it actually does work with out #ifndef, I do not know why I thought it would not, sorry for that. So I tried to reproduce the LNK2005 error. I have created 5 files for this:
TestActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestSetting.h"
#include "TestActor.generated.h"

UCLASS()
class SPACEGAME_API ATestActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ATestActor();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;
};  

TestActor.cpp

#include "TestActor.h"

ATestActor::ATestActor()
{
	PrimaryActorTick.bCanEverTick = true;
}

void ATestActor::BeginPlay()
{
	Super::BeginPlay();
}

void ATestActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

SeccondActor.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestActor.h"
#include "SeccondActor.generated.h"

class ATestActor;

UCLASS()
class SPACEGAME_API ASeccondActor : public AActor
{
	GENERATED_BODY()

public:
	ASeccondActor();

protected:
	virtual void BeginPlay() override;

public:
	virtual void Tick(float DeltaTime) override;
};  

SeccondActor.cpp

#include "SeccondActor.h"

ASeccondActor::ASeccondActor()
{
	PrimaryActorTick.bCanEverTick = true;
}

void ASeccondActor::BeginPlay()
{
	Super::BeginPlay();
}

void ASeccondActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

and TestSetting.h

#pragma once
int settingTest = 0;  

This is now every line of code. When i try to compile, I get this:

2>TestActor.cpp.obj : error LNK2005: "int settingTest" (?settingTest@@3HA) ist bereits in SeccondActor.cpp.obj definiert.
2>SeccondActor.gen.cpp.obj : error LNK2005: "int settingTest" (?settingTest@@3HA) ist bereits in SeccondActor.cpp.obj definiert.
2>TestActor.gen.cpp.obj : error LNK2005: "int settingTest" (?settingTest@@3HA) ist bereits in SeccondActor.cpp.obj definiert.
2>TestActor.cpp.obj : warning LNK4006: "int settingTest" (?settingTest@@3HA) ist bereits in "SeccondActor.cpp.obj" definiert; zweite Definition wird ignoriert.
2>SeccondActor.gen.cpp.obj : warning LNK4006: "int settingTest" (?settingTest@@3HA) ist bereits in "SeccondActor.cpp.obj" definiert; zweite Definition wird ignoriert.
2>TestActor.gen.cpp.obj : warning LNK4006: "int settingTest" (?settingTest@@3HA) ist bereits in "SeccondActor.cpp.obj" definiert; zweite Definition wird ignoriert.

“ist bereits in … definiert” means “is already defined in …” and “zweite Definition wird ignoriert” means “seccond defenition will be ignored”.

I even do not use “settingTest” but still get the error. What is going on there and how to prevent it?

Jap, tested it out, works fine. Not the answer I was hoping for but the answer on my question. You explaned what happens there so I think I can mark this as resolved. With this information I will have to think about the structure of my work again.

Thank you for your time and have a nice weekend. Robbi

Hey just remember that global variables may get you into trouble down the line – especially on mobile platforms. GL!

I ran into the same issue with my plugin. It’s very limiting to not be able to specify conditional blocks of code. But UBT (UHT in this specific case) isn’t a compiler, it just scans and generates intermediate source code. It can’t consider compile-time directives without compiling. That’s fair IMO.