Commit | Line | Data |
---|---|---|
755bb92e | 1 | #!/usr/bin/perl -w |
e3d26a3e | 2 | use strict; |
755bb92e | 3 | |
c7201ce3 | 4 | # Copyright 2000-2004 Francois Gouget for CodeWeavers |
905658c4 | 5 | # Copyright 2004 Dimitrie O. Paun |
755bb92e | 6 | # |
0799c1a7 AJ |
7 | # This library is free software; you can redistribute it and/or |
8 | # modify it under the terms of the GNU Lesser General Public | |
9 | # License as published by the Free Software Foundation; either | |
10 | # version 2.1 of the License, or (at your option) any later version. | |
11 | # | |
12 | # This library is distributed in the hope that it will be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | # Lesser General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU Lesser General Public | |
18 | # License along with this library; if not, write to the Free Software | |
360a3f91 | 19 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
0799c1a7 AJ |
20 | # |
21 | ||
905658c4 | 22 | my $version="0.6.0"; |
755bb92e FG |
23 | |
24 | use Cwd; | |
25 | use File::Basename; | |
26 | use File::Copy; | |
27 | ||
28 | ||
29 | ||
30 | ##### | |
31 | # | |
32 | # Options | |
33 | # | |
34 | ##### | |
35 | ||
36 | # The following constants define what we do with the case of filenames | |
37 | ||
38 | ## | |
39 | # Never rename a file to lowercase | |
40 | my $OPT_LOWER_NONE=0; | |
41 | ||
42 | ## | |
43 | # Rename all files to lowercase | |
44 | my $OPT_LOWER_ALL=1; | |
45 | ||
46 | ## | |
47 | # Rename only files that are all uppercase to lowercase | |
48 | my $OPT_LOWER_UPPERCASE=2; | |
49 | ||
50 | ||
51 | # The following constants define whether to ask questions or not | |
52 | ||
53 | ## | |
54 | # No (synonym of never) | |
55 | my $OPT_ASK_NO=0; | |
56 | ||
57 | ## | |
58 | # Yes (always) | |
59 | my $OPT_ASK_YES=1; | |
60 | ||
61 | ## | |
62 | # Skip the questions till the end of this scope | |
63 | my $OPT_ASK_SKIP=-1; | |
64 | ||
65 | ||
66 | # General options | |
67 | ||
c1f016be FG |
68 | ## |
69 | # This is the directory in which winemaker will operate. | |
70 | my $opt_work_dir; | |
71 | ||
755bb92e FG |
72 | ## |
73 | # Make a backup of the files | |
74 | my $opt_backup; | |
75 | ||
76 | ## | |
77 | # Defines which files to rename | |
78 | my $opt_lower; | |
79 | ||
a106edb7 FG |
80 | ## |
81 | # If we don't find the file referenced by an include, lower it | |
82 | my $opt_lower_include; | |
83 | ||
ce4e0a61 BM |
84 | ## |
85 | # If true then winemaker should not attempt to fix the source. This is | |
86 | # useful if the source is known to be already in a suitable form and is | |
87 | # readonly | |
88 | my $opt_no_source_fix; | |
755bb92e FG |
89 | |
90 | # Options for the 'Source' method | |
91 | ||
92 | ## | |
7cae558b AJ |
93 | # Specifies that we have only one target so that all sources relate |
94 | # to this target. By default this variable is left undefined which | |
95 | # means winemaker should try to find out by itself what the targets | |
96 | # are. If not undefined then this contains the name of the default | |
755bb92e FG |
97 | # target (without the extension). |
98 | my $opt_single_target; | |
99 | ||
100 | ## | |
7cae558b AJ |
101 | # If '$opt_single_target' has been specified then this is the type of |
102 | # that target. Otherwise it specifies whether the default target type | |
755bb92e FG |
103 | # is guiexe or cuiexe. |
104 | my $opt_target_type; | |
105 | ||
106 | ## | |
107 | # Contains the default set of flags to be used when creating a new target. | |
108 | my $opt_flags; | |
109 | ||
110 | ## | |
7cae558b | 111 | # If true then winemaker should ask questions to the user as it goes |
755bb92e FG |
112 | # along. |
113 | my $opt_is_interactive; | |
114 | my $opt_ask_project_options; | |
115 | my $opt_ask_target_options; | |
116 | ||
117 | ## | |
c7201ce3 | 118 | # If false then winemaker should not generate the makefiles. |
a106edb7 | 119 | my $opt_no_generated_files; |
755bb92e FG |
120 | |
121 | ## | |
122 | # Specifies not to print the banner if set. | |
123 | my $opt_no_banner; | |
124 | ||
125 | ||
126 | ||
127 | ##### | |
128 | # | |
129 | # Target modelization | |
130 | # | |
131 | ##### | |
132 | ||
7cae558b | 133 | # The description of a target is stored in an array. The constants |
755bb92e FG |
134 | # below identify what is stored at each index of the array. |
135 | ||
136 | ## | |
137 | # This is the name of the target. | |
138 | my $T_NAME=0; | |
139 | ||
140 | ## | |
141 | # Defines the type of target we want to build. See the TT_xxx | |
142 | # constants below | |
143 | my $T_TYPE=1; | |
144 | ||
755bb92e | 145 | ## |
7cae558b | 146 | # This is a bitfield containing flags refining the way the target |
755bb92e | 147 | # should be handled. See the TF_xxx constants below |
c7201ce3 | 148 | my $T_FLAGS=2; |
755bb92e FG |
149 | |
150 | ## | |
7cae558b | 151 | # This is a reference to an array containing the list of the |
755bb92e | 152 | # resp. C, C++, RC, other (.h, .hxx, etc.) source files. |
c7201ce3 FG |
153 | my $T_SOURCES_C=3; |
154 | my $T_SOURCES_CXX=4; | |
155 | my $T_SOURCES_RC=5; | |
156 | my $T_SOURCES_MISC=6; | |
157 | ||
158 | ## | |
159 | # This is a reference to an array containing the list of | |
160 | # C compiler options | |
161 | my $T_CEXTRA=7; | |
162 | ||
163 | ## | |
164 | # This is a reference to an array containing the list of | |
165 | # C++ compiler options | |
166 | my $T_CXXEXTRA=8; | |
167 | ||
168 | ## | |
169 | # This is a reference to an array containing the list of | |
170 | # RC compiler options | |
171 | my $T_RCEXTRA=9; | |
755bb92e FG |
172 | |
173 | ## | |
7cae558b | 174 | # This is a reference to an array containing the list of macro |
755bb92e | 175 | # definitions |
c7201ce3 | 176 | my $T_DEFINES=10; |
755bb92e FG |
177 | |
178 | ## | |
7cae558b | 179 | # This is a reference to an array containing the list of directory |
755bb92e | 180 | # names that constitute the include path |
c7201ce3 FG |
181 | my $T_INCLUDE_PATH=11; |
182 | ||
183 | ## | |
184 | # Flags for the linker | |
185 | my $T_LDFLAGS=12; | |
755bb92e FG |
186 | |
187 | ## | |
89a0c02b | 188 | # Same as T_INCLUDE_PATH but for the dll search path |
c7201ce3 | 189 | my $T_DLL_PATH=13; |
89a0c02b FG |
190 | |
191 | ## | |
192 | # The list of Windows dlls to import | |
c7201ce3 | 193 | my $T_DLLS=14; |
755bb92e FG |
194 | |
195 | ## | |
89a0c02b | 196 | # Same as T_INCLUDE_PATH but for the library search path |
c7201ce3 | 197 | my $T_LIBRARY_PATH=15; |
be859592 FG |
198 | |
199 | ## | |
200 | # The list of Unix libraries to link with | |
c7201ce3 | 201 | my $T_LIBRARIES=16; |
755bb92e FG |
202 | |
203 | ## | |
204 | # The list of dependencies between targets | |
c7201ce3 | 205 | my $T_DEPENDS=17; |
755bb92e FG |
206 | |
207 | ||
208 | # The following constants define the recognized types of target | |
209 | ||
210 | ## | |
7cae558b | 211 | # This is not a real target. This type of target is used to collect |
755bb92e | 212 | # the sources that don't seem to belong to any other target. Thus no |
7cae558b | 213 | # real target is generated for them, we just put the sources of the |
755bb92e FG |
214 | # fake target in the global source list. |
215 | my $TT_SETTINGS=0; | |
216 | ||
217 | ## | |
218 | # For executables in the windows subsystem | |
219 | my $TT_GUIEXE=1; | |
220 | ||
221 | ## | |
222 | # For executables in the console subsystem | |
223 | my $TT_CUIEXE=2; | |
224 | ||
225 | ## | |
226 | # For dynamically linked libraries | |
227 | my $TT_DLL=3; | |
228 | ||
229 | ||
230 | # The following constants further refine how the target should be handled | |
231 | ||
755bb92e FG |
232 | ## |
233 | # This target is an MFC-based target | |
234 | my $TF_MFC=4; | |
235 | ||
3aa9e8c6 MW |
236 | ## |
237 | # User has specified --nomfc option for this target or globally | |
238 | my $TF_NOMFC=8; | |
239 | ||
240 | ## | |
241 | # --nodlls option: Do not use standard DLL set | |
242 | my $TF_NODLLS=16; | |
243 | ||
15487bca FG |
244 | ## |
245 | # --nomsvcrt option: Do not link with msvcrt | |
246 | my $TF_NOMSVCRT=32; | |
247 | ||
755bb92e FG |
248 | ## |
249 | # Initialize a target: | |
7cae558b AJ |
250 | # - set the target type to TT_SETTINGS, i.e. no real target will |
251 | # be generated. | |
e3d26a3e | 252 | sub target_init($) |
755bb92e FG |
253 | { |
254 | my $target=$_[0]; | |
255 | ||
256 | @$target[$T_TYPE]=$TT_SETTINGS; | |
257 | # leaving $T_INIT undefined | |
258 | @$target[$T_FLAGS]=$opt_flags; | |
259 | @$target[$T_SOURCES_C]=[]; | |
260 | @$target[$T_SOURCES_CXX]=[]; | |
261 | @$target[$T_SOURCES_RC]=[]; | |
262 | @$target[$T_SOURCES_MISC]=[]; | |
c7201ce3 FG |
263 | @$target[$T_CEXTRA]=[]; |
264 | @$target[$T_CXXEXTRA]=[]; | |
265 | @$target[$T_RCEXTRA]=[]; | |
755bb92e FG |
266 | @$target[$T_DEFINES]=[]; |
267 | @$target[$T_INCLUDE_PATH]=[]; | |
c7201ce3 | 268 | @$target[$T_LDFLAGS]=[]; |
89a0c02b FG |
269 | @$target[$T_DLL_PATH]=[]; |
270 | @$target[$T_DLLS]=[]; | |
755bb92e | 271 | @$target[$T_LIBRARY_PATH]=[]; |
be859592 | 272 | @$target[$T_LIBRARIES]=[]; |
755bb92e FG |
273 | } |
274 | ||
755bb92e FG |
275 | |
276 | ||
277 | ##### | |
278 | # | |
279 | # Project modelization | |
280 | # | |
281 | ##### | |
282 | ||
7cae558b AJ |
283 | # First we have the notion of project. A project is described by an |
284 | # array (since we don't have structs in perl). The constants below | |
755bb92e FG |
285 | # identify what is stored at each index of the array. |
286 | ||
287 | ## | |
7cae558b | 288 | # This is the path in which this project is located. In other |
755bb92e FG |
289 | # words, this is the path to the Makefile. |
290 | my $P_PATH=0; | |
291 | ||
292 | ## | |
7cae558b AJ |
293 | # This index contains a reference to an array containing the project-wide |
294 | # settings. The structure of that arrray is actually identical to that of | |
755bb92e FG |
295 | # a regular target since it can also contain extra sources. |
296 | my $P_SETTINGS=1; | |
297 | ||
298 | ## | |
7cae558b AJ |
299 | # This index contains a reference to an array of targets for this |
300 | # project. Each target describes how an executable or library is to | |
301 | # be built. For each target this description takes the same form as | |
755bb92e FG |
302 | # that of the project: an array. So this entry is an array of arrays. |
303 | my $P_TARGETS=2; | |
304 | ||
305 | ## | |
306 | # Initialize a project: | |
307 | # - set the project's path | |
308 | # - initialize the target list | |
309 | # - create a default target (will be removed later if unnecessary) | |
e3d26a3e | 310 | sub project_init($$) |
755bb92e FG |
311 | { |
312 | my $project=$_[0]; | |
313 | my $path=$_[1]; | |
314 | ||
315 | my $project_settings=[]; | |
316 | target_init($project_settings); | |
317 | ||
318 | @$project[$P_PATH]=$path; | |
319 | @$project[$P_SETTINGS]=$project_settings; | |
320 | @$project[$P_TARGETS]=[]; | |
321 | } | |
322 | ||
323 | ||
324 | ||
325 | ##### | |
326 | # | |
327 | # Global variables | |
328 | # | |
329 | ##### | |
330 | ||
755bb92e FG |
331 | my %warnings; |
332 | ||
333 | my %templates; | |
334 | ||
dc754063 MJ |
335 | ## |
336 | # This maps a directory name to a reference to an array listing | |
337 | # its contents (files and directories) | |
338 | my %directories; | |
339 | ||
755bb92e | 340 | ## |
7cae558b AJ |
341 | # Contains the list of all projects. This list tells us what are |
342 | # the subprojects of the main Makefile and where we have to generate | |
755bb92e FG |
343 | # Makefiles. |
344 | my @projects=(); | |
345 | ||
346 | ## | |
7cae558b AJ |
347 | # This is the main project, i.e. the one in the "." directory. |
348 | # It may well be empty in which case the main Makefile will only | |
755bb92e FG |
349 | # call out subprojects. |
350 | my @main_project; | |
351 | ||
352 | ## | |
353 | # Contains the defaults for the include path, etc. | |
7cae558b | 354 | # We store the defaults as if this were a target except that we only |
755bb92e FG |
355 | # exploit the defines, include path, library path, library list and misc |
356 | # sources fields. | |
357 | my @global_settings; | |
358 | ||
755bb92e FG |
359 | |
360 | ||
361 | ##### | |
362 | # | |
363 | # Utility functions | |
364 | # | |
365 | ##### | |
366 | ||
367 | ## | |
7cae558b | 368 | # Cleans up a name to make it an acceptable Makefile |
755bb92e | 369 | # variable name. |
e3d26a3e | 370 | sub canonize($) |
755bb92e FG |
371 | { |
372 | my $name=$_[0]; | |
373 | ||
374 | $name =~ tr/a-zA-Z0-9_/_/c; | |
375 | return $name; | |
376 | } | |
377 | ||
378 | ## | |
379 | # Returns true is the specified pathname is absolute. | |
7cae558b | 380 | # Note: pathnames that start with a variable '$' or |
755bb92e | 381 | # '~' are considered absolute. |
e3d26a3e | 382 | sub is_absolute($) |
755bb92e FG |
383 | { |
384 | my $path=$_[0]; | |
385 | ||
386 | return ($path =~ /^[\/~\$]/); | |
387 | } | |
388 | ||
389 | ## | |
390 | # Performs a binary search looking for the specified item | |
e3d26a3e | 391 | sub bsearch($$) |
755bb92e FG |
392 | { |
393 | my $array=$_[0]; | |
394 | my $item=$_[1]; | |
395 | my $last=@{$array}-1; | |
396 | my $first=0; | |
397 | ||
398 | while ($first<=$last) { | |
399 | my $index=int(($first+$last)/2); | |
400 | my $cmp=@$array[$index] cmp $item; | |
401 | if ($cmp<0) { | |
402 | $first=$index+1; | |
403 | } elsif ($cmp>0) { | |
404 | $last=$index-1; | |
405 | } else { | |
406 | return $index; | |
407 | } | |
408 | } | |
409 | } | |
410 | ||
bebac0a4 FG |
411 | ## |
412 | # Retrieves the contents of the specified directory. | |
413 | # We either get it from the directories hashtable which acts as a | |
414 | # cache, or use opendir, readdir, closedir and store the result | |
415 | # in the hashtable. | |
416 | sub get_directory_contents($) | |
417 | { | |
418 | my $dirname=$_[0]; | |
419 | my $directory; | |
420 | ||
421 | #print "getting the contents of $dirname\n"; | |
422 | ||
423 | # check for a cached version | |
424 | $dirname =~ s+/$++; | |
425 | if ($dirname eq "") { | |
426 | $dirname=cwd; | |
427 | } | |
428 | $directory=$directories{$dirname}; | |
429 | if (defined $directory) { | |
430 | #print "->@$directory\n"; | |
431 | return $directory; | |
432 | } | |
433 | ||
434 | # Read this directory | |
435 | if (opendir(DIRECTORY, "$dirname")) { | |
436 | my @files=readdir DIRECTORY; | |
437 | closedir(DIRECTORY); | |
438 | $directory=\@files; | |
439 | } else { | |
440 | # Return an empty list | |
441 | #print "error: cannot open $dirname\n"; | |
442 | my @files; | |
443 | $directory=\@files; | |
444 | } | |
445 | #print "->@$directory\n"; | |
446 | $directories{$dirname}=$directory; | |
447 | return $directory; | |
448 | } | |
449 | ||
755bb92e FG |
450 | |
451 | ||
452 | ##### | |
453 | # | |
454 | # 'Source'-based Project analysis | |
455 | # | |
456 | ##### | |
457 | ||
458 | ## | |
459 | # Allows the user to specify makefile and target specific options | |
460 | # - target: the structure in which to store the results | |
461 | # - options: the string containing the options | |
e3d26a3e | 462 | sub source_set_options($$) |
755bb92e FG |
463 | { |
464 | my $target=$_[0]; | |
465 | my $options=$_[1]; | |
466 | ||
467 | #FIXME: we must deal with escaping of stuff and all | |
e3d26a3e | 468 | foreach my $option (split / /,$options) { |
755bb92e FG |
469 | if (@$target[$T_TYPE] == $TT_SETTINGS and $option =~ /^-D/) { |
470 | push @{@$target[$T_DEFINES]},$option; | |
471 | } elsif (@$target[$T_TYPE] == $TT_SETTINGS and $option =~ /^-I/) { | |
472 | push @{@$target[$T_INCLUDE_PATH]},$option; | |
89a0c02b FG |
473 | } elsif ($option =~ /^-P/) { |
474 | push @{@$target[$T_DLL_PATH]},"-L$'"; | |
475 | } elsif ($option =~ /^-i/) { | |
905658c4 | 476 | push @{@$target[$T_DLLS]},"$'"; |
755bb92e FG |
477 | } elsif ($option =~ /^-L/) { |
478 | push @{@$target[$T_LIBRARY_PATH]},$option; | |
be859592 | 479 | } elsif ($option =~ /^-l/) { |
89a0c02b | 480 | push @{@$target[$T_LIBRARIES]},"$'"; |
3aa9e8c6 MW |
481 | } elsif ($option =~ /^--mfc/) { |
482 | @$target[$T_FLAGS]|=$TF_MFC; | |
483 | @$target[$T_FLAGS]&=~$TF_NOMFC; | |
82747b7d FG |
484 | } elsif ($option =~ /^--nomfc/) { |
485 | @$target[$T_FLAGS]&=~$TF_MFC; | |
3aa9e8c6 MW |
486 | @$target[$T_FLAGS]|=$TF_NOMFC; |
487 | } elsif ($option =~ /^--nodlls/) { | |
488 | @$target[$T_FLAGS]|=$TF_NODLLS; | |
15487bca FG |
489 | } elsif ($option =~ /^--nomsvcrt/) { |
490 | @$target[$T_FLAGS]|=$TF_NOMSVCRT; | |
755bb92e | 491 | } else { |
3af251e4 FG |
492 | print STDERR "error: unknown option \"$option\"\n"; |
493 | return 0; | |
755bb92e FG |
494 | } |
495 | } | |
3af251e4 | 496 | return 1; |
755bb92e FG |
497 | } |
498 | ||
499 | ## | |
500 | # Scans the specified directory to: | |
7cae558b | 501 | # - see if we should create a Makefile in this directory. We normally do |
755bb92e FG |
502 | # so if we find a project file and sources |
503 | # - get a list of targets for this directory | |
504 | # - get the list of source files | |
e3d26a3e FG |
505 | sub source_scan_directory($$$$); |
506 | sub source_scan_directory($$$$) | |
755bb92e FG |
507 | { |
508 | # a reference to the parent's project | |
509 | my $parent_project=$_[0]; | |
7cae558b | 510 | # the full relative path to the current directory, including a |
755bb92e FG |
511 | # trailing '/', or an empty string if this is the top level directory |
512 | my $path=$_[1]; | |
513 | # the name of this directory, including a trailing '/', or an empty | |
514 | # string if this is the top level directory | |
515 | my $dirname=$_[2]; | |
7cae558b | 516 | # if set then no targets will be looked for and the sources will all |
3266b887 FG |
517 | # end up in the parent_project's 'misc' bucket |
518 | my $no_target=$_[3]; | |
755bb92e FG |
519 | |
520 | # reference to the project for this directory. May not be used | |
521 | my $project; | |
522 | # list of targets found in the 'current' directory | |
523 | my %targets; | |
524 | # list of sources found in the current directory | |
525 | my @sources_c=(); | |
526 | my @sources_cxx=(); | |
527 | my @sources_rc=(); | |
528 | my @sources_misc=(); | |
529 | # true if this directory contains a Windows project | |
530 | my $has_win_project=0; | |
c7201ce3 FG |
531 | # true if this directory contains headers |
532 | my $has_headers=0; | |
7cae558b AJ |
533 | # If we don't find any executable/library then we might make up targets |
534 | # from the list of .dsp/.mak files we find since they usually have the | |
755bb92e FG |
535 | # same name as their target. |
536 | my @dsp_files=(); | |
537 | my @mak_files=(); | |
538 | ||
539 | if (defined $opt_single_target or $dirname eq "") { | |
7cae558b AJ |
540 | # Either there is a single target and thus a single project, |
541 | # or we are in the top level directory for which a project | |
755bb92e FG |
542 | # already exists |
543 | $project=$parent_project; | |
544 | } else { | |
545 | $project=[]; | |
546 | project_init($project,$path); | |
547 | } | |
a106edb7 | 548 | my $project_settings=@$project[$P_SETTINGS]; |
755bb92e FG |
549 | |
550 | # First find out what this directory contains: | |
551 | # collect all sources, targets and subdirectories | |
552 | my $directory=get_directory_contents($path); | |
e3d26a3e | 553 | foreach my $dentry (@$directory) { |
755bb92e FG |
554 | if ($dentry =~ /^\./) { |
555 | next; | |
556 | } | |
557 | my $fullentry="$path$dentry"; | |
558 | if (-d "$fullentry") { | |
559 | if ($dentry =~ /^(Release|Debug)/i) { | |
7cae558b | 560 | # These directories are often used to store the object files and the |
755bb92e FG |
561 | # resulting executable/library. They should not contain anything else. |
562 | my @candidates=grep /\.(exe|dll)$/i, @{get_directory_contents("$fullentry")}; | |
e3d26a3e | 563 | foreach my $candidate (@candidates) { |
635eb3c2 | 564 | $targets{$candidate}=1; |
755bb92e | 565 | } |
4ec10596 FG |
566 | } elsif ($dentry =~ /^include/i) { |
567 | # This directory must contain headers we're going to need | |
568 | push @{@$project_settings[$T_INCLUDE_PATH]},"-I$dentry"; | |
3266b887 | 569 | source_scan_directory($project,"$fullentry/","$dentry/",1); |
755bb92e | 570 | } else { |
7cae558b AJ |
571 | # Recursively scan this directory. Any source file that cannot be |
572 | # attributed to a project in one of the subdirectories will be | |
3266b887 FG |
573 | # attributed to this project. |
574 | source_scan_directory($project,"$fullentry/","$dentry/",$no_target); | |
755bb92e FG |
575 | } |
576 | } elsif (-f "$fullentry") { | |
635eb3c2 | 577 | if ($dentry =~ /\.(exe|dll)$/i) { |
755bb92e | 578 | $targets{$dentry}=1; |
1dd53254 | 579 | } elsif ($dentry =~ /\.c$/i and $dentry !~ /\.(dbg|spec)\.c$/) { |
755bb92e FG |
580 | push @sources_c,"$dentry"; |
581 | } elsif ($dentry =~ /\.(cpp|cxx)$/i) { | |
3aa9e8c6 | 582 | if ($dentry =~ /^stdafx.cpp$/i && !(@$project_settings[$T_FLAGS] & $TF_NOMFC)) { |
a106edb7 | 583 | push @sources_misc,"$dentry"; |
82747b7d | 584 | @$project_settings[$T_FLAGS]|=$TF_MFC; |
a106edb7 FG |
585 | } else { |
586 | push @sources_cxx,"$dentry"; | |
587 | } | |
755bb92e FG |
588 | } elsif ($dentry =~ /\.rc$/i) { |
589 | push @sources_rc,"$dentry"; | |
3c6c20f8 | 590 | } elsif ($dentry =~ /\.(h|hxx|hpp|inl|rc2|dlg)$/i) { |
c7201ce3 | 591 | $has_headers=1; |
755bb92e | 592 | push @sources_misc,"$dentry"; |
3aa9e8c6 | 593 | if ($dentry =~ /^stdafx.h$/i && !(@$project_settings[$T_FLAGS] & $TF_NOMFC)) { |
82747b7d | 594 | @$project_settings[$T_FLAGS]|=$TF_MFC; |
a106edb7 | 595 | } |
755bb92e FG |
596 | } elsif ($dentry =~ /\.dsp$/i) { |
597 | push @dsp_files,"$dentry"; | |
598 | $has_win_project=1; | |
599 | } elsif ($dentry =~ /\.mak$/i) { | |
600 | push @mak_files,"$dentry"; | |
601 | $has_win_project=1; | |
602 | } elsif ($dentry =~ /^makefile/i) { | |
603 | $has_win_project=1; | |
604 | } | |
605 | } | |
606 | } | |
607 | closedir(DIRECTORY); | |
608 | ||
c7201ce3 FG |
609 | if ($has_headers) { |
610 | push @{@$project_settings[$T_INCLUDE_PATH]},"-I."; | |
611 | } | |
7cae558b | 612 | # If we have a single target then all we have to do is assign |
755bb92e FG |
613 | # all the sources to it and we're done |
614 | # FIXME: does this play well with the --interactive mode? | |
615 | if ($opt_single_target) { | |
616 | my $target=@{@$project[$P_TARGETS]}[0]; | |
617 | push @{@$target[$T_SOURCES_C]},map "$path$_",@sources_c; | |
618 | push @{@$target[$T_SOURCES_CXX]},map "$path$_",@sources_cxx; | |
619 | push @{@$target[$T_SOURCES_RC]},map "$path$_",@sources_rc; | |
620 | push @{@$target[$T_SOURCES_MISC]},map "$path$_",@sources_misc; | |
621 | return; | |
622 | } | |
3266b887 FG |
623 | if ($no_target) { |
624 | my $parent_settings=@$parent_project[$P_SETTINGS]; | |
625 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_c; | |
626 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_cxx; | |
627 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_rc; | |
628 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_misc; | |
647bb8f0 | 629 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@{@$project_settings[$T_SOURCES_MISC]}; |
3266b887 FG |
630 | return; |
631 | } | |
755bb92e | 632 | |
755bb92e FG |
633 | my $source_count=@sources_c+@sources_cxx+@sources_rc+ |
634 | @{@$project_settings[$T_SOURCES_C]}+ | |
635 | @{@$project_settings[$T_SOURCES_CXX]}+ | |
636 | @{@$project_settings[$T_SOURCES_RC]}; | |
637 | if ($source_count == 0) { | |
638 | # A project without real sources is not a project, get out! | |
639 | if ($project!=$parent_project) { | |
3266b887 | 640 | my $parent_settings=@$parent_project[$P_SETTINGS]; |
755bb92e FG |
641 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_misc; |
642 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@{@$project_settings[$T_SOURCES_MISC]}; | |
643 | } | |
644 | return; | |
645 | } | |
646 | #print "targets=",%targets,"\n"; | |
647 | #print "target_count=$target_count\n"; | |
648 | #print "has_win_project=$has_win_project\n"; | |
649 | #print "dirname=$dirname\n"; | |
650 | ||
651 | my $target_count; | |
652 | if (($has_win_project != 0) or ($dirname eq "")) { | |
7cae558b | 653 | # Deal with cases where we could not find any executable/library, and |
755bb92e FG |
654 | # thus have no target, although we did find some sort of windows project. |
655 | $target_count=keys %targets; | |
656 | if ($target_count == 0) { | |
657 | # Try to come up with a target list based on .dsp/.mak files | |
658 | my $prj_list; | |
659 | if (@dsp_files > 0) { | |
660 | $prj_list=\@dsp_files; | |
661 | } else { | |
662 | $prj_list=\@mak_files; | |
663 | } | |
e3d26a3e | 664 | foreach my $filename (@$prj_list) { |
755bb92e FG |
665 | $filename =~ s/\.(dsp|mak)$//i; |
666 | if ($opt_target_type == $TT_DLL) { | |
635eb3c2 | 667 | $filename = "$filename.dll"; |
755bb92e FG |
668 | } |
669 | $targets{$filename}=1; | |
670 | } | |
671 | $target_count=keys %targets; | |
672 | if ($target_count == 0) { | |
673 | # Still nothing, try the name of the directory | |
674 | my $name; | |
675 | if ($dirname eq "") { | |
676 | # Bad luck, this is the top level directory! | |
677 | $name=(split /\//, cwd)[-1]; | |
678 | } else { | |
679 | $name=$dirname; | |
7cae558b | 680 | # Remove the trailing '/'. Also eliminate whatever is after the last |
755bb92e FG |
681 | # '.' as it is likely to be meaningless (.orig, .new, ...) |
682 | $name =~ s+(/|\.[^.]*)$++; | |
683 | if ($name eq "src") { | |
684 | # 'src' is probably a subdirectory of the real project directory. | |
685 | # Try again with the parent (if any). | |
686 | my $parent=$path; | |
687 | if ($parent =~ s+([^/]*)/[^/]*/$+$1+) { | |
688 | $name=$parent; | |
689 | } else { | |
690 | $name=(split /\//, cwd)[-1]; | |
691 | } | |
692 | } | |
693 | } | |
694 | $name =~ s+(/|\.[^.]*)$++; | |
695 | if ($opt_target_type == $TT_DLL) { | |
635eb3c2 | 696 | $name = "$name.dll"; |
caa74b66 JS |
697 | } else { |
698 | $name = "$name.exe"; | |
755bb92e FG |
699 | } |
700 | $targets{$name}=1; | |
701 | } | |
702 | } | |
703 | ||
704 | # Ask confirmation to the user if he wishes so | |
705 | if ($opt_is_interactive == $OPT_ASK_YES) { | |
706 | my $target_list=join " ",keys %targets; | |
fb5b590e | 707 | print "\n*** In ",($path?$path:"./"),"\n"; |
a106edb7 FG |
708 | print "* winemaker found the following list of (potential) targets\n"; |
709 | print "* $target_list\n"; | |
710 | print "* Type enter to use it as is, your own comma-separated list of\n"; | |
711 | print "* targets, 'none' to assign the source files to a parent directory,\n"; | |
712 | print "* or 'ignore' to ignore everything in this directory tree.\n"; | |
713 | print "* Target list:\n"; | |
755bb92e FG |
714 | $target_list=<STDIN>; |
715 | chomp $target_list; | |
716 | if ($target_list eq "") { | |
717 | # Keep the target list as is, i.e. do nothing | |
718 | } elsif ($target_list eq "none") { | |
719 | # Empty the target list | |
720 | undef %targets; | |
721 | } elsif ($target_list eq "ignore") { | |
722 | # Ignore this subtree altogether | |
723 | return; | |
724 | } else { | |
725 | undef %targets; | |
e3d26a3e | 726 | foreach my $target (split /,/,$target_list) { |
755bb92e FG |
727 | $target =~ s+^\s*++; |
728 | $target =~ s+\s*$++; | |
755bb92e FG |
729 | $targets{$target}=1; |
730 | } | |
731 | } | |
732 | } | |
733 | } | |
734 | ||
7cae558b | 735 | # If we have no project at this level, then transfer all |
755bb92e FG |
736 | # the sources to the parent project |
737 | $target_count=keys %targets; | |
738 | if ($target_count == 0) { | |
739 | if ($project!=$parent_project) { | |
740 | my $parent_settings=@$parent_project[$P_SETTINGS]; | |
741 | push @{@$parent_settings[$T_SOURCES_C]},map "$dirname$_",@sources_c; | |
742 | push @{@$parent_settings[$T_SOURCES_CXX]},map "$dirname$_",@sources_cxx; | |
743 | push @{@$parent_settings[$T_SOURCES_RC]},map "$dirname$_",@sources_rc; | |
744 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@sources_misc; | |
745 | push @{@$parent_settings[$T_SOURCES_MISC]},map "$dirname$_",@{@$project_settings[$T_SOURCES_MISC]}; | |
746 | } | |
747 | return; | |
748 | } | |
749 | ||
7cae558b | 750 | # Otherwise add this project to the project list, except for |
755bb92e FG |
751 | # the main project which is already in the list. |
752 | if ($dirname ne "") { | |
753 | push @projects,$project; | |
754 | } | |
755 | ||
756 | # Ask for project-wide options | |
757 | if ($opt_ask_project_options == $OPT_ASK_YES) { | |
a106edb7 FG |
758 | my $flag_desc=""; |
759 | if ((@$project_settings[$T_FLAGS] & $TF_MFC)!=0) { | |
760 | $flag_desc="mfc"; | |
761 | } | |
905658c4 | 762 | print "* Type any project-wide options (-D/-I/-P/-i/-L/-l/--mfc),\n"; |
a106edb7 FG |
763 | if (defined $flag_desc) { |
764 | print "* (currently $flag_desc)\n"; | |
765 | } | |
766 | print "* or 'skip' to skip the target specific options,\n"; | |
767 | print "* or 'never' to not be asked this question again:\n"; | |
3af251e4 FG |
768 | while (1) { |
769 | my $options=<STDIN>; | |
770 | chomp $options; | |
771 | if ($options eq "skip") { | |
772 | $opt_ask_target_options=$OPT_ASK_SKIP; | |
773 | last; | |
774 | } elsif ($options eq "never") { | |
775 | $opt_ask_project_options=$OPT_ASK_NO; | |
776 | last; | |
777 | } elsif (source_set_options($project_settings,$options)) { | |
778 | last; | |
779 | } | |
780 | print "Please re-enter the options:\n"; | |
755bb92e FG |
781 | } |
782 | } | |
783 | ||
784 | # - Create the targets | |
785 | # - Check if we have both libraries and programs | |
7cae558b | 786 | # - Match each target with source files (sort in reverse |
755bb92e | 787 | # alphabetical order to get the longest matches first) |
89a0c02b | 788 | my @local_dlls=(); |
755bb92e | 789 | my @local_depends=(); |
be859592 | 790 | my @exe_list=(); |
4ae4d661 | 791 | foreach my $target_name (map (lc, (sort { $b cmp $a } keys %targets))) { |
755bb92e | 792 | # Create the target... |
755bb92e FG |
793 | my $target=[]; |
794 | target_init($target); | |
795 | @$target[$T_NAME]=$target_name; | |
a106edb7 | 796 | @$target[$T_FLAGS]|=@$project_settings[$T_FLAGS]; |
635eb3c2 | 797 | if ($target_name =~ /\.dll$/) { |
755bb92e | 798 | @$target[$T_TYPE]=$TT_DLL; |
635eb3c2 FG |
799 | push @local_depends,"$target_name.so"; |
800 | push @local_dlls,$target_name; | |
a286c202 FG |
801 | my $canon=canonize($target_name); |
802 | push @{@$target[$T_LDFLAGS]},("-shared","\$(${canon}_MODULE:%=%.spec)"); | |
755bb92e FG |
803 | } else { |
804 | @$target[$T_TYPE]=$opt_target_type; | |
be859592 | 805 | push @exe_list,$target; |
c7201ce3 | 806 | push @{@$target[$T_LDFLAGS]},(@$target[$T_TYPE] == $TT_CUIEXE ? "-mconsole" : "-mwindows"); |
755bb92e | 807 | } |
635eb3c2 FG |
808 | my $basename=$target_name; |
809 | $basename=~ s/\.(dll|exe)$//i; | |
7cae558b | 810 | # This is the default link list of Visual Studio, except odbccp32 |
b1ff875d | 811 | # which we don't have in Wine. |
905658c4 | 812 | my @std_imports=qw(odbc32 ole32 oleaut32 winspool); |
b1ff875d | 813 | my @std_libraries=qw(uuid); |
90d65280 | 814 | if ((@$target[$T_FLAGS] & $TF_NODLLS) == 0) { |
c327246a | 815 | @$target[$T_DLLS]=\@std_imports; |
b1ff875d | 816 | @$target[$T_LIBRARIES]=\@std_libraries; |
3aa9e8c6 MW |
817 | } else { |
818 | @$target[$T_DLLS]=[]; | |
b1ff875d | 819 | @$target[$T_LIBRARIES]=[]; |
3aa9e8c6 | 820 | } |
c7201ce3 FG |
821 | if ((@$target[$T_FLAGS] & $TF_NOMSVCRT) == 0) { |
822 | push @{@$target[$T_LDFLAGS]},"-mno-cygwin"; | |
823 | } | |
755bb92e FG |
824 | push @{@$project[$P_TARGETS]},$target; |
825 | ||
826 | # Ask for target-specific options | |
827 | if ($opt_ask_target_options == $OPT_ASK_YES) { | |
a106edb7 FG |
828 | my $flag_desc=""; |
829 | if ((@$target[$T_FLAGS] & $TF_MFC)!=0) { | |
830 | $flag_desc=" (mfc"; | |
831 | } | |
a106edb7 FG |
832 | if ($flag_desc ne "") { |
833 | $flag_desc.=")"; | |
834 | } | |
905658c4 | 835 | print "* Specify any link option (-P/-i/-L/-l/--mfc) specific to the target\n"; |
a106edb7 | 836 | print "* \"$target_name\"$flag_desc or 'never' to not be asked this question again:\n"; |
3af251e4 FG |
837 | while (1) { |
838 | my $options=<STDIN>; | |
839 | chomp $options; | |
840 | if ($options eq "never") { | |
841 | $opt_ask_target_options=$OPT_ASK_NO; | |
842 | last; | |
843 | } elsif (source_set_options($target,$options)) { | |
844 | last; | |
845 | } | |
846 | print "Please re-enter the options:\n"; | |
755bb92e FG |
847 | } |
848 | } | |
849 | if (@$target[$T_FLAGS] & $TF_MFC) { | |
850 | @$project_settings[$T_FLAGS]|=$TF_MFC; | |
89a0c02b FG |
851 | push @{@$target[$T_DLL_PATH]},"\$(MFC_LIBRARY_PATH)"; |
852 | push @{@$target[$T_DLLS]},"mfc.dll"; | |
7cae558b | 853 | # FIXME: Link with the MFC in the Unix sense, until we |
be859592 | 854 | # start exporting the functions properly. |
89a0c02b | 855 | push @{@$target[$T_LIBRARY_PATH]},"\$(MFC_LIBRARY_PATH)"; |
be859592 | 856 | push @{@$target[$T_LIBRARIES]},"mfc"; |
755bb92e FG |
857 | } |
858 | ||
859 | # Match sources... | |
860 | if ($target_count == 1) { | |
4ec10596 FG |
861 | push @{@$target[$T_SOURCES_C]},@{@$project_settings[$T_SOURCES_C]},@sources_c; |
862 | @$project_settings[$T_SOURCES_C]=[]; | |
755bb92e | 863 | @sources_c=(); |
4ec10596 FG |
864 | |
865 | push @{@$target[$T_SOURCES_CXX]},@{@$project_settings[$T_SOURCES_CXX]},@sources_cxx; | |
866 | @$project_settings[$T_SOURCES_CXX]=[]; | |
755bb92e | 867 | @sources_cxx=(); |
4ec10596 FG |
868 | |
869 | push @{@$target[$T_SOURCES_RC]},@{@$project_settings[$T_SOURCES_RC]},@sources_rc; | |
870 | @$project_settings[$T_SOURCES_RC]=[]; | |
755bb92e | 871 | @sources_rc=(); |
4ec10596 FG |
872 | |
873 | push @{@$target[$T_SOURCES_MISC]},@{@$project_settings[$T_SOURCES_MISC]},@sources_misc; | |
874 | # No need for sorting these sources | |
875 | @$project_settings[$T_SOURCES_MISC]=[]; | |
755bb92e FG |
876 | @sources_misc=(); |
877 | } else { | |
e3d26a3e | 878 | foreach my $source (@sources_c) { |
755bb92e FG |
879 | if ($source =~ /^$basename/i) { |
880 | push @{@$target[$T_SOURCES_C]},$source; | |
881 | $source=""; | |
882 | } | |
883 | } | |
e3d26a3e | 884 | foreach my $source (@sources_cxx) { |
755bb92e FG |
885 | if ($source =~ /^$basename/i) { |
886 | push @{@$target[$T_SOURCES_CXX]},$source; | |
887 | $source=""; | |
888 | } | |
889 | } | |
e3d26a3e | 890 | foreach my $source (@sources_rc) { |
755bb92e FG |
891 | if ($source =~ /^$basename/i) { |
892 | push @{@$target[$T_SOURCES_RC]},$source; | |
893 | $source=""; | |
894 | } | |
895 | } | |
e3d26a3e | 896 | foreach my $source (@sources_misc) { |
755bb92e FG |
897 | if ($source =~ /^$basename/i) { |
898 | push @{@$target[$T_SOURCES_MISC]},$source; | |
899 | $source=""; | |
900 | } | |
901 | } | |
902 | } | |
903 | @$target[$T_SOURCES_C]=[sort @{@$target[$T_SOURCES_C]}]; | |
904 | @$target[$T_SOURCES_CXX]=[sort @{@$target[$T_SOURCES_CXX]}]; | |
905 | @$target[$T_SOURCES_RC]=[sort @{@$target[$T_SOURCES_RC]}]; | |
906 | @$target[$T_SOURCES_MISC]=[sort @{@$target[$T_SOURCES_MISC]}]; | |
907 | } | |
908 | if ($opt_ask_target_options == $OPT_ASK_SKIP) { | |
909 | $opt_ask_target_options=$OPT_ASK_YES; | |
910 | } | |
911 | ||
905658c4 | 912 | if ((@$project_settings[$T_FLAGS] & $TF_NOMSVCRT) == 0) { |
c7201ce3 FG |
913 | push @{@$project_settings[$T_CEXTRA]},"-mno-cygwin"; |
914 | push @{@$project_settings[$T_CXXEXTRA]},"-mno-cygwin"; | |
905658c4 DP |
915 | } |
916 | ||
755bb92e FG |
917 | if (@$project_settings[$T_FLAGS] & $TF_MFC) { |
918 | push @{@$project_settings[$T_INCLUDE_PATH]},"\$(MFC_INCLUDE_PATH)"; | |
919 | } | |
7cae558b | 920 | # The sources that did not match, if any, go to the extra |
755bb92e | 921 | # source list of the project settings |
e3d26a3e | 922 | foreach my $source (@sources_c) { |
755bb92e FG |
923 | if ($source ne "") { |
924 | push @{@$project_settings[$T_SOURCES_C]},$source; | |
925 | } | |
926 | } | |
927 | @$project_settings[$T_SOURCES_C]=[sort @{@$project_settings[$T_SOURCES_C]}]; | |
e3d26a3e | 928 | foreach my $source (@sources_cxx) { |
755bb92e FG |
929 | if ($source ne "") { |
930 | push @{@$project_settings[$T_SOURCES_CXX]},$source; | |
931 | } | |
932 | } | |
933 | @$project_settings[$T_SOURCES_CXX]=[sort @{@$project_settings[$T_SOURCES_CXX]}]; | |
e3d26a3e | 934 | foreach my $source (@sources_rc) { |
755bb92e FG |
935 | if ($source ne "") { |
936 | push @{@$project_settings[$T_SOURCES_RC]},$source; | |
937 | } | |
938 | } | |
939 | @$project_settings[$T_SOURCES_RC]=[sort @{@$project_settings[$T_SOURCES_RC]}]; | |
e3d26a3e | 940 | foreach my $source (@sources_misc) { |
755bb92e FG |
941 | if ($source ne "") { |
942 | push @{@$project_settings[$T_SOURCES_MISC]},$source; | |
943 | } | |
944 | } | |
945 | @$project_settings[$T_SOURCES_MISC]=[sort @{@$project_settings[$T_SOURCES_MISC]}]; | |
946 | ||
7cae558b AJ |
947 | # Finally if we are building both libraries and programs in |
948 | # this directory, then the programs should be linked with all | |
755bb92e | 949 | # the libraries |
89a0c02b | 950 | if (@local_dlls > 0 and @exe_list > 0) { |
e3d26a3e | 951 | foreach my $target (@exe_list) { |
89a0c02b | 952 | push @{@$target[$T_DLL_PATH]},"-L."; |
635eb3c2 | 953 | push @{@$target[$T_DLLS]},@local_dlls; |
755bb92e FG |
954 | } |
955 | } | |
956 | } | |
957 | ||
958 | ## | |
959 | # Scan the source directories in search of things to build | |
e3d26a3e | 960 | sub source_scan() |
755bb92e | 961 | { |
755bb92e FG |
962 | # If there's a single target then this is going to be the default target |
963 | if (defined $opt_single_target) { | |
38b3ac59 FG |
964 | # Create the main target |
965 | my $main_target=[]; | |
966 | target_init($main_target); | |
635eb3c2 | 967 | @$main_target[$T_NAME]=$opt_single_target; |
755bb92e | 968 | @$main_target[$T_TYPE]=$opt_target_type; |
38b3ac59 FG |
969 | |
970 | # Add it to the list | |
971 | push @{$main_project[$P_TARGETS]},$main_target; | |
755bb92e FG |
972 | } |
973 | ||
974 | # The main directory is always going to be there | |
975 | push @projects,\@main_project; | |
976 | ||
977 | # Now scan the directory tree looking for source files and, maybe, targets | |
978 | print "Scanning the source directories...\n"; | |
3266b887 | 979 | source_scan_directory(\@main_project,"","",0); |
755bb92e FG |
980 | |
981 | @projects=sort { @$a[$P_PATH] cmp @$b[$P_PATH] } @projects; | |
982 | } | |
983 | ||
755bb92e FG |
984 | ##### |
985 | # | |
986 | # Source search | |
987 | # | |
988 | ##### | |
989 | ||
990 | ## | |
991 | # Performs a directory traversal and renames the files so that: | |
992 | # - they have the case desired by the user | |
993 | # - their extension is of the appropriate case | |
994 | # - they don't contain annoying characters like ' ', '$', '#', ... | |
a6eecca9 | 995 | # But only perform these changes for source files and directories. |
e3d26a3e FG |
996 | sub fix_file_and_directory_names($); |
997 | sub fix_file_and_directory_names($) | |
755bb92e FG |
998 | { |
999 | my $dirname=$_[0]; | |
1000 | ||
1001 | if (opendir(DIRECTORY, "$dirname")) { | |
e3d26a3e | 1002 | foreach my $dentry (readdir DIRECTORY) { |
755bb92e FG |
1003 | if ($dentry =~ /^\./ or $dentry eq "CVS") { |
1004 | next; | |
1005 | } | |
1006 | # Set $warn to 1 if the user should be warned of the renaming | |
a6eecca9 | 1007 | my $warn; |
755bb92e | 1008 | my $new_name=$dentry; |
755bb92e | 1009 | |
a6eecca9 FG |
1010 | if (-f "$dirname/$dentry") |
1011 | { | |
1012 | # Don't rename Winemaker's makefiles | |
1013 | next if ($dentry eq "Makefile" and | |
1014 | `head -n 1 "$dirname/$dentry"` =~ /Generated by Winemaker/); | |
1015 | ||
1016 | # Leave non-source files alone | |
1017 | next if ($new_name !~ /(^makefile|\.(c|cpp|h|rc))$/i); | |
1018 | ||
1019 | # Only all lowercase extensions are supported (because of | |
1020 | # rules like '.c.o:'. | |
1021 | $new_name =~ s/\.C$/.c/; | |
1022 | $new_name =~ s/\.cpp$/.cpp/i; | |
1023 | $warn=1 if ($new_name =~ s/\.cxx$/.cpp/i); | |
1024 | $new_name =~ s/\.rc$/.rc/i; | |
755bb92e | 1025 | # And this last one is to avoid confusion then running make |
a6eecca9 | 1026 | $warn=1 if ($new_name =~ s/^makefile$/makefile.win/i); |
755bb92e FG |
1027 | } |
1028 | ||
1029 | # Adjust the case to the user's preferences | |
7cae558b | 1030 | if (($opt_lower == $OPT_LOWER_ALL and $dentry =~ /[A-Z]/) or |
755bb92e FG |
1031 | ($opt_lower == $OPT_LOWER_UPPERCASE and $dentry !~ /[a-z]/) |
1032 | ) { | |
a6eecca9 | 1033 | $new_name=lc $new_name; |
755bb92e FG |
1034 | } |
1035 | ||
a6eecca9 FG |
1036 | # autoconf and make don't support these characters well |
1037 | $new_name =~ s/[ \$]/_/g; | |
1038 | ||
755bb92e FG |
1039 | # And finally, perform the renaming |
1040 | if ($new_name ne $dentry) { | |
1041 | if ($warn) { | |
1042 | print STDERR "warning: in \"$dirname\", renaming \"$dentry\" to \"$new_name\"\n"; | |
1043 | } | |
1044 | if (!rename("$dirname/$dentry","$dirname/$new_name")) { | |
1045 | print STDERR "error: in \"$dirname\", unable to rename \"$dentry\" to \"$new_name\"\n"; | |
1046 | print STDERR " $!\n"; | |
1047 | $new_name=$dentry; | |
1048 | } | |
1049 | } | |
1050 | if (-d "$dirname/$new_name") { | |
1051 | fix_file_and_directory_names("$dirname/$new_name"); | |
1052 | } | |
1053 | } | |
1054 | closedir(DIRECTORY); | |
1055 | } | |
1056 | } | |
1057 | ||
1058 | ||
1059 | ||
1060 | ##### | |
1061 | # | |
1062 | # Source fixup | |
1063 | # | |
1064 | ##### | |
1065 | ||
755bb92e | 1066 | ## |
7cae558b AJ |
1067 | # Try to find a file for the specified filename. The attempt is |
1068 | # case-insensitive which is why it's not trivial. If a match is | |
755bb92e | 1069 | # found then we return the pathname with the correct case. |
e3d26a3e | 1070 | sub search_from($$) |
755bb92e FG |
1071 | { |
1072 | my $dirname=$_[0]; | |
1073 | my $path=$_[1]; | |
1074 | my $real_path=""; | |
1075 | ||
1076 | if ($dirname eq "" or $dirname eq ".") { | |
1077 | $dirname=cwd; | |
a286c202 | 1078 | } elsif ($dirname !~ m+^/+) { |
755bb92e FG |
1079 | $dirname=cwd . "/" . $dirname; |
1080 | } | |
1081 | if ($dirname !~ m+/$+) { | |
1082 | $dirname.="/"; | |
1083 | } | |
1084 | ||
e3d26a3e | 1085 | foreach my $component (@$path) { |
b430295c | 1086 | #print " looking for $component in \"$dirname\"\n"; |
755bb92e FG |
1087 | if ($component eq ".") { |
1088 | # Pass it as is | |
1089 | $real_path.="./"; | |
1090 | } elsif ($component eq "..") { | |
1091 | # Go up one level | |
1092 | $dirname=dirname($dirname) . "/"; | |
1093 | $real_path.="../"; | |
1094 | } else { | |
7cae558b | 1095 | # The file/directory may have been renamed before. Also try to |
3fafafa9 FG |
1096 | # match the renamed file. |
1097 | my $renamed=$component; | |
1098 | $renamed =~ s/[ \$]/_/g; | |
1099 | if ($renamed eq $component) { | |
1100 | undef $renamed; | |
1101 | } | |
1102 | ||
755bb92e FG |
1103 | my $directory=get_directory_contents $dirname; |
1104 | my $found; | |
e3d26a3e | 1105 | foreach my $dentry (@$directory) { |
3fafafa9 FG |
1106 | if ($dentry =~ /^$component$/i or |
1107 | (defined $renamed and $dentry =~ /^$renamed$/i) | |
1108 | ) { | |
755bb92e FG |
1109 | $dirname.="$dentry/"; |
1110 | $real_path.="$dentry/"; | |
1111 | $found=1; | |
1112 | last; | |
1113 | } | |
1114 | } | |
1115 | if (!defined $found) { | |
1116 | # Give up | |
b430295c | 1117 | #print " could not find $component in $dirname\n"; |
755bb92e FG |
1118 | return; |
1119 | } | |
1120 | } | |
1121 | } | |
1122 | $real_path=~ s+/$++; | |
b430295c | 1123 | #print " -> found $real_path\n"; |
755bb92e FG |
1124 | return $real_path; |
1125 | } | |
1126 | ||
1127 | ## | |
7cae558b | 1128 | # Performs a case-insensitive search for the specified file in the |
755bb92e FG |
1129 | # include path. |
1130 | # $line is the line number that should be referenced when an error occurs | |
1131 | # $filename is the file we are looking for | |
1132 | # $dirname is the directory of the file containing the '#include' directive | |
1133 | # if '"' was used, it is an empty string otherwise | |
1134 | # $project and $target specify part of the include path | |
e3d26a3e | 1135 | sub get_real_include_name($$$$$) |
755bb92e FG |
1136 | { |
1137 | my $line=$_[0]; | |
1138 | my $filename=$_[1]; | |
1139 | my $dirname=$_[2]; | |
1140 | my $project=$_[3]; | |
1141 | my $target=$_[4]; | |
1142 | ||
1143 | if ($filename =~ /^([a-zA-Z]:)?[\/]/ or $filename =~ /^[a-zA-Z]:[\/]?/) { | |
1144 | # This is not a relative path, we cannot make any check | |
1145 | my $warning="path:$filename"; | |
1146 | if (!defined $warnings{$warning}) { | |
1147 | $warnings{$warning}="1"; | |
1148 | print STDERR "warning: cannot check the case of absolute pathnames:\n"; | |
1149 | print STDERR "$line: $filename\n"; | |
1150 | } | |
1151 | } else { | |
1152 | # Here's how we proceed: | |
1153 | # - split the filename we look for into its components | |
1154 | # - then for each directory in the include path | |
1155 | # - trace the directory components starting from that directory | |
7cae558b | 1156 | # - if we fail to find a match at any point then continue with |
755bb92e FG |
1157 | # the next directory in the include path |
1158 | # - otherwise, rejoice, our quest is over. | |
1159 | my @file_components=split /[\/\\]+/, $filename; | |
b430295c | 1160 | #print " Searching for $filename from @$project[$P_PATH]\n"; |
755bb92e FG |
1161 | |
1162 | my $real_filename; | |
1163 | if ($dirname ne "") { | |
b430295c FG |
1164 | # This is an 'include ""' -> look in dirname first. |
1165 | #print " in $dirname (include \"\")\n"; | |
755bb92e FG |
1166 | $real_filename=search_from($dirname,\@file_components); |
1167 | if (defined $real_filename) { | |
1168 | return $real_filename; | |
1169 | } | |
1170 | } | |
1171 | my $project_settings=@$project[$P_SETTINGS]; | |
e3d26a3e | 1172 | foreach my $include (@{@$target[$T_INCLUDE_PATH]}, @{@$project_settings[$T_INCLUDE_PATH]}) { |
b430295c FG |
1173 | my $dirname=$include; |
1174 | $dirname=~ s+^-I++; | |
1175 | if (!is_absolute($dirname)) { | |
1176 | $dirname="@$project[$P_PATH]$dirname"; | |
1177 | } else { | |
647bb8f0 FG |
1178 | $dirname=~ s+^\$\(TOPSRCDIR\)/++; |
1179 | $dirname=~ s+^\$\(SRCDIR\)/+@$project[$P_PATH]+; | |
b430295c FG |
1180 | } |
1181 | #print " in $dirname\n"; | |
755bb92e FG |
1182 | $real_filename=search_from("$dirname",\@file_components); |
1183 | if (defined $real_filename) { | |
1184 | return $real_filename; | |
1185 | } | |
1186 | } | |
1187 | my $dotdotpath=@$project[$P_PATH]; | |
1188 | $dotdotpath =~ s/[^\/]+/../g; | |
e3d26a3e | 1189 | foreach my $include (@{$global_settings[$T_INCLUDE_PATH]}) { |
b430295c FG |
1190 | my $dirname=$include; |
1191 | $dirname=~ s+^-I++; | |
1192 | $dirname=~ s+^\$\(TOPSRCDIR\)\/++; | |
647bb8f0 | 1193 | $dirname=~ s+^\$\(SRCDIR\)\/+@$project[$P_PATH]+; |
b430295c | 1194 | #print " in $dirname (global setting)\n"; |
755bb92e FG |
1195 | $real_filename=search_from("$dirname",\@file_components); |
1196 | if (defined $real_filename) { | |
1197 | return $real_filename; | |
1198 | } | |
1199 | } | |
1200 | } | |
1201 | $filename =~ s+\\\\+/+g; # in include "" | |
1202 | $filename =~ s+\\+/+g; # in include <> ! | |
a106edb7 | 1203 | if ($opt_lower_include) { |
755bb92e FG |
1204 | return lc "$filename"; |
1205 | } | |
1206 | return $filename; | |
1207 | } | |
1208 | ||
e3d26a3e | 1209 | sub print_pack($$$) |
c1159bed FG |
1210 | { |
1211 | my $indent=$_[0]; | |
1212 | my $size=$_[1]; | |
1213 | my $trailer=$_[2]; | |
1214 | ||
1215 | if ($size =~ /^(1|2|4|8)$/) { | |
1216 | print FILEO "$indent#include <pshpack$size.h>$trailer"; | |
1217 | } else { | |
1218 | print FILEO "$indent/* winemaker:warning: Unknown size \"$size\". Defaulting to 4 */\n"; | |
1219 | print FILEO "$indent#include <pshpack4.h>$trailer"; | |
1220 | } | |
1221 | } | |
1222 | ||
755bb92e | 1223 | ## |
7cae558b AJ |
1224 | # 'Parses' a source file and fixes constructs that would not work with |
1225 | # Winelib. The parsing is rather simple and not all non-portable features | |
1226 | # are corrected. The most important feature that is corrected is the case | |
1227 | # and path separator of '#include' directives. This requires that each | |
1228 | # source file be associated to a project & target so that the proper | |
755bb92e | 1229 | # include path is used. |
7cae558b | 1230 | # Also note that the include path is relative to the directory in which the |
b430295c | 1231 | # compiler is run, i.e. that of the project, not to that of the file. |
e3d26a3e | 1232 | sub fix_file($$$) |
755bb92e FG |
1233 | { |
1234 | my $filename=$_[0]; | |
1235 | my $project=$_[1]; | |
1236 | my $target=$_[2]; | |
1237 | $filename="@$project[$P_PATH]$filename"; | |
1238 | if (! -e $filename) { | |
1239 | return; | |
1240 | } | |
1241 | ||
1242 | my $is_rc=($filename =~ /\.(rc2?|dlg)$/i); | |
1243 | my $dirname=dirname($filename); | |
1244 | my $is_mfc=0; | |
1245 | if (defined $target and (@$target[$T_FLAGS] & $TF_MFC)) { | |
1246 | $is_mfc=1; | |
1247 | } | |
1248 | ||
1249 | print " $filename\n"; | |
7cae558b | 1250 | #FIXME:assuming that because there is a .bak file, this is what we want is |
755bb92e FG |
1251 | #probably flawed. Or is it??? |
1252 | if (! -e "$filename.bak") { | |
1253 | if (!copy("$filename","$filename.bak")) { | |
1254 | print STDERR "error: unable to make a backup of $filename:\n"; | |
1255 | print STDERR " $!\n"; | |
1256 | return; | |
1257 | } | |
1258 | } | |
1259 | if (!open(FILEI,"$filename.bak")) { | |
1260 | print STDERR "error: unable to open $filename.bak for reading:\n"; | |
1261 | print STDERR " $!\n"; | |
1262 | return; | |
1263 | } | |
1264 | if (!open(FILEO,">$filename")) { | |
1265 | print STDERR "error: unable to open $filename for writing:\n"; | |
1266 | print STDERR " $!\n"; | |
1267 | return; | |
1268 | } | |
1269 | my $line=0; | |
1270 | my $modified=0; | |
1271 | my $rc_block_depth=0; | |
1272 | my $rc_textinclude_state=0; | |
c1159bed | 1273 | my @pack_stack; |
755bb92e | 1274 | while (<FILEI>) { |
987ea468 BM |
1275 | # Remove any trailing CtrlZ, which isn't strictly in the file |
1276 | if (/\x1A/) { | |
1277 | s/\x1A//; | |
1278 | last if (/^$/) | |
1279 | } | |
755bb92e | 1280 | $line++; |
a62703e6 FG |
1281 | s/\r\n$/\n/; |
1282 | if (!/\n$/) { | |
1283 | # Make sure all files are '\n' terminated | |
1284 | $_ .= "\n"; | |
1285 | } | |
c1159bed | 1286 | if ($is_rc and !$is_mfc and /^(\s*)(\#\s*include\s*)\"afxres\.h\"/) { |
7cae558b AJ |
1287 | # VC6 automatically includes 'afxres.h', an MFC specific header, in |
1288 | # the RC files it generates (even in non-MFC projects). So we replace | |
1289 | # it with 'winres.h' its very close standard cousin so that non MFC | |
a62703e6 | 1290 | # projects can compile in Wine without the MFC sources. |
755bb92e FG |
1291 | my $warning="mfc:afxres.h"; |
1292 | if (!defined $warnings{$warning}) { | |
1293 | $warnings{$warning}="1"; | |
1294 | print STDERR "warning: In non-MFC projects, winemaker replaces the MFC specific header 'afxres.h' with 'winres.h'\n"; | |
1295 | print STDERR "warning: the above warning is issued only once\n"; | |
1296 | } | |
c1159bed FG |
1297 | print FILEO "$1/* winemaker: $2\"afxres.h\" */\n"; |
1298 | print FILEO "$1/* winemaker:warning: 'afxres.h' is an MFC specific header. Replacing it with 'winres.h' */\n"; | |
1299 | print FILEO "$1$2\"winres.h\"$'"; | |
755bb92e | 1300 | $modified=1; |
c1159bed | 1301 | |
755bb92e FG |
1302 | } elsif (/^(\s*\#\s*include\s*)([\"<])([^\"]+)([\">])/) { |
1303 | my $from_file=($2 eq "<"?"":$dirname); | |
1304 | my $real_include_name=get_real_include_name($line,$3,$from_file,$project,$target); | |
1305 | print FILEO "$1$2$real_include_name$4$'"; | |
1306 | $modified|=($real_include_name ne $3); | |
c1159bed FG |
1307 | |
1308 | } elsif (s/^(\s*)(\#\s*pragma\s+pack\s*\(\s*)//) { | |
1309 | # Pragma pack handling | |
1310 | # | |
7cae558b AJ |
1311 | # pack_stack is an array of references describing the stack of |
1312 | # pack directives currently in effect. Each directive if described | |
c1159bed FG |
1313 | # by a reference to an array containing: |
1314 | # - "push" for pack(push,...) directives, "" otherwise | |
1315 | # - the directive's identifier at index 1 | |
42a61d7e | 1316 | # - the directive's alignment value at index 2 |
c1159bed FG |
1317 | # |
1318 | # Don't believe a word of what the documentation says: it's all wrong. | |
1319 | # The code below is based on the actual behavior of Visual C/C++ 6. | |
1320 | my $pack_indent=$1; | |
1321 | my $pack_header=$2; | |
1322 | if (/^(\))/) { | |
1323 | # pragma pack() | |
1324 | # Pushes the default stack alignment | |
1325 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1326 | print FILEO "$pack_indent/* winemaker:warning: Using 4 as the default alignment */\n"; | |
1327 | print_pack($pack_indent,4,$'); | |
1328 | push @pack_stack, [ "", "", 4 ]; | |
1329 | ||
1330 | } elsif (/^(pop\s*(,\s*\d+\s*)?\))/) { | |
1331 | # pragma pack(pop) | |
1332 | # pragma pack(pop,n) | |
1333 | # Goes up the stack until it finds a pack(push,...), and pops it | |
1334 | # Ignores any pack(n) entry | |
1335 | # Issues a warning if the pack is of the form pack(push,label) | |
1336 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1337 | my $pack_comment=$'; | |
647bb8f0 | 1338 | $pack_comment =~ s/^\s*//; |
c1159bed FG |
1339 | if ($pack_comment ne "") { |
1340 | print FILEO "$pack_indent$pack_comment"; | |
1341 | } | |
1342 | while (1) { | |
1343 | my $alignment=pop @pack_stack; | |
1344 | if (!defined $alignment) { | |
1345 | print FILEO "$pack_indent/* winemaker:warning: No pack(push,...) found. All the stack has been popped */\n"; | |
1346 | last; | |
1347 | } | |
1348 | if (@$alignment[1]) { | |
1349 | print FILEO "$pack_indent/* winemaker:warning: Anonymous pop of pack(push,@$alignment[1]) (@$alignment[2]) */\n"; | |
1350 | } | |
1351 | print FILEO "$pack_indent#include <poppack.h>\n"; | |
1352 | if (@$alignment[0]) { | |
1353 | last; | |
1354 | } | |
1355 | } | |
1356 | ||
1357 | } elsif (/^(pop\s*,\s*(\w+)\s*(,\s*\d+\s*)?\))/) { | |
1358 | # pragma pack(pop,label[,n]) | |
1359 | # Goes up the stack until finding a pack(push,...) and pops it. | |
1360 | # 'n', if specified, is ignored. | |
1361 | # Ignores any pack(n) entry | |
1362 | # Issues a warning if the label of the pack does not match, | |
1363 | # or if it is in fact a pack(push,n) | |
1364 | my $label=$2; | |
1365 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1366 | my $pack_comment=$'; | |
647bb8f0 | 1367 | $pack_comment =~ s/^\s*//; |
c1159bed FG |
1368 | if ($pack_comment ne "") { |
1369 | print FILEO "$pack_indent$pack_comment"; | |
1370 | } | |
1371 | while (1) { | |
1372 | my $alignment=pop @pack_stack; | |
1373 | if (!defined $alignment) { | |
1374 | print FILEO "$pack_indent/* winemaker:warning: No pack(push,$label) found. All the stack has been popped */\n"; | |
1375 | last; | |
1376 | } | |
1377 | if (@$alignment[1] and @$alignment[1] ne $label) { | |
1378 | print FILEO "$pack_indent/* winemaker:warning: Push/pop mismatch: \"@$alignment[1]\" (@$alignment[2]) != \"$label\" */\n"; | |
1379 | } | |
1380 | print FILEO "$pack_indent#include <poppack.h>\n"; | |
1381 | if (@$alignment[0]) { | |
1382 | last; | |
1383 | } | |
1384 | } | |
1385 | ||
1386 | } elsif (/^(push\s*\))/) { | |
1387 | # pragma pack(push) | |
1388 | # Push the current alignment | |
1389 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1390 | if (@pack_stack > 0) { | |
1391 | my $alignment=$pack_stack[$#pack_stack]; | |
1392 | print_pack($pack_indent,@$alignment[2],$'); | |
1393 | push @pack_stack, [ "push", "", @$alignment[2] ]; | |
1394 | } else { | |
1395 | print FILEO "$pack_indent/* winemaker:warning: Using 4 as the default alignment */\n"; | |
1396 | print_pack($pack_indent,4,$'); | |
1397 | push @pack_stack, [ "push", "", 4 ]; | |
1398 | } | |
1399 | ||
1400 | } elsif (/^((push\s*,\s*)?(\d+)\s*\))/) { | |
1401 | # pragma pack([push,]n) | |
1402 | # Push new alignment n | |
1403 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1404 | print_pack($pack_indent,$3,"$'"); | |
1405 | push @pack_stack, [ ($2 ? "push" : ""), "", $3 ]; | |
1406 | ||
1407 | } elsif (/^((\w+)\s*\))/) { | |
1408 | # pragma pack(label) | |
1409 | # label must in fact be a macro that resolves to an integer | |
1410 | # Then behaves like 'pragma pack(n)' | |
1411 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1412 | print FILEO "$pack_indent/* winemaker:warning: Assuming $2 == 4 */\n"; | |
1413 | print_pack($pack_indent,4,$'); | |
1414 | push @pack_stack, [ "", "", 4 ]; | |
1415 | ||
1416 | } elsif (/^(push\s*,\s*(\w+)\s*(,\s*(\d+)\s*)?\))/) { | |
1417 | # pragma pack(push,label[,n]) | |
1418 | # Pushes a new label on the stack. It is possible to push the same | |
7cae558b | 1419 | # label multiple times. If 'n' is omitted then the alignment is |
c1159bed FG |
1420 | # unchanged. Otherwise it becomes 'n'. |
1421 | print FILEO "$pack_indent/* winemaker: $pack_header$1 */\n"; | |
1422 | my $size; | |
1423 | if (defined $4) { | |
1424 | $size=$4; | |
1425 | } elsif (@pack_stack > 0) { | |
1426 | my $alignment=$pack_stack[$#pack_stack]; | |
1427 | $size=@$alignment[2]; | |
1428 | } else { | |
1429 | print FILEO "$pack_indent/* winemaker:warning: Using 4 as the default alignment */\n"; | |
1430 | $size=4; | |
1431 | } | |
1432 | print_pack($pack_indent,$size,$'); | |
1433 | push @pack_stack, [ "push", $2, $size ]; | |
1434 | ||
755bb92e | 1435 | } else { |
c1159bed FG |
1436 | # pragma pack(??? -> What's that? |
1437 | print FILEO "$pack_indent/* winemaker:warning: Unknown type of pragma pack directive */\n"; | |
1438 | print FILEO "$pack_indent$pack_header$_"; | |
1439 | ||
755bb92e | 1440 | } |
c1159bed FG |
1441 | $modified=1; |
1442 | ||
755bb92e | 1443 | } elsif ($is_rc) { |
647bb8f0 | 1444 | if ($rc_block_depth == 0 and /^(\w+\s+(BITMAP|CURSOR|FONT|FONTDIR|ICON|MESSAGETABLE|TEXT|RTF)\s+((DISCARDABLE|FIXED|IMPURE|LOADONCALL|MOVEABLE|PRELOAD|PURE)\s+)*)([\"<]?)([^\">\r\n]+)([\">]?)/) { |
755bb92e FG |
1445 | my $from_file=($5 eq "<"?"":$dirname); |
1446 | my $real_include_name=get_real_include_name($line,$6,$from_file,$project,$target); | |
1447 | print FILEO "$1$5$real_include_name$7$'"; | |
1448 | $modified|=($real_include_name ne $6); | |
c1159bed | 1449 | |
755bb92e FG |
1450 | } elsif (/^(\s*RCINCLUDE\s*)([\"<]?)([^\">\r\n]+)([\">]?)/) { |
1451 | my $from_file=($2 eq "<"?"":$dirname); | |
1452 | my $real_include_name=get_real_include_name($line,$3,$from_file,$project,$target); | |
1453 | print FILEO "$1$2$real_include_name$4$'"; | |
1454 | $modified|=($real_include_name ne $3); | |
c1159bed | 1455 | |
755bb92e FG |
1456 | } elsif ($is_rc and !$is_mfc and $rc_block_depth == 0 and /^\s*\d+\s+TEXTINCLUDE\s*/) { |
1457 | $rc_textinclude_state=1; | |
1458 | print FILEO; | |
c1159bed | 1459 | |
755bb92e FG |
1460 | } elsif ($rc_textinclude_state == 3 and /^(\s*\"\#\s*include\s*\"\")afxres\.h(\"\"\\r\\n\")/) { |
1461 | print FILEO "$1winres.h$2$'"; | |
1462 | $modified=1; | |
c1159bed | 1463 | |
755bb92e FG |
1464 | } elsif (/^\s*BEGIN(\W.*)?$/) { |
1465 | $rc_textinclude_state|=2; | |
1466 | $rc_block_depth++; | |
1467 | print FILEO; | |
c1159bed | 1468 | |
755bb92e FG |
1469 | } elsif (/^\s*END(\W.*)?$/) { |
1470 | $rc_textinclude_state=0; | |
1471 | if ($rc_block_depth>0) { | |
1472 | $rc_block_depth--; | |
1473 | } | |
1474 | print FILEO; | |
c1159bed | 1475 | |
755bb92e FG |
1476 | } else { |
1477 | print FILEO; | |
1478 | } | |
c1159bed | 1479 | |
755bb92e FG |
1480 | } else { |
1481 | print FILEO; | |
1482 | } | |
1483 | } | |
c1159bed | 1484 | |
755bb92e FG |
1485 | close(FILEI); |
1486 | close(FILEO); | |
1487 | if ($opt_backup == 0 or $modified == 0) { | |
1488 | if (!unlink("$filename.bak")) { | |
1489 | print STDERR "error: unable to delete $filename.bak:\n"; | |
1490 | print STDERR " $!\n"; | |
1491 | } | |
1492 | } | |
1493 | } | |
1494 | ||
1495 | ## | |
7cae558b | 1496 | # Analyzes each source file in turn to find and correct issues |
755bb92e | 1497 | # that would cause it not to compile. |
e3d26a3e | 1498 | sub fix_source() |
755bb92e FG |
1499 | { |
1500 | print "Fixing the source files...\n"; | |
e3d26a3e FG |
1501 | foreach my $project (@projects) { |
1502 | foreach my $target (@$project[$P_SETTINGS],@{@$project[$P_TARGETS]}) { | |
e3d26a3e | 1503 | foreach my $source (@{@$target[$T_SOURCES_C]}, @{@$target[$T_SOURCES_CXX]}, @{@$target[$T_SOURCES_RC]}, @{@$target[$T_SOURCES_MISC]}) { |
755bb92e FG |
1504 | fix_file($source,$project,$target); |
1505 | } | |
1506 | } | |
1507 | } | |
1508 | } | |
1509 | ||
1510 | ||
1511 | ||
1512 | ##### | |
1513 | # | |
1514 | # File generation | |
1515 | # | |
1516 | ##### | |
1517 | ||
755bb92e | 1518 | ## |
7cae558b | 1519 | # A convenience function to generate all the lists (defines, |
755bb92e | 1520 | # C sources, C++ source, etc.) in the Makefile |
e3d26a3e | 1521 | sub generate_list($$$;$) |
755bb92e FG |
1522 | { |
1523 | my $name=$_[0]; | |
1524 | my $last=$_[1]; | |
1525 | my $list=$_[2]; | |
1526 | my $data=$_[3]; | |
82747b7d | 1527 | my $first=$name; |
755bb92e FG |
1528 | |
1529 | if ($name) { | |
fb5b590e | 1530 | printf FILEO "%-22s=",$name; |
755bb92e | 1531 | } |
82747b7d | 1532 | if (defined $list) { |
e3d26a3e | 1533 | foreach my $item (@$list) { |
755bb92e FG |
1534 | my $value; |
1535 | if (defined $data) { | |
1536 | $value=&$data($item); | |
1537 | } else { | |
1538 | $value=$item; | |
1539 | } | |
1540 | if ($value ne "") { | |
82747b7d FG |
1541 | if ($first) { |
1542 | print FILEO " $value"; | |
1543 | $first=0; | |
1544 | } else { | |
1545 | print FILEO " \\\n\t\t\t$value"; | |
1546 | } | |
755bb92e FG |
1547 | } |
1548 | } | |
1549 | } | |
1550 | if ($last) { | |
82747b7d | 1551 | print FILEO "\n"; |
755bb92e FG |
1552 | } |
1553 | } | |
1554 | ||
1555 | ## | |
a286c202 | 1556 | # Generates a project's Makefile and all the target files |
e3d26a3e | 1557 | sub generate_project_files($) |
755bb92e FG |
1558 | { |
1559 | my $project=$_[0]; | |
1560 | my $project_settings=@$project[$P_SETTINGS]; | |
be859592 FG |
1561 | my @dll_list=(); |
1562 | my @exe_list=(); | |
755bb92e FG |
1563 | |
1564 | # Then sort the targets and separate the libraries from the programs | |
e3d26a3e | 1565 | foreach my $target (sort { @$a[$T_NAME] cmp @$b[$T_NAME] } @{@$project[$P_TARGETS]}) { |
755bb92e | 1566 | if (@$target[$T_TYPE] == $TT_DLL) { |
be859592 | 1567 | push @dll_list,$target; |
755bb92e | 1568 | } else { |
be859592 | 1569 | push @exe_list,$target; |
755bb92e FG |
1570 | } |
1571 | } | |
1572 | @$project[$P_TARGETS]=[]; | |
be859592 FG |
1573 | push @{@$project[$P_TARGETS]}, @dll_list; |
1574 | push @{@$project[$P_TARGETS]}, @exe_list; | |
755bb92e | 1575 | |
905658c4 DP |
1576 | if (!open(FILEO,">@$project[$P_PATH]Makefile")) { |
1577 | print STDERR "error: could not open \"@$project[$P_PATH]/Makefile\" for writing\n"; | |
755bb92e FG |
1578 | print STDERR " $!\n"; |
1579 | return; | |
1580 | } | |
1581 | ||
be859592 FG |
1582 | print FILEO "### Generated by Winemaker\n"; |
1583 | print FILEO "\n\n"; | |
1584 | ||
905658c4 | 1585 | generate_list("SRCDIR",1,[ "." ]); |
755bb92e | 1586 | if (@$project[$P_PATH] eq "") { |
7cae558b | 1587 | # This is the main project. It is also responsible for recursively |
755bb92e | 1588 | # calling the other projects |
7cae558b | 1589 | generate_list("SUBDIRS",1,\@projects,sub |
755bb92e FG |
1590 | { |
1591 | if ($_[0] != \@main_project) { | |
1592 | my $subdir=@{$_[0]}[$P_PATH]; | |
1593 | $subdir =~ s+/$++; | |
1594 | return $subdir; | |
1595 | } | |
1596 | # Eliminating the main project by returning undefined! | |
1597 | }); | |
1598 | } | |
1599 | if (@{@$project[$P_TARGETS]} > 0) { | |
35246cbb | 1600 | generate_list("DLLS",1,\@dll_list,sub |
755bb92e FG |
1601 | { |
1602 | return @{$_[0]}[$T_NAME]; | |
1603 | }); | |
35246cbb | 1604 | generate_list("EXES",1,\@exe_list,sub |
755bb92e | 1605 | { |
635eb3c2 | 1606 | return "@{$_[0]}[$T_NAME]"; |
755bb92e | 1607 | }); |
82747b7d | 1608 | print FILEO "\n\n\n"; |
755bb92e | 1609 | |
d19aa5b7 | 1610 | print FILEO "### Common settings\n\n"; |
755bb92e | 1611 | # Make it so that the project-wide settings override the global settings |
c7201ce3 FG |
1612 | generate_list("CEXTRA",1,@$project_settings[$T_CEXTRA]); |
1613 | generate_list("CXXEXTRA",1,@$project_settings[$T_CXXEXTRA]); | |
1614 | generate_list("RCEXTRA",1,@$project_settings[$T_RCEXTRA]); | |
d19aa5b7 FG |
1615 | generate_list("INCLUDE_PATH",1,@$project_settings[$T_INCLUDE_PATH]); |
1616 | generate_list("DLL_PATH",1,@$project_settings[$T_DLL_PATH]); | |
1617 | generate_list("LIBRARY_PATH",1,@$project_settings[$T_LIBRARY_PATH]); | |
1618 | generate_list("LIBRARIES",1,@$project_settings[$T_LIBRARIES]); | |
755bb92e FG |
1619 | print FILEO "\n\n"; |
1620 | ||
1621 | my $extra_source_count=@{@$project_settings[$T_SOURCES_C]}+ | |
1622 | @{@$project_settings[$T_SOURCES_CXX]}+ | |
1623 | @{@$project_settings[$T_SOURCES_RC]}; | |
d19aa5b7 | 1624 | my $no_extra=($extra_source_count == 0); |
755bb92e FG |
1625 | if (!$no_extra) { |
1626 | print FILEO "### Extra source lists\n\n"; | |
1627 | generate_list("EXTRA_C_SRCS",1,@$project_settings[$T_SOURCES_C]); | |
1628 | generate_list("EXTRA_CXX_SRCS",1,@$project_settings[$T_SOURCES_CXX]); | |
1629 | generate_list("EXTRA_RC_SRCS",1,@$project_settings[$T_SOURCES_RC]); | |
82747b7d FG |
1630 | print FILEO "\n"; |
1631 | generate_list("EXTRA_OBJS",1,["\$(EXTRA_C_SRCS:.c=.o)","\$(EXTRA_CXX_SRCS:.cpp=.o)"]); | |
1632 | print FILEO "\n\n\n"; | |
755bb92e | 1633 | } |
35246cbb | 1634 | |
755bb92e | 1635 | # Iterate over all the targets... |
e3d26a3e | 1636 | foreach my $target (@{@$project[$P_TARGETS]}) { |
82747b7d | 1637 | print FILEO "### @$target[$T_NAME] sources and settings\n\n"; |
755bb92e FG |
1638 | my $canon=canonize("@$target[$T_NAME]"); |
1639 | $canon =~ s+_so$++; | |
caa74b66 JS |
1640 | |
1641 | generate_list("${canon}_MODULE",1,[@$target[$T_NAME]]); | |
755bb92e FG |
1642 | generate_list("${canon}_C_SRCS",1,@$target[$T_SOURCES_C]); |
1643 | generate_list("${canon}_CXX_SRCS",1,@$target[$T_SOURCES_CXX]); | |
1644 | generate_list("${canon}_RC_SRCS",1,@$target[$T_SOURCES_RC]); | |
c7201ce3 | 1645 | generate_list("${canon}_LDFLAGS",1,@$target[$T_LDFLAGS]); |
89a0c02b | 1646 | generate_list("${canon}_DLL_PATH",1,@$target[$T_DLL_PATH]); |
2aad72c4 | 1647 | generate_list("${canon}_DLLS",1,@$target[$T_DLLS]); |
35246cbb FG |
1648 | generate_list("${canon}_LIBRARY_PATH",1,@$target[$T_LIBRARY_PATH]); |
1649 | generate_list("${canon}_LIBRARIES",1,@$target[$T_LIBRARIES]); | |
82747b7d | 1650 | print FILEO "\n"; |
905658c4 | 1651 | generate_list("${canon}_OBJS",1,["\$(${canon}_C_SRCS:.c=.o)","\$(${canon}_CXX_SRCS:.cpp=.o)","\$(${canon}_RC_SRCS:.rc=.res)"]); |
82747b7d | 1652 | print FILEO "\n\n\n"; |
755bb92e FG |
1653 | } |
1654 | print FILEO "### Global source lists\n\n"; | |
35246cbb | 1655 | generate_list("C_SRCS",$no_extra,@$project[$P_TARGETS],sub |
755bb92e FG |
1656 | { |
1657 | my $canon=canonize(@{$_[0]}[$T_NAME]); | |
1658 | $canon =~ s+_so$++; | |
1659 | return "\$(${canon}_C_SRCS)"; | |
1660 | }); | |
1661 | if (!$no_extra) { | |
1662 | generate_list("",1,[ "\$(EXTRA_C_SRCS)" ]); | |
1663 | } | |
35246cbb | 1664 | generate_list("CXX_SRCS",$no_extra,@$project[$P_TARGETS],sub |
755bb92e FG |
1665 | { |
1666 | my $canon=canonize(@{$_[0]}[$T_NAME]); | |
1667 | $canon =~ s+_so$++; | |
1668 | return "\$(${canon}_CXX_SRCS)"; | |
1669 | }); | |
1670 | if (!$no_extra) { | |
1671 | generate_list("",1,[ "\$(EXTRA_CXX_SRCS)" ]); | |
1672 | } | |
35246cbb | 1673 | generate_list("RC_SRCS",$no_extra,@$project[$P_TARGETS],sub |
755bb92e FG |
1674 | { |
1675 | my $canon=canonize(@{$_[0]}[$T_NAME]); | |
1676 | $canon =~ s+_so$++; | |
1677 | return "\$(${canon}_RC_SRCS)"; | |
1678 | }); | |
1679 | if (!$no_extra) { | |
82747b7d | 1680 | generate_list("",1,[ "\$(EXTRA_RC_SRCS)" ]); |
755bb92e | 1681 | } |
755bb92e | 1682 | } |
905658c4 DP |
1683 | print FILEO "\n\n"; |
1684 | print FILEO "### Tools\n\n"; | |
1685 | print FILEO "CC = winegcc\n"; | |
1686 | print FILEO "CXX = wineg++\n"; | |
1687 | print FILEO "RC = wrc\n"; | |
905658c4 | 1688 | print FILEO "\n\n"; |
755bb92e | 1689 | |
c7201ce3 | 1690 | print FILEO "### Generic targets\n\n"; |
27c3b591 | 1691 | print FILEO "all:"; |
755bb92e | 1692 | if (@$project[$P_PATH] eq "") { |
27c3b591 | 1693 | print FILEO " \$(SUBDIRS)"; |
755bb92e | 1694 | } |
82747b7d | 1695 | if (@{@$project[$P_TARGETS]} > 0) { |
635eb3c2 | 1696 | print FILEO " \$(DLLS:%=%.so) \$(EXES:%=%.so)"; |
82747b7d FG |
1697 | } |
1698 | print FILEO "\n\n"; | |
c7201ce3 FG |
1699 | print FILEO "### Build rules\n"; |
1700 | print FILEO "\n"; | |
1701 | print FILEO ".PHONY: all clean dummy\n"; | |
1702 | print FILEO "\n"; | |
1703 | print FILEO "\$(SUBDIRS): dummy\n"; | |
1704 | print FILEO "\t\@cd \$\@ && \$(MAKE)\n"; | |
1705 | print FILEO "\n"; | |
1706 | print FILEO "# Implicit rules\n"; | |
1707 | print FILEO "\n"; | |
1708 | print FILEO ".SUFFIXES: .cpp .rc .res\n"; | |
1709 | print FILEO "DEFINCL = \$(INCLUDE_PATH) \$(DEFINES) \$(OPTIONS)\n"; | |
1710 | print FILEO "\n"; | |
1711 | print FILEO ".c.o:\n"; | |
1712 | print FILEO "\t\$(CC) -c \$(CFLAGS) \$(CEXTRA) \$(DEFINCL) -o \$\@ \$<\n"; | |
1713 | print FILEO "\n"; | |
1714 | print FILEO ".cpp.o:\n"; | |
1715 | print FILEO "\t\$(CXX) -c \$(CXXFLAGS) \$(CXXEXTRA) \$(DEFINCL) -o \$\@ \$<\n"; | |
1716 | print FILEO "\n"; | |
1717 | print FILEO ".cxx.o:\n"; | |
1718 | print FILEO "\t\$(CXX) -c \$(CXXFLAGS) \$(CXXEXTRA) \$(DEFINCL) -o \$\@ \$<\n"; | |
1719 | print FILEO "\n"; | |
1720 | print FILEO ".rc.res:\n"; | |
1721 | print FILEO "\t\$(RC) \$(RCFLAGS) \$(RCEXTRA) \$(DEFINCL) -fo\$@ \$<\n"; | |
1722 | print FILEO "\n"; | |
1723 | print FILEO "# Rules for cleaning\n"; | |
1724 | print FILEO "\n"; | |
8b84ac8d | 1725 | print FILEO "CLEAN_FILES = y.tab.c y.tab.h lex.yy.c core *.orig *.rej \\\n"; |
c7201ce3 FG |
1726 | print FILEO " \\\\\\#*\\\\\\# *~ *% .\\\\\\#*\n"; |
1727 | print FILEO "\n"; | |
1728 | print FILEO "clean:: \$(SUBDIRS:%=%/__clean__) \$(EXTRASUBDIRS:%=%/__clean__)\n"; | |
1729 | print FILEO "\t\$(RM) \$(CLEAN_FILES) \$(RC_SRCS:.rc=.res) \$(C_SRCS:.c=.o) \$(CXX_SRCS:.cpp=.o)\n"; | |
8b84ac8d | 1730 | print FILEO "\t\$(RM) \$(DLLS:%=%.so) \$(EXES:%=%.so) \$(EXES:%.exe=%)\n"; |
c7201ce3 FG |
1731 | print FILEO "\n"; |
1732 | print FILEO "\$(SUBDIRS:%=%/__clean__): dummy\n"; | |
1733 | print FILEO "\tcd `dirname \$\@` && \$(MAKE) clean\n"; | |
1734 | print FILEO "\n"; | |
1735 | print FILEO "\$(EXTRASUBDIRS:%=%/__clean__): dummy\n"; | |
1736 | print FILEO "\t-cd `dirname \$\@` && \$(RM) \$(CLEAN_FILES)\n"; | |
1737 | print FILEO "\n"; | |
35246cbb | 1738 | |
755bb92e | 1739 | if (@{@$project[$P_TARGETS]} > 0) { |
a286c202 FG |
1740 | print FILEO "### Target specific build rules\n"; |
1741 | print FILEO "DEFLIB = \$(LIBRARY_PATH) \$(LIBRARIES) \$(DLL_PATH)\n\n"; | |
e3d26a3e | 1742 | foreach my $target (@{@$project[$P_TARGETS]}) { |
755bb92e FG |
1743 | my $canon=canonize("@$target[$T_NAME]"); |
1744 | $canon =~ s/_so$//; | |
905658c4 | 1745 | |
8b84ac8d | 1746 | print FILEO "\$(${canon}_MODULE).so: \$(${canon}_OBJS)\n"; |
8d0e1e76 | 1747 | if (@{@$target[$T_SOURCES_CXX]} > 0 or @{@$project_settings[$T_SOURCES_CXX]} > 0) { |
905658c4 | 1748 | print FILEO "\t\$(CXX)"; |
8d0e1e76 | 1749 | } else { |
905658c4 | 1750 | print FILEO "\t\$(CC)"; |
8d0e1e76 | 1751 | } |
8b84ac8d | 1752 | print FILEO " \$(${canon}_LDFLAGS) -o \$\@ \$(${canon}_OBJS) \$(${canon}_LIBRARY_PATH) \$(DEFLIB) \$(${canon}_DLLS:%=-l%) \$(${canon}_LIBRARIES:%=-l%)\n"; |
82747b7d | 1753 | print FILEO "\n\n"; |
755bb92e FG |
1754 | } |
1755 | } | |
1756 | close(FILEO); | |
35246cbb | 1757 | |
755bb92e FG |
1758 | } |
1759 | ||
755bb92e | 1760 | |
755bb92e | 1761 | ## |
7cae558b | 1762 | # This is where we finally generate files. In fact this method does not |
755bb92e | 1763 | # do anything itself but calls the methods that do the actual work. |
e3d26a3e | 1764 | sub generate() |
755bb92e FG |
1765 | { |
1766 | print "Generating project files...\n"; | |
755bb92e | 1767 | |
e3d26a3e | 1768 | foreach my $project (@projects) { |
755bb92e FG |
1769 | my $path=@$project[$P_PATH]; |
1770 | if ($path eq "") { | |
1771 | $path="."; | |
1772 | } else { | |
1773 | $path =~ s+/$++; | |
1774 | } | |
1775 | print " $path\n"; | |
1776 | generate_project_files($project); | |
1777 | } | |
1778 | } | |
1779 | ||
1780 | ||
1781 | ||
1782 | ##### | |
1783 | # | |
1784 | # Option defaults | |
1785 | # | |
1786 | ##### | |
1787 | ||
1788 | $opt_backup=1; | |
1789 | $opt_lower=$OPT_LOWER_UPPERCASE; | |
a106edb7 | 1790 | $opt_lower_include=1; |
755bb92e | 1791 | |
c7201ce3 FG |
1792 | $opt_work_dir=undef; |
1793 | $opt_single_target=undef; | |
755bb92e FG |
1794 | $opt_target_type=$TT_GUIEXE; |
1795 | $opt_flags=0; | |
1796 | $opt_is_interactive=$OPT_ASK_NO; | |
1797 | $opt_ask_project_options=$OPT_ASK_NO; | |
1798 | $opt_ask_target_options=$OPT_ASK_NO; | |
a106edb7 | 1799 | $opt_no_generated_files=0; |
ce4e0a61 | 1800 | $opt_no_source_fix=0; |
755bb92e FG |
1801 | $opt_no_banner=0; |
1802 | ||
1803 | ||
1804 | ||
1805 | ##### | |
1806 | # | |
1807 | # Main | |
1808 | # | |
1809 | ##### | |
1810 | ||
e3d26a3e | 1811 | sub print_banner() |
38b3ac59 FG |
1812 | { |
1813 | print "Winemaker $version\n"; | |
1814 | print "Copyright 2000 Francois Gouget <fgouget\@codeweavers.com> for CodeWeavers\n"; | |
1815 | } | |
1816 | ||
e3d26a3e | 1817 | sub usage() |
38b3ac59 FG |
1818 | { |
1819 | print_banner(); | |
ce4e0a61 | 1820 | print STDERR "Usage: winemaker [--nobanner] [--backup|--nobackup] [--nosource-fix]\n"; |
38b3ac59 | 1821 | print STDERR " [--lower-none|--lower-all|--lower-uppercase]\n"; |
905658c4 | 1822 | print STDERR " [--lower-include|--nolower-include] [--mfc|--nomfc]\n"; |
90d65280 | 1823 | print STDERR " [--guiexe|--windows|--cuiexe|--console|--dll]\n"; |
89a0c02b | 1824 | print STDERR " [-Dmacro[=defn]] [-Idir] [-Pdir] [-idll] [-Ldir] [-llibrary]\n"; |
15487bca | 1825 | print STDERR " [--nodlls] [--nomsvcrt] [--interactive] [--single-target name]\n"; |
905658c4 | 1826 | print STDERR " [--generated-files|--nogenerated-files]\n"; |
38b3ac59 FG |
1827 | print STDERR " work_directory\n"; |
1828 | print STDERR "\nWinemaker is designed to recursively convert all the Windows sources found in\n"; | |
1829 | print STDERR "the specified directory so that they can be compiled with Winelib. During this\n"; | |
1830 | print STDERR "process it will modify and rename some of the files in that directory.\n"; | |
1831 | print STDERR "\tPlease read the manual page before use.\n"; | |
1832 | exit (2); | |
1833 | } | |
1834 | ||
90d65280 MW |
1835 | target_init(\@global_settings); |
1836 | ||
755bb92e FG |
1837 | while (@ARGV>0) { |
1838 | my $arg=shift @ARGV; | |
1839 | # General options | |
1840 | if ($arg eq "--nobanner") { | |
1841 | $opt_no_banner=1; | |
1842 | } elsif ($arg eq "--backup") { | |
1843 | $opt_backup=1; | |
1844 | } elsif ($arg eq "--nobackup") { | |
1845 | $opt_backup=0; | |
1846 | } elsif ($arg eq "--single-target") { | |
1847 | $opt_single_target=shift @ARGV; | |
1848 | } elsif ($arg eq "--lower-none") { | |
1849 | $opt_lower=$OPT_LOWER_NONE; | |
1850 | } elsif ($arg eq "--lower-all") { | |
1851 | $opt_lower=$OPT_LOWER_ALL; | |
1852 | } elsif ($arg eq "--lower-uppercase") { | |
1853 | $opt_lower=$OPT_LOWER_UPPERCASE; | |
a106edb7 FG |
1854 | } elsif ($arg eq "--lower-include") { |
1855 | $opt_lower_include=1; | |
82747b7d | 1856 | } elsif ($arg eq "--nolower-include") { |
a106edb7 | 1857 | $opt_lower_include=0; |
ce4e0a61 BM |
1858 | } elsif ($arg eq "--nosource-fix") { |
1859 | $opt_no_source_fix=1; | |
a106edb7 FG |
1860 | } elsif ($arg eq "--generated-files") { |
1861 | $opt_no_generated_files=0; | |
82747b7d | 1862 | } elsif ($arg eq "--nogenerated-files") { |
a106edb7 | 1863 | $opt_no_generated_files=1; |
755bb92e FG |
1864 | } elsif ($arg =~ /^-D/) { |
1865 | push @{$global_settings[$T_DEFINES]},$arg; | |
1866 | } elsif ($arg =~ /^-I/) { | |
1867 | push @{$global_settings[$T_INCLUDE_PATH]},$arg; | |
89a0c02b FG |
1868 | } elsif ($arg =~ /^-P/) { |
1869 | push @{$global_settings[$T_DLL_PATH]},"-L$'"; | |
1870 | } elsif ($arg =~ /^-i/) { | |
905658c4 | 1871 | push @{$global_settings[$T_DLLS]},$'; |
755bb92e FG |
1872 | } elsif ($arg =~ /^-L/) { |
1873 | push @{$global_settings[$T_LIBRARY_PATH]},$arg; | |
be859592 FG |
1874 | } elsif ($arg =~ /^-l/) { |
1875 | push @{$global_settings[$T_LIBRARIES]},$'; | |
755bb92e FG |
1876 | |
1877 | # 'Source'-based method options | |
1878 | } elsif ($arg eq "--dll") { | |
1879 | $opt_target_type=$TT_DLL; | |
1880 | } elsif ($arg eq "--guiexe" or $arg eq "--windows") { | |
1881 | $opt_target_type=$TT_GUIEXE; | |
1882 | } elsif ($arg eq "--cuiexe" or $arg eq "--console") { | |
1883 | $opt_target_type=$TT_CUIEXE; | |
1884 | } elsif ($arg eq "--interactive") { | |
1885 | $opt_is_interactive=$OPT_ASK_YES; | |
1886 | $opt_ask_project_options=$OPT_ASK_YES; | |
1887 | $opt_ask_target_options=$OPT_ASK_YES; | |
755bb92e | 1888 | } elsif ($arg eq "--mfc") { |
be859592 | 1889 | $opt_flags|=$TF_MFC; |
755bb92e | 1890 | } elsif ($arg eq "--nomfc") { |
3aa9e8c6 MW |
1891 | $opt_flags&=~$TF_MFC; |
1892 | $opt_flags|=$TF_NOMFC; | |
3aa9e8c6 MW |
1893 | } elsif ($arg eq "--nodlls") { |
1894 | $opt_flags|=$TF_NODLLS; | |
15487bca FG |
1895 | } elsif ($arg eq "--nomsvcrt") { |
1896 | $opt_flags|=$TF_NOMSVCRT; | |
755bb92e FG |
1897 | |
1898 | # Catch errors | |
1899 | } else { | |
1900 | if ($arg ne "--help" and $arg ne "-h" and $arg ne "-?") { | |
c1f016be FG |
1901 | if (!defined $opt_work_dir) { |
1902 | $opt_work_dir=$arg; | |
1903 | } else { | |
1904 | print STDERR "error: the work directory, \"$arg\", has already been specified (was \"$opt_work_dir\")\n"; | |
38b3ac59 | 1905 | usage(); |
c1f016be FG |
1906 | } |
1907 | } else { | |
38b3ac59 | 1908 | usage(); |
755bb92e | 1909 | } |
755bb92e FG |
1910 | } |
1911 | } | |
1912 | ||
c1f016be FG |
1913 | if (!defined $opt_work_dir) { |
1914 | print STDERR "error: you must specify the directory containing the sources to be converted\n"; | |
38b3ac59 | 1915 | usage(); |
c1f016be FG |
1916 | } elsif (!chdir $opt_work_dir) { |
1917 | print STDERR "error: could not chdir to the work directory\n"; | |
1918 | print STDERR " $!\n"; | |
38b3ac59 | 1919 | usage(); |
c1f016be FG |
1920 | } |
1921 | ||
38b3ac59 FG |
1922 | if ($opt_no_banner == 0) { |
1923 | print_banner(); | |
755bb92e FG |
1924 | } |
1925 | ||
3aa9e8c6 MW |
1926 | project_init(\@main_project,""); |
1927 | ||
755bb92e FG |
1928 | # Fix the file and directory names |
1929 | fix_file_and_directory_names("."); | |
1930 | ||
1931 | # Scan the sources to identify the projects and targets | |
1932 | source_scan(); | |
1933 | ||
755bb92e | 1934 | # Fix the source files |
ce4e0a61 BM |
1935 | if (! $opt_no_source_fix) { |
1936 | fix_source(); | |
1937 | } | |
755bb92e FG |
1938 | |
1939 | # Generate the Makefile and the spec file | |
a106edb7 | 1940 | if (! $opt_no_generated_files) { |
755bb92e FG |
1941 | generate(); |
1942 | } |