I am a C++ learner and I came across a concept of separating code into multiple files to speed up compiling process on bigger projects.
However what the book doesn't tell me and I have tried to find it in other books and on the web, but with no luck is how does linker (during compilation) knows what files to include.
When I make new file I connect its header to the main file with #include "newfile.h", however in this header I don't write where to find definitions of functions.
So how I imagine the process is that it starts in the main file and there it finds "connections" to other files. The question is how it finds those .cpp files that as far as I see don't need to be named the same as its header file.
Exmple:
Main file:
#include <iostream>
#include "krneki_H.h"
using namespace std;
int main()
{
krneki1();
krneki2();
krneki3();
}
And header file:
void krneki1();
void krneki2();
void krneki3();
And new .cpp file:
#include <iostream>
#include "krneki_H.h"
using namespace std;
void krneki1() {
cout<<"Krneki1"<<endl;}
void krneki2() {
cout<<"Krneki2"<<endl;}
void krneki3() {
cout<<"Krneki3"<<endl;}
Notice that there is no indication to use second cpp file. It just knows to use it. Does it search all .cpp files in the map?
Thank you for answer.
You compile both .cpp files using gcc -c or a similar command line, and then pass both of the .o files produced to the linker. The linker does not magically figure out that you want to compile another .cpp file.
For example
gcc -c main.cpp -o main.o # compile
gcc -c krneki_H.cpp -o krneki_H.o # compile
gcc main.o krneki_H.o -o main # link
Your IDE may take care of these details automatically, in which case it compiles all .cpp files you added to your project, then links all the .o files produced by the compilation step.
No. It doesn't just know to use it. In your example, if you compile with main.cpp and without that new cpp file, you'll get an "undefined reference" error.
What happens is that you're using a fancy IDE that automatically compiles all cpp files. It includes them all by default in your makefile.
I recommend that you try to design a makefile from scratch, and see for yourself how you'll get that "undefined reference" error if you don't include the cpp file that has the implementations of your functions.
Related
This question already has answers here:
VS Code will not build c++ programs with multiple .ccp source files
(17 answers)
Closed 1 year ago.
I've watched several tutorials on C++ header files and did EXACTLY what they were showing, but I can't really understand why I can't use a function from other .cpp file.
Main.cpp
#include <iostream>
#include "Header.h"
int main() {
std::cout << sum(2, 2);
return 0;
}
Header.cpp
#include "Header.h"
int sum(int a, int b) {
return (a + b);
}
Header.h
#pragma once
int sum(int a, int b);
Your program is working as can be seen here.
To get your program working on your machine follow these steps(assuming you're using g++ and Ubuntu:
Step 1: Create a binary/executable using the command:
g++ main.cpp Header.cpp -o myexecutable
Step 2: Test/Run your executable created in the last step using the command:
./myexecutable
Alternate Solution: A shortcut
Now if you're wondering that you've to type the name of every source file to make the executable, then you can take a sigh of relief because there is a shortcut as given below:
Assuming you have many source files(.cpp files) in your current directory and you want to compile them all without writing the names of all of them, then you can use the command:
g++ ./*.cpp -o myexecutable
The above command will create a binary/executable named myexecutable .
By including files, the preprocessor simply makes the included file part of the file which includes the other file.
In C++, there is the one definition rule. If you include a definition multiple times in other files, you brake that rule. Simply that.
In general, the preprocessor nor the compiler has an idea what a '.h' or a '.cpp' file is, that is only a convention. But you must not have the same definition multiple times in your source files, independent if you link multiple objects or have the definition multiple times in one source file.
If you follow the convention, that you name your definition files with '.cpp', it makes no sense to include them in other files as this will end up in multiple definitions. Once in the object file generated from the '.cpp' file and once in the file which include the '*.cpp' file.
You can include the '.cpp' file once in another object file and use it, if you don't link the object file, which will be generated from that '.cpp' file. But is is a strongly advice to not do such strange things :-)
This question already has an answer here:
"undefined reference to" errors when linking static C library with C++ code
(1 answer)
Closed 6 years ago.
I realize this question has been asked in a number of ways including this very comprehensive answer but I have looked at many and tried fixing my error to no avail.
I am using .cpp and .c files to create a program. I compiled all files with g++, it seemed to have no more linking errors, though it gave me a bunch of C++ errors related to the C syntax. This was the command I used:
g++ -o program main.cpp /data/*.c -l[...libs]
The main.cpp calls functions in the .c files.
I then understood that one should not try to compile both .c and .cpp files with one compiler, instead to use gcc for one, g++ for the other, and thereafter to simply link the object files.
So I did this (the .c files are part of a library, and already have .o files)
g++ -c main.cpp
g++ -o program main.o /data/*.o -l[..libs]
But then here I will get "undefined reference to" errors for functions called from main.cpp to the precompiled .c files, errors which I didn't get previously.
Could anyone help? Or do I maybe need to provide more information?
EDIT (a more in depth excerpt of code, I've tried to simplify otherwise this will be impossible to read, but let me know if I still need to add stuff, I'll try to remove unnecessary code):
main.cpp :
#include "header.h"
int main(int argc, char** argv) {
string s1 = argv[2];
fn1(s1)
}
header.h
void fn1(string s1)
mycfile.c
#include "header.h"
void fn1(string s1){
fprintf(stdout, " you entered %s", s1);
fflush(stdout);
}
ANSWER:
#Smeehey helped me figure out the solution, it was actually that I was still including the old headers in an .hpp file I was using. But the core solution was indeed to use the external C{}.
This is highly likely to do with C-vs-C++ linkage. In your main.cpp, you probably have something like this:
#include <data/header.h>
where header.h refers to your c library. Replace it as follows:
extern "C" {
#include <data/header.h>
}
This tells your c++ compiler not to use c++-style name mangling when defining the required symbols from the header, allowing the linker to successfully find them in the c-compiled .o files.
You have to compile C files with the gcc command, C++ files with either gcc or g++, and link with the g++ command. This sequence will probably work:
gcc -c data/*.c main.cpp
g++ -o program *.o -l <libs...>
Next step: learn to write proper makefiles.
This is a shot in the dark but the problem might be the way C and
Cpp files are compiled is simillar yet slightly different....
Due to name spaces the function foo would generate the symbol some_prefix#foo
Unlike C whereas goo generates the symbol goo
Try doing the following in your .cpp files
extern "C"
{
#include "yourcfilesheader.h"
}
And please attach your code
I have a main file main.cpp which include myclass.h. I also have myclass.o and myclass.cpp. The visual studio project is only using the files main.cpp and myclass.h.
This compile:
#include "myclass.h"
int main()
{
return 0;
}
This does not:
#include "myclass.h"
int main()
{
myclass M{};
return 0;
}
which gives a link error - probably because the myclass.cpp or myclass.o is not included in the project.
I would prefer to include only myclass.o since compiling this class is very problematic.
See
https://forum.qt.io/topic/8492/solved-cannot-get-quazip-test-to-work/3
if you are curious of which library I am using.
To my question:
Can I compile and use the class with only the header and the object file, i.e without the .cpp file at all?
Thanks!
Visual Studio generates a .obj file as its intermediate format. gcc and gcc are the ones that produce a .o file. You can include this in your project or, since libraries rarely have a single compile unit, you can build a .lib file and include that. Be warned, though, that the compiled units must be compiled using the exact same compiler switches such as run time library and etc. as you are using in you project. It is often simpler to simply compile the file from source.
We can also talk about using a DLL but that seems to be beyond the scope of your question and also introduces the complication of calling conventions.
First of all, I am a beginner programmer so, please give simple answers that are understandable.
I am suing Code::Blocks and I am trying to make a multiple file project in C++. I am using SDL2. My problem is that when I put all my codes and functions altogether, they run and when I seperate them, they don't. This is because the execution file requires object files to be built which it don't get. It don't get them because compiler don't form them. In other words, there are problems with linking. The compiler simply, said that there are not ".o" files. These files are in the project as "Link Files" and not "Compile Files". And when I make them "Compile Files" as well as "Link Files", they produces errors that various variables inside the file where I mentioned them, are not declared. But when I include that file in the file using the variables, it gets deeply nested.
Following are the two ways:
First way which is not working, with seperate files.
In main.cpp:
#include <SDL.h>
#include <other.h>
int var;
int linkVar;
int link1Var;
int link2Var;
#include "link.cpp"
#include "link1.cpp"
#include "link2.cpp"
int main( int argc, char* args[] )
{
linkFunc();
link1Func();
link2Func();
}
In link.cpp/ link1.cpp/ link2.cpp:
void linkFunc()/void link1Func()/void link2Func() //Just a reference
{
//Code associated with var, link1Var, link2Var and link3Var.
}
Second way which is working, with all functions in a single file.
First thing is that I don't want to learn makefile thing. If there is any other way to solve it then be it!
Code::Blocks makes object files for each file that it compiles as separate compilation units. It will compile and link together any files that are part of the project which it identifies as a source file.
First, remove your #includes of the cpp files. Then try the Project > Add files... menu option to add those other cpp files to the project.
First of all, you should not use #include on other cpp files, you can read about it here:
include cpp
Secondly when you are trying to compile a project composed of separate files you should use the g++ command like this: g++ main.cpp link.cpp link2.cpp etc'
you can read a basic explanation about it here: use the g++ command
To do exactly what you asked you should do:
# get rid of including any cpp files
# use forward declerations on any function belonging in other cpp files, before your main function like this:
void linkfunc();
void linkfunc2();
etc
.
.
.
int main()
{
}
# specify the direct path to your .h files like this:
#include <C:/MinGW/SDL2/SDL.h>
# use this command:
g++ -I C:/MinGW/SDL2/ main.cpp link.cpp link2.cpp link3.cpp
quick question.
I am trying to get C++ nailed down, and today I spent hours with a double definition linker error("this has already been defined!") and I finally realised it's because I had the layout as such:
main.cpp
#include Dog.cpp
Dog.cpp
#include Dog.h
Dog.h
// (Dog class and prototype of test function)
And now that I've cleared that up by including the Dog.h instead of the Dog.cpp in the main.cpp.
By including the .h file, does the .cpp file with the identical prefix get compiled with the program?
I was astounded when the program ran with only the .h included and no references whatsoever to Dog.cpp. I spent ages Googling but no answers really helped me understand what was going on.
Edit: I forgot to add that I prototyped in the .h, and defined the function for the class in the .cpp and that's what gave me the "already defined" error.
By including the .h file, does the .cpp file with the identical prefix get compiled with the program? I was astounded when the program ran with only the .h included and no references whatsoever to Dog.cpp.
No.
Your program is built in phases.
For the compilation phase, only declarations are needed in each translation unit (roughly equivalent to a single .cpp file with #includes resolved). The reason that declarations even exist in the first place is as a kind of "promise" that the full function definition will be found later.
g++ -c Dog.cpp # produces `Dog.o`
g++ -c main.cpp # produces `main.o`
For the linking phase, symbols are resolved between translation units. You must be linking together the result of compiling Dog.cpp and of compiling main.cpp (perhaps your IDE is doing this for you?), and this link process finds all the correct function definitions between them to produce the final executable.
g++ Dog.o main.o -o program # produces executable `program`
(Either that, or you actually haven't got to the link phase yet, and merely have an object file (Dog.o); you can't execute it, partially because it doesn't have all the function definitions in.)
The two phases can be done at the same time, with the "shorthand":
g++ Dog.cpp main.cpp -o program # compiles, links and produces executable
No, the .cpp file does NOT automatically get compiled. You can either do that manually, create a makefile, or use an IDE that has both of them in the same project.
You don't specify how you are compiling it. If you are using an IDE and have a new .h and .cpp to the project automatically then it will all be compiled and linked automatically.
There are 2 stages to making an executable to run: compiling and linking. Compiling is where the code gets interpretted and translated into lower level code. Linking is where all of the functions that you used get resolved. This is where you got the duplicate function error.
Inclusion does not automatically cause compilation, no.
In fact, the actual compiler never sees the #include statement at all. It's removed by an earlier step (called the preprocessor).
I'm not sure how it could build if you never compiled the Dog.cpp file. Did you reference any objects with code defined in that file?