🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Redeclarations during linkage, cross-platform compiling with different IDEs

Started by
9 comments, last by _WeirdCat_ 3 years, 8 months ago

It may be an IDE specific problem but i encountered some weirdo voodoo situation with no ideas how to perform next.

I have two different projects (in two different folders) one for windows second for android. (i compile them on windows anyway)

For one i use Android Studio for second one i use RAD Studio, anyway they are two separated project sharing a library folder with source.

basically to share shared libraries i used:

mklink /D c:\anroid\project1/share e:\shared_lib

mklink /D e:\projects\c++\win\project2\share e:\shared_lib

Now shared libraries need to know either i want to compile WINDOWS or LINUX port so in each project root folder (which contains this share folder) i place three fies: PORTDEF.h, PATHDEF.h, PATH_DEF.cpp

where i put defines: (well actually ill show you the code maybe its important however header guards are used)

#ifndef PORT_DEFH
#define PORT_DEFH

//#define WINDOWS_PORT
#define LINUX_PORT


#endif

PATH_DEF.cpp

#ifndef pathdefcpp
#define pathdefcpp

#include "PATH_DEF.h"


CAnsiString APP_PATH;
CAnsiString DATA_PATH;
CAnsiString APP_PKG_NAME;


#endif

PATH_DEF.h

#ifndef PATH_DEFH
#define PATH_DEFH

#include "PORT_DEF.h"



#include "share/txtfile/stringlist.cpp"
#include "share/FileHandling.h"



extern CAnsiString APP_PATH;
extern CAnsiString DATA_PATH;
extern CAnsiString APP_PKG_NAME;

#ifdef WINDOWS_PORT
inline void FindPaths()
{

}
#endif

#ifdef LINUX_PORT
inline void FindPaths()
{

}
#endif

#endif

now in android project i have a main glcode.cpp file where i include

#include "PORT_DEF.h"
#include "PATH_DEF.cpp"

and files in share folder use them too in manner of that they are included with relative path

#include "../PORT_DEF.h"
#include "../PATH_DEF.cpp"

Hit build everything is fine and works…

However… on windows

There are 3 units. One is Project.cpp (which is the main compilation file) and Unit1.cpp, Unit2.cpp (along with their headers)

During writing this post i faced new issues so lets get over with it:

i hit compile and get multiple definition of 'DATA_PATH'

No having no idea what would cause that, i started poking around and ended with something like that:

in file share/sharedlib1.h cannot find file “.PORTDEF.h” @ #include “../PORT_DEF.h”

After an hour of trys and fails, i came with an idea to to add PORT_DEF.h to a project. (so it wil be visible for compiler)

but this requires me to change from #include “../PORTDEF.h” to #include “PORT_DEF.h”

i tried this in Androdi Studio (basically added this to cmakelists.txt)

include_directories(${CMAKE_SOURCE_DIR})
add_library(sharewithphone SHARED
            PORT_DEF.h PATH_DEF.cpp gl_code.cpp)

hit compile

error: CMakeFiles/s/gl_code.cpp.o: multiple definition of 'DATA_PATH'

so i actually reproduced the same error on two IDEs now how i am supposed to to get rid of this multiple definition thingy.

I was searching for circular references there are none

basically these are all files included



#include <stdio.h>
#include <dirent.h>
#include <vector>
#include <fstream>
#include <sstream>
#include <math>
#include "string"
#include "stdlib.h"
#include <iostream>
#include <algorithm>
#include <cstring>

all cpp files have headerguards (ones that are included in #include) the same goes for all headers they too have headerguards

yet still even when including

PORT_DEF.h AND PATH_DEF.cpp at the beggining of project they shoul reside there

yet when hitting another file which uses these files it rants about mutiple declaration. ???? IM OUT OF IDEAS

Advertisement

This sounds really interesting and I guess there is no easy solution because of your overall setup. First, you don't need header guards in your CPP files as every compilation unit runs exactly 1 single cpp file to produce object code unless you included cpp files anywhere which is a no-no and should be done only if there is no other option to achieve what you need.

Second, naming your header guards: You should take care that you don't use “simple” naming for them. Are you sure there is not a file that already defines PATH_DEFH? My naming for those guards is always like the filename except I replace every dot by an underscore. For example

#define Array_h

This helps to avoid most cases of unintended definition clashes for me.

Something you might want to try is to resetup your projects. Start with a new clean solution and set include paths properly to the folder at which you store your shared libraries code and use the library sub-folder to prefix inclusion. Our build tool for example generates such inclusion entries in for example Visual Studio in a way that it adds the module root folder to the project as include path and we barely have files in the module root but store everything in a sub-folder. This way our includes always are either common for everything that is not specific to any module and then we have for example the Math folder in the Math module that then prefixes the include of anything inside it. For example

#include <Common/Array.h>

#include <Math/Vector3.h>

Finally this helps at least to determine where each file came from

Regarding header-guards, today I would just drop them completely and simply use “#pramga once” at t he top of each header. Every standard compiler should undestand it, its less to write, no need to worry about how to name those stupid things etc…

i don't know if you have resolved the issue but try these:

  • step1: use pragma once as juliean suggest, makes life much easier
  • s2: try not to include any header file in your headers (try using forward declaration instead), include header files in your headers only if u must (for example when a class inherits from another or when the compiler needs to know the size of a member variable typed pointer)
  • s3: move as many of your header includes into the cpp (this step and s2 will make your compilations a bit faster too, not that speed is your problem)
  • s4: try moving all your platform defines in the cpp as well (if it is not needed in the header)
  • s5: it may also be worth trying undef'ing DATA_PATH in the file that complains:
// put this undef in the first file (of the cpp or header) that complains about it
#undef DATA_PATH

u may need to reinstate the DATA_PATH elsewhere if necessary but for now see what happens, hope it works 4 ya ?

That's it … all the best ?

Juliean said:
Every standard compiler should undestand it

I wouldn't bet on it though, it is still a Microsoft thing

Shaarigan said:
I wouldn't bet on it though, it is still a Microsoft thing

Well its not guaranteed, but just look at that list of supported compilers:

https://en.wikipedia.org/wiki/Pragma_once#Portability

I wouldn't make my life more difficult unless I explicitely needed to support a specific an esoteric compiler, like for embedded system programming or what not.

I've just started to mess around. Changing PORTDEF etc to PORTDEF123 etc doesnt solve the problem, ant find any info about using pragma once in android studio thus i dnt even know which compiler it uses, anyway maybe theres a way to force compiler to access project root folder from symlinked folder root/Math/mymath.h → #include “../../PATH_DEF.cpp” so instead going directory up within absolute path it will go ow its done on android studio to the root project folder. SO i can keep consistent codebase for now and mess with compilation itself.

anyway even setting pragma once i get multiple decl errors

[ilink64 Error] Error: Public symbol 'APP_PATH' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O

I have a very specified question regarding Unit2.h file so please read on.

Project3.cpp is main file where it is (please don't even dare to care about useform macro i just added PORTDEF and PATH_DEF here for fun.. (it doesn't change anything except less errors if i remove these two)

#include <C:\Program Files (x86)\Embarcadero\Studio\20.0\include\windows\vcl\vcl.h>
#include "PORT_DEF.h"
#include "PATH_DEF.cpp"
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
#include <Vcl.Styles.hpp>
#include <Vcl.Themes.hpp>
//#include "PORT_DEF.h"
//#include "PATH_DEF.cpp"
USEFORM("Unit3.cpp", Form3);
USEFORM("Unit2.cpp", PAS);
USEFORM("Unit4.cpp", vidfrm);
USEFORM("Unit7.cpp", Form7);
USEFORM("Unit6.cpp", About);
//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
        TStyleManager::TrySetStyle("TabletDark");
		Application->Title = "PC Android Share";
		Application->CreateForm(__classid(TPAS), &PAS);
 //uses PORT_DEF.h AND PATH_DEF.cpp
		Application->CreateForm(__classid(Tvidfrm), &vidfrm); //uses one file from sharedlib that is not connected to PORT And PATH DEF (stringlist.cpp) but  PATH_DEF uses stringlist.cpp
		Application->CreateForm(__classid(TAbout), &About);
		Application->CreateForm(__classid(TForm7), &Form7);
		Application->CreateForm(__classid(TForm3), &Form3);
		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");
		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
		}
	}
	return 0;
}
//---------------------------------------------------------------------------

stringlist.cpp

#ifndef strlstcpp14447
#define strlstcpp14447
#include "stringlist.h"
#include <algorithm>    // std::transform

tFloatConversionRule FLOAT_CONVERSION;
std::vector <CAnsiString , std::allocator<CAnsiString> > w_nawiasie[10];
#endif

stringlist.h

#ifndef stringlistH14447
#define stringlistH14447


#include "../FileHandling.h"

#include <vector>


#include <fstream>
#include <sstream>
#include "../Math/DxcMath.h"
 <-- this uses only <math.h> "stdlib.h" and <vector>
#include "string"
#include "stdlib.h"
#include <iostream>
#include <algorithm>
#include <cstring>
typedef std::string CAnsiString;
enum tFloatConversionRule { tFCDot, tFCcomma };

extern tFloatConversionRule FLOAT_CONVERSION;
extern std::vector <CAnsiString, std::allocator<CAnsiString> > w_nawiasie[10];
#endif

FileHandling.h includes

#include <stdio.h>
#include <string>
#include <fstream>
#include <dirent.h>

….

One another thing worth sharing is PAS form Unit2.cpp

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "scControls"
#pragma link "scGPControls"
#pragma link "scGPFontControls"
#pragma link "scModernControls"
#pragma link "scStyledForm"
#pragma link "scGPImages"
#pragma link "scImageCollection"
#pragma link "scStyleManager"
#pragma link "scAdvancedControls"
#pragma link "scControls"
#pragma link "scGPControls"
#pragma link "scGPFontControls"
#pragma link "scGPImages"
#pragma link "scImageCollection"
#pragma link "scModernControls"
#pragma link "scStyledForm"
#pragma link "scStyleManager"
#pragma resource "*.dfm"

Unit2.h

#ifndef Unit2H
#define Unit2H

#include all sort o vcl classes from rad studio
#include <memory>       //for STL auto_ptr class
#include "scannet.hpp"
#include "ShellAPI.hpp"
#include "Unit4.h"
#include "Unit6.h"
#include "Unit7.h"
#include "QR/QrCode.h"

#include "PORT_DEF.h"
#include "PATH_DEF.cpp"
#include "share/txtfile/stringlist.cpp"
#include "share/Math/DxcMath.h"
#include "desktop_window_manager.h" <-- what if i include PATH_DEF.h here that shouldnt be any circular reference since PATHDEF only needs stringlist.cpp and filehandling which use stl and nothing more...
#include "share/txtfile/READ_CONFIG_UNIT.h"

And here's full build log [edited - too not make post too long]

Checking project dependencies...

[ilink64 Error] Error: Public symbol 'APP_PKG_NAME' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PATH_DEF.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O
[ilink64 Error] Error: Public symbol 'FLOAT_CONVERSION' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O
[ilink64 Error] Error: Public symbol 'FLOAT_CONVERSION' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT4.O
[ilink64 Error] Error: Public symbol 'w_nawiasie' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O
[ilink64 Error] Error: Public symbol 'w_nawiasie' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT4.O
[ilink64 Error] Error: Public symbol 'APP_PATH' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O
[ilink64 Error] Error: Public symbol 'DATA_PATH' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O
[ilink64 Error] Error: Public symbol 'APP_PKG_NAME' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\PROJECT3.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O
[ilink64 Error] Error: Public symbol 'FLOAT_CONVERSION' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT4.O
[ilink64 Error] Error: Public symbol 'w_nawiasie' defined in both module E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT2.O and E:\PROJECTS\CODE\C++\WIN\PASHARE\UNIT4.O
Failed
Elapsed time: 00:00:39.5

_WeirdCat_ said:
Changing PORTDEF etc to PORTDEF123 etc doesnt solve the problem

Did you change those by hand or auto replacement?

The whole thing sounds like you have multiple files that however, define your special definitions or at least include files that do so without respecting the include guard. Maybe a copy paste error?

I changed it by hand, thanks for the tip i have to check like 100 files and their dependencies, this is going to be a tough week, and alot of handwriting

Well… it may be fixed, I didn't check whole library if it works as expected.

Anyway the thing is i had to configure project, no more one file only compilation but i actually had to add every file that had cpp to project, deleted include “x.cpp” and replaced with include “x.h” and thats all…

Stupidly there's a difference how compilers and linkers maintain source and header files, but i say stupid and yet use externs…. you guys actually helped me cause i had to do 2 things you came up with to find actual problem.

Thanks again.

This topic is closed to new replies.

Advertisement