Today I made a very small modification to a library that has worked perfectly for many months. The change was to add a static boolean member variable name "DoTrace", which enables/disables the function of the rest of the class. I added the TraceOn() and TraceOff() methods to set/clear DoTrace, and put the guts of the TraceAppend method inside if (DoTrace) {}. On compile, this results in this warning:
MasterStateTraceRecord.cpp.o:In function
MasterStateTraceRecord::TraceAppend(unsigned long, t_MasterStates, int, int)' MasterStateTraceRecord.cpp:186: warning: undefined reference to
MasterStateTraceRecord::DoTrace'
Oddly, this message points to the last line of the TraceAppend method, while the reference to DoTrace is the first line of the method. The references to DoTrace in TraceOn() and TraceOff() do NOT generate this warning, nor to the accesses to the other static member data items within TraceAppend. "DoTrace" does not appear anywhere else within the project (which is about 40 source files...).
I'm stumped as to why this warning is being generated. Any ideas?
The .h File:
#ifndef MASTERSTATETRACERECORD_H
#define MASTERSTATETRACERECORD_H
#include "StateTraceRecord.h"
#include "MasterStates.h"
#define MASTER_TRACE_QUEUE_DEPTH 150
class MasterStateTraceRecord : public StateTraceRecord
{
public:
MasterStateTraceRecord();
MasterStateTraceRecord(unsigned long timestamp, t_MasterStates state);
virtual void Dump(Stream *console);
const char *GetStateName(t_MasterStates state);
static void TraceFlush(void);
static void TraceAppend(unsigned long timestamp, t_MasterStates state, int pos, int pwm);
static void TraceDump(Stream *console);
static unsigned long GetStartTime(unsigned long time);
static void TraceOn(void);
static void TraceOff(void);
t_MasterStates State;
static boolean DoTrace;
static const char *MasterStateStrings[MASTER_STATE_MAX+1];
static MasterStateTraceRecord MasterTraceQueue[MASTER_TRACE_QUEUE_DEPTH];
static int MasterTraceCnt;
static boolean MasterTraceDone;
};
#endif
The .cpp File:
#include "StateTraceRecord.h"
#include "MasterStateTraceRecord.h"
const char *MasterStateTraceRecord::MasterStateStrings[MASTER_STATE_MAX+1] =
{
STRINGIFY(MASTER_IDLE),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_1),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_2),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_3),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_4),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_5),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_6),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_7),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_8),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_9),
STRINGIFY(MASTER_LOAD_FROM_CAROUSEL_10),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_1),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_2),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_3),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_4),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_5),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_6),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_7),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_8),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_9),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_10),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_11),
STRINGIFY(MASTER_LOAD_TO_CAROUSEL_12),
STRINGIFY(MASTER_LOAD_FROM_SPINDLE),
STRINGIFY(MASTER_LOAD_FROM_SPINDLE_1),
STRINGIFY(MASTER_LOAD_FROM_SPINDLE_2),
STRINGIFY(MASTER_LOAD_FROM_SPINDLE_3),
STRINGIFY(MASTER_LOAD_FROM_SPINDLE_4),
STRINGIFY(MASTER_LOAD_TO_SPINDLE),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_1),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_2),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_3),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_4),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_5),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_6),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_7),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_8),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_9),
STRINGIFY(MASTER_LOAD_TO_SPINDLE_10),
STRINGIFY(MASTER_TO_PARK),
STRINGIFY(MASTER_TO_PARK_1),
STRINGIFY(MASTER_TO_PARK_2),
STRINGIFY(MASTER_TO_PARK_3),
STRINGIFY(MASTER_MOUNT_FIRST_TOOL),
STRINGIFY(MASTER_LOAD_FIRST_TOOL_1),
STRINGIFY(MASTER_UNMOUNT_LAST_TOOL),
STRINGIFY(MASTER_UNLOAD_LAST_TOOL_1),
STRINGIFY(MASTER_UNLOAD_LAST_TOOL_2),
STRINGIFY(MASTER_LOAD_TOOL),
STRINGIFY(MASTER_LOAD_TOOL_1),
STRINGIFY(MASTER_LOAD_TOOL_2),
STRINGIFY(MASTER_LOAD_TOOL_3),
STRINGIFY(MASTER_SWAP_TOOL),
STRINGIFY(MASTER_SWAP_TOOL_1),
STRINGIFY(MASTER_SWAP_TOOL_2),
STRINGIFY(MASTER_SWAP_TOOL_3),
STRINGIFY(MASTER_PARK_ARM),
STRINGIFY(MASTER_PARK_ARM_1),
STRINGIFY(MASTER_PARK_ARM_2),
STRINGIFY(MASTER_PARK_ARM_3),
STRINGIFY(MASTER_PARK_ARM_4),
STRINGIFY(MASTER_INSERT_TO_SPINDLE),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_1),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_2),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_3),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_4),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_5),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_6),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_7),
STRINGIFY(MASTER_INSERT_TO_SPINDLE_8),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_1),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_2),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_3),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_4),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_5),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_6),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_7),
STRINGIFY(MASTER_INSERT_TO_CAROUSEL_8),
STRINGIFY(MASTER_HOME_ALL),
STRINGIFY(MASTER_HOME_ALL_1),
STRINGIFY(MASTER_HOME_ALL_2),
STRINGIFY(MASTER_HOME_ALL_3),
STRINGIFY(MASTER_HOME_ALL_4),
STRINGIFY(MASTER_HOME_ALL_5),
STRINGIFY(MASTER_HOME_ALL_6),
STRINGIFY(MASTER_HOME_ALL_7),
STRINGIFY(MASTER_RANDOM_SEEK_TEST),
STRINGIFY(MASTER_DONE),
STRINGIFY(MASTER_ERR),
STRINGIFY(MASTER_STATE_MAX),
};
MasterStateTraceRecord MasterStateTraceRecord::MasterTraceQueue[MASTER_TRACE_QUEUE_DEPTH];
int MasterStateTraceRecord::MasterTraceCnt = 0;
boolean MasterStateTraceRecord::MasterTraceDone = false;
MasterStateTraceRecord::MasterStateTraceRecord()
{
Device = TRACE_DEVICE_NONE;
Timestamp = 0;
State = MASTER_IDLE;
}
MasterStateTraceRecord::MasterStateTraceRecord(unsigned long timestamp, t_MasterStates state)
{
Device = TRACE_DEVICE_MASTER;
Timestamp = timestamp;
State = state;
}
void MasterStateTraceRecord::TraceOn(void)
{
DoTrace = true;
}
void MasterStateTraceRecord::TraceOff(void)
{
DoTrace = false;
}
const char *MasterStateTraceRecord::GetStateName(t_MasterStates state)
{
const char *ret = NULL;
if (state < MASTER_STATE_MAX)
ret = MasterStateStrings[state];
return ret;
}
void MasterStateTraceRecord::Dump(Stream *console)
{
char *s;
if (State < MASTER_STATE_MAX)
{
if (GetStateName(State) != NULL)
s = (char *)GetStateName(State);
} else
s = "Unknown";
DoDump(console, s);
}
/**************************************************
* MasterTraceFlush()
*************************************************/
void MasterStateTraceRecord::TraceFlush(void)
{
MasterTraceCnt = 0;
MasterTraceDone = false;
}
/**************************************************
* MasterTraceAppend()
*************************************************/
void MasterStateTraceRecord::TraceAppend(unsigned long timestamp, t_MasterStates state, int pos, int pwm)
{
if (DoTrace)
{
if (MasterTraceCnt < MASTER_TRACE_QUEUE_DEPTH)
{
MasterTraceQueue[MasterTraceCnt].Device = TRACE_DEVICE_MASTER;
if (MasterTraceCnt == 0)
MasterTraceQueue[MasterTraceCnt].Timestamp = timestamp;
else
MasterTraceQueue[MasterTraceCnt].Timestamp = timestamp - MasterTraceQueue[0].Timestamp;
MasterTraceQueue[MasterTraceCnt].State = state;
MasterTraceQueue[MasterTraceCnt].CurrentPos = pos;
MasterTraceQueue[MasterTraceCnt].CurrentPWM = pwm;
MasterTraceCnt++;
}
if (state == MASTER_IDLE)
MasterTraceDone = true;
}
}
/**************************************************
* MasterTraceDump()
*************************************************/
void MasterStateTraceRecord::TraceDump(Stream *console)
{
unsigned long start;
if (MasterTraceDone)
{
if (MasterTraceCnt)
{
console->println("Trace Begin");
MasterTraceQueue[0].Timestamp = 0;
for (int i=0; i<MasterTraceCnt; i++)
MasterTraceQueue[i].Dump(console);
console->println("Trace End");
MasterTraceCnt = 0;
MasterTraceDone = false;
}
}
}
unsigned long MasterStateTraceRecord::GetStartTime(unsigned long time)
{
unsigned long ret = time;
if (MasterTraceCnt)
ret = MasterTraceQueue[0].Timestamp;
return ret;
}