Changeset 239

Show
Ignore:
Timestamp:
07/15/07 10:23:13 (1 year ago)
Author:
ddribin
Message:

Add --output-dir, --machine-dir, and --human-dir options. Import ddcli 1.0 for command line parsing. Beef up help output. Bump version to 1.4.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cocoa/mogenerator

    • Property svn:ignore set to
      build
      scratch
  • trunk/cocoa/mogenerator/mogenerator.m

    r236 r239  
    1515#import "nsenumerate.h" 
    1616#import "NSString+MiscAdditions.h" 
    17  
    18 #include <getopt.h> 
     17#import "DDCommandLineInterface.h" 
    1918 
    2019NSString        *gCustomBaseClass; 
     
    165164         
    166165        NSLog(@"appSupportFileNamed(@\"%@\"): file not found", fileName_); 
    167         exit(1); 
     166        exit(EXIT_FAILURE); 
    168167        return nil; 
    169168} 
    170169 
    171 #define DEOPT_(OPTION_NAME) OPTION_NAME+(sizeof("opt_")-1) 
    172 #define LONG_OPT(OPTION_NAME, HAS_ARG)  {DEOPT_(#OPTION_NAME), HAS_ARG, NULL, OPTION_NAME} 
    173 #define LONG_OPT_LAST { NULL,0,NULL,0 } 
    174  
    175 enum { 
    176         opt_help = 1, 
    177         opt_version, 
    178         opt_model, 
    179         opt_baseClass, 
    180         opt_includem, 
    181         opt_templatePath 
    182 }; 
    183  
    184 int main (int argc, const char * argv[]) { 
    185         NSAutoreleasePool       *pool = [[NSAutoreleasePool alloc] init]; 
    186          
    187         NSManagedObjectModel *model = nil; 
    188         NSString                        *tempMOMPath = nil; 
    189         NSString                        *mfilePath = nil; 
    190         NSMutableString         *mfileContent = [NSMutableString stringWithString:@""]; 
    191          
    192         static struct option longopts[] = { 
    193                 LONG_OPT(opt_help, no_argument), 
    194                 LONG_OPT(opt_version, no_argument), 
    195                 LONG_OPT(opt_model, required_argument), 
    196                 LONG_OPT(opt_baseClass, required_argument), 
    197                 LONG_OPT(opt_includem, required_argument), 
    198                 LONG_OPT(opt_templatePath, required_argument), 
    199                 LONG_OPT_LAST 
    200         }; 
    201         int opt_code; 
    202         while ((opt_code = getopt_long_only(argc, (char* const*)argv, "m:", longopts, NULL)) != -1) { 
    203                 switch (opt_code) { 
    204                         case opt_model: 
    205                                 assert(!model); // Currently we only can load one model. 
    206                                 NSString *path = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:optarg length:strlen(optarg)]; 
    207  
    208                                 if( ![[NSFileManager defaultManager] fileExistsAtPath:path]){ 
    209                                         fprintf(stderr, "mogenerator: error loading file at %s: no such file exists.\n", optarg); 
    210                                         return ENOENT; 
    211                                 } 
    212                                          
    213                                 if ([[path pathExtension] isEqualToString:@"xcdatamodel"]) { 
    214                                         //      We've been handed a .xcdatamodel data model, transparently compile it into a .mom managed object model. 
    215                                         NSString *momc = [[NSFileManager defaultManager] fileExistsAtPath:@"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"] 
    216                                                 ? @"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc" 
    217                                                 : @"/Developer/Library/Xcode/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"; 
    218                                          
    219                                         tempMOMPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[(id)CFUUIDCreateString(kCFAllocatorDefault, CFUUIDCreate(kCFAllocatorDefault)) autorelease]] stringByAppendingPathExtension:@"mom"]; 
    220                                         system([[NSString stringWithFormat:@"\"%@\" %@ %@", momc, path, tempMOMPath] UTF8String]); // Ignored system's result -- momc doesn't return any relevent error codes. 
    221                                         path = tempMOMPath; 
    222                                 } 
    223                                 model = [[[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]] autorelease]; 
    224                                 assert(model); 
    225                                 break; 
    226                         case opt_baseClass: 
    227                                 gCustomBaseClass = [NSString stringWithUTF8String:optarg]; 
    228                                 break; 
    229                         case opt_includem: 
    230                                 assert(!mfilePath); 
    231                                 mfilePath = [NSString stringWithUTF8String:optarg]; 
    232                                 assert(mfilePath); 
    233                                 assert([mfilePath length]); 
    234                                 break; 
    235                         case opt_version: 
    236                                 printf("mogenerator 1.3. By Jonathan 'Wolf' Rentzsch + friends.\n"); 
    237                                 break; 
    238                         case opt_templatePath: 
    239                                 gTemplatePath = [NSString stringWithUTF8String:optarg]; 
    240                                 break; 
    241                         case opt_help: 
    242                         default: 
    243                                 printf("mogenerator [-model /path/to/file.xcdatamodel] [-baseClass MyBaseClassMO] [-includem include.m] [-version] [-templatePath] [-help]\n"); 
    244                                 printf("Implements generation gap codegen pattern for Core Data. Inspired by eogenerator.\n"); 
    245                 } 
    246         } 
    247         argc -= optind; 
    248         argv += optind; 
    249          
     170@interface MOGeneratorApp : NSObject <DDCliApplicationDelegate> 
     171
     172        NSString * tempMOMPath; 
     173    NSManagedObjectModel * model; 
     174    NSString * baseClass; 
     175    NSString * includem; 
     176    NSString * templatePath; 
     177    NSString * outputDir; 
     178    NSString * machineDir; 
     179    NSString * humanDir; 
     180    BOOL _help; 
     181    BOOL _version; 
     182
     183 
     184@end 
     185 
     186@implementation MOGeneratorApp 
     187 
     188- (void) application: (DDCliApplication *) app 
     189    willParseOptions: (DDGetoptLongParser *) optionsParser; 
     190
     191    [optionsParser setGetoptLongOnly: YES]; 
     192    DDGetoptOption optionTable[] =  
     193    { 
     194    // Long             Short   Argument options 
     195    {@"model",          'm',    DDGetoptRequiredArgument}, 
     196    {@"base-class",      0,     DDGetoptRequiredArgument}, 
     197    // For compatibility: 
     198    {@"baseClass",      0,      DDGetoptRequiredArgument}, 
     199    {@"includem",       0,      DDGetoptRequiredArgument}, 
     200    {@"template-path",  0,      DDGetoptRequiredArgument}, 
     201    // For compatibility: 
     202    {@"templatePath",   0,      DDGetoptRequiredArgument}, 
     203    {@"output-dir",     'O',    DDGetoptRequiredArgument}, 
     204    {@"machine-dir",    'M',    DDGetoptRequiredArgument}, 
     205    {@"human-dir",      'H',    DDGetoptRequiredArgument}, 
     206 
     207    {@"help",           'h',    DDGetoptNoArgument}, 
     208    {@"version",        0,      DDGetoptNoArgument}, 
     209    {nil,               0,      0}, 
     210    }; 
     211    [optionsParser addOptionsFromTable: optionTable]; 
     212
     213 
     214- (void) printUsage; 
     215
     216    ddprintf(@"%@: Usage [OPTIONS] <argument> [...]\n", DDCliApp); 
     217    printf("\n" 
     218           "  -m, --model MODEL             Path to model\n" 
     219           "      --base-class CLASS        Custom base class\n" 
     220           "      --includem FILE           Generate aggregate include file\n" 
     221           "      --template-path PATH      Path to templates\n" 
     222           "  -O, --output-dir DIR          Output directory\n" 
     223           "  -M, --machine-dir DIR         Output directory for machine files\n" 
     224           "  -H, --human-dir DIR           Output director for human files\n" 
     225           "      --version                 Display version and exit\n" 
     226           "  -h, --help                    Display this help and exit\n" 
     227           "\n" 
     228           "Implements generation gap codegen pattern for Core Data.\n" 
     229           "Inspired by eogenerator.\n"); 
     230
     231 
     232- (void) setModel: (NSString *) path; 
     233
     234    assert(!model); // Currently we only can load one model. 
     235 
     236    if( ![[NSFileManager defaultManager] fileExistsAtPath:path]){ 
     237        NSString * reason = [NSString stringWithFormat: @"error loading file at %@: no such file exists", path]; 
     238        DDCliParseException * e = [DDCliParseException parseExceptionWithReason: reason 
     239                                                                       exitCode: EX_NOINPUT]; 
     240        @throw e; 
     241    } 
     242 
     243    if ([[path pathExtension] isEqualToString:@"xcdatamodel"]) { 
     244        //      We've been handed a .xcdatamodel data model, transparently compile it into a .mom managed object model. 
     245        NSString *momc = [[NSFileManager defaultManager] fileExistsAtPath:@"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"] 
     246        ? @"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc" 
     247        : @"/Developer/Library/Xcode/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"; 
     248         
     249        tempMOMPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[(id)CFUUIDCreateString(kCFAllocatorDefault, CFUUIDCreate(kCFAllocatorDefault)) autorelease]] stringByAppendingPathExtension:@"mom"]; 
     250        system([[NSString stringWithFormat:@"\"%@\" %@ %@", momc, path, tempMOMPath] UTF8String]); // Ignored system's result -- momc doesn't return any relevent error codes. 
     251        path = tempMOMPath; 
     252    } 
     253    model = [[[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]] autorelease]; 
     254    assert(model); 
     255
     256 
     257- (int) application: (DDCliApplication *) app 
     258   runWithArguments: (NSArray *) arguments; 
     259
     260    if (_help) 
     261    { 
     262        [self printUsage]; 
     263        return EXIT_SUCCESS; 
     264    } 
     265     
     266    if (_version) 
     267    { 
     268        printf("mogenerator 1.4. By Jonathan 'Wolf' Rentzsch + friends.\n"); 
     269        return EXIT_SUCCESS; 
     270    } 
     271     
     272    gCustomBaseClass = [baseClass retain]; 
     273    gTemplatePath = templatePath; 
     274    NSString * mfilePath = includem; 
     275        NSMutableString * mfileContent = [NSMutableString stringWithString:@""]; 
     276    if (outputDir == nil) 
     277        outputDir = @""; 
     278    if (machineDir == nil) 
     279        machineDir = outputDir; 
     280    if (humanDir == nil) 
     281        humanDir = outputDir; 
     282 
    250283        NSFileManager *fm = [NSFileManager defaultManager]; 
    251  
     284     
    252285        int machineFilesGenerated = 0;         
    253286        int humanFilesGenerated = 0; 
     
    262295                MiscMergeEngine *humanM = engineWithTemplatePath(appSupportFileNamed(@"human.m.motemplate")); 
    263296                assert(humanM);  
    264  
     297         
    265298                int entityCount = [[model entities] count]; 
    266  
     299         
    267300                if(entityCount == 0){  
    268301                        printf("No entities found in model. No files will be generated.\n"); 
     
    272305                nsenumerate ([model entities], NSEntityDescription, entity) { 
    273306                        NSString *entityClassName = [entity managedObjectClassName]; 
    274  
     307             
    275308                        if ([entityClassName isEqualToString:@"NSManagedObject"] || 
    276309                                [entityClassName isEqualToString:gCustomBaseClass]){ 
    277                                 printf("skipping entity %s because it doesn't use a custom subclass.\n",  
    278                                           [entityClassName cStringUsingEncoding:NSUTF8StringEncoding]); 
     310                                ddprintf(@"skipping entity %@ because it doesn't use a custom subclass.\n",  
     311                         entityClassName); 
    279312                                continue; 
    280313                        } 
     
    287320                        BOOL machineDirtied = NO; 
    288321                         
    289                         NSString *machineHFileName = [NSString stringWithFormat:@"_%@.h", entityClassName]; 
     322                        NSString *machineHFileName = [machineDir stringByAppendingPathComponent: 
     323                [NSString stringWithFormat:@"_%@.h", entityClassName]]; 
    290324                        if (![fm regularFileExistsAtPath:machineHFileName] || ![generatedMachineH isEqualToString:[NSString stringWithContentsOfFile:machineHFileName]]) { 
    291325                                //      If the file doesn't exist or is different than what we just generated, write it out. 
     
    294328                                machineFilesGenerated++; 
    295329                        } 
    296                         NSString *machineMFileName = [NSString stringWithFormat:@"_%@.m", entityClassName]; 
     330                        NSString *machineMFileName = [machineDir stringByAppendingPathComponent: 
     331                [NSString stringWithFormat:@"_%@.m", entityClassName]]; 
    297332                        if (![fm regularFileExistsAtPath:machineMFileName] || ![generatedMachineM isEqualToString:[NSString stringWithContentsOfFile:machineMFileName]]) { 
    298333                                //      If the file doesn't exist or is different than what we just generated, write it out. 
     
    301336                                machineFilesGenerated++; 
    302337                        } 
    303                         NSString *humanHFileName = [NSString stringWithFormat:@"%@.h", entityClassName]; 
     338                        NSString *humanHFileName = [humanDir stringByAppendingPathComponent: 
     339                [NSString stringWithFormat:@"%@.h", entityClassName]]; 
    304340                        if ([fm regularFileExistsAtPath:humanHFileName]) { 
    305341                                if (machineDirtied) 
     
    309345                                humanFilesGenerated++; 
    310346                        } 
    311                         NSString *humanMFileName = [NSString stringWithFormat:@"%@.m", entityClassName]; 
    312                         NSString *humanMMFileName = [NSString stringWithFormat:@"%@.mm", entityClassName]; 
     347                        NSString *humanMFileName = [humanDir stringByAppendingPathComponent: 
     348                [NSString stringWithFormat:@"%@.m", entityClassName]]; 
     349                        NSString *humanMMFileName = [humanDir stringByAppendingPathComponent: 
     350                [NSString stringWithFormat:@"%@.mm", entityClassName]]; 
    313351                        if (![fm regularFileExistsAtPath:humanMFileName] && [fm regularFileExistsAtPath:humanMMFileName]) { 
    314352                                //      Allow .mm human files as well as .m files. 
     
    324362                        } 
    325363                         
    326                         [mfileContent appendFormat:@"#include \"%@\"\n#include \"%@\"\n", humanMFileName, machineMFileName]; 
     364                        [mfileContent appendFormat:@"#include \"%@\"\n#include \"%@\"\n", 
     365                [humanMFileName lastPathComponent], [machineMFileName lastPathComponent]]; 
    327366                } 
    328367        } 
     
    339378        printf("%d machine files%s %d human files%s generated.\n", machineFilesGenerated, 
    340379                   (mfileGenerated ? "," : " and"), humanFilesGenerated, (mfileGenerated ? " and one include.m file" : "")); 
    341          
    342         [pool release]; 
    343         return 0; 
    344 
     380     
     381    return EXIT_SUCCESS; 
     382
     383 
     384@end 
     385 
     386int main (int argc, char * const * argv) 
     387
     388    return DDCliAppRunWithClass([MOGeneratorApp class]); 
     389
     390 
  • trunk/cocoa/mogenerator/mogenerator.xcodeproj/project.pbxproj

    r228 r239  
    88 
    99/* Begin PBXBuildFile section */ 
     10                55200E960C49FEEA00018A42 /* DDCliApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200E900C49FEEA00018A42 /* DDCliApplication.m */; }; 
     11                55200E970C49FEEA00018A42 /* DDCliUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200E920C49FEEA00018A42 /* DDCliUtil.m */; }; 
     12                55200E980C49FEEA00018A42 /* DDGetoptLongParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200E950C49FEEA00018A42 /* DDGetoptLongParser.m */; }; 
     13                55200F9D0C4A2CA800018A42 /* DDCliParseException.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200F9C0C4A2CA800018A42 /* DDCliParseException.m */; }; 
    1014                79D2BF3F0ACFB25B00F3F141 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79D2BF3E0ACFB25B00F3F141 /* CoreData.framework */; }; 
    1115                79D2BFA20ACFB51A00F3F141 /* _MiscMergeBreakCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 79D2BF530ACFB51A00F3F141 /* _MiscMergeBreakCommand.m */; }; 
     
    5761                08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 
    5862                32A70AAB03705E1F00C91783 /* mogenerator_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mogenerator_Prefix.pch; sourceTree = "<group>"; }; 
     63                55200E8F0C49FEEA00018A42 /* DDCliApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCliApplication.h; sourceTree = "<group>"; }; 
     64                55200E900C49FEEA00018A42 /* DDCliApplication.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDCliApplication.m; sourceTree = "<group>"; }; 
     65                55200E910C49FEEA00018A42 /* DDCliUtil.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCliUtil.h; sourceTree = "<group>"; }; 
     66                55200E920C49FEEA00018A42 /* DDCliUtil.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDCliUtil.m; sourceTree = "<group>"; }; 
     67                55200E930C49FEEA00018A42 /* DDCommandLineInterface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCommandLineInterface.h; sourceTree = "<group>"; }; 
     68                55200E940C49FEEA00018A42 /* DDGetoptLongParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDGetoptLongParser.h; sourceTree = "<group>"; }; 
     69                55200E950C49FEEA00018A42 /* DDGetoptLongParser.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDGetoptLongParser.m; sourceTree = "<group>"; }; 
     70                55200F9B0C4A2CA800018A42 /* DDCliParseException.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCliParseException.h; sourceTree = "<group>"; }; 
     71                55200F9C0C4A2CA800018A42 /* DDCliParseException.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDCliParseException.m; sourceTree = "<group>"; }; 
    5972                79D2BF3E0ACFB25B00F3F141 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; 
    6073                79D2BF520ACFB51A00F3F141 /* _MiscMergeBreakCommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = _MiscMergeBreakCommand.h; path = ../MiscMerge/_MiscMergeBreakCommand.h; sourceTree = "<group>"; }; 
     
    161174                                08FB7795FE84155DC02AAC07 /* Source */, 
    162175                                79D2BF510ACFB51000F3F141 /* MiscMerge */, 
     176                                55200E8E0C49FEEA00018A42 /* ddcli */, 
    163177                                08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, 
    164178                                1AB674ADFE9D54B511CA2CBB /* Products */, 
     
    194208                        ); 
    195209                        name = Products; 
     210                        sourceTree = "<group>"; 
     211                }; 
     212                55200E8E0C49FEEA00018A42 /* ddcli */ = { 
     213                        isa = PBXGroup; 
     214                        children = ( 
     215                                55200F9B0C4A2CA800018A42 /* DDCliParseException.h */, 
     216                                55200F9C0C4A2CA800018A42 /* DDCliParseException.m */, 
     217                                55200E8F0C49FEEA00018A42 /* DDCliApplication.h */, 
     218                                55200E900C49FEEA00018A42 /* DDCliApplication.m */, 
     219                                55200E910C49FEEA00018A42 /* DDCliUtil.h */, 
     220                                55200E920C49FEEA00018A42 /* DDCliUtil.m */, 
     221                                55200E930C49FEEA00018A42 /* DDCommandLineInterface.h */, 
     222                                55200E940C49FEEA00018A42 /* DDGetoptLongParser.h */, 
     223                                55200E950C49FEEA00018A42 /* DDGetoptLongParser.m */, 
     224                        ); 
     225                        path = ddcli; 
    196226                        sourceTree = "<group>"; 
    197227                }; 
     
    364394                                79D2BFEF0ACFB51A00F3F141 /* NSString+MiscAdditions.m in Sources */, 
    365395                                79D2C05A0ACFBCB500F3F141 /* FoundationAdditions.m in Sources */, 
     396                                55200E960C49FEEA00018A42 /* DDCliApplication.m in Sources */, 
     397                                55200E970C49FEEA00018A42 /* DDCliUtil.m in Sources */, 
     398                                55200E980C49FEEA00018A42 /* DDGetoptLongParser.m in Sources */, 
     399                                55200F9D0C4A2CA800018A42 /* DDCliParseException.m in Sources */, 
    366400                        ); 
    367401                        runOnlyForDeploymentPostprocessing = 0; 
     
    409443                        buildSettings = { 
    410444                                GCC_C_LANGUAGE_STANDARD = c99; 
     445                                GCC_ENABLE_OBJC_EXCEPTIONS = YES; 
    411446                                GCC_WARN_ABOUT_RETURN_TYPE = YES; 
    412447                                GCC_WARN_UNUSED_VARIABLE = YES; 
     
    420455                        buildSettings = { 
    421456                                GCC_C_LANGUAGE_STANDARD = c99; 
     457                                GCC_ENABLE_OBJC_EXCEPTIONS = YES; 
    422458                                GCC_WARN_ABOUT_RETURN_TYPE = YES; 
    423459                                GCC_WARN_UNUSED_VARIABLE = YES; 
  • trunk/cocoa/mogenerator/mogeneratorTestMule

    • Property svn:ignore set to
      build