1
/*******************************************************************************
2
* Copyright (c) 2000, 2011 QNX Software Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* QNX Software Systems - Initial API and implementation
10
* Wind River Systems - Bug 338936
11
*******************************************************************************/
12
package org.eclipse.cdt.make.internal.core.makefile.gnu;
14
import java.io.IOException;
15
import java.io.InputStreamReader;
16
import java.io.Reader;
18
import java.util.ArrayList;
19
import java.util.Arrays;
20
import java.util.List;
21
import java.util.Stack;
22
import java.util.StringTokenizer;
24
import org.eclipse.cdt.make.core.MakeCorePlugin;
25
import org.eclipse.cdt.make.core.makefile.IDirective;
26
import org.eclipse.cdt.make.core.makefile.IMakefile;
27
import org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider;
28
import org.eclipse.cdt.make.core.makefile.gnu.IGNUMakefile;
29
import org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile;
30
import org.eclipse.cdt.make.internal.core.makefile.BadDirective;
31
import org.eclipse.cdt.make.internal.core.makefile.Command;
32
import org.eclipse.cdt.make.internal.core.makefile.Comment;
33
import org.eclipse.cdt.make.internal.core.makefile.DefaultRule;
34
import org.eclipse.cdt.make.internal.core.makefile.Directive;
35
import org.eclipse.cdt.make.internal.core.makefile.EmptyLine;
36
import org.eclipse.cdt.make.internal.core.makefile.IgnoreRule;
37
import org.eclipse.cdt.make.internal.core.makefile.InferenceRule;
38
import org.eclipse.cdt.make.internal.core.makefile.MakeFileConstants;
39
import org.eclipse.cdt.make.internal.core.makefile.MakefileReader;
40
import org.eclipse.cdt.make.internal.core.makefile.PosixRule;
41
import org.eclipse.cdt.make.internal.core.makefile.PreciousRule;
42
import org.eclipse.cdt.make.internal.core.makefile.Rule;
43
import org.eclipse.cdt.make.internal.core.makefile.SccsGetRule;
44
import org.eclipse.cdt.make.internal.core.makefile.SilentRule;
45
import org.eclipse.cdt.make.internal.core.makefile.SpecialRule;
46
import org.eclipse.cdt.make.internal.core.makefile.SuffixesRule;
47
import org.eclipse.cdt.make.internal.core.makefile.Target;
48
import org.eclipse.cdt.make.internal.core.makefile.TargetRule;
49
import org.eclipse.cdt.make.internal.core.makefile.Util;
50
import org.eclipse.cdt.make.internal.core.makefile.posix.PosixMakefileUtil;
51
import org.eclipse.core.filesystem.EFS;
52
import org.eclipse.core.filesystem.IFileInfo;
53
import org.eclipse.core.filesystem.IFileStore;
54
import org.eclipse.core.filesystem.URIUtil;
55
import org.eclipse.core.runtime.CoreException;
58
* Makefile : ( statement ) *
59
* statement : rule | macro_definition | comments | empty
60
* rule : inference_rule | target_rule
61
* inference_rule : target ':' <nl> ( <tab> command <nl> ) +
62
* target_rule : target [ ( target ) * ] ':' [ ( prerequisite ) * ] [ ';' command ] <nl>
64
* macro_definition : string '=' (string)*
65
* comments : ('#' (string) <nl>) *
67
* command : <tab> prefix_command string <nl>
69
* prefix_command : '-' | '@' | '+'
70
* internal_macro : "$<" | "$*" | "$@" | "$?" | "$%"
73
public class GNUMakefile extends AbstractMakefile implements IGNUMakefile {
75
public static String PATH_SEPARATOR = System.getProperty("path.separator", ":"); //$NON-NLS-1$ //$NON-NLS-2$
76
public static String FILE_SEPARATOR = System.getProperty("file.separator", "/"); //$NON-NLS-1$ //$NON-NLS-2$
78
String[] includeDirectories = new String[0];
79
IDirective[] builtins = new IDirective[0];
80
private IMakefileReaderProvider makefileReaderProvider;
82
public GNUMakefile() {
87
* @see org.eclipse.cdt.make.core.makefile.IMakefile#getMakefileReaderProvider()
89
public IMakefileReaderProvider getMakefileReaderProvider() {
90
return makefileReaderProvider;
93
public void parse(String filePath, Reader reader) throws IOException {
94
parse(URIUtil.toURI(filePath), new MakefileReader(reader));
98
* @see org.eclipse.cdt.make.core.makefile.IMakefile#parse(java.net.URI, org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider)
100
public void parse(URI fileURI,
101
IMakefileReaderProvider makefileReaderProvider) throws IOException {
102
this.makefileReaderProvider = makefileReaderProvider;
103
MakefileReader reader;
104
if (makefileReaderProvider == null) {
106
final IFileStore store = EFS.getStore(fileURI);
107
final IFileInfo info = store.fetchInfo();
108
if (!info.exists() || info.isDirectory())
109
throw new IOException();
111
reader = new MakefileReader(new InputStreamReader(
112
store.openInputStream(EFS.NONE, null)));
113
} catch (CoreException e) {
114
MakeCorePlugin.log(e);
115
throw new IOException(e.getMessage());
118
reader = new MakefileReader(makefileReaderProvider.getReader(fileURI));
120
parse(fileURI, reader);
123
public void parse(URI filePath, Reader reader) throws IOException {
124
parse(filePath, new MakefileReader(reader));
128
protected void parse(URI fileURI, MakefileReader reader) throws IOException {
131
Stack<Directive> conditions = new Stack<Directive>();
132
Stack<VariableDefinition> defines = new Stack<VariableDefinition>();
136
// Clear any old directives.
142
while ((line = reader.readLine()) != null) {
143
startLine = endLine + 1;
144
endLine = reader.getLineNumber();
146
// Check if we enter in "define"
147
if (GNUMakefileUtil.isEndef(line)) {
148
// We should have a "define" for a "endef".
149
if (!defines.empty()) {
150
VariableDefinition def = defines.pop();
151
def.setEndLine(endLine);
153
Endef endef = new Endef(this);
154
endef.setLines(startLine, endLine);
155
addDirective(conditions, endef);
157
} else if (GNUMakefileUtil.isDefine(line)) {
158
VariableDefinition def = parseVariableDefinition(line);
159
def.setLines(startLine, endLine);
160
addDirective(conditions, def);
163
} else if (GNUMakefileUtil.isOverrideDefine(line)) {
164
VariableDefinition oDef = parseVariableDefinition(line);
165
oDef.setLines(startLine, endLine);
166
addDirective(conditions, oDef);
171
// We still in a define.
172
if (!defines.empty()) {
173
VariableDefinition def = defines.peek();
174
StringBuffer sb = def.getValue();
175
if (sb.length() > 0) {
182
// 1- Try command first, since we can not strip '#' in command line
183
if (PosixMakefileUtil.isCommand(line)) {
184
Command cmd = new Command(this, line);
185
cmd.setLines(startLine, endLine);
186
if (!conditions.empty()) {
187
addDirective(conditions, cmd);
189
} else if (rules != null) {
190
// The command is added to the rules
191
for (Rule rule : rules) {
192
rule.addDirective(cmd);
193
rule.setEndLine(endLine);
197
// If we have no rules/condition for the command,
198
// give the other directives a chance by falling through
201
// 2- Strip away any comments.
202
int pound = Util.indexOfComment(line);
204
Comment cmt = new Comment(this, line.substring(pound + 1));
205
cmt.setLines(startLine, endLine);
207
// The comment is added to the rules.
208
for (Rule rule : rules) {
209
rule.addDirective(cmt);
210
rule.setEndLine(endLine);
213
addDirective(conditions, cmt);
215
line = line.substring(0, pound);
216
// If all we have left are spaces continue
217
if (Util.isEmptyLine(line)) {
220
// The rest of the line maybe a valid directives.
221
// keep on trying by falling through.
225
if (Util.isEmptyLine(line)) {
226
Directive empty = new EmptyLine(this);
227
empty.setLines(startLine, endLine);
229
// The EmptyLine is added to the rules.
230
for (Rule rule : rules) {
231
rule.addDirective(empty);
232
rule.setEndLine(endLine);
235
addDirective(conditions, empty);
240
// 4- reset the rules to null
241
// The first non empty line that does not begin with a <TAB> or '#'
242
// shall begin a new entry.
245
if (GNUMakefileUtil.isElse(line)) {
246
Conditional elseDirective = parseConditional(line);
247
elseDirective.setLines(startLine, endLine);
248
// Are we missing a if condition ?
249
if (!conditions.empty()) {
250
Conditional cond = (Conditional) conditions.pop();
251
cond.setEndLine(endLine - 1);
253
addDirective(conditions, elseDirective);
254
conditions.push(elseDirective);
256
} else if (GNUMakefileUtil.isEndif(line)) {
257
Endif endif = new Endif(this);
258
endif.setLines(startLine, endLine);
259
// Are we missing a if/else condition ?
260
if (!conditions.empty()) {
261
Conditional cond = (Conditional) conditions.pop();
262
cond.setEndLine(endLine);
264
addDirective(conditions, endif);
268
// 5- Check for the conditionnals.
269
Directive directive = processConditions(line);
270
if (directive != null) {
271
directive.setLines(startLine, endLine);
272
addDirective(conditions, directive);
273
conditions.push(directive);
277
// 6- Check for other special gnu directives.
278
directive = processGNUDirectives(line);
279
if (directive != null) {
280
directive.setLines(startLine, endLine);
281
addDirective(conditions, directive);
285
// 7- Check for GNU special rules.
286
SpecialRule special = processSpecialRules(line);
287
if (special != null) {
288
rules = new Rule[] { special };
289
special.setLines(startLine, endLine);
290
addDirective(conditions, special);
294
// - Check for inference rule.
295
if (PosixMakefileUtil.isInferenceRule(line)) {
296
InferenceRule irule = parseInferenceRule(line);
297
irule.setLines(startLine, endLine);
298
addDirective(conditions, irule);
299
rules = new Rule[] { irule };
303
// - Variable Definiton ?
304
if (GNUMakefileUtil.isVariableDefinition(line)) {
305
VariableDefinition vd = parseVariableDefinition(line);
306
vd.setLines(startLine, endLine);
307
addDirective(conditions, vd);
308
if (!vd.isTargetSpecific()) {
313
// - GNU Static Target rule ?
314
if (GNUMakefileUtil.isStaticTargetRule(line)) {
315
StaticTargetRule[] srules = parseStaticTargetRule(line);
316
for (StaticTargetRule srule : srules) {
317
srule.setLines(startLine, endLine);
318
addDirective(conditions, srule);
325
if (GNUMakefileUtil.isGNUTargetRule(line)) {
326
TargetRule[] trules = parseGNUTargetRules(line);
327
for (TargetRule trule : trules) {
328
trule.setLines(startLine, endLine);
329
addDirective(conditions, trule);
335
// XXX ?? Should not be here.
336
BadDirective stmt = new BadDirective(this, line);
337
stmt.setLines(startLine, endLine);
338
addDirective(conditions, stmt);
341
setLines(1, endLine);
345
// TEST please remove.
346
//GNUMakefileValidator validator = new GNUMakefileValidator();
347
//validator.validateDirectives(null, getDirectives());
350
private void addDirective(Stack<Directive> conditions, Directive directive) {
351
if (conditions.empty()) {
352
addDirective(directive);
354
Conditional cond = (Conditional) conditions.peek();
355
cond.addDirective(directive);
356
cond.setEndLine(directive.getEndLine());
360
protected Conditional processConditions(String line) {
361
Conditional stmt = null;
362
if (GNUMakefileUtil.isIfdef(line)) {
363
stmt = parseConditional(line);
364
} else if (GNUMakefileUtil.isIfndef(line)) {
365
stmt = parseConditional(line);
366
} else if (GNUMakefileUtil.isIfeq(line)) {
367
stmt = parseConditional(line);
368
} else if (GNUMakefileUtil.isIfneq(line)) {
369
stmt = parseConditional(line);
374
protected Directive processGNUDirectives(String line) {
375
Directive stmt = null;
376
if (GNUMakefileUtil.isUnExport(line)) {
377
stmt = parseUnExport(line);
378
} else if (GNUMakefileUtil.isVPath(line)) {
379
stmt = parseVPath(line);
380
} else if (GNUMakefileUtil.isInclude(line)) {
381
stmt = parseInclude(line);
386
protected SpecialRule processSpecialRules(String line) {
387
SpecialRule stmt = null;
388
if (PosixMakefileUtil.isIgnoreRule(line)) {
389
stmt = parseSpecialRule(line);
390
} else if (PosixMakefileUtil.isPosixRule(line)) {
391
stmt = parseSpecialRule(line);
392
} else if (PosixMakefileUtil.isPreciousRule(line)) {
393
stmt = parseSpecialRule(line);
394
} else if (PosixMakefileUtil.isSilentRule(line)) {
395
stmt = parseSpecialRule(line);
396
} else if (PosixMakefileUtil.isSuffixesRule(line)) {
397
stmt = parseSpecialRule(line);
398
} else if (PosixMakefileUtil.isDefaultRule(line)) {
399
stmt = parseSpecialRule(line);
400
} else if (PosixMakefileUtil.isSccsGetRule(line)) {
401
stmt = parseSpecialRule(line);
402
} else if (GNUMakefileUtil.isPhonyRule(line)) {
403
stmt = parseSpecialRule(line);
404
} else if (GNUMakefileUtil.isIntermediateRule(line)) {
405
stmt = parseSpecialRule(line);
406
} else if (GNUMakefileUtil.isSecondaryRule(line)) {
407
stmt = parseSpecialRule(line);
408
} else if (GNUMakefileUtil.isDeleteOnErrorRule(line)) {
409
stmt = parseSpecialRule(line);
410
} else if (GNUMakefileUtil.isLowResolutionTimeRule(line)) {
411
stmt = parseSpecialRule(line);
412
} else if (GNUMakefileUtil.isExportAllVariablesRule(line)) {
413
stmt = parseSpecialRule(line);
414
} else if (GNUMakefileUtil.isNotParallelRule(line)) {
415
stmt = parseSpecialRule(line);
420
protected SpecialRule parseSpecialRule(String line) {
422
String keyword = null;
423
String[] reqs = null;
424
SpecialRule special = null;
425
int index = Util.indexOf(line, ':');
427
keyword = line.substring(0, index).trim();
428
String req = line.substring(index + 1);
429
reqs = PosixMakefileUtil.findPrerequisites(req);
432
reqs = new String[0];
434
if (keyword.equals(MakeFileConstants.RULE_IGNORE)) {
435
special = new IgnoreRule(this, reqs);
436
} else if (keyword.equals(MakeFileConstants.RULE_POSIX)) {
437
special = new PosixRule(this);
438
} else if (keyword.equals(MakeFileConstants.RULE_PRECIOUS)) {
439
special = new PreciousRule(this, reqs);
440
} else if (keyword.equals(MakeFileConstants.RULE_SILENT)) {
441
special = new SilentRule(this, reqs);
442
} else if (keyword.equals(MakeFileConstants.RULE_SUFFIXES)) {
443
special = new SuffixesRule(this, reqs);
444
} else if (keyword.equals(MakeFileConstants.RULE_DEFAULT)) {
445
special = new DefaultRule(this, new Command[0]);
446
} else if (keyword.equals(MakeFileConstants.RULE_SCCS_GET)) {
447
special = new SccsGetRule(this, new Command[0]);
448
} else if (keyword.equals(GNUMakefileConstants.RULE_PHONY)) {
449
special = new PhonyRule(this, reqs);
450
} else if (keyword.equals(GNUMakefileConstants.RULE_INTERMEDIATE)) {
451
special = new IntermediateRule(this, reqs);
452
} else if (keyword.equals(GNUMakefileConstants.RULE_SECONDARY)) {
453
special = new SecondaryRule(this, reqs);
454
} else if (keyword.equals(GNUMakefileConstants.RULE_DELETE_ON_ERROR)) {
455
special = new DeleteOnErrorRule(this, reqs);
456
} else if (keyword.equals(GNUMakefileConstants.RULE_LOW_RESOLUTION_TIME)) {
457
special = new LowResolutionTimeRule(this, reqs);
458
} else if (keyword.equals(GNUMakefileConstants.RULE_EXPORT_ALL_VARIABLES)) {
459
special = new ExportAllVariablesRule(this, reqs);
460
} else if (keyword.equals(GNUMakefileConstants.RULE_NOT_PARALLEL)) {
461
special = new NotParallelRule(this, reqs);
474
protected Conditional parseConditional(String line) {
475
Conditional condition = null;
477
String keyword = null;
478
// Move pass the keyword
479
for (int i = 0; i < line.length(); i++) {
480
if (Util.isSpace(line.charAt(i))) {
481
keyword = line.substring(0, i);
482
line = line.substring(i).trim();
486
if (keyword == null) {
489
if (keyword.equals(GNUMakefileConstants.CONDITIONAL_IFDEF)) {
490
condition = new Ifdef(this, line);
491
} else if (keyword.equals(GNUMakefileConstants.CONDITIONAL_IFNDEF)) {
492
condition = new Ifndef(this, line);
493
} else if (keyword.equals(GNUMakefileConstants.CONDITIONAL_IFEQ)) {
494
condition = new Ifeq(this, line);
495
} else if (keyword.equals(GNUMakefileConstants.CONDITIONAL_IFNEQ)) {
496
condition = new Ifneq(this, line);
497
} else if (keyword.equals(GNUMakefileConstants.CONDITIONAL_ELSE)) {
498
condition = new Else(this);
504
* Format of the include directive:
505
* include filename1 filename2 ...
507
protected Include parseInclude(String line) {
509
StringTokenizer st = new StringTokenizer(line);
510
int count = st.countTokens();
512
filenames = new String[count - 1];
513
for (int i = 0; i < count; i++) {
516
// ignore the "include" keyword.
519
filenames[i - 1] = st.nextToken();
522
filenames = new String[0];
524
return new Include(this, filenames, getIncludeDirectories());
528
* There are three forms of the "vpath" directive:
529
* "vpath PATTERN DIRECTORIES"
530
* Specify the search path DIRECTORIES for file names that match PATTERN.
532
* The search path, DIRECTORIES, is a list of directories to be
533
* searched, separated by colons (semi-colons on MS-DOS and
534
* MS-Windows) or blanks, just like the search path used in the `VPATH' variable.
537
* Clear out the search path associated with PATTERN.
540
* Clear all search paths previously specified with `vpath' directives.
542
protected VPath parseVPath(String line) {
543
String pattern = null;
544
String[] directories;
545
StringTokenizer st = new StringTokenizer(line);
546
int count = st.countTokens();
547
List<String> dirs = new ArrayList<String>(count);
549
for (int i = 0; i < count; i++) {
551
// ignore the "vpath" directive
553
} else if (count == 1) {
554
pattern = st.nextToken();
555
} else if (count == 3) {
556
String delim = " \t\n\r\f" + GNUMakefile.PATH_SEPARATOR; //$NON-NLS-1$
557
dirs.add(st.nextToken(delim));
559
dirs.add(st.nextToken());
563
directories = dirs.toArray(new String[0]);
564
if (pattern == null) {
565
pattern = new String();
567
return new VPath(this, pattern, directories);
570
protected UnExport parseUnExport(String line) {
571
// Pass over "unexport"
572
for (int i = 0; i < line.length(); i++) {
573
if (Util.isSpace(line.charAt(i))) {
574
line = line.substring(i).trim();
578
return new UnExport(this, line);
581
protected GNUTargetRule[] parseGNUTargetRules(String line) {
582
String[] targetNames;
586
boolean doubleColon = false;
587
int index = Util.indexOf(line, ':');
590
String target = line.substring(0, index);
591
targetNames = PosixMakefileUtil.findTargets(target.trim());
593
// Some TargetRule have "::" for separator
594
String req = line.substring(index + 1);
595
doubleColon = req.startsWith(":"); //$NON-NLS-1$
597
// move pass the second ':'
598
req = req.substring(1);
602
int semicolon = Util.indexOf(req, ';');
603
if (semicolon != -1) {
604
cmd = req.substring(semicolon + 1);
605
req = req.substring(0, semicolon);
608
// Check for Normal and order prerequisites
609
String normalReq = null;
610
String orderReq = null;
611
int pipe = Util.indexOf(req, '|');
613
normalReq = req.substring(0, pipe);
614
orderReq = req.substring(pipe + 1);
617
orderReq = ""; //$NON-NLS-1$
620
normalReqs = PosixMakefileUtil.findPrerequisites(normalReq.trim());
621
orderReqs = PosixMakefileUtil.findPrerequisites(orderReq.trim());
623
targetNames = PosixMakefileUtil.findTargets(line);
624
normalReqs = new String[0];
625
orderReqs = new String[0];
628
GNUTargetRule[] rules = new GNUTargetRule[targetNames.length];
629
for (int i = 0; i < targetNames.length; i++) {
630
rules[i] = new GNUTargetRule(this, new Target(targetNames[i]), doubleColon, normalReqs, orderReqs, new Command[0]);
632
rules[i].addDirective(new Command(this, cmd));
638
protected VariableDefinition parseVariableDefinition(String line) {
640
VariableDefinition vd;
643
int type = VariableDefinition.TYPE_RECURSIVE_EXPAND;
644
boolean isDefine = false;
645
boolean isOverride = false;
646
boolean isTargetVariable = false;
647
boolean isExport = false;
648
String targetName = ""; //$NON-NLS-1$
651
StringBuffer value = new StringBuffer();
653
// Check for Target: Variable-assignment
654
isTargetVariable = GNUMakefileUtil.isTargetVariable(line);
655
if (isTargetVariable) {
656
// move to the first ':'
657
int colon = Util.indexOf(line, ':');
659
targetName = line.substring(0, colon).trim();
660
line = line.substring(colon + 1).trim();
662
targetName = ""; //$NON-NLS-1$
666
// Check for Override condition.
667
if (GNUMakefileUtil.isOverride(line)) {
669
// Move pass the keyword override.
670
for (int i = 0; i < line.length(); i++) {
671
if (Util.isSpace(line.charAt(i))) {
672
line = line.substring(i).trim();
678
// Check for "define"
679
if (GNUMakefileUtil.isDefine(line)) {
681
// Move pass the keyword define.
682
for (int i = 0; i < line.length(); i++) {
683
if (Util.isSpace(line.charAt(i))) {
684
line = line.substring(i).trim();
690
// Check for Override condition.
691
if (GNUMakefileUtil.isExport(line)) {
693
// Move pass the keyword export.
694
for (int i = 0; i < line.length(); i++) {
695
if (Util.isSpace(line.charAt(i))) {
696
line = line.substring(i).trim();
702
// Check for Target-variable
704
int index = line.indexOf('=');
706
int separator = index;
707
// Check for "+=", ":=", "?="
709
type = line.charAt(index - 1);
710
if (type == VariableDefinition.TYPE_SIMPLE_EXPAND
711
|| type == VariableDefinition.TYPE_APPEND
712
|| type == VariableDefinition.TYPE_CONDITIONAL) {
713
separator = index - 1;
715
type = VariableDefinition.TYPE_RECURSIVE_EXPAND;
718
name = line.substring(0, separator).trim();
719
value.append(line.substring(index + 1).trim());
724
if (isTargetVariable) {
725
vd = new TargetVariable(this, targetName, name, value, isOverride, type);
726
} else if (isOverride && isDefine) {
727
vd = new OverrideDefine(this, name, value);
728
} else if (isDefine) {
729
vd = new DefineVariable(this, name, value);
730
} else if (isOverride) {
731
vd = new OverrideVariable(this, name, value, type);
732
} else if (isExport) {
733
vd = new ExportVariable(this, name, value, type);
735
vd = new VariableDefinition(this, name, value, type);
740
protected StaticTargetRule[] parseStaticTargetRule(String line) {
741
// first colon: the Targets
742
String targetPattern;
743
String[] prereqPatterns;
745
int colon = Util.indexOf(line, ':');
747
String targetLine = line.substring(0, colon).trim();
748
targets = PosixMakefileUtil.findTargets(targetLine);
749
// second colon: Target-Pattern
750
line = line.substring(colon + 1);
751
colon = Util.indexOf(line, ':');
753
targetPattern = line.substring(0, colon).trim();
754
line = line.substring(colon + 1);
755
StringTokenizer st = new StringTokenizer(line);
756
int count = st.countTokens();
757
prereqPatterns = new String[count];
758
for (int i = 0; i < count; i++) {
759
prereqPatterns[i] = st.nextToken();
762
targetPattern = ""; //$NON-NLS-1$
763
prereqPatterns = new String[0];
766
targets = new String[0];
767
targetPattern = ""; //$NON-NLS-1$
768
prereqPatterns = new String[0];
771
StaticTargetRule[] staticRules = new StaticTargetRule[targets.length];
772
for (int i = 0; i < targets.length; i++) {
773
staticRules[i] = new StaticTargetRule(this, new Target(targets[i]), targetPattern, prereqPatterns, new Command[0]);
778
protected InferenceRule parseInferenceRule(String line) {
780
int index = Util.indexOf(line, ':');
782
tgt = line.substring(0, index);
786
return new InferenceRule(this, new Target(tgt));
790
public IDirective[] getDirectives(boolean expand) {
792
return getDirectives();
794
IDirective[] dirs = getDirectives();
795
ArrayList<IDirective> list = new ArrayList<IDirective>(Arrays.asList(dirs));
796
for (int i = 0; i < dirs.length; ++i) {
797
if (dirs[i] instanceof Include) {
798
Include include = (Include)dirs[i];
799
IDirective[] includedMakefiles = include.getDirectives();
800
for (int j = 0; j < includedMakefiles.length; ++j) {
801
IMakefile includedMakefile = (IMakefile)includedMakefiles[j];
802
list.addAll(Arrays.asList(includedMakefile.getDirectives()));
806
return list.toArray(new IDirective[list.size()]);
810
* @see org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile#getBuiltins()
813
public IDirective[] getBuiltins() {
817
public void setIncludeDirectories(String[] dirs) {
818
includeDirectories = dirs;
821
public String[] getIncludeDirectories() {
822
return includeDirectories;