关于出现Precompiled header uses __DATE__ or __TIME__警告的探讨和解决方案。
Posted JoySeeDog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于出现Precompiled header uses __DATE__ or __TIME__警告的探讨和解决方案。相关的知识,希望对你有一定的参考价值。
在使用旧版本YYKit的时候,出现了这个警告。具体警告的代码在YYKitMarco.h里面
static inline NSDate *YYCompileTime()
NSString *timeStr = [NSString stringWithFormat:@"%s %s",__DATE__, __TIME__];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMM dd yyyy HH:mm:ss"];
[formatter setLocale:locale];
return [formatter dateFromString:timeStr];
作者给的解决方式在里面 https://github.com/ibireme/YYKit/issues/152,使用新版YYKit即可解决问题,不过作者自己没有分析出现的原因和问题所在。本文将分析问题的根源。
需要明确一点,在不使用Pch文件的时候是不会出现这个错误的,所以需要结合PCH文件的原理来分析问题的所在,我们从以下两方面分析问题:
PCH文件
__DATE__
和__TIME__
等标准预编译宏的用途
PCH文件
首先一点,我们自己建立是 prefix header,就是预编译头文件。在Xcode 6之后,新建项目的时候不会自动生成PCH文件。
预编译的初衷是为了提高整体的编译速度,当项目中很多的文件都需要引用一些共同个头文件时。我们可以把该文件放入PCH文件,当编译项目中的源文件时,我们首先加载PCH文件(作为前缀头),作为该源文件头的替代。
加载PCH文件比重新解析存储在PCH文件中的头文件显着更快。因此,预编译头文件设计是为了最小化读取PCH文件的成本。】
PCH文件编译的时间肯定是早于源文件的编译时间。这就使得源文件如果使用了和编译相关的数据就会出现错误。
参考资料:http://osr600doc.sco.com/en/SDK_cprog/CCCS_CPrecompiledHeaders.html
__DATE__
和__TIME__
等标准预编译宏的用途
__DATE__
This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like “Feb 12 1996”. If the day of the month is less than 10, it is padded with a space on the left.
If GCC cannot determine the current date, it will emit a warning message (once per compilation) and__DATE__
will expand to “??? ?? ????”.
__TIME__
This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like “23:59:01”.
If GCC cannot determine the current time, it will emit a warning message (once per compilation) and __TIME__
will expand to “??:??:??”.
__DATE__
和__TIME__
都是代表了编译当前文件所用的时间,如果使用内联函数,我们在编译PCH文件的时候就会取得该值,这个值在以后的编译文件中都会保持不变。所以获取到的编译时间都是编译PCH文件的时间而不是编译当前文件的时间。
参考地址:https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
测试两种不同的写法的时间差别。新建了一个类,在类里面再获取一次编译时间。然后对比使用两种不同情况的时间区别,为了方便起见,我修改了YYKitMarco里面发返回值为NSString。
#import "TestObject.h"
#import <sys/time.h>
@implementation TestObject
- (void)printPchCompileTime
NSString *date = YYCompileTime();
NSLog(@"YYTime time is %@",date);
- (void)printNormalCompileTime
NSString *date = NormalCompileTime();
static inline NSDate *NormalCompileTime()
NSString *timeStr = [NSString stringWithFormat:@"%s %s",__DATE__, __TIME__];
// NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// [formatter setDateFormat:@"MMM dd yyyy HH:mm:ss"];
// [formatter setLocale:locale];
// return [formatter dateFromString:timeStr];
NSLog(@"slef time is %@",timeStr);
return nil;
首先是使用内联函数的形式。
static inline NSDate *YYCompileTime()
NSString *timeStr = [NSString stringWithFormat:@"%s %s",__DATE__, __TIME__];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMM dd yyyy HH:mm:ss"];
[formatter setLocale:locale];
return [formatter dateFromString:timeStr];
。
时间差别如下,YYKitTime是通过PCH文件里面的内联函数获取到的时间,self time是通过自己源文件获取到的时间。
2016-11-28 10:47:57.611526 PCHDemo[2571:1773812] YYTime time is Nov 28 2016 10:47:52
2016-11-28 10:47:57.611637 PCHDemo[2571:1773812] slef time is Nov 28 2016 10:47:52
乍一看时间是一样的,因为我们的测试工程很小,时间差距不大。我们修改一下TestObject里面的代码,重新编译
2016-11-28 10:48:14.738561 PCHDemo[2573:1774045] YYTime time is Nov 28 2016 10:47:52
2016-11-28 10:48:14.738678 PCHDemo[2573:1774045] slef time is Nov 28 2016 10:48:09
可以看到YYTime时间一直保持和PCH文件第一次编译时间保持一致。
然后使用宏的形式。
static inline NSString *_YYCompileTime(const char *data, const char *time)
NSString *timeStr = [NSString stringWithFormat:@"%s %s",data,time];
// NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// [formatter setDateFormat:@"MMM dd yyyy HH:mm:ss"];
// [formatter setLocale:locale];
return timeStr;
/**
Get compile timestamp.
@return A new date object set to the compile date and time.
*/
#ifndef YYCompileTime
// use macro to avoid compile warning when use pch file
#define YYCompileTime() _YYCompileTime(__DATE__, __TIME__)
#endif
时间差别如下,YYKitTime是通过PCH文件里面的内联函数获取到的时间,self time是通过自己源文件获取到的时间。
2016-11-28 10:49:12.458607 PCHDemo[2575:1774369] YYTime time is Nov 28 2016 10:49:07
2016-11-28 10:49:12.458713 PCHDemo[2575:1774369] slef time is Nov 28 2016 10:49:07
在第一次编译后,修改一下TestObject里面的代码重新编译。
2016-11-28 10:49:35.608224 PCHDemo[2577:1774614] YYTime time is Nov 28 2016 10:49:31
2016-11-28 10:49:35.608347 PCHDemo[2577:1774614] slef time is Nov 28 2016 10:49:31
可以看到使用宏之后,两者获取到的时间保持一致。达到了预期的要求。
宏是在具体源文件之中展开的。所以编译时间获取的是当前编译文件的时间。
其他参考文档:
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20150831/137365.html
DATE.html”>http://www.cprogramming.com/reference/preprocessor/DATE.html
http://clang.llvm.org/docs/DiagnosticsReference.html
http://blog.chinaunix.net/uid-30127490-id-5063666.html
https://msdn.microsoft.com/zh-cn/library/hd8sctab.aspx
http://stackoverflow.com/questions/23648593/what-is-prefix-pch-file-in-xcode
http://clang.llvm.org/docs/PCHInternals.html
http://clang.llvm.org/docs/Modules.html
http://useyourloaf.com/blog/modules-and-precompiled-headers/
http://gamesfromwithin.com/the-care-and-feeding-of-pre-compiled-headers
http://stackoverflow.com/questions/27100847/llvm-6-prefix-header-vs-preprocessor-macros-not-used-in-precompiled-headers
http://osr600doc.sco.com/en/SDK_cprog/CCCS_CPrecompiledHeaders.html
https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
以上是关于关于出现Precompiled header uses __DATE__ or __TIME__警告的探讨和解决方案。的主要内容,如果未能解决你的问题,请参考以下文章
iOS遇到的问题:OC与swift混编造成的 Failed to emit precompiled header
添加头文件的报错failed to emit precompiled header 的解决办法
fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to ad
解决错误 fatal error C1010: unexpected end of file while looking for precompiled head
QT小技巧—更好管理项目(增加预编译头文件,并且指定moc文件的生成位置)good
Visual Studio解决错误 fatal error C1010: unexpected end of file while looking for precompiled head(转)(