unit test - recompile only around "int main()" to reduce compilation time - c++

A project in my Visual Studio solution can be divided into :-
Library.h, Library.cpp
User.h, User.cpp (#include Library.h)
Main.h, Main.cpp (#include User.h) has "int main()"
(The real project is far bigger than this.)
Whenever I edit any Library.h file and press F5, it will recompile the whole project. It makes sense.
Now I want to code/debug Library and test it alone, and I don't want to recompile everything because it costs more time.
Therefore :-
I created Main2.cpp that #include only Library.h, and have no code involving User at all.
I commented out the whole main.cpp.
Here is my main2.cpp :-
#include "Library.h"
int main(){ .... some code about library ....}
When I press F5, it compiled all .cpp and run fine. That still makes sense.
Problem
If I edited Library.h, and press F5 again, it will recompile :-
library.cpp
User.cpp <--- no!
main.cpp <--- no!
main2.cpp
Question
How to make Visual Studio recompile only necessary files to save compilation time?
(compile only library.cpp and main2.cpp in this case)
I guess the need to recompile a lot of files is that there may be some static function inside User that do something about library.
What if I know for sure that there are not?
Even if there is something, I want to (risk) ignore it.

Separate your solution into 3 projects:
Library
LibraryTests
Main
When you don't want to re-compile 'Main', just right-click it and unload the project.
You should probably look to break up Library.h into smaller pieces, so that the dependencies are more self-contained.

I'd recommend instead of suffering headache with visual studio to download the MinGW c++ compiler for Windows and just compile a smaller unit-test instance of the files which you need as a sort of different project all together in with the console.

Related

C++ - errors after changing .h file fixed only by recompilation

I have a header file called gui.h where I keep all my gui stuff. Because of this I often change its contents. The problem is: every time I do this I get a runtime error usually related to memory. However, when I recompile all the project, everything works properly. The error occurs always after changing the .h file contents and it's always fixed by recompilation. Why is this happening? Is there any way I can fix it or I'll have to recompile entire project after every gui change?
EDIT:
I'm using Visual Studio IDE, normal project, not CMake
The files
gui.h
globals.h
Game.cpp
gui.cpp
Includes
gui.cpp has #include "gui.h"
globals.h has #include "gui.h"
Game.cpp has #include "globals.h"
The story
I make a change in gui.h
I hit F5
I see globals.h getting recompiled
I see gui.cpp getting recompiled
I see "Generating code" message in Build log
The project runs
I immediately get a runtime error related to memory (access violation)
The solution:
Recompile all the files that require gui.h to work manually (in this case Game.cpp)
The problem:
Why isn't Game.cpp recompiled automatically?
You haven't specified what tool you use to build your program. What is probably happening is that the tool you're using doesn't realize that a change to that particular h file requires anyone including it (directly or indirectly) needs to be recompiled.
For instance, if you're using "make", your Makefile may have a line that looks like this:
foo.o: foo.cpp foo.h
But it really would need to be:
foo.o: foo.cpp foo.h gui.h
In other words -- foo.o requires not only the corresponding .cpp and .h file, but also this huge gui.h file.
Any .cpp that directly or indirection includes gui.h probably needs recompiling when gui.h changes. That is:
#include "gui.h"
-or-
#include "foo.h"
and foo.h has an include of gui.h.
Since the content of the header file is pasted into the source files that include it by the compiler preprocessor, whenever you change the header, the program will remain the same, since it has been compiled from a source file that contained the content of the old header file.
I suggest that you could try to set incremental compilation.
Project->Properties->Configuration Properties->C/C++-Code Generation->Enable Minimal Regbuild: Yes(/Gm)
Project->Properties->Configuration Properties->C/C++->General->Debugging Information Format: Program Database (/Zi)
Project->Properties->Configuration Properties->Linker->General->Enable incremental linking: select "Yes"
Tools->Options->Projects and Solutions->Build and Run->On Run, when projects are out of date: select "Prompt to generate"
Tools->Options->Projects and Solutions->Build and Run->Check Only build startup projects and dependencies on Run
Tools->Options->Projects and Solutions->Build and Run->MSBuild project build output verbosity: select "Minimal"

Is normal to list all the cpp/cc files when compiling with g++?

I'm doing the "Hello World" in the GTKMM tutorial, the "app" uses three files, the main.cc, helloworld.h and helloworld.cc.
At the beginning I thought that compiling the main.cc :
g++ -o HW main.cc $(pkg-config ... )
would be enough, but gives an error (undefined reference to Helloworld::Helloworld), etc.
In other words, it compiles the main and the header, but not the HW class, and this makes sense because the header is included in Main but not the Helloworld.cc. The thing is I'm kinda scared of including it because I read in other question that "including everything was a bad practice".
That being said, when I compile using all the files in the same command:
g++ -o HW main.cc helloworld.cc $(pkg-config ... )
the "app" works without errors.
So, since using the last command works, is compiling in this way a good practice?
What happens if my app uses a big ton of classes?
Must I manually write them all down in the command?
If not, must I use #include?
Is it good practice using #include for all cc used files?
Is normal to list all the cpp/cc files when compiling with g++?
Yes, completely.
How else will it know what source code you want it to compile?
The thing is I'm kinda scared of including it because I read in other question that including everything was a bad practice.
#includeing excess headers is bad practice.
Passing your complete source code to the compiler is not.
Is it good practice using #include for all cc used files?
Absolutely not.
What happens if my app uses a big ton of classes? Must I manually write them all down in the command?
No. You should be using a build system that handles this for you. That could be an IDE which takes all the files in your project and passes them to the compiler in turn, or it could be a CMakeLists.txt/Makefile with a *.cpp wildcard in (although I actually recommend listing source files explicitly, one-by-one; it's not hard).
Invoking g++ manually on the command-line is fine for a quick test, but for real usage you don't want to be clowning around with such machinery.
is good practice using #include for all cc used files
It's not only bad practice, never do it.
In order to create an executable you actually have to do two things:
Compile all the source code files to object files or libraries.
Link all the object files and needed libraries into an executable.
You seem to be missing the point that the link phase is where symbols defined in separate source files are resolved or linked.
Must I manually write them all down in the command?
For the compiler to know about the DEFINTION of the symbols DECLARED in your headers, you must include all source files. Exceptions to this rule can be (but are not limited to) headers containing template metaprogramming (TMP) code that usually exist entirely in header files.
What happens if my app uses a big ton of classes?
Most of the large C++ projects utilize build configuration tools such as CMAKE to handle the generation of makefiles for them.

How do I add cpp file to an arduino project?

I am trying to add a cpp file to arduino project that has the following setup...
project
--folder
--foo.h
--foo.cpp
--project.ino
I have a #include "folder/foo.h at the top of project.ino. However while the header provides the prototype of the function, the function definition is in the cpp file. When I try to compile the code using the Arduino IDE, it fails with error
Undefined reference to 'bar()'
and bar() is located in foo.cpp
I looked at this but I do not have a setting for sketch/import library (however I do have sketch/include library, however I did not see anything close to using a custom folder location)
I looked at this too. But same as above, that setting does not exist in my ide. (Which I downloaded recently)
Code
//project.ino
#include "folder/foo.h"
void setup() {
Serial.begin(9600);
}
void loop() {
bar();
}
//folder/foo.h
#include "Arduino.h"
void bar();
//folder/foo.cpp
#include "foo.h"
void bar() {
Serial.println("bar");
}
Error
/tmp/ccNTRFfU.ltrans0.ltrans.o: In function `loop':
/home/temporary/project/project.ino:9: undefined reference to `bar()'
collect2: error: ld returned 1 exit status
exit status 1
What I would expect to happened is a way to link the cpp folder without having to put all the files in the same root folder of the project.
--Edit 1:
added code
--Edit 2:
added #include "Arduino.h"
--Edit 3:
added Serial.begin(9600);
How to properly include C/C++ headers and source files in your Arduino Project.
This answer has been tested and compiled to ensure it works. (Completed in Linux Ubuntu with the Arduino 1.8.7 IDE).
You have 2 problems.
1st: Arduino's unusual build process (described here) doesn't allow including from sub-folders in your project directory where your .ino file for this project is located.
[UPDATE: THIS ONE MAY HAVE BEEN MY MISTAKE ONLY, NOT YOURS, when I was duplicating your code on my PC: I accidentally used foo.c instead of foo.cpp]
2nd: C++ can only be used inside C++ source files, so you must change foo.c to foo.cpp, since Serial.println() is a C++ call to a C++ class's (Serial's) println() method.
To fix 1, simply change your folder structure to have everything in a single folder:
project
├── foo.cpp
├── foo.hh
└── project.ino
I present an alternate fix for #1 below too.
To fix 2, (this is mandatory!) make foo.c --> foo.cpp and (optionally, but recommended, to show it is a C++ header file) foo.h --> foo.hh. Update your includes in the .ino and .cpp file now too to #include "foo.hh".
That's it! Now close the Arduino IDE, then reopen it and reopen your project, and you'll see the following new tabs show up:
It now compiles just fine!
Learning: how did I figure this out?
First, turn on verbose compilation in the Arduino IDE: File --> Preferences --> check the box for "Show verbose output during 'compilation'".
Now, when you compile, all errors will show up in the bottom of the IDE window, as well as the exact compilation or linking commands which throw the error.
Once I fixed the folder structure, but your files were still C instead of C++ files, I saw this error:
Compiling sketch...
/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/tools/avr/bin/avr-gcc -c -g -Os -w -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/arduino/avr/cores/arduino -I/home/gabriel/Downloads/Install_Files/Arduino/arduino-1.8.7/hardware/arduino/avr/variants/eightanaloginputs /tmp/arduino_build_233569/sketch/foo.c -o /tmp/arduino_build_233569/sketch/foo.c.o
/tmp/arduino_build_233569/sketch/foo.c: In function 'bar':
foo.c:9:5: error: 'Serial' undeclared (first use in this function)
Serial.println("bar");
^
/tmp/arduino_build_233569/sketch/foo.c:9:5: note: each undeclared identifier is reported only once for each function it appears in
exit status 1
'Serial' undeclared (first use in this function)
Notice the file it failed to compile was /tmp/arduino_build_233569/sketch/foo.c, and that the avr-gcc C compiler (rather than the avr-g++ C++ compiler) was in use at the time.
I then opened the /tmp/arduino_build_233569/sketch/foo.c file to examine it and look for anything unusual about it.
Next, I used Eclipse to start tracking down includes, to see where Serial gets pulled in (it should have been obvious to me already what the problem was, but I didn't see it yet). I found the following:
Arduino.h is found in "Arduino/Source/Arduino/hardware/arduino/avr/cores/arduino/Arduino.h". It includes "HardwareSerial.h". This header externs the Serial object:
#if defined(UBRRH) || defined(UBRR0H)
extern HardwareSerial Serial;
#define HAVE_HWSERIAL0
#endif
HOWEVER, looking back at Arduino.h you'll see that HardwareSerial.h is ONLY included if you are compiling with C++:
#ifdef __cplusplus <========= This means that the following headers are ONLY included if you are compiling with C++! BOOM! That's when it hit me! You're compiling a C file with the C compiler to access a C++ object. That's not ok. Use the C++ compiler!
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
#include "USBAPI.h"
#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
#error "Targets with both UART0 and CDC serial not supported"
#endif
#ifdef __cplusplus means that the headers above are ONLY included if you are compiling with C++! That's when it hit me! You're compiling a C file with the C compiler to access a C++ object. That's not ok. You must use the C++ compiler instead. Do this simply by changing foo.c to foo.cpp. Done.
Alternate fix for your problem #1 (the folder structure):
Find your "Sketchbook location" from Arduino IDE: File --> Preferences. Mine, for example, is /home/gabriel/dev/Arduino/Sketches.
Now, go there and create a "libraries" folder. For me that would now be /home/gabriel/dev/Arduino/Sketches/libraries. Everything inside this folder is now considered an Arduino "library", and can be included. Move foo.h [do NOT use foo.hh in this case] and foo.cpp there, like this:
/home/gabriel/dev/Arduino/Sketches/libraries/foo
├── foo.cpp
└── foo.h <==== NOT foo.hh in this case!
Now close and reopen the Arduino IDE, then go to Sketch --> Include Library --> foo, and it will automatically add the following line for you:
#include <foo.h>
The reason you can't use foo.hh in this case is simply because Arduino is looking for .h files only when you add your library include using the menus in this way. That's a bug as far as I'm concerned, and should probably be reported to the Arduino developers. Feel free to take that on.
Addendum:
16 Apr. 2019:
A google search for "arduino add include path" led me to this: https://forum.arduino.cc/index.php?topic=445230.0, where user #pert says:
In recent versions of the Arduino IDE(including 1.6.10) if you want to include libraries from the sketch folder you need to put them in a src subfolder. For example:
Blink
|_Blink.ino
|_src
|_BlinkLib
|_BlinkLib.h
He then says you can include like this:
#include "src/BlinkLib/BlinkLib.h"
I haven't tried this, but that'd be super useful if it works. Give it a shot and let me know if it works. Be sure to tell us which OS and Arduino IDE version you are using.
See Also:
Additional discussion on Github here: https://github.com/arduino/Arduino/issues/5186.
The official Arduino Library specification here: https://arduino.github.io/arduino-cli/latest/library-specification/.
Open a tab in your project for each file.
You can create a new file or import an existing file into your project.
This way you can use multiple *.ino, *.c, *.cpp and *.h files. I didn't find a way to import a local directory or to configure your project structure.
Place your folder inside libraries folder that is a subdirectory of your sketchbook directory.
Open Arduino IDE (if it is already open, quit it and reopen).
Go to Sketch->Include Library. You will find folder under Contributed Libraries section.
Choose folder and you are good to go.
According to "Sketch specification":
In Arduino IDE 1.6.5-r5 and older, no recursive compilation was done.
In Arduino IDE 1.6.6 - 1.6.9, recursive compilation was done of all subfolders of the sketch folder.
In Arduino IDE 1.6.10 and newer, recursive compilation is limited to the src subfolder of the sketch folder.
So, putting your source code files into 'src' subfolder should solve the problem. Tested in "Arduino IDE" v2.0.3.

CodeBlocks files not recognized in project

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.

Stripping Down VS 2008 Win32 DLL to one file

I have a VS generated C++ Win32 DLL project. It has the following files:
stdafx.h
targetver.h
myProject.h
dllmain.cpp
myProject.cpp
stdafx.cpp
I can remove targetver.h, and merge dllmain.cpp into myProject.cpp. What more can I do to get the simplest file structure, preferably one file. I need to dynamically emit this code file and build it into a Win32 DLL.
If you want a minimalistic file structure, you could just create the files yourself. Start an empty project, or delete all the files. Heck, just make a folder, write main.cpp, and compile it from the command line with cl.
Few IDEs really try to minimize files like you're trying to -- but when you create the project, you can cut back a little: stdafx.[h, cpp] are for precompiled headers, which you could disable when creating the project.
That said, I don't really see the value in minimizing the amount of source code in a compiled language project -- it's not going to have a meaningful impact on the number of output files/dlls and, properly used, using more files only helps your code's clarity.
In addition to what Andy said, you can merge the myProject header and implementation files as well with dllmain.cpp. But why not just keep these files and create the vsproj file at runtime?
Or you could just create an empty project.
IIRC, myProject.h and myProject.cpp both contain an example of an exported class. You can easily delete those.
stdafx.cpp and stdafx.h are used for the standard precompiled header file. If you turn off the setting that requires a precompiled header, then those files won't be necessary, either.
You could #include your generated file into a existing multi-file project. That way you can have a shell of a complicated project and only emit something smaller, like a simple function.
For example:
#include <system_stuff>
void main()
{
Go();
}
#include "generated_file_that_has_method_go.cpp"
void other_code()
{
}