// // "$Id$" // // IDE and Build FIle generation for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2009 by Bill Spitzak and others. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library 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 // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // // Please report all bugs and problems on the following page: // // http://www.fltk.org/str.php // #define XCODE_DEFAULT 1 /* XCODE 3.0 IDE FILES The Xcode 3.0 IDE file format is using a quite comlex tree of multiply linked entries to leave as much possibilities to developers as somehow possible. To write this format, we will need to generate a bunch of new unique IDs that will be stored in the DB. "rootObject" is a PBXProject [/ide/Xcode/xcRootObjectID] link to "buildConfigurationList" [/ide/Xcode/xcBuildConfigurationListID] link to "mainGroup" PBXGroup [/ide/Xcode/xcMainGroupID] link to "productRefGroup" PBXGroup [/ide/Xcode/xcProductsGroupID] array of links to "target" PBXNativeTarget [/targets/apps|libs|tests/#/xcTargetID] "buildConfigurationList" is a XCConfigurationList array of links to buildConfiguration "Debug" [/ide/Xcode/xcBuildConfigurationDebugID] "Release" [/ide/Xcode/xcBuildConfigurationReleaseID] ... but also [/targets/apps|libs|tests/#/xcBuildConfigurationListID] [/targets/apps|libs|tests/#/xcBuildConfigurationDebugID] [/targets/apps|libs|tests/#/xcBuildConfigurationReleaseID] "buildConfiguration" is a XCBuildConfiguration no links "mainGroup" is a PBXGroup array of links to PBXFileReference and PBXGroup [/ide/Xcode/xc...GroupID] and also [/targets/apps|libs/#/xcGroupID] "target" is a "PBXNaticeTarget" [/targets/apps|libs|tests/#/xcTargetID] link to buildConfigurationList [/targets/apps|libs|tests/#/xcBuildConfigurationListID] array of links to buildPhases Headers [/targets/apps|libs|tests/#/xcBuildHeadersID] (libs only) Resources [/targets/apps|libs|tests/#/xcBuildResourcesID] Sources [/targets/apps|libs|tests/#/xcBuildSourcesID] Frameworks [/targets/apps|libs|tests/#/xcBuildFrameworksID] CopyFiles [/targets/apps|libs|tests/#/xcBuildCopyFilesID] (not for libs) array of links to buildRules [/targets/apps|libs|tests/#/xcBuildRuleFlID] etc. array of links to dependencies [/targets/apps|libs|tests/#/dependencies/#/xcDependencyID] link to productReference [/targets/apps|libs|tests/#/xcProductID] "buildPhase" is a PBX...BuildPhase [/targets/apps|libs|tests/#/xcBuild...ID] array of links to buildFile [/targets/apps|libs|tests/#/sources|libs|fl/#/xcBuildFileID] "buildFile" is a PBXBuildFile [/targets/apps|libs|tests/#/sources|libs|fl/#/xcBuildFileID] links to file (PBXFileReference) [/files/#/xcFileID] "buildRule" is a PBXBuildRule [/targets/apps|libs|tests/#/xcBuildRuleFlID] etc. no links "dependency" is a PBXTargetDependency [/targets/apps|libs|tests/#/dependencies/#/xcDependencyID] link to target "PBXNativeTarget" (see above) link to targetProxy "PBXContainerItemProxy" /targets/apps|libs|tests/#/dependencies/#/xcProxyID] "file" "productReference" is a PBXFileReference no links "targetProxy" is a PBXContainerItemProxy links to containerPortal (=rootObject) [/ide/Xcode/xcRootObjectID] links to remoteGlobalIDString "PBXNativeTarget" (see above) [/targets/apps|libs|tests/#/xcTargetID] */ #include "ide_support.h" #include #include #include "../src/flstring.h" #include "Fl_Type.h" /* * This class creates all Xcode 3.0 IDE files. */ class Xcode3_IDE { char *rootDir; char projectName[80]; Fl_Preferences tgtAppsDB; int nTgtApps; Fl_Preferences tgtLibsDB; int nTgtLibs; Fl_Preferences tgtTestsDB; int nTgtTests; Fl_Preferences filesDB; int nFiles; Fl_Preferences ideDB; XCID xcRootNodeID; XCID xcBuildConfigurationListID; XCID xcMainGroupID; XCID xcProductsGroupID; XCID xcAppsGroupID; XCID xcLibsGroupID; XCID xcTestsGroupID; XCID xcBuildConfigurationDebugID; XCID xcBuildConfigurationReleaseID; public: Xcode3_IDE(Fl_Preferences &db, const char *rootDirA) : rootDir(strdup(rootDirA)), tgtAppsDB(db, "targets/apps"), tgtLibsDB(db, "targets/libs"), tgtTestsDB(db, "targets/tests"), filesDB(db, "files"), ideDB(db, "ide/Xcode") { db.get("projectName", projectName, "Unnamed", 80); nTgtApps = tgtAppsDB.groups(); nTgtLibs = tgtLibsDB.groups(); nTgtTests = tgtTestsDB.groups(); nFiles = filesDB.groups(); getXCID(ideDB, "xcRootNodeID", xcRootNodeID); getXCID(ideDB, "xcBuildConfigurationListID", xcBuildConfigurationListID); getXCID(ideDB, "xcMainGroupID", xcMainGroupID); getXCID(ideDB, "xcProductsGroupID", xcProductsGroupID); getXCID(ideDB, "xcAppsGroupID", xcAppsGroupID); getXCID(ideDB, "xcLibsGroupID", xcLibsGroupID); getXCID(ideDB, "xcTestsGroupID", xcTestsGroupID); getXCID(ideDB, "xcBuildConfigurationDebugID", xcBuildConfigurationDebugID); getXCID(ideDB, "xcBuildConfigurationReleaseID", xcBuildConfigurationReleaseID); } ~Xcode3_IDE() { if (rootDir) free(rootDir); } /* * Write all files required during the actual build. * These are actually forwarding links from the build setup into the * files section. */ int writeBuildFiles(FILE *out, Fl_Preferences &targetDB) { // FIXME: also write .app, .plist, and maybe headers // --- write all references to sources from the given target Fl_Preferences sourcesDB(targetDB, "sources"); int i, n = sourcesDB.groups(); for (i=0; i\"; };\n", xcFileID, fullName, fullName, pathAndName ); filetype = 0L; } else if (strcmp(ext, ".framework")==0) { fprintf(out, "\t\t%s /* %s */ = {isa = PBXFileReference; " "lastKnownFileType = \"wrapper.framework\"; " "name = %s; path = %s; " "sourceTree = \"\"; };\n", xcFileID, fullName, fullName, pathAndName ); filetype = 0L; } else if (strcmp(ext, ".icns")==0) { fprintf(out, "\t\t%s /* %s */ = {isa = PBXFileReference; " "lastKnownFileType = \"image.icns\"; " "name = %s; path = %s; " "sourceTree = \"\"; };\n", xcFileID, fullName, fullName, pathAndName ); filetype = 0L; } else if (strcmp(ext, ".plist")==0) { filetype = "text.plist.xml"; } if (filetype) fprintf(out, "\t\t%s /* %s */ = {isa = PBXFileReference; fileEncoding = 4; " "lastKnownFileType = %s; name = %s; " "path = ../../%s; sourceTree = SOURCE_ROOT; };\n", xcFileID, fullName, filetype, fullName, pathAndName); } fprintf(out, "/* End PBXFileReference section */\n\n"); return 0; } /* * List all framework build phases */ int writeFrameworksBuildPhase(FILE *out, Fl_Preferences &targetDB) { MAKE_XCID(xcBuildFrameworksID, targetDB); fprintf(out, "\t\t%s /* Frameworks */ = {\n", xcBuildFrameworksID); fprintf(out, "\t\t\tisa = PBXFrameworksBuildPhase;\n"); fprintf(out, "\t\t\tbuildActionMask = 2147483647;\n"); fprintf(out, "\t\t\tfiles = (\n"); Fl_Preferences libsDB(targetDB, "libs"); int i, n = libsDB.groups(); for (i=0; i\";\n"); fprintf(out, "\t\t};\n"); return 0; } /* * Groups define the folder hierarchy in the "Groups & Files" panel */ int writeGroupSection(FILE *out) { int i; char name[80]; fprintf(out, "/* Begin PBXGroup section */\n"); // --- FIXME: missing "icons" group // --- main group fprintf(out, "\t\t%s = {\n", xcMainGroupID); fprintf(out, "\t\t\tisa = PBXGroup;\n"); fprintf(out, "\t\t\tchildren = (\n"); fprintf(out, "\t\t\t\t%s /* Applications */,\n", xcAppsGroupID); fprintf(out, "\t\t\t\t%s /* Frameworks */,\n", xcLibsGroupID); fprintf(out, "\t\t\t\t%s /* Tests */,\n", xcTestsGroupID); fprintf(out, "\t\t\t\t%s /* Products */,\n", xcProductsGroupID); // link to "Products" group fprintf(out, "\t\t\t);\n"); fprintf(out, "\t\t\tsourceTree = \"\";\n"); fprintf(out, "\t\t};\n"); // --- "Products" group fprintf(out, "\t\t%s /* Products */ = {\n", xcProductsGroupID); fprintf(out, "\t\t\tisa = PBXGroup;\n"); fprintf(out, "\t\t\tchildren = (\n"); for (i=0; i\";\n"); fprintf(out, "\t\t};\n"); // --- FIXME: missing "plists" group // --- "Applications" group fprintf(out, "\t\t%s /* Applications */ = {\n", xcAppsGroupID); fprintf(out, "\t\t\tisa = PBXGroup;\n"); fprintf(out, "\t\t\tchildren = (\n"); for (i=0; i\";\n"); fprintf(out, "\t\t};\n"); for (i=0; i\";\n"); fprintf(out, "\t\t};\n"); for (i=0; i\";\n"); fprintf(out, "\t\t};\n"); for (i=0; i\n#endif\n\n", f); fclose(f); return 0; } int createIcons(const char *filepath) { // FIXME: LATER: create a minimum set of icon files? return 0; } /* * create a single plists/[name]-Info.plist */ int writePList(const char *filepath, Fl_Preferences &target_db, int fmwk=0) { char name[80]; target_db.get("name", name, "DBERROR", 79); char filename[2048]; fl_snprintf(filename, 2047, "%s/%s-Info.plist", filepath, name); FILE *f = fopen(filename, "wb"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\tCFBundleDevelopmentRegion\n"); fprintf(f, "\tEnglish\n"); if (strcmp(name, "Fluid")==0) { // TODO: this option is not yet in the database fprintf(f, "\tCFBundleDocumentTypes\n"); fprintf(f, "\t\n"); fprintf(f, "\t\t\n"); fprintf(f, "\t\t\tCFBundleTypeExtensions\n"); fprintf(f, "\t\t\t\n"); fprintf(f, "\t\t\t\tfl\n"); fprintf(f, "\t\t\t\n"); fprintf(f, "\t\t\tCFBundleTypeIconFile\n"); fprintf(f, "\t\t\tfluid_doc\n"); fprintf(f, "\t\t\tCFBundleTypeName\n"); fprintf(f, "\t\t\tFluid Documents\n"); fprintf(f, "\t\t\tCFBundleTypeOSTypes\n"); fprintf(f, "\t\t\t\n"); fprintf(f, "\t\t\t\tflid\n"); fprintf(f, "\t\t\t\n"); fprintf(f, "\t\t\tCFBundleTypeRole\n"); fprintf(f, "\t\t\tEditor\n"); fprintf(f, "\t\t\tLSTypeIsPackage\n"); fprintf(f, "\t\t\t\n"); fprintf(f, "\t\t\tNSPersistentStoreTypeKey\n"); fprintf(f, "\t\t\tBinary\n"); fprintf(f, "\t\t\n"); fprintf(f, "\t\n"); } fprintf(f, "\tCFBundleExecutable\n"); fprintf(f, "\t${EXECUTABLE_NAME}\n"); // find the first suitable icon file if there is one Fl_Preferences extsDB(target_db, "externals"); int i, n = extsDB.groups(); for (i=0; iCFBundleIconFile\n\t%s", fileDB.fileName()); break; } } } fprintf(f, "\tCFBundleIdentifier\n"); fprintf(f, "\torg.fltk.%s\n", name); fprintf(f, "\tCFBundleInfoDictionaryVersion\n"); fprintf(f, "\t6.0\n"); fprintf(f, "\tCFBundlePackageType\n"); if (fmwk) fprintf(f, "\tFMWK\n"); else fprintf(f, "\tAPPL\n"); fprintf(f, "\tCFBundleSignature\n"); fprintf(f, "\tFLTK\n"); fprintf(f, "\tCFBundleVersion\n"); fprintf(f, "\t1.0\n"); fprintf(f, "\n"); fprintf(f, "\t\n"); fclose(f); return 0; } /* * Create the plist files for all apps and tests */ int writePLists(const char *filepath) { int i; for (i=0; i : create all IDE files for an Xcode3 project"; } int arg(int argc, char **argv, int &i) { if (argc>=i+1 && strcmp(argv[i], "--dbxcode3")==0) { if (argc>=i+3 && argv[i+1][0]!='-' && argv[i+2][0]!='-') { fprintf(stderr, "Creating Xcode 3.0 IDE from %s in %s\n", argv[i+1], argv[i+2]); exit_early = 1; generate_fltk_Xcode3_support(argv[i+1], argv[i+2]); i = i+3; return 3; } else { fprintf(stderr, "Missing argument: --dbxcode3 \n"); return 1; } } return 0; } int test(const char *a1, const char *a2, const char *a3) { generate_fltk_Xcode3_support(a1, a2); return 0; } }; Fl_IDE_Xcode_Plugin IDE_Xcode_Plugin; /* Random bit of information: ~/Library/Application Support/Developer/Shared/Xcode/Specifications/fluid.pbfilespec { Identifier = sourcecode.fluid; BasedOn = sourcecode; Extensions = (fl); }, */ // // End of "$Id$". //