Make - Multiple definitions errors when compiling C++ project - c++

I have a problem and yes I acknowledge this kind of question has been asked before, but none of them were really helping me, as the context and kind of errors given were not exactly the same.
I have a project I'm trying to compile with a makefile. The compilation process is the following :
game_f.exe : objects/game_f.o objects/game_f_main.o archives/io.a
#g++ $^ $(ALL_OTHER_NEEDED_LIBS) -o $# -std=c++11 -pedantic -Wall -g
Now those lines are creating 'multiple definitions' errors. Such as those :
io.cpp:(.text+0x1FDA) : multiple definitions of <some function or variable name> :
archives/io.a(io.o):io.cpp:(.text+0x1FDA) : defined for the first time here
Now this is coming from a header file where I create a namespace. The namespace is created as such :
io.h :
namespace io {
extern int TermWidth;
[some other variables, declared with "extern <some type> name;"]
extern void getTermWidth();
[some other functions, declared with "extern <some type> name(args)"
}
io.cpp :
namespace io {
TermWidth = 0;
[other variables definitions]
void getTermWidth() { ... }
}
The compiler seems to ignore the extern word when compiling from the makefile. But what is weird is if I type the entire g++ line, without going through the makefile, the compilation works.
This compiles fine on my macOS machine when going through the makefile, by the way, which is even weirder.
Does g++ have a special option for extern definitions ? Is this a known problem of g++ and make ? How could I avoid this error ?
EDIT : Yes, the .h files have include guards.

Related

No multiple definition error despite including source file in another and compiling both

Let's say I have 3 files:
Test.hh
#ifndef TEST_HH_
#define TEST_HH_
class Test
{
int test() const;
};
#endif /* TEST_HH_ */
Test.cc:
#include "Test.hh"
int Test::test() const
{
return 0;
}
main.cc:
#include "Test.cc"
int main()
{
return 0;
}
It does not compile (rather does not link), I understand why, I defined Test::test() in multiple translation units (in main.cc that includes Test.cc and in Test.cc):
g++ -Wall -g -std=c++17 -c main.cc -o main.o
g++ -Wall -g -std=c++17 -c Test.cc -o Test.o
g++ -o bin main.o Test.o
Test.o: In function `Test::test()':
Test.cc:12: multiple definition of `Test::test()'
main.o:Test.cc:12: first defined here
collect2: error: ld returned 1 exit status
Edit: This is NOT my issue, my issue is that with a seemingly identical situation, in a bigger project, the previous example produces a binary (i.e. compiles and links) when, as far as I understand it, it shouldn't. I will now describe the real case with a bit more details and how the problem suddenly arised when previously it was working fine (when it shouldn't have).
--
I am currently working on a large project (~2500 files), and while trying to use the "Test" class above, I ended up having a lot of "multiple definitions" errors at link time. To translate it to our example, it's like I had another class doing this:
OtherClass.hh
#include "Test.hh" // including or using forward declaration led to the same results
//class Test; forward declaration
class OtherClass
{
// Some stuff, whatever
};
I ended up finding that Test.cc was included in another source file (main.cc in my very simplified exemple though it was in another "someClass.cc" in my actual project). After including the header instead of the source, it compiled again. What's more surprising is that other classes had been using Test.hh the same way until then without any problems.
Since I was really surprised, I ended up doing a grep on all my files and found that another 2 source files had included other sources files as well.
WhateverClass.cc
#include "Test2.cc"
YetAnotherClass.cc
#include "Test3.cc"
All those files are compiled and contain function definitions yet the linker does not complain. I tried doing a compilation from scratch and it still worked.
So my question is: Why does this compile even though some source files include others and all of them are compiled ? And why did it suddenly stop working even though I just included the header of one of those source files just like other classes had been doing ? Is there a kind of "undefined behavior" for cases like this ?
If it is of any help, my project is using CMake. I tried compiling with ninja or Make with the same results.
I had a similar question before. So, here's what I learned- never include source file. Only include header files. Your error comes from including a source (.cc) file in your main. You should include Test.hh instead. Declare all your classes and functions in header, include that header to all the source files where the definitions and the calls are.

include class and compile with g++

Im a beginner in C++ and working with unix. So here is my question.
I`ve written few lines in the main-function, and i needed a function, that is defined in the c_lib - library.
main.cpp:
#include <iostream>
#include "c_lib.cpp"
int main()
{
return 0;
}
i want to execute it on the terminal, so i wrote
g++ -c c_lib.cpp
g++ -c main.cpp
g++ -o run c_lib.o main.o
Until here, there is no error report.
Then
./run
I get the error
error: ./run: No such file or directory
What's wrong?
Including a .cpp is not usually done, usually only headers are included. Headers usually contain the declarations that define the interface to the code in the other .cpp
Can you show us the source of c_lib? That may help.
As the source of c_lib is #included, there is no need to compile it seperately. In fact this can/will cause errors (multiple definitions being the first to come to mind). You should only need to do:
g++ -o run main.cpp
to compile your code in this case.
(When using a header (.h), you will need to compile the implementation (.cpp) seperately)
Compile with warnings turned on:
g++ -Wall -Wextra -o run main.cpp
and you will get more output if there are problems with your code.
Is the run file being output by gcc? You can test by calling ls in the terminal (or ls run to only show the executable if it is present).
If the executable is present, it could be that it isn't marked as runnable. I'll go into that if it is a problem as it is outside the general scope of the site (though still related)
First of all you should not include source file into another source. You should create a header file and put declarations there (that allows main() to call functions from c_lib.cpp or use global variables if any)
When you run g++ you have to look into it's output, if operation succeed or not. In your case it failed so executable run was not created.
Usually you do not call compiler manually but write a makefile and let make utility to call g++.

Mixed C and C++ makefile

I am trying to compile c and c++ file using Make.
I am not very familiar with make , and i have managed writing a simple make file below
all:
g++ bits.c -o bits.out
g++ bits1.cpp -o bits1.out
clean:
rm bits.out
rm bits1.out
g++ can compile 'c' file as well , so i have written g++ for all the files I am using here.
And I am trying to call one of the function in ".cpp" file from ".c" file .
And this giving me an error as "undefined reference to function"
To explain it , I have function by name "returnfun()" in "bits1.cpp" file , whose declaration is in "bits1.h" file and i have included "bits1.h" file in "bits.c" and calling the same function from bits.c , which is throwing me an error.
Is there are any other ways of writing makefile?
Your problem is not in the Makefile. Your problem is with c++ name mangling.
Try surrounding the function declaration with the following to prevent name mangling.
extern "C" {
returnfun();
}
Your Makefile also has a problem, but it is a separate problem. The problem is that you are not providing all the source and object files necessary to run the program. The following is one possible way to fix it.
all:
g++ bits.c bits1.cpp -o bits

How do I compile "c++ functions from c" if c++ functions need other libraries?

I have these files in the same folder:
function.h
function.cpp
main.c
If I have a simple function like sum(int a){return a+a;} (in function.cpp), I am able to compile it, but I need to use a library like this:
#include "something.hh"
void function(){
ClassX* test;
...
}
The problem is that, when I'm trying to compile this, I get "undefined reference" in every class.
How should I compile this?
Is this possible? I've read somewhere you can use a c++ function in c while its return type and its parameters are accessible from C. Is there any other requirement?
What I do:
g++ -c -I /folder/include function.cpp -o function.o
gcc -c main.c -o main.o
gcc main.o function.o -o exec
In function.cpp undefined reference to ClassX
I think your problem is not use of C and C++ but that file containing entire ClassX is not compiled and hence in the third stage in link time it gives error
gcc main.o function.o -o exec
Make sure that ClassX is defined in one .o file and that file is passed in above step.
Now coming to your question,
you can't compile C++ code is C compilers because C is not forward compatible but C++ is backward compatible to C that is to say that most of the C code will get compiled by C++ compiler with little change. But you can write a library in c or compile c code to .o and then use it in C++ compiler to do that you need to use extern "C" linkage.
extern "C"
{
....
}
Check this link
Thanks
How should i compile this? Is this possible?
Normally, there are two possibilities:
define your header file API in terms of functions only, declare those functions with extern "C" linkage and use them in C code.
if you have class declarations or other C++ specific code, compile your client code to C++ (i.e. move main.c to main.cpp).
In your case, you are trying to access a C++ class, in C code. This is not possible.
You can still use the functionality, but you will have to create an adaptation layer (with APIs declared as extern "C" and declaring no classes, templates or other C++ features).
Within this adaptation layer, classes or other C++ constructs can be hidden in structures opaque to client code.

Anonymous namespace causes undefined reference here - works there

I've written some C++ code for an embedded system which works like a charm. The current task is to emulate the behaviour of this device on a PC. Some of the code has to be ported: For a first test I'm using mingw (g++) while the Embedded system is an STM32 and uses the KEIL µVision toolchain.
I've run into a problem that is not really related to functional behaviour rather than a compiler specific weirdness. I have 2 classes defined in an anonymous namespace because they are included throughout the whole project. Now on the embedded device this compiles and runs without a problem. g++ complains about an undefined reference!
When I remove the anonymous namespace arround the class it compiles and runs! But why? Here is some example code that reproduces the situation:
main.cpp:
#include "notmain.h"
#include "theclass.h"
A *ourA=NULL;
int main()
{
theA = new A();
theA->dostuff(1024);
sunshine sun;
sun.Init();
}
notmain.cpp:
#include "notmain.h"
#include "theclass.h"
void sunshine::Init()
{
theA->dostuff(127);
}
notmain.h:
#ifndef NOTMAIN_H_
#define NOTMAIN_H_
class sunshine
{
public:
void Init();
};
#endif
theclass.h:
#ifndef THECLASS_H_
#define THECLASS_H_
#include <stdio.h>
#define theA ourA
namespace
{
class A
{
public:
void dostuff(int b)
{
a = b;
printf("Hello: %d\n",a);
}
private:
int a;
};
}
extern A *ourA;
#endif
Compiler/Linker Output:
09:09:57 ** Incremental Build of configuration Debug for project Testo **
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o main.o "..\main.cpp"
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o notmain.o "..\notmain.cpp"
g++ -o Testo.exe notmain.o main.o
notmain.o: In function ZN8sunshine4InitEv':
D:\Projekte\Testo\Debug/../notmain.cpp:6: undefined reference toourA'
collect2.exe: error: ld returned 1 exit status
09:09:57 Build Finished (took 702ms)
Removing that namespace fixes the problem but why does it compile, link, work in KEIL? Can anyone explain this to me?
I would suggest that that is an abuse of the anonymous namespace feature. It does exactly the opposite of what you are trying to achieve.
Anonymous namespaces are used to localise a definition to a single translation unit. If you place one in a header file, then include that header in multiple translation units, that will result in multiple independent definitions in your code.
What is happening here VC++ is that a global ourA has been instantiated as a pointer to one local definition of A defined in main.cpp, then later that local definition is no longer visible but is distinct from the currently visible local version in notmain.cpp. The name mangling of ZN8sunshine4InitEv distinguishes between independent definitions, but name mangling is compiler defined, and I guess ARM's RealView compiler (used by uVision) has a different scheme that fails to spot this error.
It is unclear in fact what the result if this error is in RealView, but it cannot be correct or at least well defined.
RealView is in fact rather poor at issuing warnings that other compilers do normally, and is somewhat permissive when it comes to undefined behaviour I have found. It is always worth using another toolchain such as MinGW/GCC with -Werror -Wall or using a static analysis tool to clean up your code.
To solve this problem you should use an explicitly named namespace, or no namespace at all.