I don't really understand the why behind this, but I think I've figured out the what.
My brother is working on a homework project and they're using Visual Studio. He was having issues getting his project to compile. The project in question consisted of:
main.cpp
classes.h
class_functions.cpp
general_functions.cpp
They had the following import structure:
main.cpp
#include "classes.h"
#include "class_functions.cpp"
#include "general_functions.cpp"
class_functions.cpp
#include "classes.h"
general_functions.cpp
#include "classes.h"
He kept getting link errors when trying to compile, even though g++ would compile it just fine. So I tried via Visual Studio command prompt and cl. This compiled just fine, so I tried msbuild which (obviously?) failed. I went into the vxproj file, because hey, what is it telling cl that I'm not?
In the proj file it was including classes.h, general_functions.cpp and class_functions.cpp, as well as main.cpp. When I removed general and class functions, msbuild ran just fine. Put either of them back and boom. classes.h contains
#ifndef myclasses
#define myclasses
/* Code here */
#endif
And the other .cpp files contain similar directives.
I finally figured out how to eliminate the problem - eliminate
#include "general_functions.cpp"
#include "class_functions.cpp"
from the code base, and now Visual Studio compiles this just fine.
The question is why? What is the justification or possible benefits from doing this?
the difference between .cpp and .h files is that the .h files are usually included with the #include directive while .cpp files are included in the linking process.
The #include instruction will insert a copy of the included file in the code you are compiling, so by including the .cpp files you will compile a single source file that contains all your .cpp files. It's very bad practice but still could work.
But if you are then adding the .cpp files also in the linking step then you are adding those files a second time creating probably duplicate definitions of your functions, e.g. linker error. I think that's probably the main error (without the linker error codes I'm just guessing).
Related
When I am making changes to my code, the external files are compiled multiple times. I am using math library glm, and Visual Studio seem to be compiling exactly same glm/vec3.hpp file multiple times. I have included glm header multiple time, and it seems that it doesn't use previously compiled code, but recompiles it again.
For example, in my math.h I have included.
#ifndef MATH_HH
#define MATH_HH
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
...
And when I am compiling after changes to code, I see that Visual Studio compiles glm/vec3.hpp multiples times. Basically it compiles it each time that it compiles one of my edited files.
For example, the Visual Studio output looks like this:
1>C:\test\external\glm\glm\detail\type_vec3.hpp(50,1): warning C4201: nonstandard extension used: nameless struct/union
...
10>own_file.cc
11>C:\test\external\glm\glm\detail\type_vec3.hpp(50,1): warning C4201: nonstandard extension used: nameless struct/union
...
Is there a way to prevent this? Or do I need to compile them each time some cpp file uses them? Or am I just confused of Visual Studio's style warnings?
Basically it compiles it each time that it compiles one of my edited files.
That's how C++ works. It compiles source files. Including a header file is just taking the text in that file and dumping it into your source file. Therefore, if you include a header file in 3 source files, the text of that header will be compiled 3 times.
There are precompiled headers (a compiler-specific tool), and the C++20 modules feature, that can avoid this. But outside of those, there's nothing you can do.
I just moved all my header files to be in the include directory of my project, rather than having both .cpp and .h in the src directory. I'm using YouCompleteMe in vim and now when I open vim, it tells me that my header files cannot be found on the side to alert me of compiler errors. Specifically, it gives me errors on the #include "my_header.h" of my_header.h file not found and errors on each method saying use of undeclared identifier. However, the code compiles just fine. And the auto-completion works fine. It seems that clang cannot find where my header files are located now since I moved them ../include. If I change my #include line to be #include "../include/my_header", all of the errors to away. But it seems better to only have #include "my_header.h" in all of my .cpp files or #include <my_header.h>.
Can anyone help me solve this issue?
I've been using code blocks for a long time, but never really made my programs into actual code blocks projects. I tried to do it today, and I kept getting errors due to code blocks not recognizing my files. Here is what I have : ---->
CodeBlocks Include Error
When I try to buiild my project I get that cout,cin and my class objects are not defined in my menu.cpp file. So I can only guess code blocks is not properly handling the files.
I would love if someone could help me out as to why this is happening.
Thanks a ton in advance :)
When I try to buiild my project I get that cout,cin and my class objects are not defined in my menu.cpp file.
That's because they're not. You #included neither iostream nor class.h in menu.cpp, so you can't access the declarations therein.
Note that Code Blocks (just like any properly set up build tools) will compile each cpp file separately. This means that not only will it compile menu.cpp as part of the compilation of main.cpp (because you include it), it will also compile it on its own. In the latter case the includes from main.cpp will not be available, so menu.cpp needs its own includes.
This also means that once it does compile (i.e. once you added the includes), you'll get a linker error because the definitions from menu.cpp are now defined twice (once in main.o -- because you included menu.cpp in main.cpp -- and once in menu.o). That's the reason why you should never include cpp files into each other.
PS: This is unrelated to your problem, but it's considered bad practice to use using namespace in a header file. You should put that in your cpp files instead (if you want to use it at all). You should also put the #include <iostream> in those files where you actually need it, rather than the header file.
I cannot explain the behaviour I am seeing when linking my code. Maybe someone has an idea what's going on...
I have a multiple file C++ project which uses GNU automake tools as its build system (all on Linux).
After adding a source and header file (lets call them util.cc and util.h) to the project and having an already existing source file (calc.cc) calling a function from the newly added files I get a linking error depending on where the include statement appears. I repeat: The error occurs in the linking step, compilation runs fine!!
Example:
I get an error when putting the new include statement at the end of the preexisting statements, like:
calc.cc:
#include "file1.h"
#include "file2.h"
#include "file3.h"
#include "file4.h"
#include "util.h" // new header
This version compiles fine. But linking produces an error (symbol not found)!!
Now, when changing this to
#include "util.h" // new header
#include "file1.h"
#include "file2.h"
#include "file3.h"
#include "file4.h"
then compilation and linking runs fine!
Since the linker only reads the .o files, this must mean that different content is produced depending on where the include statement appears. How can this be?
Compiler is g++ (GCC) 4.4.6
Chances are that util.h has a #define that changes the behaviour of one of the other files.
Your best chance of working out exactly what is going on would involve examining those header files for the name of the missing symbol and getting the pre-processor output from compiling calc.cc both 'working' and 'non working' way, and comparing the two files.
Simple, header files can (re)define macros which can change the interpretation of later macros.
For instance, in your example above, if file1.h does
#define lseek lseek64
and util.h has an inline function which calls lseek, then depending on the include order the generated object code will have a symbol reference to lseek or lseek64.
Which is why projects tend to have rules that config.h (generated by autoconf) is included first.
You're absolutley right: different object code is produced in the two cases. As #hmjd also points out, most likely there's a macro in util.h which one of the other (.h or .c) files use, and any undeclared, called identifier is assumed to be a function by the compiler -- this is most likely the error here.
I have a objective c/c++ project under iOS, moving it from OS/X and I get a 'file not found' error on
#include <string>
It's a clean project, and I've just added the files from the old project. Are the STL includes set up in XCode? A find produces a number of possibilities e.g.
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/include/c++/4.2.1/debug/
but adding this to the search path just threw up more errors. Any suggestions?
(apart from don't use string - it's in house code I'm porting)
xcode 4.2.1, ios5.0 running on OS/X 10.7.3 and it's in a .cpp file, the code works fine on OS/X
Are you really sure <string> is included only from a .cpp file?
I just tested on a fresh project, by adding a .cpp file and including <string>, and it works, just as expected (same Xcode version, same SDK version).
But if I include <string> in a .m file, then of course I got a «file not found» compiler error.
So double-check this, as the error may come from here.
Do you include <string> from a .cpp file only, or from a .h file, intended to be used by a .cpp implementation?
Then maybe it's also included by a .m file, hence the error.
Also check your precompiled headers, if any, to see if you include some C++ stuff there...
Also remember, in that later case, that you can rely on the __cplusplus macro, when needed.
If you include a header in an ObjC file and it includes <string> then you hit errors like this. For all .m files XCode uses a C compiler (clang or llvm-gcc). For all .mm files it will use (clang++ or llvm-g++).
I suggest going through and renaming all your .m files to .mm. Including main.m to main.mm.
For me the reason was
MyHeader.h (which includes #include ) target was public. Changed it to project and it compiled.
For cocoa pod:
s.public_header_files = 'MyProject/Classes/**/*.h'
s.project_header_files = 'MyProject/Classes/MyHeader.h'