Compiler bug?

i porting my sketch from UNO to Atmega8 breadboard.
But I found one problem.
When I compilling sketch I get error about SoftwareSerial. (Is some problem with softwareserial function on Atmega8... But it is not needed in my sketch, I using sserial only for debugging).

So, software serial is forbidden via Debug function in my sketch. But why arduino compiler building software serial function, when I have commented it via debug function? Please, can you help me?

#include <avr/wdt.h>


//------------------------------------------------
//#define DEBUG    // Debug ON (this switch on software serial)                    DEBUG 1/2 !!!!
//------------------------------------------------
#ifdef DEBUG 
#include <SoftwareSerial.h>
#endif

//SoftwareSerial mySerial(11, 12); // RX, TX
// if DEBUG, MUST be uncomment                                                  DEBUG 2/2 !!!!
// -------------------------------- debug 
#ifdef DEBUG
#define DBG(x) x
#define DBG_PRINT(x) mySerial.println(x)
#define DBG_PRINTnoln(x) mySerial.print(x)
#else
#define DBG(x)
#define DBG_PRINT(x)
#define DBG_PRINTnoln(x)
#endif


void setup() {                
  wdt_enable(WDTO_2S); // have the wdt reset the chip
    
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
  pinMode(button, INPUT_PULLUP);
// initialize serial:
  Serial.begin(19200);

  #ifdef DEBUG
  mySerial.begin(19200);
  #endif

   DBG_PRINT("DBG: FUNCTION > =SETUP= is ending...");
 
}

In code I use this lines :

DBG_PRINT("DBG> my debug note...");

Why compiler build sotfwareserial function, when I commented DEBUG variable? Is some error in my debug function or this is arduino bug? I don´t use any softwareserial function in SETUP or LOOP. When I change line :

#include <SoftwareSerial.h>

to

#include <SoxxxareSerial.h>

Now everything is OK and builded code is shorted. So arduino use some cache of libraries or this is some bug?

Many thanks,
Petr

The IDE copies file to another directory for compilation. It ignores preprocessor directives when doing that. So, SoftwareSerial.h (and SoftwareSerial.cpp) get copied, and added to the list of files to be compiled.

When the compiler compiles your sketch, it sees that SoftwareSerial is not actually needed, and the linker doesn't care whether SoftwareSerial compiled, or not, since it isn't planning to link anything from SoftwareSerial.o into the hex file.

So, no, it is not a compiler bug. It is an IDE feature.

PaulS:
The IDE copies file to another directory for compilation. It ignores preprocessor directives when doing that. So, SoftwareSerial.h (and SoftwareSerial.cpp) get copied, and added to the list of files to be compiled.

When the compiler compiles your sketch, it sees that SoftwareSerial is not actually needed, and the linker doesn't care whether SoftwareSerial compiled, or not, since it isn't planning to link anything from SoftwareSerial.o into the hex file.

So, no, it is not a compiler bug. It is an IDE feature.

If it were only that simple and actually worked that way.

In reality what happens is that the IDE tries to be "smart" and make things easier for the user by
not requiring the user to write valid/correct/proper C/C++ code.
In order to do this, it has to correct the users code for things like missing function prototypes
and forward variable references.
(That is why it must make a copy of your code into a temporary working area)
In order to do that, it goes in and tries to analyze your code to be able to create prototypes for the functions
and pull in the libraries "it thinks" the code uses and declare references for certain known objects.

And there is where the problem is.
The IDE is simply not smart enough to pull that off.
(BTW, that is a very difficult thing to do properly)
The code that does the analyzing is too simple and doesn't understand even some simple things
like conditional compilation.
As a result it will try to pull in code that is no used
and then depend on the linker to remove it later.

In this case, with the SoftSerial code, the linker cannot remove the code and
the code will be pulled in even though the user code is not referencing or using any of it.
This is because the SoftSerial code uses interrupts and has an ISR routine.
The way the code is written, declared ISR routines will always be pulled in, and because of that other SoftSerial routines
are pulled in, and then because of those, most if not all the SoftSerial code and data variables
will be pulled in.

You can see this if you use avr-objdump to create a .lss file and then look at what code is actually
included into the final linked .elf file that will be used to create the final .hex image which
is what will be uploaded to the AVR.

This is a great example of how the current Arduino build methodology simply doesn't work very well.
There are some simple things that could be done to avoid things like this but so far the Arduino Team
seems very unwilling to address things like this.

If you look at the .lss file you will also see the HardwarSerial code and data being pulled.
Similar thing going on there as well. It is part of the core code and since it has ISRs it
ends up getting pulled in.

This is all done because of combination of the build methodology and the way the code is written/declared/used.
There are some ways to fix this but it takes modifications to the actual library code and to the IDE
so it's not really something than an average Arduino user will be able to fix.

So from my point of view, I see this as a well intended "feature" that kind of sort of works,
but in reality creates many other subtle hard to work around issues.

--- bill

Ok, many thanks for explanation.
I can accept this reality if I used "IF" function :

#ifdef DEBUG 
#include <SoftwareSerial.h>
#endif

But why compiller can not ignore this line when I commented this?

when I make :

//#ifdef DEBUG 
//#include <SoftwareSerial.h>
//#endif

I thought comments are absolutely ignored. So why arduino IDE use this if methods and softwareserial include line when it is commented?

I will be confused when I must remove or update everything debug declarations and functions before compile code.

But why compiller can not ignore this line when I commented this?

It does. It would really help if you explained the errors you are getting, instead of us guessing.

C:\arduino-1.0.2\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega8 -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=102 -IC:\arduino-1.0.2\hardware\arduino\cores\arduino -IC:\arduino-1.0.2\hardware\arduino\variants\standard -IC:\arduino-1.0.2\libraries\SoftwareSerial -IC:\arduino-1.0.2\libraries\SoftwareSerial\utility C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp -o C:\DOCUME~1\Notebook\LOCALS~1\Temp\build1882666110994170942.tmp\SoftwareSerial\SoftwareSerial.cpp.o
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:59: warning: only initialized variables can be placed into program memory area
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function 'void SoftwareSerial::begin(long int)':
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:396: error: 'PCICR' was not declared in this scope
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:399: error: 'PCMSK2' was not declared in this scope
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:399: error: 'PCMSK0' was not declared in this scope
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:399: error: 'PCMSK1' was not declared in this scope
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function 'void SoftwareSerial::end()':
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:414: error: 'PCMSK2' was not declared in this scope
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:414: error: 'PCMSK0' was not declared in this scope
C:\arduino-1.0.2\libraries\SoftwareSerial\SoftwareSerial.cpp:414: error: 'PCMSK1' was not declared in this scope

The compiler and the IDE are not the same thing.

The compiler works correctly and the way you expect things to work.
It is the IDE that is not working the way you expect.

The IDE has the problem not the compiler.

In your example code above you commented out the #define
The ifdef and include are not commented out.
The IDE is DUMB. It does not understand ifdefs it simply looks
for #includes and if it sees them for a library,
(even if inside code that is conditionally not used by the compiler),
the IDE will build the library and link against.

This is what I talked about earlier.

--- bill

This error when I use :

/*
//------------------------------------------------
//#define DEBUG    // zapnout LADENI (zapne software serial)                    DEBUG 1/2 !!!!
//------------------------------------------------
#ifdef DEBUG 
#include <SoftwareSerial.h>
#endif
*/

when I make :

/*
//------------------------------------------------
//#define DEBUG    // zapnout LADENI (zapne software serial)                    DEBUG 1/2 !!!!
//------------------------------------------------
#ifdef DEBUG 
#include <SXXXwareSerial.h>
#endif
*/

now everything is ok and compiled done...

Do why compiller accept commented lines? It´s bug! :slight_smile:

I understand everything if I use only IFDEF procedure...

But when I comment whole block as I post at top, I don´t know why IDE can not ignore it and still using this commented lines...

Only when I corrupt name of include - Sxxxrial - now IDE ignore it... It´s very bad :frowning:

Some of the errors you are geting looks
like you are running into another "feature" (bug) of the IDE.
The IDE for some crazy reason trys to look for code inside your code
in order to place the include for its include.

In order work around this I recommend creating a line of code at the very top of your code
to force the IDE to place it's include at the top vs down lower which probably lands inside
your ifdef.

So place this line at the very top of your code:

static char stupidIDE;

This will trick/force the IDE into placing its header file correctly into your working
temporary file and since your code is not referencing the dummy variable, the linker will remove it.

---- bill

This no help :frowning:

bperrybap:

static char stupidIDE;

This will trick/force the IDE into placing its header file correctly into your working
temporary file and since your code is not referencing the dummy variable, the linker will remove it.

---- bill

darksir:
I understand everything if I use only IFDEF procedure...

But when I comment whole block as I post at top, I don´t know why IDE can not ignore it and still using this commented lines...

Only when I corrupt name of include - Sxxxrial - now IDE ignore it... It´s very bad :frowning:

But you didn't comment out everything in the code example in your first post.
This was in that code:

//------------------------------------------------
//#define DEBUG    // Debug ON (this switch on software serial)                    DEBUG 1/2 !!!!
//------------------------------------------------
#ifdef DEBUG 
#include <SoftwareSerial.h>
#endif

The #include is not commented out.
It is inside a conditional compilation block controlled by the define DEBUG but that is not a comment.
While the compiler understands conditionals, the IDE does not.

The IDE saw the include for the SoftwareSerial header and
assumes a reference to SoftwareSerial and so it decided to help you out by
including the library for you as part of the build.
(The IDE tells the compiler what to compile and the linker what to link)

The errors I saw from your compilation were not related to this.
They appeared to be related to the IDE incorrectly inserting its "Arduino.h" header and prototypes
incorrectly.

Attached are examples of how the IDE creates your .cpp file with/without the dummy variable declaration
at the top of you code.
When including header files and especially when doing any conditional compilation, it is usually mandatory
to add this dummy variable to the top of your sketch code because the IDE can often drop its header include
and declarations in a bad location rather than at the top where it needs to be.

To avoid the IDE issue of incorrectly inserting its header and prototypes, I always declare
a dummy static variable at the very top of all my code that is used with the Arduino IDE.

--- bill

test3a.cpp (1.06 KB)

test3b.cpp (1.08 KB)

darksir:
This no help :frowning:

Your example code from your initial post (cleaned up a little) compiled just fine for me.
(I had to correct a few things).
It is a attached.

--- bill

test3.pde (1.04 KB)

Do you compile it for ATMEGA8 ? when I compile it for UNO, everything is ok - atmega8 cannot accept software serial so for this reason make error. This is why I found this error. When I use UNO, I can not see when software serial is compiled. it is silent.

My first code i WRONG !!! I compile it with my second code in middle of this topic.
When I use IFDEF, I can hope IDE use include directive.

But I use this :

/*
//------------------------------------------------
//#define DEBUG    // zapnout LADENI (zapne software serial)                    DEBUG 1/2 !!!!
//------------------------------------------------
//#ifdef DEBUG 
//#include <SoftwareSerial.h>
//#endif
*/
//SoftwareSerial mySerial(11, 12); // RX, TX
// if DEBUG, MUST be uncomment

and still I GET error about software serial, which IS COMMENTED .....

You must select arduino board : Arduino NG or older w/ Atmega8.... UNO work super with softwareserial and you can not find this error...

But it is not error in header files, libraries etc... it is Arduino IDE error.. When i change commented line with
Include softwareserial to Include xxxserial - now everything is ok.... Now arduino dont send error about software serial and dont compile software serial.

Use File + Preferences to turn on verbose output. Find the temporary directories where compilation actually takes place. Delete all of them. Then, try compiling again. Does the commented out #include of SoftwareSerial still generate issues?

Even if it does, it is NOT a compiler issue. It is an IDE issue. Look in the build directory. Is SoftwareSerial.cpp and SoftwareSerial.h there? They would not be if the IDE was working correctly.

I have verbose outup ON still...

When I open NEW project and insert into this new code test3.pde from bperrybap - I still get error when I select Arduino MEGA8 board...

So what can I test now? I use arduino 1.0.2 .... I go to test it in newer 1.0.3 IDE... But I think it is some IDE bug :frowning:

darksir:
I have verbose outup ON still...

When I open NEW project and insert into this new code test3.pde from bperrybap - I still get error when I select Arduino MEGA8 board...

So what can I test now? I use arduino 1.0.2 .... I go to test it in newer 1.0.3 IDE... But I think it is some IDE bug :frowning:

I explained how it works. (I don't like how it works either)
The IDE looks for certain include files or objects to be referenced. If it sees those, the IDE
includes the library associated with those header files or objects in the build.
The IDE analyzer is too simplistic and does not understand conditional compilation.
When you really do comment out the includes in your sample code yes it does compile even for Atmega 8.
I commented out include for SoftSerial and it compiles just fine.

The file I used with the commented out include is attached.

The reason it works when you changed the name of the include is that the IDE is no longer
recognizing that header as part of the SoftSerial library and so it is no longer trying to pull in
the SoftSerial library.

Again, the issue is the IDE and it's simplistic internal preprocessor that looks for
Arduino libraries and objects in an attempt to fix up the user sketch code.
If it recognizes what it considers to be Arduino headers or objects related to Arduino libraries,
it will build and link against the associated library.
It does not understand conditional compilation and that is where you are having issues.

The way the IDE works today, you can not use a conditional to selectively include an arduino library.
The IDE will trigger on seeing the library header or object regardless of whether it is inside
a disabled conditional.

--- bill

test3.pde (1.04 KB)

I found source of problem -
Arduino IDE treated differently to each method of commenting.
when I close include directive to /* as comment - IDE ignore this comment symbol and read this line as normal.
when I use // before line - IDE don´t compile it. It´s not good IMHO. /* block and // is too same and compiler (Arduino IDE) must respect both of this comments methods.
If is accepted only one way, it can lead to unpredictable behavior.

I think it could be proposed as a fix for the next version of ide.
What do you think about it?

Interesting.
You should definitely enter a bug report for it into the issues list.

I tried using /* */ all on the same line and the IDE does recognize this
as commenting out that line.

In the larger picture, in my opinion, the IDE does lots of silly stuff.
The build methodology of trying to parse the file for libraries and referenced objects
has tons of problems.
I've even had it barf on code that is perfectly valid C code and crash the IDE.
Those are very hard to track down and the only option is to move some of your code around
to different lines until it works again.


In your case since you seem to be using the SoftSerial for output only,
I'd go in and create a new SoftSerial "library" that does non interrupt driven output only - the output routines
can be much simpler than the input routines as there are no interrupts.
It doesn't even have to be a real Arduino library.
Take the SoftSerial library code, crush it down and rip it apart
and put all the code and new class definition in a single header file.
Then, you can use your debug ifdefs to include the header file for
your SoftSerialDebug class (library) and do what you originally wanted to do.

--- bill