Skip (re-)creation of cmake files during build passes.
[profile/ivi/qtbase.git] / bin / syncqt
1 #!/usr/bin/perl
2 #############################################################################
3 ##
4 ## Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
5 ## Contact: http://www.qt-project.org/
6 ##
7 ## This file is part of the build configuration tools of the Qt Toolkit.
8 ##
9 ## $QT_BEGIN_LICENSE:LGPL$
10 ## GNU Lesser General Public License Usage
11 ## This file may be used under the terms of the GNU Lesser General Public
12 ## License version 2.1 as published by the Free Software Foundation and
13 ## appearing in the file LICENSE.LGPL included in the packaging of this
14 ## file. Please review the following information to ensure the GNU Lesser
15 ## General Public License version 2.1 requirements will be met:
16 ## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ##
18 ## In addition, as a special exception, Nokia gives you certain additional
19 ## rights. These rights are described in the Nokia Qt LGPL Exception
20 ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ##
22 ## GNU General Public License Usage
23 ## Alternatively, this file may be used under the terms of the GNU General
24 ## Public License version 3.0 as published by the Free Software Foundation
25 ## and appearing in the file LICENSE.GPL included in the packaging of this
26 ## file. Please review the following information to ensure the GNU General
27 ## Public License version 3.0 requirements will be met:
28 ## http://www.gnu.org/copyleft/gpl.html.
29 ##
30 ## Other Usage
31 ## Alternatively, this file may be used in accordance with the terms and
32 ## conditions contained in a signed written agreement between you and Nokia.
33 ##
34 ##
35 ##
36 ##
37 ##
38 ##
39 ## $QT_END_LICENSE$
40 ##
41 #############################################################################
42
43 #
44 # Synchronizes Qt header files - internal development tool.
45 #
46
47 # use packages -------------------------------------------------------
48 use File::Basename;
49 use File::Path;
50 use File::Spec;
51 use Cwd;
52 use Cwd 'abs_path';
53 use Config;
54 use strict;
55 use warnings;
56 use English qw(-no_match_vars );
57
58 my $normalizePath_fixDrive = ($^O eq "msys" ? 1 : 0);
59
60 ######################################################################
61 # Syntax:  normalizePath(\$path)
62 # Params:  Reference to a path that's going to be normalized.
63 #
64 # Purpose: Converts the path into a form that can be used as include
65 #          path from C++ sources and qmake's .pro files.
66 #          Only relevant on Windows.
67 # Returns: -none-
68 ######################################################################
69 sub normalizePath {
70     my $s = shift;
71     $$s =~ s=\\=/=g;
72     if ($normalizePath_fixDrive && $$s =~ m,^/([a-zA-Z])/(.*),) {
73         $$s = lc($1) . ":/$2";
74     }
75 }
76
77 # set output basedir to be where ever syncqt is run from
78 our $out_basedir = getcwd();
79 normalizePath(\$out_basedir);
80 our $basedir;
81 our $quoted_basedir;
82
83 # Make sure we use Windows line endings for chomp and friends on Windows.
84 $INPUT_RECORD_SEPARATOR = "\r\n" if ($^O eq "msys");
85
86 my $qtbasedir = dirname(dirname($0));
87 normalizePath(\$qtbasedir) if (defined $qtbasedir);
88
89 # will be defined based on the modules sync.profile
90 our (%modules, %moduleheaders, @allmoduleheadersprivate, %classnames, %modulepris, %explicitheaders, %deprecatedheaders);
91 our @qpa_headers = ();
92
93 # global variables (modified by options)
94 my $isunix = 0;
95 my $module = 0;
96 my $showonly = 0;
97 my $verbose_level = 1;
98 my $remove_stale = 1;
99 my $force_win = 0;
100 my $force_relative = 0;
101 my $check_includes = 0;
102 my $copy_headers = 0;
103 my $create_uic_class_map = 0;
104 my $create_private_headers = 1;
105 my $module_fwd = "";
106 my $developer_build = 0;
107 my @modules_to_sync ;
108 $force_relative = 1 if ( -d "/System/Library/Frameworks" );
109
110
111 # functions ----------------------------------------------------------
112
113 ######################################################################
114 # Syntax:  showUsage()
115 # Params:  -none-
116 #
117 # Purpose: Show the usage of the script.
118 # Returns: -none-
119 ######################################################################
120 sub showUsage
121 {
122     print "$0 usage:\n";
123     print "  <module directory>    Specifies which module to sync header files for (required for shadow builds!)\n\n";
124
125     print "  -copy                 Copy headers instead of include-fwd(default: " . ($copy_headers ? "yes" : "no") . ")\n";
126     print "  -remove-stale         Removes stale headers              (default: " . ($remove_stale ? "yes" : "no") . ")\n";
127     print "  -relative             Force relative symlinks            (default: " . ($force_relative ? "yes" : "no") . ")\n";
128     print "  -windows              Force platform to Windows          (default: " . ($force_win ? "yes" : "no") . ")\n";
129     print "  -showonly             Show action but not perform        (default: " . ($showonly ? "yes" : "no") . ")\n";
130     print "  -outdir <PATH>        Specify output directory for sync  (default: $out_basedir)\n";
131     print "  -qtdir <PATH>         Set the path to QtBase             (detected: " . (defined $qtbasedir ? $qtbasedir : "-none-") . ")\n";
132     print "  -quiet                Only report problems, not activity (same as -verbose 0)\n";
133     print "  -v, -verbose <level>  Sets the verbosity level (max. 4)  (default: $verbose_level)\n";
134     print "                        The short form increases the level by +1\n";
135     print "  -separate-module <NAME>:<PROFILEDIR>:<HEADERDIR>\n";
136     print "                        Create headers for <NAME> with original headers in\n";
137     print "                        <HEADERDIR> relative to <PROFILEDIR> \n";
138     print "  -private              Force copy private headers         (default: " . ($create_private_headers ? "yes" : "no") . ")\n";
139     print "  -module-fwd <PATH>    Create fwd includes for module pri files in the given\n";
140     print "                        path (default: none)\n";
141     print "  -developer-build      Point libraries and binaries to a common directory for\n";
142     print "                        easy development\n";
143     print "  -help                 This help\n";
144     exit 0;
145 }
146
147 ######################################################################
148 # Syntax:  checkUnix()
149 # Params:  -none-
150 #
151 # Purpose: Check if script runs on a Unix system or not. Cygwin
152 #          systems are _not_ detected as Unix systems.
153 # Returns: 1 if a unix system, else 0.
154 ######################################################################
155 sub checkUnix {
156     my ($r) = 0;
157     if ( $force_win != 0) {
158         return 0;
159     } elsif ( -f "/bin/uname" ) {
160         $r = 1;
161         (-f "\\bin\\uname") && ($r = 0);
162     } elsif ( -f "/usr/bin/uname" ) {
163         $r = 1;
164         (-f "\\usr\\bin\\uname") && ($r = 0);
165     }
166     if($r) {
167         $_ = $Config{'osname'};
168         $r = 0 if( /(ms)|(cyg)win/i );
169     }
170     return $r;
171 }
172
173 sub checkRelative {
174     my ($dir) = @_;
175     return 0 if($dir =~ /^\//);
176     return 0 if(!checkUnix() && $dir =~ /[a-zA-Z]:[\/\\]/);
177     return 1;
178 }
179
180 ######################################################################
181 # Syntax:  classNames(iheader)
182 # Params:  iheader, string, filename to parse for classname "symlinks"
183 #
184 # Purpose: Scans through iheader to find all classnames that should be
185 #          synced into library's include structure.
186 # Returns: List of all class names in a file.
187 ######################################################################
188 sub classNames {
189     my @ret;
190     my ($iheader) = @_;
191
192     my $classname = $classnames{basename($iheader)};
193     push @ret, $classname if ($classname);
194
195     my $parsable = "";
196     if(open(F, "<$iheader")) {
197         while(<F>) {
198             my $line = $_;
199             chomp $line;
200                         chop $line if ($line =~ /\r$/);
201             if($line =~ /^\#/) {
202                 if($line =~ /\\$/) {
203                     while($line = <F>) {
204                         chomp $line;
205                         last unless($line =~ /\\$/);
206                     }
207                 }
208                 return @ret if($line =~ m/^#pragma qt_sync_stop_processing/);
209                 push(@ret, $1) if($line =~ m/^#pragma qt_class\(([^)]*)\)[\r\n]*$/);
210                 $line = 0;
211             }
212             if($line) {
213                 $line =~ s,//.*$,,; #remove c++ comments
214                 $line .= ";" if($line =~ m/^Q_[A-Z_]*\(.*\)[\r\n]*$/); #qt macro
215                 $line .= ";" if($line =~ m/^QT_(BEGIN|END)_HEADER[\r\n]*$/); #qt macro
216                 $line .= ";" if($line =~ m/^QT_(BEGIN|END)_NAMESPACE(_[A-Z]+)*[\r\n]*$/); #qt macro
217                 $line .= ";" if($line =~ m/^QT_MODULE\(.*\)[\r\n]*$/); # QT_MODULE macro
218                 $parsable .= " " . $line;
219             }
220         }
221         close(F);
222     }
223
224     my $last_definition = 0;
225     my @namespaces;
226     for(my $i = 0; $i < length($parsable); $i++) {
227         my $definition = 0;
228         my $character = substr($parsable, $i, 1);
229         if($character eq "/" && substr($parsable, $i+1, 1) eq "*") { #I parse like this for greedy reasons
230             for($i+=2; $i < length($parsable); $i++) {
231                 my $end = substr($parsable, $i, 2);
232                 if($end eq "*/") {
233                     $last_definition = $i+2;
234                     $i++;
235                     last;
236                 }
237             }
238         } elsif($character eq "{") {
239             my $brace_depth = 1;
240             my $block_start = $i + 1;
241           BLOCK: for($i+=1; $i < length($parsable); $i++) {
242               my $ignore = substr($parsable, $i, 1);
243               if($ignore eq "{") {
244                   $brace_depth++;
245               } elsif($ignore eq "}") {
246                   $brace_depth--;
247                   unless($brace_depth) {
248                       for(my $i2 = $i+1; $i2 < length($parsable); $i2++) {
249                           my $end = substr($parsable, $i2, 1);
250                           if($end eq ";" || $end ne " ") {
251                               $definition = substr($parsable, $last_definition, $block_start - $last_definition) . "}";
252                               $i = $i2 if($end eq ";");
253                               $last_definition = $i + 1;
254                               last BLOCK;
255                           }
256                       }
257                   }
258               }
259           }
260         } elsif($character eq ";") {
261             $definition = substr($parsable, $last_definition, $i - $last_definition + 1);
262             $last_definition = $i + 1;
263         } elsif($character eq "}") {
264             # a naked } must be a namespace ending
265             # if it's not a namespace, it's eaten by the loop above
266             pop @namespaces;
267             $last_definition = $i + 1;
268         }
269
270         if (substr($parsable, $last_definition, $i - $last_definition + 1) =~ m/ namespace ([^ ]*) /
271             && substr($parsable, $i+1, 1) eq "{") {
272             push @namespaces, $1;
273
274             # Eat the opening { so that the condensing loop above doesn't see it
275             $i++;
276             $last_definition = $i + 1;
277         }
278
279         if($definition) {
280             $definition =~ s=[\n\r]==g;
281             my @symbols;
282             if($definition =~ m/^ *typedef *.*\(\*([^\)]*)\)\(.*\);$/) {
283                 push @symbols, $1;
284             } elsif($definition =~ m/^ *typedef +(.*) +([^ ]*);$/) {
285                 push @symbols, $2;
286             } elsif($definition =~ m/^ *(template *<.*> *)?(class|struct) +([^ ]* +)?([^<\s]+) ?(<[^>]*> ?)?\s*((,|:)\s*(public|protected|private) *.*)? *\{\}$/) {
287                 push @symbols, $4;
288             } elsif($definition =~ m/^ *Q_DECLARE_.*ITERATOR\((.*)\);$/) {
289                 push @symbols, "Q" . $1 . "Iterator";
290                 push @symbols, "QMutable" . $1 . "Iterator";
291             }
292
293             our $publicclassregexp;
294             foreach my $symbol (@symbols) {
295                 $symbol = (join("::", @namespaces) . "::" . $symbol) if (scalar @namespaces);
296
297                 if ($symbol =~ /^Q[^:]*$/           # no-namespace, starting with Q
298                     || $symbol =~ /^Phonon::/) {    # or in the Phonon namespace
299                     push @ret, $symbol;
300                 } elsif (defined($publicclassregexp)) {
301                     push @ret, $symbol if ($symbol =~ $publicclassregexp);
302                 }
303             }
304         }
305     }
306     return @ret;
307 }
308
309 sub make_path {
310     my ($dir, $lib, $be_verbose) = @_;
311     unless(-e $dir) {
312         mkpath $dir;
313         $dir = "<outbase>" . substr($dir, length($out_basedir)) if ($be_verbose < 3);
314         print "$lib: mkpath $dir\n" if ($be_verbose > 1);
315     }
316 }
317
318 ######################################################################
319 # Syntax:  syncHeader(header, iheader, copy, timestamp)
320 # Params:  header, string, filename to create "symlink" for
321 #          iheader, string, destination name of symlink
322 #          copy, forces header to be a copy of iheader
323 #          timestamp, the requested modification time if copying
324 #
325 # Purpose: Syncronizes header to iheader
326 # Returns: 1 if successful, else 0.
327 ######################################################################
328 sub syncHeader {
329     my ($lib, $header, $iheader, $copy, $ts) = @_;
330     normalizePath(\$iheader);
331     normalizePath(\$header);
332     return copyFile($lib, $iheader, $header) if($copy);
333
334     unless(-e $header) {
335         my $header_dir = dirname($header);
336         make_path($header_dir, $lib, $verbose_level);
337
338         #write it
339         my $iheader_out = fixPaths($iheader, $header_dir);
340         open(HEADER, ">$header") || die "Could not open $header for writing: $!\n";
341         print HEADER "#include \"$iheader_out\"\n";
342         close HEADER;
343         if(defined($ts)) {
344             utime(time, $ts, $header) or die "$iheader, $header";
345         }
346         return 1;
347     }
348     return 0;
349 }
350
351 ######################################################################
352 # Syntax:  fixPaths(file, dir)
353 # Params:  file, string, filepath to be made relative to dir
354 #          dir, string, dirpath for point of origin
355 #
356 # Purpose: file is made relative (if possible) of dir.
357 # Returns: String with the above applied conversion.
358 ######################################################################
359
360 sub cleanupPath {
361     my ($file) = @_;
362     normalizePath(\$file);
363     while ($file =~ s,/[^/]+/\.\./,/,) {}
364     return $file;
365 }
366
367 sub fixPaths {
368     my ($file, $dir) = @_;
369
370     my $out = File::Spec->abs2rel(cleanupPath($file), cleanupPath($dir));
371     $out =~ s,\\,/,g;
372     return $out;
373 }
374
375 ######################################################################
376 # Syntax:  fileContents(filename)
377 # Params:  filename, string, filename of file to return contents
378 #
379 # Purpose: Get the contents of a file.
380 # Returns: String with contents of the file, or empty string if file
381 #          doens't exist.
382 # Warning: Dies if it does exist but script cannot get read access.
383 ######################################################################
384 sub fileContents {
385     my ($filename) = @_;
386     my $filecontents = "";
387     if (-e $filename) {
388         open(I, "< $filename") || die "Could not open $filename for reading, read block?";
389         local $/;
390         binmode I;
391         $filecontents = <I>;
392         close I;
393     }
394     return $filecontents;
395 }
396
397 ######################################################################
398 # Syntax:  fileCompare(file1, file2)
399 # Params:  file1, string, filename of first file
400 #          file2, string, filename of second file
401 #
402 # Purpose: Determines if files are equal, and which one is newer.
403 # Returns: 0 if files are equal no matter the timestamp, -1 if file1
404 #          is newer, 1 if file2 is newer.
405 ######################################################################
406 sub fileCompare {
407     my ($file1, $file2) = @_;
408     my $file1contents = fileContents($file1);
409     my $file2contents = fileContents($file2);
410     if (! -e $file1) { return 1; }
411     if (! -e $file2) { return -1; }
412     return $file1contents ne $file2contents ? (stat($file2))[9] <=> (stat($file1))[9] : 0;
413 }
414
415 ######################################################################
416 # Syntax:  copyFile(file, ifile)
417 # Params:  file, string, filename to create duplicate for
418 #          ifile, string, destination name of duplicate
419 #
420 # Purpose: Keeps files in sync so changes in the newer file will be
421 #          written to the other.
422 # Returns: 1 if files were synced, else 0.
423 # Warning: Dies if script cannot get write access.
424 ######################################################################
425 sub copyFile
426 {
427     my ($lib, $file,$ifile, $copy,$knowdiff,$filecontents,$ifilecontents) = @_;
428     # Bi-directional synchronization
429     open( I, "< " . $file ) || die "Could not open $file for reading";
430     local $/;
431     binmode I;
432     $filecontents = <I>;
433     close I;
434     if ( open(I, "< " . $ifile) ) {
435         local $/;
436         binmode I;
437         $ifilecontents = <I>;
438         close I;
439         $copy = fileCompare($file, $ifile);
440         $knowdiff = 0,
441     } else {
442         $copy = -1;
443         $knowdiff = 1;
444     }
445
446     if ( $knowdiff || ($filecontents ne $ifilecontents) ) {
447         if ( $copy > 0 ) {
448             my $file_dir = dirname($file);
449             make_path($file_dir, $lib, $verbose_level);
450             open(O, "> " . $file) || die "Could not open $file for writing (no write permission?)";
451             local $/;
452             binmode O;
453             print O $ifilecontents;
454             close O;
455             utime time, (stat($ifile))[9], $file;
456             return 1;
457         } elsif ( $copy < 0 ) {
458             my $ifile_dir = dirname($ifile);
459             make_path($ifile_dir, $lib, $verbose_level);
460             open(O, "> " . $ifile) || die "Could not open $ifile for writing (no write permission?)";
461             local $/;
462             binmode O;
463             print O $filecontents;
464             close O;
465             utime time, (stat($file))[9], $ifile;
466             return 1;
467         }
468     }
469     return 0;
470 }
471
472 ######################################################################
473 # Syntax:  symlinkFile(file, ifile)
474 # Params:  file, string, filename to create "symlink" for
475 #          ifile, string, destination name of symlink
476 #
477 # Purpose: File is symlinked to ifile (or copied if filesystem doesn't
478 #          support symlink).
479 # Returns: 1 on success, else 0.
480 ######################################################################
481 sub symlinkFile
482 {
483     my ($lib, $file, $ifile) = @_;
484
485     if ($isunix) {
486         print "$lib: symlink created for $file " if ($verbose_level);
487         if ( $force_relative && ($ifile =~ /^$quoted_basedir/)) {
488             my $t = getcwd();
489             my $c = -1;
490             my $p = "../";
491             $t =~ s-^$quoted_basedir/--;
492             $p .= "../" while( ($c = index( $t, "/", $c + 1)) != -1 );
493             $file =~ s-^$quoted_basedir/-$p-;
494             print " ($file)\n" if($verbose_level);
495         }
496         print "\n" if($verbose_level);
497         return symlink($file, $ifile);
498     }
499     return copyFile($lib, $file, $ifile);
500 }
501
502 ######################################################################
503 # Syntax:  findFiles(dir, match, descend)
504 # Params:  dir, string, directory to search for name
505 #          match, string, regular expression to match in dir
506 #          descend, integer, 0 = non-recursive search
507 #                            1 = recurse search into subdirectories
508 #
509 # Purpose: Finds files matching a regular expression.
510 # Returns: List of matching files.
511 #
512 # Examples:
513 #   findFiles("/usr","\.cpp$",1)  - finds .cpp files in /usr and below
514 #   findFiles("/tmp","^#",0)      - finds #* files in /tmp
515 ######################################################################
516 sub findFiles {
517     my ($dir,$match,$descend) = @_;
518     my ($file,$p,@files);
519     local(*D);
520     normalizePath(\$dir);
521     ($dir eq "") && ($dir = ".");
522     if ( opendir(D,$dir) ) {
523         if ( $dir eq "." ) {
524             $dir = "";
525         } else {
526             ($dir =~ /\/$/) || ($dir .= "/");
527         }
528         foreach $file ( sort readdir(D) ) {
529             next if ( $file  =~ /^\.\.?$/ );
530             $p = $file;
531             ($file =~ /$match/) && (push @files, $p);
532             if ( $descend && -d $p && ! -l $p ) {
533                 push @files, &findFiles($p,$match,$descend);
534             }
535         }
536         closedir(D);
537     }
538     return @files;
539 }
540
541 ######################################################################
542 # Syntax:  loadSyncProfile()
543 #
544 # Purpose: Locates the sync.profile.
545 # Returns: Hashmap of module name -> directory.
546 ######################################################################
547 sub loadSyncProfile {
548     my ($srcbase, $outbase) = @_;
549     if ($verbose_level) {
550         print("<srcbase> = $$srcbase \n");
551         print("<outbase> = $$outbase \n");
552     }
553
554     my $syncprofile = "$$srcbase/sync.profile";
555     my $result;
556     unless ($result = do "$syncprofile") {
557         die "syncqt couldn't parse $syncprofile: $@" if $@;
558         die "syncqt couldn't execute $syncprofile: $!" unless defined $result;
559     }
560     return $result;
561 }
562
563 sub basePrettify {
564     my ($arg) = @_;
565     $$arg =~ s,^\Q$basedir\E,<srcbase>,;
566     $$arg =~ s,^\Q$out_basedir\E,<outbase>,;
567 }
568
569 sub cleanPath {
570     my ($arg) = @_;
571     while ($arg =~ s,[^/]+/\.\.(/|$),,) {}
572     return $arg;
573 }
574
575 sub locateSyncProfile
576 {
577     my ($directory) = @_;
578     $directory = abs_path($directory);
579     while (1) {
580         my $file = $directory."/sync.profile";
581         return $file if (-e $file);
582         my $odir = $directory;
583         $directory = dirname($directory);
584         return undef if ($directory eq $odir);
585     }
586 }
587
588 sub isQpaHeader
589 {
590     my ($header) = @_;
591     foreach my $qpa_header (@qpa_headers) {
592         return 1 if ($header =~ $qpa_header);
593     }
594     return 0;
595 }
596
597 # check if this is an in-source build, and if so use that as the basedir too
598 $basedir = locateSyncProfile($out_basedir);
599 if ($basedir) {
600     $basedir = dirname($basedir) ;
601     normalizePath(\$basedir);
602     $quoted_basedir = "\Q$basedir";
603 }
604
605 # --------------------------------------------------------------------
606 # "main" function
607 # --------------------------------------------------------------------
608
609 while ( @ARGV ) {
610     my $var = 0;
611     my $val = 0;
612
613     #parse
614     my $arg = shift @ARGV;
615     if ($arg eq "-h" || $arg eq "-help" || $arg eq "-?" || $arg eq "?") {
616         $var = "show_help";
617         $val = "yes";
618     } elsif($arg eq "-copy") {
619         $var = "copy";
620         $val = "yes";
621     } elsif($arg eq "-o" || $arg eq "-outdir") {
622         $var = "output";
623         $val = shift @ARGV;
624     } elsif($arg eq "-showonly" || $arg eq "-remove-stale" || $arg eq "-windows" ||
625             $arg eq "-relative" || $arg eq "-check-includes") {
626         $var = substr($arg, 1);
627         $val = "yes";
628     } elsif($arg eq "-module-fwd") {
629         $var = "module_fwd";
630         $val = shift @ARGV;
631     } elsif($arg eq "-developer-build") {
632         $var = "developer_build";
633         $val = "yes";
634     } elsif($arg =~ /^-no-(.*)$/) {
635         $var = $1;
636         $val = "no";
637         #these are for commandline compat
638     } elsif($arg eq "-inc") {
639         $var = "output";
640         $val = shift @ARGV;
641     } elsif($arg eq "-module") {
642         $var = "module";
643         $val = shift @ARGV;
644     } elsif($arg eq "-separate-module") {
645         $var = "separate-module";
646         $val = shift @ARGV;
647     } elsif($arg eq "-show") {
648         $var = "showonly";
649         $val = "yes";
650     } elsif($arg eq "-quiet") {
651         $var = "verbose";
652         $val = "0";
653     } elsif($arg eq "-v") {
654         $var = "verbose";
655         $val = "yes";
656     } elsif($arg eq "-verbose") {
657         $var = "verbose";
658         $val = shift @ARGV;
659     } elsif($arg eq "-private") {
660         $var = "create_private_headers";
661         $val = "yes";
662     } elsif($arg eq "-qtdir") {
663         $var = "qtdir";
664         $val = shift @ARGV;
665     } elsif($arg =~/^-/) {
666         print "Unknown option: $arg\n\n" if(!$var);
667         showUsage();
668     } else {
669         $basedir = locateSyncProfile($arg);
670         die "Could not find a sync.profile for '$arg'\n" if (!$basedir);
671         $basedir = dirname($basedir);
672         normalizePath(\$basedir);
673         $quoted_basedir = "\Q$basedir";
674         $var = "ignore";
675     }
676
677     #do something
678     if(!$var || $var eq "show_help") {
679         print "Unknown option: $arg\n\n" if(!$var);
680         showUsage();
681     } elsif ($var eq "copy") {
682         if($val eq "yes") {
683             $copy_headers++;
684         } elsif($showonly) {
685             $copy_headers--;
686         }
687     } elsif ($var eq "showonly") {
688         if($val eq "yes") {
689             $showonly++;
690         } elsif($showonly) {
691             $showonly--;
692         }
693     } elsif ($var eq "verbose") {
694         if($val eq "yes") {
695             $verbose_level++;
696         } elsif($val eq "no" && $verbose_level) {
697             $verbose_level--;
698         } else {
699             $verbose_level = int($val);
700         }
701     } elsif ($var eq "check-includes") {
702         if($val eq "yes") {
703             $check_includes++;
704         } elsif($check_includes) {
705             $check_includes--;
706         }
707     } elsif ($var eq "remove-stale") {
708         if($val eq "yes") {
709             $remove_stale++;
710         } elsif($remove_stale) {
711             $remove_stale--;
712         }
713     } elsif ($var eq "windows") {
714         if($val eq "yes") {
715             $force_win++;
716         } elsif($force_win) {
717             $force_win--;
718         }
719     } elsif ($var eq "relative") {
720         if($val eq "yes") {
721             $force_relative++;
722         } elsif($force_relative) {
723             $force_relative--;
724         }
725     } elsif ($var eq "module") {
726         print "module :$val:\n" if($verbose_level);
727         die "No such module: $val" unless(defined $modules{$val});
728         push @modules_to_sync, $val;
729     } elsif ($var eq "separate-module") {
730         my ($module, $prodir, $headerdir) = split(/:/, $val);
731         $modules{$module} = $prodir;
732         push @modules_to_sync, $module;
733         $moduleheaders{$module} = $headerdir;
734         $create_uic_class_map = 0;
735     } elsif ($var eq "qtdir") {
736         if($val) {
737             $qtbasedir = $val;
738             normalizePath(\$qtbasedir);
739         } else {
740             die "The -qtdir option requires an argument";
741         }
742     } elsif ($var eq "module_fwd") {
743         $module_fwd = $val;
744     } elsif ($var eq "developer_build") {
745         $developer_build = 1;
746     } elsif ($var eq "output") {
747         my $outdir = $val;
748         if(checkRelative($outdir)) {
749             $out_basedir = getcwd();
750             chomp $out_basedir;
751             $out_basedir .= "/" . $outdir;
752         } else {
753             $out_basedir = $outdir;
754         }
755         normalizePath(\$out_basedir);
756     }
757 }
758
759 die "Cannot automatically detect/use provided path to QtBase's build directory!\n" .
760     "QTDIR detected/provided: " . (defined $qtbasedir ? $qtbasedir : "-none-") . "\n" .
761     "Please use the -qtdir option to provide the correct path.\nsyncqt failed"
762         if (!$qtbasedir || !-d "$qtbasedir/mkspecs");
763
764 # if we have no $basedir we cannot be sure which sources you want, so die
765 die "Could not find any sync.profile for your module!\nPass <module directory> to syncqt to sync your header files.\nsyncqt failed" if (!$basedir);
766
767 my $class_lib_map_contents = "";
768 our @ignore_headers = ();
769 our @ignore_for_master_contents = ();
770 our @ignore_for_include_check = ();
771 our @ignore_for_qt_begin_header_check = ();
772 our @ignore_for_qt_begin_namespace_check = ();
773 our @ignore_for_qt_module_check = ();
774 our %inject_headers = ();
775
776 # load the module's sync.profile here, before we can
777 loadSyncProfile(\$basedir, \$out_basedir);
778
779 @modules_to_sync = keys(%modules) if($#modules_to_sync == -1);
780
781 my %allmoduleheadersprivate = map { $_ => 1 } @allmoduleheadersprivate;
782
783 $isunix = checkUnix; #cache checkUnix
784
785 my $qt_version = fileContents($qtbasedir."/mkspecs/qconfig.pri");
786 if (length($qt_version)) {
787     $qt_version =~ s,.*^QT_VERSION\h*=\h*(\S+).*,$1,sm;
788 } else {
789     $qt_version = fileContents($basedir."/src/corelib/global/qglobal.h");
790     $qt_version =~ s,.*^#\h*define\h+QT_VERSION_STR\h+"([^"]+)".*,$1,sm;
791 }
792 foreach my $lib (@modules_to_sync) {
793     #iteration info
794     my $dir = $modules{$lib};
795
796     my $project = $dir;
797     $project =~ s,/([^/]+)$,/$1/$1.pro,;
798     my $module_version = fileContents($project);
799     $module_version = $qt_version unless ($module_version =~ s,.*^VERSION\h*=\h*(\S+).*,$1,sm);
800
801     # Backwards compatibility for modules with checked in .pri files.
802     if (defined $modulepris{$lib} and -e "$modulepris{$lib}") {
803         my $content = fileContents($modulepris{$lib});
804         my @version_rows = grep(/QT\..*\.VERSION/, split('\n', $content));
805         if(@version_rows) {
806             # We only pick the first one, since each module need a separate .pri file
807             $module_version = $version_rows[0];
808             chomp $module_version;
809             $module_version =~ s/^\s*QT\..*\.VERSION\s*=\s*([^#]+).*$/$1/;
810             $module_version =~ s/\s+$//;
811         }
812     }
813
814     my $pathtoheaders = "";
815     $pathtoheaders = $moduleheaders{$lib} if ($moduleheaders{$lib});
816
817     my $allheadersprivate = 0;
818     $allheadersprivate = 1 if $allmoduleheadersprivate{$lib};
819
820     #information used after the syncing
821     my $pri_install_classes = "";
822     my $pri_install_files = "";
823     my $pri_install_pfiles = "";
824     my $pri_install_qpafiles = "";
825
826     push @{$inject_headers{$dir}}, lc($lib)."version.h";
827     $classnames{lc($lib)."version.h"} = $lib."Version";
828
829     #remove the old files
830     if($remove_stale) {
831         my %injections = ();
832         for my $p (keys %inject_headers) {
833             next unless ($p =~ /^\Q$dir\E(\/|$)/);
834             my $sp = $p;
835             $sp =~ s,^\Q$basedir\E/,$out_basedir/,;
836             for my $n (@{$inject_headers{$p}}) {
837                 $injections{$sp."/".$n} = 1;
838             }
839         }
840         my @subdirs = ("$out_basedir/include/$lib");
841         foreach my $subdir (@subdirs) {
842             if (opendir DIR, $subdir) {
843                 foreach my $t (sort readdir(DIR)) {
844                     my $file = "$subdir/$t";
845                     if(-d $file) {
846                         push @subdirs, $file unless($t eq "." || $t eq "..");
847                     } else {
848                         my @files = ($file);
849                         #push @files, "$out_basedir/include/Qt/$t" if(-e "$out_basedir/include/Qt/$t");
850                         foreach my $file (@files) {
851                            my $remove_file = 0;
852                            if(open(F, "<$file")) {
853                                 while(my $line = <F>) {
854                                     chomp $line;
855                                     if($line =~ /^\#include \"([^\"]*)\"$/) {
856                                         my $include = $1;
857                                         $include = $subdir . "/" . $include unless(substr($include, 0, 1) eq "/");
858                                         $remove_file = 1 unless(-e $include or defined $injections{cleanPath($include)});
859                                     } else {
860                                         $remove_file = 0;
861                                         last;
862                                     }
863                                 }
864                                 close(F);
865                                 unlink $file if($remove_file);
866                             }
867                         }
868                     }
869                 }
870                 closedir DIR;
871             }
872
873         }
874     }
875
876     #create the new ones
877     foreach my $current_dir (split(/;/, $dir)) {
878         my @headers_paths = split(/;/, $pathtoheaders);
879         if (@headers_paths) {
880             @headers_paths = map { "$current_dir/$_" } @headers_paths;
881         } else {
882             push @headers_paths, $current_dir;
883         }
884
885         foreach my $headers_dir (@headers_paths) {
886             #calc subdirs
887             my @subdirs = ($headers_dir);
888             foreach my $subdir (@subdirs) {
889                 if ($subdir =~ /\/doc$/) {
890                     next;
891                 }
892                 opendir DIR, $subdir or next;
893                 foreach my $t (sort readdir(DIR)) {
894                     push @subdirs, "$subdir/$t" if(-d "$subdir/$t" && !($t eq ".") &&
895                                                    !($t eq "..") && !($t eq ".obj") &&
896                                                    !($t eq ".moc") && !($t eq ".rcc") &&
897                                                    !($t eq ".uic") && !($t eq "build"));
898                 }
899                 closedir DIR;
900             }
901
902             #calc files and "copy" them
903             foreach my $subdir (@subdirs) {
904                 my @headers = findFiles($subdir, "^[-a-z0-9_]*\\.h\$" , 0);
905                 if (defined $inject_headers{$subdir}) {
906                     foreach my $if (@{$inject_headers{$subdir}}) {
907                         @headers = grep(!/^\Q$if\E$/, @headers); #in case we configure'd previously
908                         push @headers, "*".$if;
909                     }
910                 }
911                 my $header_dirname = "";
912                 foreach my $header (@headers) {
913                     my $shadow = ($header =~ s/^\*//);
914                     $header = 0 if($header =~ /^ui_.*.h/);
915                     foreach (@ignore_headers) {
916                         $header = 0 if($header eq $_);
917                     }
918                     if($header) {
919                         my $header_copies = 0;
920                         #figure out if it is a public header
921                         my $public_header = $header;
922                         my $qpa_header = 0;
923                         if(isQpaHeader($public_header)) {
924                             $public_header = 0;
925                             $qpa_header = 1;
926                         } elsif($allheadersprivate || $public_header =~ /_p.h$/ || $public_header =~ /_pch.h$/) {
927                             $public_header = 0;
928                         } else {
929                             foreach (@ignore_for_master_contents) {
930                                 $public_header = 0 if($header eq $_);
931                             }
932                         }
933
934                         my $iheader = $subdir . "/" . $header;
935                         $iheader =~ s/^\Q$basedir\E/$out_basedir/ if ($shadow);
936                         my @classes = $public_header ? classNames($iheader) : ();
937                         if($showonly) {
938                             print "$header [$lib]\n";
939                             foreach(@classes) {
940                                 print "SYMBOL: $_\n";
941                             }
942                         } else {
943                             my $ts = (stat($iheader))[9];
944                             #find out all the places it goes..
945                             my @headers;
946                             if ($public_header) {
947                                 @headers = ( "$out_basedir/include/$lib/$header" );
948                                 foreach my $full_class (@classes) {
949                                     my $header_base = basename($header);
950                                     # Strip namespaces:
951                                     my $class = $full_class;
952                                     $class =~ s/^.*:://;
953     #                               if ($class =~ m/::/) {
954     #                                  class =~ s,::,/,g;
955     #                               }
956
957                                     if (defined $explicitheaders{$lib}{$class}) {
958                                         $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$explicitheaders{$lib}{$class}", 0, $ts));
959                                     } else {
960                                         $class_lib_map_contents .= "QT_CLASS_LIB($full_class, $lib, $header_base)\n";
961                                         $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts));
962                                     }
963
964                                     # KDE-Compat headers for Phonon
965                                     if ($lib eq "phonon") {
966                                         $header_copies++ if (syncHeader($lib, "$out_basedir/include/phonon_compat/Phonon/$class", "$out_basedir/include/$lib/$header", 0, $ts));
967                                     }
968                                 }
969
970                                 if ($explicitheaders{$lib}{basename($header)}) {
971                                     $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$explicitheaders{$lib}{basename($header)}", "$out_basedir/include/$lib/$header", 0, $ts));
972                                 }
973
974                             } elsif ($create_private_headers && !$qpa_header) {
975                                 @headers = ( "$out_basedir/include/$lib/$module_version/$lib/private/$header" );
976                             } elsif ($create_private_headers) {
977                                 @headers = ( "$out_basedir/include/$lib/$module_version/$lib/qpa/$header" );
978                             }
979
980                             foreach(@headers) { #sync them
981                                 $header_copies++ if(syncHeader($lib, $_, $iheader, $copy_headers && !$shadow, $ts));
982                             }
983
984                             if($public_header) {
985                                 #deal with the install directives
986                                 if($public_header) {
987                                     my $pri_install_iheader = fixPaths($iheader, $current_dir);
988                                     foreach my $class (@classes) {
989                                         # Strip namespaces:
990                                         $class =~ s/^.*:://;
991     #                                   if ($class =~ m/::/) {
992     #                                       $class =~ s,::,/,g;
993     #                                   }
994                                         my $class_header = fixPaths("$out_basedir/include/$lib/$class",
995                                                                     $current_dir) . " ";
996                                         $pri_install_classes .= $class_header
997                                                                     unless($pri_install_classes =~ $class_header);
998                                     }
999                                     if ($explicitheaders{$lib}{basename($iheader)}) {
1000                                         my $compat_header = fixPaths("$out_basedir/include/$lib/$explicitheaders{$lib}{basename($iheader)}", $current_dir) . " ";
1001                                         $pri_install_files .= $compat_header unless($pri_install_files =~ $compat_header);
1002                                     }
1003                                     $pri_install_files.= "$pri_install_iheader ";;
1004                                 }
1005                             }
1006                             elsif ($qpa_header) {
1007                                 my $pri_install_iheader = fixPaths($iheader, $current_dir);
1008                                 $pri_install_qpafiles.= "$pri_install_iheader ";;
1009                             }
1010                             else {
1011                                 my $pri_install_iheader = fixPaths($iheader, $current_dir);
1012                                 $pri_install_pfiles.= "$pri_install_iheader ";;
1013                             }
1014                         }
1015
1016                         if ($verbose_level && $header_copies) {
1017                             my $new_header_dirname = dirname($iheader);
1018                             basePrettify(\$new_header_dirname) if ($new_header_dirname && $verbose_level < 2);
1019                             my $header_base = basename($iheader);
1020                             if ($verbose_level < 3) {
1021                                 my $line_prefix = ",";
1022                                 if ($new_header_dirname ne $header_dirname) {
1023                                     $line_prefix = "$lib: created fwd-include header(s) for $new_header_dirname/ {";
1024                                     $line_prefix = " }\n".$line_prefix if ($header_dirname);
1025                                     $header_dirname = $new_header_dirname;
1026                                 } else {
1027                                     $line_prefix = ",";
1028                                 }
1029                                 print "$line_prefix $header_base ($header_copies)";
1030                             } else { # $verbose_level >= 3
1031                                 basePrettify(\$iheader) if ($verbose_level == 3);
1032                                 print "$lib: created $header_copies fwd-include headers for $iheader\n";
1033                             }
1034                         }
1035                     }
1036                 }
1037                 print " }\n" if ($header_dirname && $verbose_level > 0 && $verbose_level < 3);
1038             }
1039         }
1040     }
1041
1042     unless($showonly) {
1043         # create deprecated headers
1044         my $first = 1;
1045         while (my ($header, $include) = each %{$deprecatedheaders{$lib}}) {
1046             my $public_header = 0;
1047             $public_header = 1 unless ($allheadersprivate || ($header =~ /_p\.h$/));
1048             next unless ($public_header || $create_private_headers);
1049
1050             my $header_path = "$out_basedir/include/$lib/";
1051             unless ($public_header) {
1052                 $header_path .= "$module_version/$lib/private/";
1053             }
1054             $header_path .= "$header";
1055
1056             unless (-e $header_path) {
1057                 my $guard = "DEPRECATED_HEADER_" . $lib . "_" . $header;
1058                 $guard =~ s/([^a-zA-Z0-9_])/_/g;
1059
1060                 my $header_dir = dirname($header_path);
1061                 make_path($header_dir, $lib, $verbose_level);
1062
1063                 open(HEADER, ">$header_path") || die "Could not open $header_path for writing: $!\n";
1064                 print HEADER "#ifndef $guard\n";
1065                 print HEADER "#define $guard\n";
1066                 my $warning = "Header <$lib/";
1067                 $warning .= "private/" unless ($public_header);
1068                 $warning .= "$header> is deprecated. Please include <$include> instead.";
1069                 print HEADER "#if defined(__GNUC__)\n";
1070                 print HEADER "#  warning $warning\n";
1071                 print HEADER "#elif defined(_MSC_VER)\n";
1072                 print HEADER "#  pragma message (\"$warning\")\n";
1073                 print HEADER "#endif\n";
1074                 print HEADER "#include <$include>\n";
1075                 if ($public_header) {
1076                     print HEADER "#if 0\n";
1077                     print HEADER "#pragma qt_no_master_include\n";
1078                     print HEADER "#endif\n";
1079                 }
1080                 print HEADER "#endif\n";
1081                 close HEADER;
1082
1083                 if ($verbose_level < 3) {
1084                     my $line_prefix = ",";
1085                     $line_prefix = "$lib: created deprecated header(s) {" if ($first);
1086                     print "$line_prefix $header";
1087                 } else {
1088                     print "$lib: created deprecated header $header => $include\n";
1089                 }
1090                 $first = 0;
1091             }
1092
1093             my $addendum = fixPaths($header_path, $dir) . " ";
1094             if ($public_header) {
1095                 $pri_install_files .=  $addendum;
1096             } else {
1097                 $pri_install_pfiles .=  $addendum;
1098             }
1099         }
1100         if ($verbose_level < 3) {
1101             print " }\n" unless ($first);
1102         }
1103
1104         # KDE-Compat master header for Phonon
1105         if ($lib eq "phonon") {
1106             syncHeader($lib, "$out_basedir/include/phonon_compat/Phonon/Phonon", "$out_basedir/include/phonon/phonon", 0);
1107         }
1108
1109         #handle the headers.pri for each module
1110         my $headers_pri_contents = "";
1111         $headers_pri_contents .= "SYNCQT.HEADER_FILES = $pri_install_files\n";
1112         $headers_pri_contents .= "SYNCQT.HEADER_CLASSES = $pri_install_classes\n";
1113         $headers_pri_contents .= "SYNCQT.PRIVATE_HEADER_FILES = $pri_install_pfiles\n";
1114         $headers_pri_contents .= "SYNCQT.QPA_HEADER_FILES = $pri_install_qpafiles\n";
1115         my $headers_pri_file = "$out_basedir/include/$lib/headers.pri";
1116         if(-e $headers_pri_file) {
1117             open HEADERS_PRI_FILE, "<$headers_pri_file";
1118             local $/;
1119             binmode HEADERS_PRI_FILE;
1120             my $old_headers_pri_contents = <HEADERS_PRI_FILE>;
1121             close HEADERS_PRI_FILE;
1122             $old_headers_pri_contents =~ s/\r//g; # remove \r's , so comparison is ok on all platforms
1123             $headers_pri_file = 0 if($old_headers_pri_contents eq $headers_pri_contents);
1124         }
1125         if($headers_pri_file) {
1126             my $headers_pri_dir = dirname($headers_pri_file);
1127             make_path($headers_pri_dir, $lib, $verbose_level);
1128             open HEADERS_PRI_FILE, ">$headers_pri_file";
1129             print HEADERS_PRI_FILE $headers_pri_contents;
1130             close HEADERS_PRI_FILE;
1131             print "$lib: created headers.pri file\n" if($verbose_level);
1132         }
1133
1134         # create forwarding module pri in qtbase/mkspecs/modules
1135         if ($module_fwd) {
1136             my $modulepri = $modulepris{$lib};
1137             if (defined $modulepri and -e $modulepri) {
1138                 my $modulepriname = basename($modulepri);
1139                 make_path($module_fwd, $lib, $verbose_level);
1140                 my $moduleprifwd = "$module_fwd/$modulepriname";
1141                 my $mod_base = $basedir;
1142                 my $mod_component_base = $developer_build ? $qtbasedir : $out_basedir;
1143                 open MODULE_PRI_FILE, ">$moduleprifwd" or die("Could not open $moduleprifwd for writing");
1144                 print MODULE_PRI_FILE "QT_MODULE_BASE = $mod_base\n";
1145                 print MODULE_PRI_FILE "QT_MODULE_BIN_BASE = $mod_component_base/bin\n";
1146                 print MODULE_PRI_FILE "QT_MODULE_INCLUDE_BASE = $out_basedir/include\n";
1147                 print MODULE_PRI_FILE "QT_MODULE_IMPORT_BASE = $mod_component_base/imports\n";
1148                 print MODULE_PRI_FILE "QT_MODULE_LIB_BASE = $mod_component_base/lib\n";
1149                 print MODULE_PRI_FILE "QT_MODULE_PLUGIN_BASE = $mod_component_base/plugins\n";
1150                 print MODULE_PRI_FILE "include($modulepri)\n";
1151                 close MODULE_PRI_FILE;
1152                 utime(time, (stat($modulepri))[9], $moduleprifwd);
1153             } elsif ($modulepri) {
1154                 print "$lib: WARNING: Module\'s pri file '$modulepri' not found.\n$lib: Skipped creating forwarding pri.\n";
1155             }
1156         }
1157     }
1158 }
1159 unless($showonly || !$create_uic_class_map) {
1160     my $class_lib_map = "$out_basedir/src/tools/uic/qclass_lib_map.h";
1161     if(-e $class_lib_map) {
1162         open CLASS_LIB_MAP, "<$class_lib_map";
1163         local $/;
1164         binmode CLASS_LIB_MAP;
1165         my $old_class_lib_map_contents = <CLASS_LIB_MAP>;
1166         close CLASS_LIB_MAP;
1167         $old_class_lib_map_contents =~ s/\r//g; # remove \r's , so comparison is ok on all platforms
1168         $class_lib_map = 0 if($old_class_lib_map_contents eq $class_lib_map_contents);
1169     }
1170     if($class_lib_map) {
1171         my $class_lib_map_dir = dirname($class_lib_map);
1172         make_path($class_lib_map_dir, "<outdir>", $verbose_level);
1173         open CLASS_LIB_MAP, ">$class_lib_map";
1174         print CLASS_LIB_MAP $class_lib_map_contents;
1175         close CLASS_LIB_MAP;
1176     }
1177 }
1178
1179 if($check_includes) {
1180     for my $lib (keys(%modules)) {
1181             #calc subdirs
1182             my @subdirs = ($modules{$lib});
1183             foreach my $subdir (@subdirs) {
1184                 opendir DIR, $subdir or die "Huh, directory ".$subdir." cannot be opened.";
1185                 foreach my $t (sort readdir(DIR)) {
1186                     push @subdirs, "$subdir/$t" if(-d "$subdir/$t" && !($t eq ".") &&
1187                                                    !($t eq "..") && !($t eq ".obj") &&
1188                                                    !($t eq ".moc") && !($t eq ".rcc") &&
1189                                                    !($t eq ".uic") && !($t eq "build"));
1190                 }
1191                 closedir DIR;
1192             }
1193
1194             foreach my $subdir (@subdirs) {
1195                 my $header_skip_qt_module_test = 0;
1196                 foreach(@ignore_for_qt_module_check) {
1197                     foreach (split(/;/, $_)) {
1198                         $header_skip_qt_module_test = 1 if ($subdir =~ /^$_/);
1199                     }
1200                 }
1201                 my @headers = findFiles($subdir, "^[-a-z0-9_]*\\.h\$" , 0);
1202                 foreach my $header (@headers) {
1203                     my $header_skip_qt_begin_header_test = 0;
1204                     my $header_skip_qt_begin_namespace_test = 0;
1205                     $header = 0 if($header =~ /^ui_.*.h/);
1206                     foreach (@ignore_headers) {
1207                         $header = 0 if($header eq $_);
1208                     }
1209                     if($header) {
1210                         my $public_header = $header;
1211                         if($public_header =~ /_p.h$/ || $public_header =~ /_pch.h$/) {
1212                             $public_header = 0;
1213                         } elsif (isQpaHeader($public_header)) {
1214                             $public_header = 0;
1215                         } else {
1216                             foreach (@ignore_for_master_contents) {
1217                                 $public_header = 0 if($header eq $_);
1218                             }
1219                             if($public_header) {
1220                                 foreach (@ignore_for_include_check) {
1221                                     $public_header = 0 if($header eq $_);
1222                                 }
1223                                 foreach(@ignore_for_qt_begin_header_check) {
1224                                     $header_skip_qt_begin_header_test = 1 if ($header eq $_);
1225                                 }
1226                                 foreach(@ignore_for_qt_begin_namespace_check) {
1227                                     $header_skip_qt_begin_namespace_test = 1 if ($header eq $_);
1228                                 }
1229                             }
1230                         }
1231
1232                         my $iheader = $subdir . "/" . $header;
1233                         if($public_header) {
1234                             if(open(F, "<$iheader")) {
1235                                 my $qt_begin_header_found = 0;
1236                                 my $qt_end_header_found = 0;
1237                                 my $qt_begin_namespace_found = 0;
1238                                 my $qt_end_namespace_found = 0;
1239                                 my $line;
1240                                 while($line = <F>) {
1241                                     chomp $line;
1242                                     my $output_line = 1;
1243                                     if($line =~ /^ *\# *pragma (qt_no_included_check|qt_sync_stop_processing)/) {
1244                                         last;
1245                                     } elsif($line =~ /^ *\# *include/) {
1246                                         my $include = $line;
1247                                         if($line =~ /<.*>/) {
1248                                             $include =~ s,.*<(.*)>.*,$1,;
1249                                         } elsif($line =~ /".*"/) {
1250                                             $include =~ s,.*"(.*)".*,$1,;
1251                                         } else {
1252                                             $include = 0;
1253                                         }
1254                                         if($include) {
1255                                             for my $trylib (keys(%modules)) {
1256                                                 if(-e "$out_basedir/include/$trylib/$include") {
1257                                                     print "$lib: WARNING: $iheader includes $include when it should include $trylib/$include\n";
1258                                                 }
1259                                             }
1260                                         }
1261                                     } elsif ($header_skip_qt_begin_header_test == 0 and $line =~ /^QT_BEGIN_HEADER\s*$/) {
1262                                         $qt_begin_header_found = 1;
1263                                     } elsif ($header_skip_qt_begin_header_test == 0 and $line =~ /^QT_END_HEADER\s*$/) {
1264                                         $qt_end_header_found = 1;
1265                                     } elsif ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_BEGIN_NAMESPACE\s*$/) {
1266                                         $qt_begin_namespace_found = 1;
1267                                     } elsif ($header_skip_qt_begin_namespace_test == 0 and $line =~ /^QT_END_NAMESPACE\s*$/) {
1268                                         $qt_end_namespace_found = 1;
1269                                     }
1270                                 }
1271                                 if ($header_skip_qt_begin_header_test == 0) {
1272                                     if ($qt_begin_header_found == 0) {
1273                                         print "$lib: WARNING: $iheader does not include QT_BEGIN_HEADER\n";
1274                                     }
1275
1276                                     if ($qt_begin_header_found && $qt_end_header_found == 0) {
1277                                         print "$lib: WARNING: $iheader has QT_BEGIN_HEADER but no QT_END_HEADER\n";
1278                                     }
1279                                 }
1280
1281                                 if ($header_skip_qt_begin_namespace_test == 0) {
1282                                     if ($qt_begin_namespace_found == 0) {
1283                                         print "$lib: WARNING: $iheader does not include QT_BEGIN_NAMESPACE\n";
1284                                     }
1285
1286                                     if ($qt_begin_namespace_found && $qt_end_namespace_found == 0) {
1287                                         print "$lib: WARNING: $iheader has QT_BEGIN_NAMESPACE but no QT_END_NAMESPACE\n";
1288                                     }
1289                                 }
1290
1291                                 close(F);
1292                             }
1293                         }
1294                     }
1295                 }
1296             }
1297     }
1298 }
1299
1300 exit 0;