Adding a cpp file to library (not included) causes "not declared in this scope"

My sketch, barebones, compiles without complaint. The library includes my homegrown SAMD_port.h.

However, when I add my homegrown Functions_Lib.cpp to the library, even though it is not referenced in the barebones sketch, the compiler barfs.

/**  
 * @file       MKR_sketch_barebones.ino
 * @brief      Example all libraries, min functionality -- to demonstrate 
 * @author     Robert Hadow
 * @date       February 2021
 * @par Revision History:
 * 
**/

#include <SD.h>
//#define CHIPSEL_594X      /**< AD5940 or AD5941 Remember to uncomment inside ad5940.h file */
#include <TimeLib.h>        // remember to delete or rename Time.h in the Time library
#include <ad5940.h>
#include "SAMD_Port.h"      // My own header
#include <RTCZero.h>
#include <FlashStorage.h>
#include <ArduinoLowPower.h>
#include <SPI.h>
#include <Wire.h>
//#include "Functions_Lib.cpp"


// Global declarations for SPI
const char chipSelectSD = 10;   // for SD card check this  https://www.arduino.cc/en/Guide/MKRMEMShield
const char chipSelectAD = 10;   // for AD chip
int delayTime = 50;


// Global declarations for time
time_t posixTimeInt = 1614262756; //Number of seconds since 1970-01-01-00:00:00 (Unix EPOCH)
tmElements_t posixTimeStr;

// Global declarations for SD utility library functions:  https://www.arduino.cc/en/Tutorial/LibraryExamples/CardInfo

Sd2Card card;
SdVolume volume;
SdFile root;
// see above for pin assignments


//Global declarations for storing deviceID in flash

// Create a structure that describes *this hardware unit*.
// The "valid" variable is set to "true" once
// the structure is filled with actual data for the first time.

struct deviceDescription {
  boolean valid;
  unsigned int bigSerialNumber;
  unsigned int buildDate;
};

// Create a "deviceDescription" structure and call it "thisDevice"
struct deviceDescription thisDevice;  // playing 2021/02/26
// Make a place for deviceID in the flash
FlashStorage(deviceID, deviceDescription);


// I replaced SERIAL_PORT_MONITOR with Serial  2021-02-24 1614

void setup() {
  Serial.begin(9600);
  // Serial.begin(9600);
  while (!Serial) { }
  //while (!SERIAL_PORT_MONITOR) { }

  //displayPowerState();

  // Then crank up SPI (trying SD card first)

  pinMode(chipSelectSD, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);

  // Check SD card
  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!

  if (!card.init(SPI_HALF_SPEED, chipSelectSD)) {
    Serial.println("SD initialization failed.");
    while (1);
  } else {
    Serial.println("SD card is operational.");
  }
 
  // Then crank up AD5940

}  // end of setup


void loop() {
  // main code here, running repeatedly:

}

The error comes like this:

In file included from C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\libraries\Wire/Wire.h:24:0,
                 from C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp:11:
C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp: In function 'void displayPowerState()':
C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\variants\mkrwifi1010/variant.h:223:39: error: 'SerialUSB' was not declared in this scope
   #define Serial                      SerialUSB
                                       ^
C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp:30:7: note: in expansion of macro 'Serial'
       Serial.println("Battery Not Charging.");
       ^~~~~~

Here is the homegrown H file that works fine.

/**  
 * @file       SAMD_Port.h
 * @brief      AD5940 library. This file contains AD5940 library functions required of user, specific to MCU SAMD
 * @author     Robert Hadow
 * @date       February 2021
 * @par Revision History:
 * 
 * For more information see: https://wiki.analog.com/resources/eval/user-guides/eval-ad5940/tools/porting_source_code
 * 
**/


void AD5940_CsClr(void);
void AD5940_CsSet(void);
void AD5940_RstClr(void);
void AD5940_RstSet(void);
void AD5940_Delay10us(uint32_t time);
void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer,unsigned char *pRecvBuff,unsigned long length);

Here is the offending cpp file that the compiler processes, even though it's not part of the barebone INO.

/**  
 * @file       Functions_Lib.cpp
 * @brief      Functions for BIG device.
 * @author     Robert Hadow
 * @date       February 2021
 * @par Revision History:
 * 
 * 
**/

#include <Wire.h>
#define PMIC_ADDRESS 0x6B
#define PMIC_REG08   0x08

#ifndef SERIAL_PORT_MONITOR
  #define SERIAL_PORT_MONITOR         Serial
#endif

 
void displayPowerState() {
  Wire.beginTransmission(PMIC_ADDRESS);
  Wire.write(PMIC_REG08);
  Wire.requestFrom(PMIC_ADDRESS, 1);
  int8_t ps = Wire.read();  // ps power state
  Wire.endTransmission();

  ps = (ps & 24) >> 4;  //mask and shift
  switch(ps) {
    case 00:
      Serial.println("Battery Not Charging.");
    case 01:
      Serial.println("Battery Pre-charge VBATLOWV>");
    case 10:
        Serial.println("Battery Fast Charging.");
    case 11:
          Serial.println("Battery charge complete.");
    default:
      Serial.println("No battery charging information available.");
  }
}

Question (1): Why does the IDE compiler touch the Function.Lib.cpp file when it isn't referenced in the INO sketch at all?

Question (2): Kernighan and Ritchie tell me that a control line of the form
#define identifier token-sequence
causes the preprocessor to replace subsequent sequences of the identifier with the given sequence of tokens ... A second #define for the same identifier is erroneous unless the second token is identical to the first ...
Is the order in which the #include statements appear important?

Question (3): What boneheaded mistake did I make? I do want to include the function(s) described in Function_Lib.cpp into my INO.

Hi

  • where is Functions_Lib.cpp located? (in the sketch folder or in the libraries)?
  • what Arduino target platform did you pick?

Side note: as 24 is 0b00011000, you probably wanted to shift only by 3 and not 4 here ps = (ps & 24) >> 4;(I suppose you want the bits 3 and 4, starting from 0 at LSb)

You also forgot 0b in front of your case constants here

 ps = (ps & 24) >> 4;  //mask and shift
  switch(ps) {
    case 00: // <<== 0b00
      Serial.println("Battery Not Charging.");
    case 01:  // <<== 0b01
      Serial.println("Battery Pre-charge VBATLOWV>");
    case 10: // <<== 0b10
        Serial.println("Battery Fast Charging.");
    case 11: // <<== 0b11
          Serial.println("Battery charge complete.");
    default:
      Serial.println("No battery charging information available.");
  }

(the first two would work because the octal representation of 0 and 1 are the same as in binary) but 10 and 11 are not the same as 2 and 3 which I suspect is what you wanted.

PS2: You could save the shift operation if your case includes directly 0b00000, 0b01000, 0b10000, 0b11000 since you masked the other bits and as there is no gain to compare only a couple bits, the processor will compare a full byte anyway.

PS3: the default

    default:
      Serial.println("No battery charging information available.");

will never be executed give the mask on 2 bits, you've tested all possible values before.

roberthadow:
Question (1): Why does the IDE compiler touch the Function.Lib.cpp file when it isn't referenced in the INO sketch at all?

It is including the library "SAMD_PORT-master" and there is a "Functions_Lib.cpp" in that library so it compiles that file as part of the library. Later, if none of the symbols in the object file are referenced, the object file won't be included in the link so it won't be part of your program... but every part of the library will be compiled.
Perhaps it is getting confused between your "SAMD_Port.h" and whatever is in the "SAMD_PORT-master" library.

Updates:

Thanks for the help on the details of Function_Lib.cpp. I'll get to those as soon as I can get the whole barebones to compile.

If I add a setup() and loop() to Function_Lib.cpp and rename it INO, it compiles okay, too

I am building for target platform MKR 1010 Wifi

Directory structure:

../Arduino/MKR_sketch_barebones/MKR_sketch_barebones.INO

../Arduino/Libraries/SAMD_PORT-master/SAMD_Port.h
../Arduino/Libraries/SAMD_PORT-master/Function_Lib.cpp
../Arduino/Libraries/ [nine other imported libraries]

I accept that Functions_Lib.cpp gets compiled just because it sits in the library. What is in that cpp file that makes the barebones.INO compile barf? If I #include it, it barfs too.

I suspect that the answer is buried somewhere in this sentence, but I can't make heads of tails of it: "The scope of a name defined with #define is from the point of definition to the end of the source file being compiled."

BTW, I can copy the cpp function definition into the INO file, where it will compile. For the sake of good order, though, keeping the length of the INO file to something reasonable would have kept my profs and bosses happy.

Many thanks for quick response.

Could you share the full compiler (verbose mode) error?

It seems to complain about SerialUSB not being defined when compiling the "library"

full error, verbose mode, attempted compile INO file which does not include Function_Lib.cpp

blah blah blah, all good

Compiling library "SAMD_PORT-master"
"C:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -mcpu=cortex-m0plus -mthumb -c -g -Os -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD -DF_CPU=48000000L -DARDUINO=10813 -DARDUINO_SAMD_MKRWIFI1010 -DARDUINO_ARCH_SAMD -DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ -DUSB_VID=0x2341 -DUSB_PID=0x8054 -DUSBCON "-DUSB_MANUFACTURER=\"Arduino LLC\"" "-DUSB_PRODUCT=\"Arduino MKR WiFi 1010\"" -DUSE_BQ24195L_PMIC "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\tools\\CMSIS\\4.5.0/CMSIS/Include/" "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\tools\\CMSIS-Atmel\\1.2.0/CMSIS/Device/ATMEL/" "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\hardware\\samd\\1.8.10\\cores\\arduino/api/deprecated" "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\hardware\\samd\\1.8.10\\cores\\arduino" "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\hardware\\samd\\1.8.10\\variants\\mkrwifi1010" "-IC:\\Program Files\\WindowsApps\\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\\libraries\\SD\\src" "-IC:\\Users\\Robert\\Documents\\Arduino\\libraries\\Time" "-IC:\\Users\\Robert\\Documents\\Arduino\\libraries\\ad5940lib-master" "-IC:\\Users\\Robert\\Documents\\Arduino\\libraries\\SAMD_PORT-master" "-IC:\\Users\\Robert\\Documents\\Arduino\\libraries\\RTCZero\\src" "-IC:\\Users\\Robert\\Documents\\Arduino\\libraries\\FlashStorage-master\\src" "-IC:\\Users\\Robert\\Documents\\Arduino\\libraries\\Arduino_Low_Power\\src" "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\hardware\\samd\\1.8.10\\libraries\\SPI" "-IC:\\Users\\Robert\\Documents\\ArduinoData\\packages\\arduino\\hardware\\samd\\1.8.10\\libraries\\Wire" "C:\\Users\\Robert\\Documents\\Arduino\\libraries\\SAMD_PORT-master\\Functions_Lib.cpp" -o "C:\\Users\\Robert\\AppData\\Local\\Temp\\arduino_build_233470\\libraries\\SAMD_PORT-master\\Functions_Lib.cpp.o"
In file included from C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\libraries\Wire/Wire.h:24:0,
                 from C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp:11:
C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp: In function 'void displayPowerState()':
C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\variants\mkrwifi1010/variant.h:223:39: error: 'SerialUSB' was not declared in this scope
   #define Serial                      SerialUSB
                                       ^
C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp:31:7: note: in expansion of macro 'Serial'
       Serial.println("Battery Not Charging.");
       ^~~~~~
C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\variants\mkrwifi1010/variant.h:223:39: note: suggested alternative: 'Serial2'
   #define Serial                      SerialUSB
                                       ^
C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master\Functions_Lib.cpp:31:7: note: in expansion of macro 'Serial'
       Serial.println("Battery Not Charging.");
       ^~~~~~
Using library SD at version 1.2.4 in folder: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\SD 
Using library Time at version 1.6 in folder: C:\Users\Robert\Documents\Arduino\libraries\Time 
Using library ad5940lib-master in folder: C:\Users\Robert\Documents\Arduino\libraries\ad5940lib-master (legacy)
Using library SAMD_PORT-master in folder: C:\Users\Robert\Documents\Arduino\libraries\SAMD_PORT-master (legacy)
Using library RTCZero at version 1.6.0 in folder: C:\Users\Robert\Documents\Arduino\libraries\RTCZero 
Using library FlashStorage-master at version 1.0.0 in folder: C:\Users\Robert\Documents\Arduino\libraries\FlashStorage-master 
Using library Arduino_Low_Power at version 1.2.2 in folder: C:\Users\Robert\Documents\Arduino\libraries\Arduino_Low_Power 
Using library SPI at version 1.0 in folder: C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\libraries\SPI 
Using library Wire at version 1.0 in folder: C:\Users\Robert\Documents\ArduinoData\packages\arduino\hardware\samd\1.8.10\libraries\Wire 
exit status 1
Error compiling for board Arduino MKR WiFi 1010.

Are you using latest version of SAMD board? (1.8.8, double check under Boards Manager)

As @johnwasser Saïd even if your .ino does not call any function in that file, it’s part of the library so gets compiled.

There was a bug in the past where the Serial define was an issue but that was addressed in a core tools update if I remember correctly. I’ll try to find the discussion to see if there was more info on addressing it

Edit: found the link to the discussion, nothing special unfortunately besides updating to the latest

Adding a cpp file to library (not included) causes "not declared in this scope" SOLVED

All of the problems described above were symptoms, not the problem.

It is true, simply adding a cpp file to the library will cause it to compile along with the INO file, even if none of its functions are called. This may cause your INO compile to barf.

The solution is this:

Create a functions collection foo.cpp with starts with #include "foo.h" There define your functions.

Create a functions header foo.h with all the #includes, #defines, and your function declarations .

Add #include "foo.h" to your INO sketch.

The logic:

#include or #define only has scope in a single compiled file. The cpp is separate from the INO file. Therefore, there needs to be a mention of them everywhere, but not duplicated. Functions are exercised in the INO sketch. Functions are declared in the foo.h script. Functions are defined in the foo.cpp code. I have not had to use the extern specifier.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.