/* AggregateProjectType.m Implementation of the AggregateProjectType class for the ProjectManager application. Copyright (C) 2005 Saso Kiselkov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #import "AggregateProjectType.h" #import #import #import #import #import #import #import #import #import #import "../../ProjectDocument.h" #import "../../ProjectModule.h" #import "../../ProjectModules/MakeBuilder/MakeBuilder.h" #import "../../ProjectModules/SubprojectsManager/SubprojectsManager.h" #import "../../NSImageAdditions.h" #import "../../CommonFunctions/MakefileChecking.h" static inline void InsertMakefileVariable(NSMutableString * makefileString, NSString * name, NSString * value) { [makefileString appendString: [NSString stringWithFormat: @"\n" @"%@ = %@\n", name, value]]; } static void InsertMakefileEnumerationVariable(NSMutableString * makefileString, NSString * name, NSArray * values) { NSEnumerator * e; NSString * value; [makefileString appendString: [NSString stringWithFormat: @"\n" @"%@ = ", name]]; e = [values objectEnumerator]; while ((value = [e nextObject]) != nil) { [makefileString appendString: [NSString stringWithFormat: @"%@ \\\n", value]]; } } @interface AggregateProjectType (Private) - (BOOL) prepareMakefile; @end @implementation AggregateProjectType (Private) /** * Prepares the project's makefile. */ - (BOOL) prepareMakefile { NSString * buildDir = [owner projectDirectory]; NSString * makefile = [buildDir stringByAppendingPathComponent: @"GNUmakefile"]; NSMutableString * makefileString = [NSMutableString string]; if (oldMakeHash != 0) { if (oldMakeHash != ComputeHashFromMakefile(makefile)) { switch (NSRunAlertPanel(_(@"Warning: GNUmakefile changed"), _(@"It seems the build settings in the GNUmakefile have been\n" @"edited since I've last regenerated it. You shouldn't do\n" @"this. Please, put build customizations in GNUmakefile." @"preamble\n" @"or GNUmakefile.postamble. For now, I can backup your current\n" @"GNUmakefile (it will be named GNUmakefile~) or overwrite it."), _(@"Back it up"), _(@"Overwrite"), _(@"Cancel"))) { case NSAlertDefaultReturn: if (![[NSFileManager defaultManager] movePath: makefile toPath: [makefile stringByAppendingString: @"~"] handler: nil]) { NSRunAlertPanel(_(@"Backup failed"), _(@"Failed to move the old GNUmakefile to GNUmakefile~.\n" @"Safety stop."), nil, nil, nil); return NO; } break; case NSAlertAlternateReturn: break; case NSAlertOtherReturn: return NO; } } } [makefileString appendString: [NSString stringWithContentsOfFile: [[NSBundle bundleForClass: [self class]] pathForResource: @"MakefileEditWarning" ofType: @"txt"]]]; [makefileString appendString: @"\n" @"include $(GNUSTEP_MAKEFILES)/common.make\n"]; // SUBPROJECTS { SubprojectsManager * subprojectsManager = [owner projectModuleWithName: @"SubprojectsManager"]; NSArray * subprojectNames = [subprojectsManager subprojectNames]; NSEnumerator * e; NSString * subprojectName; NSMutableArray * subprojects = [NSMutableArray arrayWithCapacity: [subprojectNames count]]; e = [subprojectNames objectEnumerator]; while ((subprojectName = [e nextObject]) != nil) { [subprojects addObject: [@"Subprojects" stringByAppendingPathComponent: subprojectName]]; } InsertMakefileEnumerationVariable(makefileString, @"SUBPROJECTS", subprojects); } [makefileString appendString: @"\n" @"-include GNUmakefile.preamble\n" @"include $(GNUSTEP_MAKEFILES)/aggregate.make\n" @"-include GNUmakefile.postamble\n"]; oldMakeHash = ComputeHashFromMakeString(makefileString); return [makefileString writeToFile: makefile atomically: NO]; } @end @implementation AggregateProjectType + (NSString *) projectTypeID { return @"Aggregate"; } + (NSString *) humanReadableProjectTypeName { return _(@"Aggregate"); } + (NSString *) projectTypeDescription { return [NSString stringWithContentsOfFile: [[NSBundle bundleForClass: self] pathForResource: @"Description" ofType: @"txt"]]; } + (NSImage *) projectTypeIcon { static NSImage * icon = nil; if (icon == nil) { ASSIGN(icon, [NSImage imageNamed: @"AggregateProjectType" owner: self]); } return icon; } + (NSArray *) projectModules { return [NSArray arrayWithObjects: @"ProjectAttributes", @"MakeBuilder", @"SubprojectsManager", nil]; } + (NSDictionary *) projectTemplateDescriptions { NSBundle * myBundle = [NSBundle bundleForClass: self]; return [NSDictionary dictionaryWithObjectsAndKeys: PMCreateTemplateDescription(_(@"An empty aggregate project."), [NSImage imageNamed: @"AggregateProjectType" owner: self]), _(@"Empty Aggregate"), nil]; } + (NSString *) pathToProjectTemplate: (NSString *) templateName { NSBundle * myBundle = [NSBundle bundleForClass: self]; return [myBundle pathForResource: @"EmptyAggregate" ofType: @"template"]; } - initWithDocument: (ProjectDocument *) anOwner infoDictionary: (NSDictionary *) infoDict projectModules: (NSArray *) projectModules { if ((self = [self init]) != nil) { NSNotificationCenter * nc = [NSNotificationCenter defaultCenter]; owner = anOwner; ASSIGN(builder, [owner projectModuleWithName: @"MakeBuilder"]); oldMakeHash = [[infoDict objectForKey: @"MakefileHash"] intValue]; } return self; } - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; TEST_RELEASE(builder); [super dealloc]; } - (NSDictionary *) infoDictionary { return [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: oldMakeHash] forKey: @"MakefileHash"]; } - (BOOL) regenerateDerivedFiles { return [self prepareMakefile]; } - (NSString *) pathToSubprojectsDirectory { return [[owner projectDirectory] stringByAppendingPathComponent: @"Subprojects"]; } - (NSArray *) tabIdentifiersForProjectAttributes: (id) sender { return nil; } - (NSString *) projectAttributes: (id) sender toolbarItemLabelForTabIdentifier: (NSString *) tab { return nil; } - (NSString *) projectAttributes: (id) sender toolbarItemToolTipForTabIdentifier: (NSString *) tab { return nil; } - (NSImage *) projectAttributes: (id) sender toolbarItemIconForTabIdentifier: (NSString *) tab { return nil; } - (NSView *) projectAttributes: (id) sender viewForTabIdentifier: (NSString *) tab { return nil; } - (NSArray *) buildTargetsForMakeBuilder: (id) sender { return [NSArray arrayWithObjects: _(@"Default"), _(@"Debug"), _(@"Profile"), _(@"Install"), nil]; } - (BOOL) prepareForBuildByBuilder: (id) sender target: (NSString *) aTarget { return [self prepareMakefile]; } - (NSArray *) buildArgumentsForBuilder: (id) sender target: (NSString *) aTarget { if ([aTarget isEqualToString: _(@"Default")]) { return nil; } else if ([aTarget isEqualToString: _(@"Debug")]) { return [NSArray arrayWithObject: @"debug=yes"]; } else if ([aTarget isEqualToString: _(@"Profile")]) { return [NSArray arrayWithObject: @"profile=yes"]; } else if ([aTarget isEqualToString: _(@"Install")]) { return [NSArray arrayWithObject: @"install"]; } else { NSLog(@"Unknown target \"%@\" passed to " @"-prepareForBuildByBuilder:target:", aTarget); return nil; } } - (BOOL) prepareForCleanByBuilder: (id) sender target: (NSString *) aTarget { return [self prepareMakefile]; } - (NSArray *) cleanArgumentsForBuilder: (id) sender target: (NSString *) aTarget { if ([aTarget isEqualToString: _(@"Default")] || [aTarget isEqualToString: _(@"Install")]) { return [NSArray arrayWithObject: @"clean"]; } else { return [NSArray arrayWithObject: @"distclean"]; } } @end