Merge topic 'automoc-using-depfiles'

aebfbcaa46 AutoGen: Use depfiles for the XXX_autogen ninja targets
f765fdea03 AutoGen: Use moc's feature to output dependencies
f8c505d4b3 Add a parser for GCC-style depfiles

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Jan Niklas Hasse <jhasse@bixense.com>
Merge-request: !4221
This commit is contained in:
Brad King
2020-01-30 14:52:07 +00:00
committed by Kitware Robot
31 changed files with 3657 additions and 28 deletions

View File

@@ -99,6 +99,7 @@ The following individuals and institutions are among the Contributors:
* Sebastian Holtermann <sebholt@xwmw.org>
* Stephen Kelly <steveire@gmail.com>
* Sylvain Joubert <joubert.sy@gmail.com>
* The Qt Company Ltd.
* Thomas Sondergaard <ts@medical-insight.com>
* Tobias Hunger <tobias.hunger@qt.io>
* Todd Gamblin <tgamblin@llnl.gov>

View File

@@ -26,6 +26,9 @@ See :prop_tgt:`AUTOGEN_TARGET_DEPENDS` for reference.
By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from
:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default.
From Qt 5.15.0 on this variable is ignored as moc is able to output the correct
dependencies.
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.

View File

@@ -134,6 +134,9 @@ set(SRCS
LexerParser/cmFortranParser.cxx
LexerParser/cmFortranParserTokens.h
LexerParser/cmFortranParser.y
LexerParser/cmGccDepfileLexer.cxx
LexerParser/cmGccDepfileLexer.h
LexerParser/cmGccDepfileLexer.in.l
LexerParser/cmListFileLexer.c
LexerParser/cmListFileLexer.in.l
@@ -270,6 +273,10 @@ set(SRCS
cmFortranParserImpl.cxx
cmFSPermissions.cxx
cmFSPermissions.h
cmGccDepfileLexerHelper.cxx
cmGccDepfileLexerHelper.h
cmGccDepfileReader.cxx
cmGccDepfileReader.h
cmGeneratedFileStream.cxx
cmGeneratorExpressionContext.cxx
cmGeneratorExpressionContext.h

View File

@@ -16,4 +16,6 @@
/cmFortranLexer.h generated
/cmFortranParser.cxx generated
/cmFortranParserTokens.h generated
/cmGccDepfileLexer.cxx generated
/cmGccDepfileLexer.h generated
/cmListFileLexer.c generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,687 @@
#ifndef cmGccDepfile_yyHEADER_H
#define cmGccDepfile_yyHEADER_H 1
#define cmGccDepfile_yyIN_HEADER 1
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
#ifdef yy_create_buffer
#define cmGccDepfile_yy_create_buffer_ALREADY_DEFINED
#else
#define yy_create_buffer cmGccDepfile_yy_create_buffer
#endif
#ifdef yy_delete_buffer
#define cmGccDepfile_yy_delete_buffer_ALREADY_DEFINED
#else
#define yy_delete_buffer cmGccDepfile_yy_delete_buffer
#endif
#ifdef yy_scan_buffer
#define cmGccDepfile_yy_scan_buffer_ALREADY_DEFINED
#else
#define yy_scan_buffer cmGccDepfile_yy_scan_buffer
#endif
#ifdef yy_scan_string
#define cmGccDepfile_yy_scan_string_ALREADY_DEFINED
#else
#define yy_scan_string cmGccDepfile_yy_scan_string
#endif
#ifdef yy_scan_bytes
#define cmGccDepfile_yy_scan_bytes_ALREADY_DEFINED
#else
#define yy_scan_bytes cmGccDepfile_yy_scan_bytes
#endif
#ifdef yy_init_buffer
#define cmGccDepfile_yy_init_buffer_ALREADY_DEFINED
#else
#define yy_init_buffer cmGccDepfile_yy_init_buffer
#endif
#ifdef yy_flush_buffer
#define cmGccDepfile_yy_flush_buffer_ALREADY_DEFINED
#else
#define yy_flush_buffer cmGccDepfile_yy_flush_buffer
#endif
#ifdef yy_load_buffer_state
#define cmGccDepfile_yy_load_buffer_state_ALREADY_DEFINED
#else
#define yy_load_buffer_state cmGccDepfile_yy_load_buffer_state
#endif
#ifdef yy_switch_to_buffer
#define cmGccDepfile_yy_switch_to_buffer_ALREADY_DEFINED
#else
#define yy_switch_to_buffer cmGccDepfile_yy_switch_to_buffer
#endif
#ifdef yypush_buffer_state
#define cmGccDepfile_yypush_buffer_state_ALREADY_DEFINED
#else
#define yypush_buffer_state cmGccDepfile_yypush_buffer_state
#endif
#ifdef yypop_buffer_state
#define cmGccDepfile_yypop_buffer_state_ALREADY_DEFINED
#else
#define yypop_buffer_state cmGccDepfile_yypop_buffer_state
#endif
#ifdef yyensure_buffer_stack
#define cmGccDepfile_yyensure_buffer_stack_ALREADY_DEFINED
#else
#define yyensure_buffer_stack cmGccDepfile_yyensure_buffer_stack
#endif
#ifdef yylex
#define cmGccDepfile_yylex_ALREADY_DEFINED
#else
#define yylex cmGccDepfile_yylex
#endif
#ifdef yyrestart
#define cmGccDepfile_yyrestart_ALREADY_DEFINED
#else
#define yyrestart cmGccDepfile_yyrestart
#endif
#ifdef yylex_init
#define cmGccDepfile_yylex_init_ALREADY_DEFINED
#else
#define yylex_init cmGccDepfile_yylex_init
#endif
#ifdef yylex_init_extra
#define cmGccDepfile_yylex_init_extra_ALREADY_DEFINED
#else
#define yylex_init_extra cmGccDepfile_yylex_init_extra
#endif
#ifdef yylex_destroy
#define cmGccDepfile_yylex_destroy_ALREADY_DEFINED
#else
#define yylex_destroy cmGccDepfile_yylex_destroy
#endif
#ifdef yyget_debug
#define cmGccDepfile_yyget_debug_ALREADY_DEFINED
#else
#define yyget_debug cmGccDepfile_yyget_debug
#endif
#ifdef yyset_debug
#define cmGccDepfile_yyset_debug_ALREADY_DEFINED
#else
#define yyset_debug cmGccDepfile_yyset_debug
#endif
#ifdef yyget_extra
#define cmGccDepfile_yyget_extra_ALREADY_DEFINED
#else
#define yyget_extra cmGccDepfile_yyget_extra
#endif
#ifdef yyset_extra
#define cmGccDepfile_yyset_extra_ALREADY_DEFINED
#else
#define yyset_extra cmGccDepfile_yyset_extra
#endif
#ifdef yyget_in
#define cmGccDepfile_yyget_in_ALREADY_DEFINED
#else
#define yyget_in cmGccDepfile_yyget_in
#endif
#ifdef yyset_in
#define cmGccDepfile_yyset_in_ALREADY_DEFINED
#else
#define yyset_in cmGccDepfile_yyset_in
#endif
#ifdef yyget_out
#define cmGccDepfile_yyget_out_ALREADY_DEFINED
#else
#define yyget_out cmGccDepfile_yyget_out
#endif
#ifdef yyset_out
#define cmGccDepfile_yyset_out_ALREADY_DEFINED
#else
#define yyset_out cmGccDepfile_yyset_out
#endif
#ifdef yyget_leng
#define cmGccDepfile_yyget_leng_ALREADY_DEFINED
#else
#define yyget_leng cmGccDepfile_yyget_leng
#endif
#ifdef yyget_text
#define cmGccDepfile_yyget_text_ALREADY_DEFINED
#else
#define yyget_text cmGccDepfile_yyget_text
#endif
#ifdef yyget_lineno
#define cmGccDepfile_yyget_lineno_ALREADY_DEFINED
#else
#define yyget_lineno cmGccDepfile_yyget_lineno
#endif
#ifdef yyset_lineno
#define cmGccDepfile_yyset_lineno_ALREADY_DEFINED
#else
#define yyset_lineno cmGccDepfile_yyset_lineno
#endif
#ifdef yyget_column
#define cmGccDepfile_yyget_column_ALREADY_DEFINED
#else
#define yyget_column cmGccDepfile_yyget_column
#endif
#ifdef yyset_column
#define cmGccDepfile_yyset_column_ALREADY_DEFINED
#else
#define yyset_column cmGccDepfile_yyset_column
#endif
#ifdef yywrap
#define cmGccDepfile_yywrap_ALREADY_DEFINED
#else
#define yywrap cmGccDepfile_yywrap
#endif
#ifdef yyalloc
#define cmGccDepfile_yyalloc_ALREADY_DEFINED
#else
#define yyalloc cmGccDepfile_yyalloc
#endif
#ifdef yyrealloc
#define cmGccDepfile_yyrealloc_ALREADY_DEFINED
#else
#define yyrealloc cmGccDepfile_yyrealloc
#endif
#ifdef yyfree
#define cmGccDepfile_yyfree_ALREADY_DEFINED
#else
#define yyfree cmGccDepfile_yyfree
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
/* end standard C headers. */
/* flex integer type definitions */
#ifndef FLEXINT_H
#define FLEXINT_H
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
#ifndef SIZE_MAX
#define SIZE_MAX (~(size_t)0)
#endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
/* begin standard C++ headers. */
/* TODO: this is always defined, so inline it */
#define yyconst const
#if defined(__GNUC__) && __GNUC__ >= 3
#define yynoreturn __attribute__((__noreturn__))
#else
#define yynoreturn
#endif
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
/* For convenience, these vars (plus the bison vars far below)
are macros in the reentrant scanner. */
#define yyin yyg->yyin_r
#define yyout yyg->yyout_r
#define yyextra yyg->yyextra_r
#define yyleng yyg->yyleng_r
#define yytext yyg->yytext_r
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k.
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
* Ditto for the __ia64__ case accordingly.
*/
#define YY_BUF_SIZE 32768
#else
#define YY_BUF_SIZE 16384
#endif /* __ia64__ */
#endif
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
/* Whether we're considered to be at the beginning of a line.
* If so, '^' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
void yyrestart ( FILE *input_file , yyscan_t yyscanner );
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
void yypop_buffer_state ( yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
#define cmGccDepfile_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
#define INITIAL 0
#endif
#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endif
int yylex_init (yyscan_t* scanner);
int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int yylex_destroy ( yyscan_t yyscanner );
int yyget_debug ( yyscan_t yyscanner );
void yyset_debug ( int debug_flag , yyscan_t yyscanner );
YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
FILE *yyget_in ( yyscan_t yyscanner );
void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
FILE *yyget_out ( yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
int yyget_leng ( yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner );
int yyget_lineno ( yyscan_t yyscanner );
void yyset_lineno ( int _line_number , yyscan_t yyscanner );
int yyget_column ( yyscan_t yyscanner );
void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap ( yyscan_t yyscanner );
#else
extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
#endif
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k */
#define YY_READ_BUF_SIZE 16384
#else
#define YY_READ_BUF_SIZE 8192
#endif /* __ia64__ */
#endif
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
extern int yylex (yyscan_t yyscanner);
#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
#undef YY_NEW_FILE
#undef YY_FLUSH_BUFFER
#undef yy_set_bol
#undef yy_new_buffer
#undef yy_set_interactive
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
#ifndef cmGccDepfile_yy_create_buffer_ALREADY_DEFINED
#undef yy_create_buffer
#endif
#ifndef cmGccDepfile_yy_delete_buffer_ALREADY_DEFINED
#undef yy_delete_buffer
#endif
#ifndef cmGccDepfile_yy_scan_buffer_ALREADY_DEFINED
#undef yy_scan_buffer
#endif
#ifndef cmGccDepfile_yy_scan_string_ALREADY_DEFINED
#undef yy_scan_string
#endif
#ifndef cmGccDepfile_yy_scan_bytes_ALREADY_DEFINED
#undef yy_scan_bytes
#endif
#ifndef cmGccDepfile_yy_init_buffer_ALREADY_DEFINED
#undef yy_init_buffer
#endif
#ifndef cmGccDepfile_yy_flush_buffer_ALREADY_DEFINED
#undef yy_flush_buffer
#endif
#ifndef cmGccDepfile_yy_load_buffer_state_ALREADY_DEFINED
#undef yy_load_buffer_state
#endif
#ifndef cmGccDepfile_yy_switch_to_buffer_ALREADY_DEFINED
#undef yy_switch_to_buffer
#endif
#ifndef cmGccDepfile_yypush_buffer_state_ALREADY_DEFINED
#undef yypush_buffer_state
#endif
#ifndef cmGccDepfile_yypop_buffer_state_ALREADY_DEFINED
#undef yypop_buffer_state
#endif
#ifndef cmGccDepfile_yyensure_buffer_stack_ALREADY_DEFINED
#undef yyensure_buffer_stack
#endif
#ifndef cmGccDepfile_yylex_ALREADY_DEFINED
#undef yylex
#endif
#ifndef cmGccDepfile_yyrestart_ALREADY_DEFINED
#undef yyrestart
#endif
#ifndef cmGccDepfile_yylex_init_ALREADY_DEFINED
#undef yylex_init
#endif
#ifndef cmGccDepfile_yylex_init_extra_ALREADY_DEFINED
#undef yylex_init_extra
#endif
#ifndef cmGccDepfile_yylex_destroy_ALREADY_DEFINED
#undef yylex_destroy
#endif
#ifndef cmGccDepfile_yyget_debug_ALREADY_DEFINED
#undef yyget_debug
#endif
#ifndef cmGccDepfile_yyset_debug_ALREADY_DEFINED
#undef yyset_debug
#endif
#ifndef cmGccDepfile_yyget_extra_ALREADY_DEFINED
#undef yyget_extra
#endif
#ifndef cmGccDepfile_yyset_extra_ALREADY_DEFINED
#undef yyset_extra
#endif
#ifndef cmGccDepfile_yyget_in_ALREADY_DEFINED
#undef yyget_in
#endif
#ifndef cmGccDepfile_yyset_in_ALREADY_DEFINED
#undef yyset_in
#endif
#ifndef cmGccDepfile_yyget_out_ALREADY_DEFINED
#undef yyget_out
#endif
#ifndef cmGccDepfile_yyset_out_ALREADY_DEFINED
#undef yyset_out
#endif
#ifndef cmGccDepfile_yyget_leng_ALREADY_DEFINED
#undef yyget_leng
#endif
#ifndef cmGccDepfile_yyget_text_ALREADY_DEFINED
#undef yyget_text
#endif
#ifndef cmGccDepfile_yyget_lineno_ALREADY_DEFINED
#undef yyget_lineno
#endif
#ifndef cmGccDepfile_yyset_lineno_ALREADY_DEFINED
#undef yyset_lineno
#endif
#ifndef cmGccDepfile_yyget_column_ALREADY_DEFINED
#undef yyget_column
#endif
#ifndef cmGccDepfile_yyset_column_ALREADY_DEFINED
#undef yyset_column
#endif
#ifndef cmGccDepfile_yywrap_ALREADY_DEFINED
#undef yywrap
#endif
#ifndef cmGccDepfile_yyget_lval_ALREADY_DEFINED
#undef yyget_lval
#endif
#ifndef cmGccDepfile_yyset_lval_ALREADY_DEFINED
#undef yyset_lval
#endif
#ifndef cmGccDepfile_yyget_lloc_ALREADY_DEFINED
#undef yyget_lloc
#endif
#ifndef cmGccDepfile_yyset_lloc_ALREADY_DEFINED
#undef yyset_lloc
#endif
#ifndef cmGccDepfile_yyalloc_ALREADY_DEFINED
#undef yyalloc
#endif
#ifndef cmGccDepfile_yyrealloc_ALREADY_DEFINED
#undef yyrealloc
#endif
#ifndef cmGccDepfile_yyfree_ALREADY_DEFINED
#undef yyfree
#endif
#ifndef cmGccDepfile_yytext_ALREADY_DEFINED
#undef yytext
#endif
#ifndef cmGccDepfile_yyleng_ALREADY_DEFINED
#undef yyleng
#endif
#ifndef cmGccDepfile_yyin_ALREADY_DEFINED
#undef yyin
#endif
#ifndef cmGccDepfile_yyout_ALREADY_DEFINED
#undef yyout
#endif
#ifndef cmGccDepfile_yy_flex_debug_ALREADY_DEFINED
#undef yy_flex_debug
#endif
#ifndef cmGccDepfile_yylineno_ALREADY_DEFINED
#undef yylineno
#endif
#ifndef cmGccDepfile_yytables_fload_ALREADY_DEFINED
#undef yytables_fload
#endif
#ifndef cmGccDepfile_yytables_destroy_ALREADY_DEFINED
#undef yytables_destroy
#endif
#ifndef cmGccDepfile_yyTABLES_NAME_ALREADY_DEFINED
#undef yyTABLES_NAME
#endif
#undef cmGccDepfile_yyIN_HEADER
#endif /* cmGccDepfile_yyHEADER_H */

View File

@@ -0,0 +1,72 @@
%{
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
/* IWYU pragma: no_forward_declare yyguts_t */
#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
#include <cmGccDepfileLexerHelper.h>
#include <string>
%}
%option prefix="cmGccDepfile_yy"
%option noyywrap
%option reentrant
%pointer
WSPACE [ \t]
NEWLINE \r?\n
%%
\${2} {
// Unescape the dollar sign.
yyextra->addToCurrentPath("$");
}
\\# {
// Unescape the hash.
yyextra->addToCurrentPath("#");
}
(\\\\)*\\[ ] {
// 2N+1 backslashes plus space -> N backslashes plus space.
size_t c = (strlen(yytext) - 1) / 2;
std::string s(c, '\\');
s.push_back(' ');
yyextra->addToCurrentPath(s.c_str());
}
(\\\\)+[ ] {
// 2N backslashes plus space -> 2N backslashes, end of filename.
yytext[strlen(yytext) - 1] = 0;
yyextra->addToCurrentPath(yytext);
yyextra->newDependency();
}
{WSPACE}*\\{NEWLINE} {
// A line continuation ends the current file name.
yyextra->newDependency();
}
{NEWLINE} {
// A newline ends the current file name and the current rule.
yyextra->newEntry();
}
:{WSPACE}+ {
// A colon followed by space ends the rules and starts a new dependency.
yyextra->newDependency();
}
{WSPACE}+ {
// Rules and dependencies are separated by blocks of whitespace.
yyextra->newRuleOrDependency();
}
[a-zA-Z0-9+,/_.~()}{%=@\x5B\x5D!\x80-\xFF-]+ {
// Got a span of plain text.
yyextra->addToCurrentPath(yytext);
}
. {
// Got an otherwise unmatched character.
yyextra->addToCurrentPath(yytext);
}
%%
/*--------------------------------------------------------------------------*/
#endif /* __clang_analyzer__ */

View File

@@ -0,0 +1,126 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGccDepfileLexerHelper.h"
#include <cstdio>
#include <memory>
#include <string>
#include <vector>
#include "cmGccDepfileReaderTypes.h"
#include "LexerParser/cmGccDepfileLexer.h"
#ifdef _WIN32
# include "cmsys/Encoding.h"
#endif
bool cmGccDepfileLexerHelper::readFile(const char* filePath)
{
#ifdef _WIN32
wchar_t* wpath = cmsysEncoding_DupToWide(filePath);
FILE* file = _wfopen(wpath, L"rb");
free(wpath);
#else
FILE* file = fopen(filePath, "r");
#endif
if (!file) {
return false;
}
newEntry();
yyscan_t scanner;
cmGccDepfile_yylex_init(&scanner);
cmGccDepfile_yyset_extra(this, scanner);
cmGccDepfile_yyrestart(file, scanner);
cmGccDepfile_yylex(scanner);
cmGccDepfile_yylex_destroy(scanner);
sanitizeContent();
fclose(file);
return true;
}
void cmGccDepfileLexerHelper::newEntry()
{
this->HelperState = State::Rule;
this->Content.emplace_back();
newRule();
}
void cmGccDepfileLexerHelper::newRule()
{
auto& entry = this->Content.back();
if (entry.rules.empty() || !entry.rules.back().empty()) {
entry.rules.emplace_back();
}
}
void cmGccDepfileLexerHelper::newDependency()
{
// printf("NEW DEP\n");
this->HelperState = State::Dependency;
if (this->Content.back().paths.empty() ||
!this->Content.back().paths.back().empty()) {
this->Content.back().paths.emplace_back();
}
}
void cmGccDepfileLexerHelper::newRuleOrDependency()
{
if (this->HelperState == State::Rule) {
newRule();
} else {
newDependency();
}
}
void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
{
if (this->Content.empty()) {
return;
}
cmGccStyleDependency* dep = &this->Content.back();
std::string* dst = nullptr;
switch (this->HelperState) {
case State::Rule: {
if (dep->rules.empty()) {
return;
}
dst = &dep->rules.back();
} break;
case State::Dependency: {
if (dep->paths.empty()) {
return;
}
dst = &dep->paths.back();
} break;
}
dst->append(s);
}
void cmGccDepfileLexerHelper::sanitizeContent()
{
for (auto it = this->Content.begin(); it != this->Content.end();) {
// Remove empty rules
for (auto rit = it->rules.begin(); rit != it->rules.end();) {
if (rit->empty()) {
rit = it->rules.erase(rit);
} else {
++rit;
}
}
// Remove the entry if rules are empty
if (it->rules.empty()) {
it = this->Content.erase(it);
} else {
// Remove empty paths
for (auto pit = it->paths.begin(); pit != it->paths.end();) {
if (pit->empty()) {
pit = it->paths.erase(pit);
} else {
++pit;
}
}
++it;
}
}
}

View File

@@ -0,0 +1,40 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGccDepfileLexerHelper_h
#define cmGccDepfileLexerHelper_h
#include <utility>
#include <cmGccDepfileReaderTypes.h>
class cmGccDepfileLexerHelper
{
public:
cmGccDepfileLexerHelper() = default;
bool readFile(const char* filePath);
cmGccDepfileContent extractContent() && { return std::move(this->Content); }
// Functions called by the lexer
void newEntry();
void newRule();
void newDependency();
void newRuleOrDependency();
void addToCurrentPath(const char* s);
private:
void sanitizeContent();
cmGccDepfileContent Content;
enum class State
{
Rule,
Dependency
};
State HelperState = State::Rule;
};
#define YY_EXTRA_TYPE cmGccDepfileLexerHelper*
#endif

View File

@@ -0,0 +1,18 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGccDepfileReader.h"
#include <type_traits>
#include <utility>
#include "cmGccDepfileLexerHelper.h"
cmGccDepfileContent cmReadGccDepfile(const char* filePath)
{
cmGccDepfileContent result;
cmGccDepfileLexerHelper helper;
if (helper.readFile(filePath)) {
result = std::move(helper).extractContent();
}
return result;
}

View File

@@ -0,0 +1,10 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGccDepfileReader_h
#define cmGccDepfileReader_h
#include "cmGccDepfileReaderTypes.h"
cmGccDepfileContent cmReadGccDepfile(const char* filePath);
#endif

View File

@@ -0,0 +1,17 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmGccDepfileReaderTypes_h
#define cmGccDepfileReaderTypes_h
#include <string>
#include <vector>
struct cmGccStyleDependency
{
std::vector<std::string> rules;
std::vector<std::string> paths;
};
using cmGccDepfileContent = std::vector<cmGccStyleDependency>;
#endif

View File

@@ -1171,13 +1171,51 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
}
std::vector<std::string> dependencies(
this->AutogenTarget.DependFiles.begin(),
this->AutogenTarget.DependFiles.end());
const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) &&
this->GlobalGen->GetName().find("Ninja") != std::string::npos;
if (useNinjaDepfile) {
// Create a custom command that generates a timestamp file and
// has a depfile assigned. The depfile is created by JobDepFilesMergeT.
// Add additional autogen target dependencies
for (const cmTarget* t : this->AutogenTarget.DependTargets) {
dependencies.push_back(t->GetName());
}
const char timestampFileName[] = "timestamp";
const std::string outputFile =
cmStrCat(this->Dir.Build, "/", timestampFileName);
this->AutogenTarget.DepFile = cmStrCat(this->Dir.Build, "/deps");
this->AutogenTarget.DepFileRuleName =
cmStrCat(this->GenTarget->GetName(), "_autogen/", timestampFileName);
commandLines.push_back(cmMakeCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));
this->AddGeneratedSource(outputFile, this->Moc);
const std::string no_main_dependency;
this->LocalGen->AddCustomCommandToOutput(
outputFile, dependencies, no_main_dependency, commandLines,
autogenComment.c_str(), this->Dir.Work.c_str(), /*replace=*/false,
/*escapeOldStyle=*/false,
/*uses_terminal=*/false,
/*command_expand_lists=*/false, this->AutogenTarget.DepFile);
// Alter variables for the autogen target which now merely wraps the
// custom command
dependencies.clear();
dependencies.push_back(outputFile);
commandLines.clear();
autogenComment.clear();
}
// Create autogen target
cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
this->AutogenTarget.Name, true, this->Dir.Work.c_str(),
/*byproducts=*/autogenProvides,
std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),
this->AutogenTarget.DependFiles.end()),
commandLines, false, autogenComment.c_str());
/*depends=*/dependencies, commandLines, false, autogenComment.c_str());
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen));
@@ -1188,9 +1226,11 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
autogenTarget->AddUtility(depName.Value, this->Makefile);
}
}
// Add additional autogen target dependencies to autogen target
for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
autogenTarget->AddUtility(depTarget->GetName(), this->Makefile);
if (!useNinjaDepfile) {
// Add additional autogen target dependencies to autogen target
for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
autogenTarget->AddUtility(depTarget->GetName(), this->Makefile);
}
}
// Set FOLDER property in autogen target
@@ -1408,12 +1448,15 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
info.SetConfig("INCLUDE_DIR", this->Dir.Include);
info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);
info.SetUInt("QT_VERSION_MINOR", this->QtVersion.Minor);
info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable);
info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable);
info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);
info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
info.Set("DEP_FILE", this->AutogenTarget.DepFile);
info.Set("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName);
info.SetArray("HEADER_EXTENSIONS",
this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
info.SetArrayArray(

View File

@@ -191,6 +191,8 @@ private:
bool DependOrigin = false;
std::set<std::string> DependFiles;
std::set<cmTarget*> DependTargets;
std::string DepFile;
std::string DepFileRuleName;
// Sources to process
std::unordered_map<cmSourceFile*, MUFileHandle> Headers;
std::unordered_map<cmSourceFile*, MUFileHandle> Sources;

View File

@@ -25,6 +25,8 @@
#include "cmCryptoHash.h"
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
@@ -170,7 +172,7 @@ public:
// -- Attributes
// - Config
bool MultiConfig = false;
unsigned int QtVersionMajor = 4;
IntegerVersion QtVersion = { 4, 0 };
unsigned int ThreadCount = 0;
// - Directories
std::string AutogenBuildDir;
@@ -179,6 +181,8 @@ public:
std::string CMakeExecutable;
cmFileTime CMakeExecutableTime;
std::string ParseCacheFile;
std::string DepFile;
std::string DepFileRuleName;
std::vector<std::string> HeaderExtensions;
};
@@ -216,6 +220,7 @@ public:
bool SettingsChanged = false;
bool RelaxedMode = false;
bool PathPrefix = false;
bool CanOutputDependencies = false;
cmFileTime ExecutableTime;
std::string Executable;
std::string CompFileAbs;
@@ -485,8 +490,17 @@ public:
class JobCompileMocT : public JobCompileT
{
public:
using JobCompileT::JobCompileT;
JobCompileMocT(MappingHandleT uicMapping,
std::unique_ptr<std::string> reason,
ParseCacheT::FileHandleT cacheEntry)
: JobCompileT(std::move(uicMapping), std::move(reason))
, CacheEntry(std::move(cacheEntry))
{
}
void Process() override;
protected:
ParseCacheT::FileHandleT CacheEntry;
};
/** uic compiles a file. */
@@ -504,6 +518,12 @@ public:
void Process() override;
};
class JobDepFilesMergeT : public JobFenceT
{
private:
void Process() override;
};
/** @brief The last job. */
class JobFinishT : public JobFenceT
{
@@ -546,6 +566,9 @@ private:
void Abort(bool error);
// -- Generation
bool CreateDirectories();
// -- Support for depfiles
static std::vector<std::string> dependenciesFromDepFile(
const char* filePath);
private:
// -- Settings
@@ -951,7 +974,7 @@ void cmQtAutoMocUicT::JobParseT::MocMacro()
void cmQtAutoMocUicT::JobParseT::MocDependecies()
{
if (MocConst().DependFilters.empty()) {
if (MocConst().DependFilters.empty() || MocConst().CanOutputDependencies) {
return;
}
@@ -1674,8 +1697,13 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
if (Probe(*mapping, reason.get())) {
// Register the parent directory for creation
MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
// Fetch the cache entry for the source file
std::string const& sourceFile = mapping->SourceFile->FileName;
ParseCacheT::GetOrInsertT cacheEntry =
BaseEval().ParseCache.GetOrInsert(sourceFile);
// Add moc job
Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(mapping, std::move(reason));
Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(
mapping, std::move(reason), std::move(cacheEntry.first));
// Check if a moc job for a mocs_compilation.cpp entry was generated
if (compFile) {
MocEval().CompUpdated = true;
@@ -1779,6 +1807,14 @@ cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
std::string const& sourceDir, std::string const& includeString) const
{
using ResPair = std::pair<std::string, cmFileTime>;
// moc's dependency file contains absolute paths
if (MocConst().CanOutputDependencies) {
ResPair res{ includeString, {} };
if (res.second.Load(res.first)) {
return res;
}
return {};
}
// Search in vicinity of the source
{
ResPair res{ sourceDir + includeString, {} };
@@ -1898,6 +1934,11 @@ void cmQtAutoMocUicT::JobProbeDepsFinishT::Process()
Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
}
if (!BaseConst().DepFile.empty()) {
// Add job to merge dep files
Gen()->WorkerPool().EmplaceJob<JobDepFilesMergeT>();
}
// Add finish job
Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}
@@ -1947,6 +1988,9 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
}
// Add extra options
cm::append(cmd, MocConst().OptionsExtra);
if (MocConst().CanOutputDependencies) {
cmd.emplace_back("--output-dep-file");
}
// Add output file
cmd.emplace_back("-o");
cmd.push_back(outputFile);
@@ -1956,12 +2000,7 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
// Execute moc command
cmWorkerPool::ProcessResultT result;
if (RunProcess(GenT::MOC, result, cmd, Reason.get())) {
// Moc command success. Print moc output.
if (!result.StdOut.empty()) {
Log().Info(GenT::MOC, result.StdOut);
}
} else {
if (!RunProcess(GenT::MOC, result, cmd, Reason.get())) {
// Moc command failed
std::string includers;
if (!Mapping->IncluderFiles.empty()) {
@@ -1976,6 +2015,28 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
MessagePath(outputFile), '\n', includers,
result.ErrorMessage),
cmd, result.StdOut);
return;
}
// Moc command success. Print moc output.
if (!result.StdOut.empty()) {
Log().Info(GenT::MOC, result.StdOut);
}
// Extract dependencies from the dep file moc generated for us
if (MocConst().CanOutputDependencies) {
const std::string depfile = outputFile + ".d";
if (Log().Verbose()) {
Log().Info(GenT::MOC,
"Reading dependencies from " + MessagePath(depfile));
}
if (!cmSystemTools::FileExists(depfile)) {
Log().Warning(GenT::MOC,
"Dependency file " + MessagePath(depfile) +
" does not exist.");
return;
}
CacheEntry->Moc.Depends = dependenciesFromDepFile(depfile.c_str());
}
}
@@ -1992,7 +2053,7 @@ void cmQtAutoMocUicT::JobCompileUicT::Process()
auto optionIt = UicConst().UiFiles.find(sourceFile);
if (optionIt != UicConst().UiFiles.end()) {
UicMergeOptions(allOpts, optionIt->second.Options,
(BaseConst().QtVersionMajor == 5));
(BaseConst().QtVersion.Major == 5));
}
cm::append(cmd, allOpts);
}
@@ -2067,6 +2128,106 @@ void cmQtAutoMocUicT::JobMocsCompilationT::Process()
}
}
/*
* Escapes paths for Ninja depfiles.
* This is a re-implementation of what moc does when writing depfiles.
*/
std::string escapeDependencyPath(cm::string_view path)
{
std::string escapedPath;
escapedPath.reserve(path.size());
const size_t s = path.size();
int backslashCount = 0;
for (size_t i = 0; i < s; ++i) {
if (path[i] == '\\') {
++backslashCount;
} else {
if (path[i] == '$') {
escapedPath.push_back('$');
} else if (path[i] == '#') {
escapedPath.push_back('\\');
} else if (path[i] == ' ') {
// Double the amount of written backslashes,
// and add one more to escape the space.
while (backslashCount-- >= 0) {
escapedPath.push_back('\\');
}
}
backslashCount = 0;
}
escapedPath.push_back(path[i]);
}
return escapedPath;
}
void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
{
if (Log().Verbose()) {
Log().Info(GenT::MOC, "Merging MOC dependencies");
}
auto processDepFile =
[](const std::string& mocOutputFile) -> std::vector<std::string> {
std::string f = mocOutputFile + ".d";
if (!cmSystemTools::FileExists(f)) {
return {};
}
return dependenciesFromDepFile(f.c_str());
};
std::vector<std::string> dependencies;
ParseCacheT& parseCache = BaseEval().ParseCache;
auto processMappingEntry = [&](const MappingMapT::value_type& m) {
auto cacheEntry = parseCache.GetOrInsert(m.first);
if (cacheEntry.first->Moc.Depends.empty()) {
cacheEntry.first->Moc.Depends = processDepFile(m.second->OutputFile);
}
dependencies.insert(dependencies.end(),
cacheEntry.first->Moc.Depends.begin(),
cacheEntry.first->Moc.Depends.end());
};
std::for_each(MocEval().HeaderMappings.begin(),
MocEval().HeaderMappings.end(), processMappingEntry);
std::for_each(MocEval().SourceMappings.begin(),
MocEval().SourceMappings.end(), processMappingEntry);
// Remove duplicates to make the depfile smaller
std::sort(dependencies.begin(), dependencies.end());
dependencies.erase(std::unique(dependencies.begin(), dependencies.end()),
dependencies.end());
// Add form files
for (const auto& uif : UicEval().UiFiles) {
dependencies.push_back(uif.first);
}
// Write the file
cmsys::ofstream ofs;
ofs.open(BaseConst().DepFile.c_str(),
(std::ios::out | std::ios::binary | std::ios::trunc));
if (!ofs) {
LogError(GenT::GEN,
cmStrCat("Cannot open ", MessagePath(BaseConst().DepFile),
" for writing."));
return;
}
ofs << BaseConst().DepFileRuleName << ": \\" << std::endl;
for (const std::string& file : dependencies) {
ofs << '\t' << escapeDependencyPath(file) << " \\" << std::endl;
if (!ofs.good()) {
LogError(GenT::GEN,
cmStrCat("Writing depfile", MessagePath(BaseConst().DepFile),
" failed."));
return;
}
}
// Add the CMake executable to re-new cache data if necessary.
// Also, this is the last entry, so don't add a backslash.
ofs << '\t' << escapeDependencyPath(BaseConst().CMakeExecutable)
<< std::endl;
}
void cmQtAutoMocUicT::JobFinishT::Process()
{
Gen()->AbortSuccess();
@@ -2082,7 +2243,8 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
{
// -- Required settings
if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
!info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
!info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersion.Major, true) ||
!info.GetUInt("QT_VERSION_MINOR", BaseConst_.QtVersion.Minor, true) ||
!info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
!info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
!info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir,
@@ -2090,6 +2252,9 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
!info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
!info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile,
true) ||
!info.GetString("DEP_FILE", BaseConst_.DepFile, false) ||
!info.GetString("DEP_FILE_RULE_NAME", BaseConst_.DepFileRuleName,
false) ||
!info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
!info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
!info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
@@ -2143,8 +2308,10 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
MocConst_.MacroFilters.emplace_back(
item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
}
// Dependency filters
{
// Can moc output dependencies or do we need to setup dependency filters?
if (BaseConst_.QtVersion >= IntegerVersion(5, 15)) {
MocConst_.CanOutputDependencies = true;
} else {
Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
if (!val.isArray()) {
return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array.");
@@ -2660,6 +2827,19 @@ bool cmQtAutoMocUicT::CreateDirectories()
return true;
}
std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
const char* filePath)
{
cmGccDepfileContent content = cmReadGccDepfile(filePath);
if (content.empty()) {
return {};
}
// Moc outputs a depfile with exactly one rule.
// Discard the rule and return the dependencies.
return content.front().paths;
}
void cmQtAutoMocUicT::Abort(bool error)
{
if (error) {

View File

@@ -11,6 +11,7 @@ set(CMakeLib_TESTS
testCTestResourceAllocator.cxx
testCTestResourceSpec.cxx
testCTestResourceGroups.cxx
testGccDepfileReader.cxx
testGeneratedFileStream.cxx
testRST.cxx
testRange.cxx
@@ -35,6 +36,7 @@ set(testRST_ARGS ${CMAKE_CURRENT_SOURCE_DIR})
set(testUVProcessChain_ARGS $<TARGET_FILE:testUVProcessChainHelper>)
set(testUVStreambuf_ARGS $<TARGET_FILE:cmake>)
set(testCTestResourceSpec_ARGS ${CMAKE_CURRENT_SOURCE_DIR})
set(testGccDepfileReader_ARGS ${CMAKE_CURRENT_SOURCE_DIR})
if(WIN32)
list(APPEND CMakeLib_TESTS

View File

@@ -0,0 +1,131 @@
#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "cmsys/FStream.hxx"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h" // for cmGccDepfileContent, cmGccStyle...
#include "cmSystemTools.h"
namespace {
cmGccDepfileContent readPlainDepfile(const char* filePath)
{
cmGccDepfileContent result;
cmsys::ifstream is(filePath);
if (!is.is_open())
return result;
std::string line;
cmGccStyleDependency dep;
bool readingRules = true;
while (cmSystemTools::GetLineFromStream(is, line)) {
if (line == "--RULES--") {
if (!dep.rules.empty()) {
result.push_back(std::move(dep));
dep = cmGccStyleDependency();
}
readingRules = true;
} else if (line == "--DEPENDENCIES--") {
readingRules = false;
} else {
std::vector<std::string>& dst = readingRules ? dep.rules : dep.paths;
dst.push_back(std::move(line));
line = std::string();
}
}
if (!dep.rules.empty()) {
result.push_back(std::move(dep));
}
return result;
}
bool compare(const std::vector<std::string>& actual,
const std::vector<std::string>& expected, const char* msg)
{
if (actual.size() != expected.size()) {
std::cerr << msg << "expected " << expected.size() << " entries."
<< std::endl
<< "Actual number of entries: " << actual.size() << std::endl;
return false;
}
for (std::size_t i = 0; i < actual.size(); ++i) {
if (actual[i] != expected[i]) {
std::cerr << msg << std::endl
<< "expected: " << expected[i] << std::endl
<< "actual: " << actual[i] << std::endl;
return false;
}
}
return true;
}
bool compare(const cmGccDepfileContent& actual,
const cmGccDepfileContent& expected)
{
if (actual.size() != expected.size()) {
std::cerr << "Expected " << expected.size() << " entries." << std::endl
<< "Actual number of entries: " << actual.size() << std::endl;
return false;
}
for (std::size_t i = 0; i < actual.size(); ++i) {
if (!compare(actual[i].rules, expected[i].rules, "Rules differ: ") ||
!compare(actual[i].paths, expected[i].paths, "Paths differ: ")) {
return false;
}
}
return true;
}
void dump(const char* label, const cmGccDepfileContent& dfc)
{
std::cerr << label << std::endl;
for (const auto& entry : dfc) {
auto rit = entry.rules.cbegin();
if (rit != entry.rules.cend()) {
std::cerr << *rit;
for (++rit; rit != entry.rules.cend(); ++rit) {
std::cerr << " " << *rit;
}
std::cerr << ": " << std::endl;
}
for (const auto& path : entry.paths) {
std::cerr << " " << path << std::endl;
}
}
}
} // anonymous namespace
int testGccDepfileReader(int argc, char* argv[])
{
if (argc < 2) {
std::cout << "Invalid arguments.\n";
return -1;
}
std::string dataDirPath = argv[1];
dataDirPath += "/testGccDepfileReader_data";
const int numberOfTestFiles = 3;
for (int i = 1; i <= numberOfTestFiles; ++i) {
const std::string base = dataDirPath + "/deps" + std::to_string(i);
const std::string depfile = base + ".d";
const std::string plainDepfile = base + ".txt";
std::cout << "Comparing " << base << " with " << plainDepfile << std::endl;
const auto actual = cmReadGccDepfile(depfile.c_str());
const auto expected = readPlainDepfile(plainDepfile.c_str());
if (!compare(actual, expected)) {
dump("actual", actual);
dump("expected", expected);
return 1;
}
}
return 0;
}

View File

@@ -0,0 +1,20 @@
main.o: main.cpp /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
/usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/bits/long-double.h \
/usr/include/x86_64-linux-gnu/gnu/stubs.h \
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-linux-gnu/8/include/stddef.h \
/usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h \
/usr/include/x86_64-linux-gnu/bits/types.h \
/usr/include/x86_64-linux-gnu/bits/typesizes.h \
/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h \
/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h \
/usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
/usr/include/x86_64-linux-gnu/bits/types/FILE.h \
/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h \
/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h \
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h

View File

@@ -0,0 +1,26 @@
--RULES--
main.o
--DEPENDENCIES--
main.cpp
/usr/include/stdc-predef.h
/usr/include/stdio.h
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h
/usr/include/features.h
/usr/include/x86_64-linux-gnu/sys/cdefs.h
/usr/include/x86_64-linux-gnu/bits/wordsize.h
/usr/include/x86_64-linux-gnu/bits/long-double.h
/usr/include/x86_64-linux-gnu/gnu/stubs.h
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
/usr/lib/gcc/x86_64-linux-gnu/8/include/stddef.h
/usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h
/usr/include/x86_64-linux-gnu/bits/types.h
/usr/include/x86_64-linux-gnu/bits/typesizes.h
/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h
/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h
/usr/include/x86_64-linux-gnu/bits/types/__FILE.h
/usr/include/x86_64-linux-gnu/bits/types/FILE.h
/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h
/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h

View File

@@ -0,0 +1 @@
foo.o bar.o: foobar.c

View File

@@ -0,0 +1,5 @@
--RULES--
foo.o
bar.o
--DEPENDENCIES--
foobar.c

View File

@@ -0,0 +1,2 @@
main.o: main.cpp foo\#bar.h foo\\#bar.h foo\ bar.h \
foo\\\ bar.h foo\\\\\ bar.h foo\\\\ foo$$bar.h

View File

@@ -0,0 +1,11 @@
--RULES--
main.o
--DEPENDENCIES--
main.cpp
foo#bar.h
foo\#bar.h
foo bar.h
foo\ bar.h
foo\\ bar.h
foo\\\\
foo$bar.h

View File

@@ -10,7 +10,7 @@ class StyleA : public QStylePlugin
Q_OBJECT
// Json file in source local directory
Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json")
A_CUSTOM_MACRO(SomeArg, "StyleA_Custom.json", AnotherArg)
A_CUSTOM_MACRO(org.styles.A, "StyleA_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};

View File

@@ -10,7 +10,7 @@ class StyleB : public QStylePlugin
Q_OBJECT
// Json file in source local subdirectory
Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json")
A_CUSTOM_MACRO(SomeArg, "jsonIn/StyleB_Custom.json", AnotherArg)
A_CUSTOM_MACRO(org.styles.B, "jsonIn/StyleB_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};

View File

@@ -10,7 +10,7 @@ class StyleC : public QStylePlugin
Q_OBJECT
// Json file in global root directory
Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json")
A_CUSTOM_MACRO(SomeArg, "StyleC_Custom.json", AnotherArg)
A_CUSTOM_MACRO(org.styles.C, "StyleC_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};

View File

@@ -10,7 +10,7 @@ class StyleD : public QStylePlugin
Q_OBJECT
// Json file in global sub director
Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json")
A_CUSTOM_MACRO(SomeArg, "sub/StyleD_Custom.json", AnotherArg)
A_CUSTOM_MACRO(org.styles.D, "sub/StyleD_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};

View File

@@ -10,7 +10,7 @@ class StyleE : public QStylePlugin
Q_OBJECT
// Json files in global root directory
Q_PLUGIN_METADATA(IID "org.styles.E" FILE "StyleE.json")
A_CUSTOM_MACRO(SomeArg, "StyleE_Custom.json", AnotherArg)
A_CUSTOM_MACRO(org.styles.E, "StyleE_Custom.json", AnotherArg)
public:
QStyle* create(const QString& key);
};

View File

@@ -1,7 +1,7 @@
#ifndef UTILITYMACROS_HPP
#define UTILITYMACROS_HPP
// Empty test macro definition
#define A_CUSTOM_MACRO(name, jsonFile, pluginRegistrations)
#define A_CUSTOM_MACRO(url, jsonFile, pluginRegistrations) \
Q_PLUGIN_METADATA(IID #url FILE jsonFile)
#endif

View File

@@ -11,8 +11,20 @@ target_link_libraries(exe PRIVATE Qt5::Core)
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(exe)
set(moc_writes_depfiles 0)
if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
set(moc_writes_depfiles 1)
endif()
set(autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation.cpp")
if(moc_writes_depfiles)
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/deps")
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/timestamp")
endif()
foreach(c IN LISTS CMAKE_CONFIGURATION_TYPES)
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp")
if(moc_writes_depfiles)
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp.d")
endif()
endforeach()
file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(AUTOGEN_FILES [==[${autogen_files}]==])\n")

View File

@@ -14,7 +14,8 @@ for lexer in \
CTestResourceGroups \
DependsJava \
Expr \
Fortran
Fortran \
GccDepfile
do
cxx_file=cm${lexer}Lexer.cxx
h_file=cm${lexer}Lexer.h