.cpp files not working as I expect

Status
Not open for further replies.

PAAUX4

Well-known member
Please explain .cpp files.

I have been working on a large project without .cpp files because I was fine with the longer compilation times and I put most of my forward declarations in a single file at the start (and then a few in a second one later).

I am considering growing up and using .cpp files, but I am getting loads of errors, probably because I don't properly understand the compilation/linking process.

Am I right in thinking that all the included .h files are in one compilation unit and each of the .cpp files are in others, with each compilation unit needing all the header files to which it refers included?

My code is here: https://github.com/StagBeetle/Buttseqs but I expect someone knowledgeable can figure it out without looking at the code. To summarise, I moved the definition of two of my functions from the debug.h into a debug.cpp file, added the includes to header files (each with header guards) that it seemed to need, and now I have many of multiple definition errors.

Here are the first four errors out of about 50:

C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\sequencer.ino.cpp.o: In function `nullIntFunc(int)':
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch/forwarddec.h:274: multiple definition of `nullIntFunc(int)'
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\debug.cpp.o:C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch/Utility.h:21: first defined here
c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\sequencer.ino.cpp.o: In function `nullIntFunc(int)':
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch/forwarddec.h:274: multiple definition of `modes::encoderAllocator(int, int)'
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\debug.cpp.o:c:\program files (x86)\arduino\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1/functional:1829: first defined here

C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\sequencer.ino.cpp.o: In function `nullIntFunc(int)':
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch/forwarddec.h:274: multiple definition of `nullFunc()'
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\debug.cpp.o:c:\program files (x86)\arduino\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1/functional:1829: first defined here

C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\sequencer.ino.cpp.o: In function `nullIntFunc(int)':
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch/forwarddec.h:274: multiple definition of `scheduled::newEvent(scheduled::lOE::listOfEvents, std::function<void ()>, long)'
C:\Users\Lynxwave\AppData\Local\Temp\arduino_build_328148\sketch\debug.cpp.o:c:\program files (x86)\arduino\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1/functional:1829: first defined here

Each one starts "In function "nullIntFunc(int)", despite the definition of that function simply being {;}
Each of them seems to claim the error is in forwarddec.h:274 and each (after the first) says the first definition is in functional:1829

What is going wrong here? Thanks in advance.
 
What is the build environment? An .ino is not apparent in the github tree - is that a library folder independent of the sketch?

It should follow normal build rules - .cpp files are compiled and needed .h's need #include and prototypes before use.

In the Arduino IDE the INO is needed to define a sketch - they cheat and look up prototypes in that INO file. Other .cpp files in that sketch folder are compiled using standard tools. Any included library is 'self standing' compiled as a separate unit to be linked later.

As far as the error the provided text suggests : multiple definition of `nullIntFunc(int)'

It is like `nullIntFunc(int)' is defined in the INO and also the header :: sketch/forwarddec.h

Where what appears in the header should just be a prototype if defined in the sketch.

The github link shows a file like forwarddec2.h - but no sign of what is in :: forwarddec.h
 
Thanks for the response. The build environmnet is just the Arduino IDE. That library structure is the contents of my sketch folder. I've added those files which I tried to upload in bulk earlier.

As far as I can see, there is only one nullIntFunc(int) in utility.h.
 
As @defragster mentioned, I would have expected to see a file like: ButtSeqs.ino in that folder if this is something to build using Arduino.

Arduino can build .cpp files and I do it all of the time, But Arduino does expect at least one .ino file in your folder and one of them needs to be the name of your sketch folder (.ino).
If there are multiple .ino files they are combined together logically into one compile unit. Whereas .cpp files are compiled individually.

Also .ino files, the build system does some stuff for you like create forward function definitions, and autmatically includes Arduino.h. .cpp files are built as is. So for example if your .cpp files calls something like digitalWrite, than that file needs to include the Arduino.h file.
 
Updated github shows : sequencer.ino and forwarddec.h

But neither of them show anything now for nullIntFunc()?

Error next refers to :: \sketch\debug.cpp.o:c:\program files (x86)\arduino\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1/functional:1829: first defined here

Not sure what that comes from?
 
It's in a folder called sequencer on my computer with a sequencer.ino file, now uploaded. The file that makes things go wrong is debug.cpp.
 
Defragster, I don't know either. I was hoping somebody else would. The errors don't make any sense to me because the lines in functional and forwarddec.h to which are referenced look like they have nothing to do with the definitions.
 
maybe there is some residual .o files
force rebuild
either exit and restart Arduino
or change a parameter in tools (e.g.F_CPU)
or delete temp arduino build folder
 
Last edited:
Has anyone got any ideas?
Lots, but maybe none that will help here ;)

My problem here is, I have no idea of how you build this? Yes you say Arduino and you uploaded the .ino file. But does this github project actually match the folder that you are trying to build?
If I try to download your project and open up sequencer.ino it will say it must move that file into a folder named sequencer, so I know it does not match exactly your setup. Maybe all of the files under it do?

Often times it is easier to just create a zip file of your Arduino project. You can do this under Arduino Tools->Archive Sketch... Although I am not sure how that actually works when you have sub-directories like src...

But I tried downloading and it would not compile... Figured out I needed USB to be some form of MIDI. Now it errors saying something like Audio does not have a member usb2...

So again for someone to help, it would be good to know exact steps needed to build it. Things like what version of Arduino and Teensyduino you are using. What external libraries are you using?
What are your compiler settings (Serial->Midi or is it Midi4 or midi16....).

But in this case it is unclear to me where these errors are. Is it in the compiling or linking phase?

My guess is linking?

Probably the issue for nullIntFunc is there could be lots of them...

That is you define it in a header file:
Code:
#ifndef Utility_h
#define Utility_h

#include <bitset>	
#include <vector> 
#include "scheduled.h"
//#include "forwarddec.h"

typedef void (*voidvoid) ();
typedef void (*voidint)  (int);
typedef void (*voiduint8t)  (uint8_t);
typedef void (*voidbool) (bool);
typedef void (*voidu3) (uint8_t, uint8_t, uint8_t);

//Functions:
typedef const char* (*charpvoid) ();
typedef int (*intvoid) ();
typedef bool (*boolvoid) ();

void nullFunc(){;}
void nullIntFunc(int u){;}
...
So suppose utility.h is now included in 10 .cpp files, this will cause this function to be created 10 times.

Could probably solve it by having it defined as extern in the header file and put the actual functions in a .cpp file.

Or maybe you can define the function as static so it is only seen within each compiled unit.
 
WMXZ,

Thank you but I think the answer is to do with a lack of extern.

KurtE,

Thanks for your support and patience. On my PC the code is all in a folder called sequencer and its USB type is Serial + MIDI + Audio.

However, the error is in the linking phase and it seems the issue is most likely due to lack of extern, as you say, so either I have to add .cpp files for every .h or continue to not use .cpp files. I think using static would cause problems in my situation.

Looks like it's solved, but I don't understand why C++ isnt clever enough to figure out that its the same definition appearing twice. Probably because when using C++ properly this error does not occur, but come on Bjarne. Something to consider when you're working on C+++.

The line numbers and files in the error messages still seem wrong though.

Thanks for your help.
 
...
I don't understand why C++ isnt clever enough to figure out that its the same definition appearing twice. Probably because when using C++ properly this error does not occur
...

c/c++ are cleverly designed to do as told - for better or worse - c++ did incorporate some typical clever stuff that all the cool kids were doing

proper use of 'extern' is needed to avoid redefinition.
 
Status
Not open for further replies.
Back
Top