Compile err: RTCZero::getEpoch()::tm tm has incomplete type and can't be defined

I'm sure I'm doing something wrong here, but I don't know what. I am using the RTCZero (v1.5.0) library in a project to be compiled for TinyScreen+ from TinyCircuits. I have seen another project for TinyScreen+ use this lib, so have reason to believe it's appropriate. In fact, this error is documented in a page describing the project, OWatch (Simple Watch Using RTC - Hackster.io), but I have made the suggested correction, restarted Arduino, and the problem still recurs. Leads me to believe I still have time.h included via some other lib, but I'm not seeing it in the verbose compiler output below. Anyone have ideas what could be wrong?

(I've been trying to replace long strings to trim the compiler output down below the forum's limit, but can't. So here is just the error output. Entire output can be seen at http://pastebin.com/hLY2jgH2)

Compiling library "RTCZero"
"C:\Users\tastewar\AppData\Local\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++" -mcpu=cortex-m0plus -mthumb -c -g -Os -w -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=10611 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_SAMD  -D__SAMD21G18A__ -DUSB_VID=0x03EB -DUSB_PID=0x8009 -DUSBCON '-DUSB_MANUFACTURER="TinyCircuits"' '-DUSB_PRODUCT="TinyScreen+"' "-IC:\Users\tastewar\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel/CMSIS/Include/" "-IC:\Users\tastewar\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel/Device/ATMEL/" "-IC:\Users\tastewar\AppData\Local\Arduino15\packages\TinyCircuits\hardware\samd\1.0.3\cores\arduino" "-IC:\Users\tastewar\AppData\Local\Arduino15\packages\TinyCircuits\hardware\samd\1.0.3\variants\tinyscreen_p" "-IC:\Users\tastewar\Documents\Arduino\libraries\Time" "-IC:\Users\tastewar\Documents\Arduino\libraries\Timezone" "-IC:\Users\tastewar\Documents\Arduino\libraries\Flash\src" "-IC:\Users\tastewar\Documents\Arduino\libraries\TinyCircuits-TinyScreen_Lib" "-IC:\Users\tastewar\AppData\Local\Arduino15\packages\TinyCircuits\hardware\samd\1.0.3\libraries\SPI" "-IC:\Users\tastewar\AppData\Local\Arduino15\packages\TinyCircuits\hardware\samd\1.0.3\libraries\Wire" "-IC:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src" "C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp" -o "C:\Users\tastewar\AppData\Local\Temp\buildb02b8a053f3066e48b3ad8ad08f7b235.tmp\libraries\RTCZero\RTCZero.cpp.o"
C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp: In member function 'uint32_t RTCZero::getEpoch()':

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:373:13: error: aggregate 'RTCZero::getEpoch()::tm tm' has incomplete type and cannot be defined

   struct tm tm;

             ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:385:20: error: 'mktime' was not declared in this scope

   return mktime(&tm);

                    ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp: In member function 'void RTCZero::setEpoch(uint32_t)':

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:31: error: 'gmtime' was not declared in this scope

     struct tm* tmp = gmtime(&t);

                               ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:403:36: error: invalid use of incomplete type 'struct RTCZero::setEpoch(uint32_t)::tm'

     RTC->MODE2.CLOCK.bit.YEAR = tmp->tm_year - EPOCH_TIME_YEAR_OFF;

                                    ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:12: error: forward declaration of 'struct RTCZero::setEpoch(uint32_t)::tm'

     struct tm* tmp = gmtime(&t);

            ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:404:37: error: invalid use of incomplete type 'struct RTCZero::setEpoch(uint32_t)::tm'

     RTC->MODE2.CLOCK.bit.MONTH = tmp->tm_mon + 1;

                                     ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:12: error: forward declaration of 'struct RTCZero::setEpoch(uint32_t)::tm'

     struct tm* tmp = gmtime(&t);

            ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:405:35: error: invalid use of incomplete type 'struct RTCZero::setEpoch(uint32_t)::tm'

     RTC->MODE2.CLOCK.bit.DAY = tmp->tm_mday;

                                   ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:12: error: forward declaration of 'struct RTCZero::setEpoch(uint32_t)::tm'

     struct tm* tmp = gmtime(&t);

            ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:406:36: error: invalid use of incomplete type 'struct RTCZero::setEpoch(uint32_t)::tm'

     RTC->MODE2.CLOCK.bit.HOUR = tmp->tm_hour;

                                    ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:12: error: forward declaration of 'struct RTCZero::setEpoch(uint32_t)::tm'

     struct tm* tmp = gmtime(&t);

            ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:407:38: error: invalid use of incomplete type 'struct RTCZero::setEpoch(uint32_t)::tm'

     RTC->MODE2.CLOCK.bit.MINUTE = tmp->tm_min;

                                      ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:12: error: forward declaration of 'struct RTCZero::setEpoch(uint32_t)::tm'

     struct tm* tmp = gmtime(&t);

            ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:408:38: error: invalid use of incomplete type 'struct RTCZero::setEpoch(uint32_t)::tm'

     RTC->MODE2.CLOCK.bit.SECOND = tmp->tm_sec;

                                      ^

C:\Users\tastewar\Documents\Arduino\libraries\RTCZero\src\RTCZero.cpp:401:12: error: forward declaration of 'struct RTCZero::setEpoch(uint32_t)::tm'

     struct tm* tmp = gmtime(&t);

            ^

I am using the RTCZero (v1.5.0) library

That you got on the discount table at K-Mart?

Anyone have ideas what could be wrong?

Your code. Since you didn’t post it, and a link to the library, we can’t help.

Sorry, I thought RTCZero was the official lib for the RTC on the Arduino Zero, and would be generally known. Perhaps not. It’s on GitHub:

It’s a pretty big project, with many libraries. I am hoping that the error message would ring a bell for someone. The claim made at the page I referred to in my original post is,

To start with, is you read the header Time.h is pretty much useless - all it does it #include <TimeLib.h> - so, for all sane purposes, there is no point in having it around.

For some reason, that library’s author decided to name it just “Time” and from that give it a header file “Time.h” - but there is a standard C/C++ header called “time.h” (which predates Arduino and the Time library by decades, so no excuses for not knowing about it). These two file names only differ by the case of the letter “t”! This means that the Time library. as supplied, is only safe to use under Linux (or similar OS) which has case-sensitive filenames. Both Windows and Macintosh OSes are case-insensitive so they will treat #include <time.h> and #include <Time.h> the same.

The result that it is effectively random which header is read in and so whether or not the code will compile for you.

Ok, the choice will be dictated by the order that the -I options are passed to the compiler. BUT the order of these options is not normally supposed to matter. So one version of the IDE may use a slightly different order from another and it is even possible that the order is indeterminate and changes over time on your computer: when the IDE is started up it will scan the various directories, building up a list of libraries and, as it finds them, adding them to the list of paths to use with the -I option. The order that the libraries are found will depend upon how you have set up the IDE (“portable” or default) and the order they are stored in the directory which is not alphabetically sorted but is effectively random (certainly under Windows).

All of which means that if you have this problem and then just randomly fiddle around with the files - by re-installing, changing from one version of the IDE to another and back again etc etc - then one random change will magically fix the problem. On your computer but sadly not necessarily for anyone else.

Why this state of affairs exists is a bit of a mystery - having been made aware of it for the first time when I tried to build this example, I did a quick search and there are plenty of forum postings that are clearly due to this problem. There is a comment within TimeLib.h that indicates the author does know that Windows and Macintosh will have problems but continues with some statements that are of - arguable value.

Which made a certain amount of sense, but I did make the suggested mod:

Find where your copy ot the Time library has been installed - for me, it was put into arduino\portable\sketchbook\libraries\Time - and rename the file Time.h to Time_h (or you can just delete it altogether). Then edit the files DateStrings.cpp and Time.cpp changing
#include <Time.h>
into
#include <TimeLib.h>

Restart the Arduino IDE and those compilation errors should have gone away.

But I am still getting those errors. Since others had success with the solution, I suspect that a “time.h” is getting included some other way, but I couldn’t see it in the output from the compiler.

If nobody has an idea from that info, I will endeavor to trim down my project and see when the problem is eliminated/introduced. But I remain optimistic that someone might have seen something similar, and might be able to steer me in a productive direction. :slight_smile:

Which made a certain amount of sense, but I did make the suggested mod:

First, we can't see that you made the changes correctly, since you didn't post the modified code.
Second, you don't mention renaming the Time.h file TimeLib.h.

I suspect that the second item is the culprit.

Thanks, Paul. The directions call for renaming Time.h (or deleting it). Here’s a directory listing:

08/29/2016  10:01 PM    <DIR>          .
08/29/2016  10:01 PM    <DIR>          ..
08/29/2016  09:24 PM             3,302 DateStrings.cpp
08/29/2016  09:24 PM    <DIR>          examples
08/29/2016  09:24 PM               857 keywords.txt
08/29/2016  09:24 PM               416 library.json
08/29/2016  09:24 PM               394 library.properties
08/29/2016  09:24 PM             6,913 Readme.txt
08/29/2016  09:24 PM             9,097 Time.cpp
08/29/2016  09:24 PM             6,696 TimeLib.h
08/29/2016  09:24 PM                22 Time_h
               8 File(s)         27,697 bytes
               3 Dir(s)  17,730,088,960 bytes free

Here’s the top of the file DateStrings.cpp:

/* DateStrings.cpp
 * Definitions for date strings for use with the Time library
 *
 * Updated for Arduino 1.5.7 18 July 2014
 *
 * No memory is consumed in the sketch if your code does not call any of the string methods
 * You can change the text of the strings, make sure the short strings are each exactly 3 characters 
 * the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in TimeLib.h
 * 
 */

#if defined(__AVR__)
#include <avr/pgmspace.h>
#else
// for compatiblity with Arduino Due and Teensy 3.0 and maybe others?
#define PROGMEM
#define PGM_P  const char *
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned char **)(addr))
#define strcpy_P(dest, src) strcpy((dest), (src))
#endif
#include <string.h> // for strcpy_P or strcpy
#include "TimeLib.h"

And the top of the file Time.cpp:

/*
  time.c - low level time and date functions
  Copyright (c) Michael Margolis 2009-2014

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  
  1.0  6  Jan 2010 - initial release
  1.1  12 Feb 2010 - fixed leap year calculation error
  1.2  1  Nov 2010 - fixed setTime bug (thanks to Korman for this)
  1.3  24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update
                     status, updated examples for Arduino 1.0, fixed ARM
                     compatibility issues, added TimeArduinoDue and TimeTeensy3
                     examples, add error checking and messages to RTC examples,
                     add examples to DS1307RTC library.
  1.4  5  Sep 2014 - compatibility with Arduino 1.5.7
*/

#if ARDUINO >= 100
#include <Arduino.h> 
#else
#include <WProgram.h> 
#endif

#include "TimeLib.h"

So, I’m no expert, but it strikes me that

struct tm tm;

is pretty bad form – giving a variable the same name as the defined struct type. Maybe it’s allowed, but seems bound to be confusing. And this is at least part of what the compiler is complaining about. But apparently, it is working for others.

Here’s the next big question: where is mktime supposed to be defined? I don’t see it in either TimeLib or RTCZero. In fact a search of all *.c, *.cpp and *.h files in my Arduino\libraries folder finds only this call to mktime in RTCZero.

I performed a few experiments at this point. I tried explicitly including <time.h> in my sketch, prior to the inclusion of RTCZero. Perhaps mktime is defined there, and it would at least change the error. I didn’t check all the error messages, but the first one was the same. I changed the order of includes so that RTCZero was first, but still got the same first error message.

The fact that explicitly including time.h didn’t change the (first…) error messages does make me wonder if it’s being included by some other library. But my reading of the verbose compiler output doesn’t show it! On the other hand, I’m completely baffled by “struct tm tm;” and the call to mktime The compiler does complain that it’s not defined, so how/where is it supposed to be included? From this reference:

http://www.nongnu.org/avr-libc/user-manual/group__avr__time.html

It sure looks like it’s part of the “built in” time library, so why even when I explicitly include it, ahead of RTCZero, is it not being found?