From 349c02dc2a2edae31c6a478d53367d3f28a71214 Mon Sep 17 00:00:00 2001 From: Dimitre Date: Tue, 10 Sep 2024 17:42:16 -0300 Subject: [PATCH] V75 (#572) --- .github/workflows/build-linux.yml | 2 +- .github/workflows/build-macos.yml | 2 +- commandLine/src/addons/ofAddon.h | 3 +- commandLine/src/defines.h | 4 +- commandLine/src/main.cpp | 179 ++++++------ commandLine/src/projects/baseProject.cpp | 90 +++++- commandLine/src/projects/baseProject.h | 45 +-- .../src/projects/visualStudioProject.cpp | 1 + commandLine/src/projects/xcodeProject.cpp | 264 +++++++++--------- 9 files changed, 305 insertions(+), 285 deletions(-) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 552b54b2..ca14601e 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.12 + uses: hendrikmuhs/ccache-action@v1.2.14 with: key: ${{ matrix.cfg.target }} diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 08fee503..56ee9d71 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -27,7 +27,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.12 + uses: hendrikmuhs/ccache-action@v1.2.14 with: # key: ${{ matrix.os }}-${{ matrix.type }} key: ${{ matrix.os }}-${{ matrix.cfg.target }} diff --git a/commandLine/src/addons/ofAddon.h b/commandLine/src/addons/ofAddon.h index dc6af653..6bb8ac38 100644 --- a/commandLine/src/addons/ofAddon.h +++ b/commandLine/src/addons/ofAddon.h @@ -218,7 +218,8 @@ class ofAddon { fs::path normalizePath(const fs::path& path) { try { - auto value = fs::weakly_canonical(path); +// auto value = fs::weakly_canonical(path); + auto value = fs::relative(path); return value; } catch (const std::exception& ex) { std::cout << "Canonical path for [" << path << "] threw exception:\n" diff --git a/commandLine/src/defines.h b/commandLine/src/defines.h index 24027822..bdfb00ab 100644 --- a/commandLine/src/defines.h +++ b/commandLine/src/defines.h @@ -1,5 +1,5 @@ #define OFPROJECTGENERATOR_MAJOR_VERSION 0 -#define OFPROJECTGENERATOR_MINOR_VERSION 74 +#define OFPROJECTGENERATOR_MINOR_VERSION 75 #define OFPROJECTGENERATOR_PATCH_VERSION 0 -#define PG_VERSION "0.74.0" +#define PG_VERSION "0.75.0" diff --git a/commandLine/src/main.cpp b/commandLine/src/main.cpp index ce69d536..8b26d712 100644 --- a/commandLine/src/main.cpp +++ b/commandLine/src/main.cpp @@ -43,9 +43,9 @@ constexpr option::Descriptor usage[] = { { DRYRUN, 0, "d", "dryrun", option::Arg::None, " --dryrun, -d \tdry run, don't change files" }, { SRCEXTERNAL, 0, "s", "source", option::Arg::Optional, " --source, -s \trelative or absolute path to source or include folders external to the project (such as ../../../../common_utils/" }, { VERSION, 0, "w", "version", option::Arg::None, " --version, -w \treturn the current version" }, - { GET_OFPATH, 0, "g", "getofpath", option::Arg::None, " --getofpath, -g \treturn the current ofPath" }, - { GET_HOST_PLATFORM, 0, "i", "platform", option::Arg::None, " --getplatform, -i \treturn the current host platform" }, - { COMMAND, 0, "c", "command", option::Arg::None, " --command, -c \truns command" }, + { GET_OFPATH, 0, "g", "getofpath", option::Arg::None, " --getofpath, -g \treturn the current ofPath" }, + { GET_HOST_PLATFORM, 0, "i", "platform", option::Arg::None, " --getplatform, -i \treturn the current host platform" }, + { COMMAND, 0, "c", "command", option::Arg::None, " --command, -c \truns command" }, { BACKUP_PROJECT_FILES, 0, "b", "backup", option::Arg::None, " --backup, -b \tbackup project files when replacing with template" }, { 0, 0, 0, 0, 0, 0 } }; @@ -95,7 +95,7 @@ void printVersion() { } void printOFPath() { - std::cout << ofPath.string() << endl; + std::cout << ofPath.string() << endl; } void setofPath(const fs::path& path) { @@ -155,12 +155,12 @@ bool printTemplates() { } } -void handleCommand(const std::string& args) { - if (args == "ping") { - std::cout << "pong" << args << std::endl; - } else { - std::cout << "Unknown custom command: " << args << std::endl; - } +void handleCommand(const std::string & args) { + if (args == "ping") { + std::cout << "pong" << args << std::endl; + } else { + std::cout << "Unknown custom command: " << args << std::endl; + } } @@ -199,7 +199,7 @@ bool isGoodProjectPath(fs::path path) { bool isGoodOFPath(const fs::path & path) { if (!fs::is_directory(path)) { - // ofLogVerbose() << "ofPath: not a directory: " << path.string(); + ofLogVerbose() << "ofPath: not a directory: " << path; return false; } bool bHasTemplates = containsFolder(path, "scripts"); @@ -214,7 +214,7 @@ fs::path findOFPathUpwards(const fs::path & startPath) { // ofLogNotice() << "startPath: " << currentPath.string(); if (currentPath.empty() || currentPath == currentPath.root_path()) { ofLogError() << "Starting path is empty or root path, cannot find OF path." << "\" }"; - return fs::path(); + return {}; } while (!currentPath.empty() && currentPath != currentPath.root_path()) { // ofLogWarning() << "currentPath: " << currentPath.string(); @@ -227,15 +227,15 @@ fs::path findOFPathUpwards(const fs::path & startPath) { currentPath = currentPath.parent_path(); } // ofLogError() << "No valid OF path found... please use -o or --ofPath or set a PG_OF_PATH environment variable: " << startPath.string(); - return fs::path(); + return {}; } void updateProject(const fs::path & path, const string & target, bool bConsiderParameterAddons = true) { - // alert("updateProject path=" + path.string() , 34); + // alert("updateProject path=" + path.string() , 34); // bConsiderParameterAddons = do we consider that the user could call update with a new set of addons // either we read the addons.make file, or we look at the parameter list. // if we are updating recursively, we *never* consider addons passed as parameters. - cout << endl; + consoleSpace(); ofLogNotice() << "updating project " << path; if (!bDryRun) { @@ -260,7 +260,9 @@ void updateProject(const fs::path & path, const string & target, bool bConsiderP void recursiveUpdate(const fs::path & path, const string & target) { // FIXME: remove - alert("recursiveUpdate:[" + path.string() + "]"); +// alert("recursiveUpdate :[" + path.string() + "]"); + ofLogNotice() << "recursiveUpdate " << path; + if (!fs::is_directory(path)) return; vector folders; @@ -269,7 +271,7 @@ void recursiveUpdate(const fs::path & path, const string & target) { folders.emplace_back(path); } - // MARK: - Known issue. it can add undesired folders which can mirror directory of a valid project like + // MARK: Known issue. it can add undesired folders which can mirror directory of a valid project like // "./templates/allAddonsExample/obj/osx/Release" // "./templates/allAddonsExample/bin/build/build/arm64-apple-darwin_Release/obj.room/Volumes/tool/ofw/addons/ofxKinect" @@ -285,9 +287,6 @@ void recursiveUpdate(const fs::path & path, const string & target) { fs::path ofCalcPath = fs::weakly_canonical(fs::current_path() / ofPath); for (auto & path : folders) { - // cout << "------" << endl; - // cout << path << endl; - // cout << "------" << endl; nProjectsUpdated++; if (!ofPath.is_absolute()) { @@ -296,17 +295,14 @@ void recursiveUpdate(const fs::path & path, const string & target) { setofPath(fs::relative(ofCalcPath, path)); } } -// setOFRoot(ofPath); - fs::current_path(path); - //alert ("ofRoot " + ofPath.string()); - //alert ("cwd " + path.string()); + fs::current_path(path); updateProject(path, target, false); } } int updateOFPath(fs::path path) { - + std::string ofPathEnv; auto envValue = ofGetEnv("PG_OF_PATH"); if(!envValue.empty()) { @@ -315,50 +311,50 @@ int updateOFPath(fs::path path) { } if ((ofPath.empty() && !ofPathEnv.empty()) || - ((!ofPath.empty() && !isGoodOFPath(ofPath)) && + ((!ofPath.empty() && !isGoodOFPath(ofPath)) && (!ofPathEnv.empty() && isGoodOFPath(ofPathEnv)))) { setofPath(ofPathEnv); ofLogNotice() << "PG_OF_PATH set: ofPath [" << ofPath << "]"; } of::filesystem::path exePath = ofFilePath::getCurrentExeDir(); - - fs::path startPath = normalizePath(exePath); + + fs::path startPath = normalizePath(exePath); generatorPath = startPath; ofLogVerbose() << "projectGenerator cmd path: {" << startPath << "] }"; - //ofFilePath::getAbsolutePathFS(fs::current_path(), false); + //ofFilePath::getAbsolutePathFS(fs::current_path(), false); // ofLogNotice() << "startPath: " << startPath.string(); - fs::path foundOFPath = findOFPathUpwards(startPath); - if (foundOFPath.empty() && ofPath.empty()) { - ofLogError() << "{ \"errorMessage: \"" << "oF path not found: please use -o or --ofPath or set 'PG_OF_PATH' environment var. Auto up folders from :[" << startPath.string() << "]" << "\" }"; - return EXIT_FAILURE; - } else { - if (!ofPath.empty() && isGoodOFPath(ofPath)) { - ofLogNotice() << "ofPath set and valid using [" << ofPath << "]"; - } else { - if(isGoodOFPath(foundOFPath)) - setofPath(foundOFPath); + fs::path foundOFPath = findOFPathUpwards(startPath); + if (foundOFPath.empty() && ofPath.empty()) { + ofLogError() << "{ \"errorMessage: \"" << "oF path not found: please use -o or --ofPath or set 'PG_OF_PATH' environment var. Auto up folders from :[" << startPath.string() << "]" << "\" }"; + return EXIT_FAILURE; + } else { + if (!ofPath.empty() && isGoodOFPath(ofPath)) { + ofLogNotice() << "ofPath set and valid using [" << ofPath << "]"; + } else { + if(isGoodOFPath(foundOFPath)) + setofPath(foundOFPath); setOFRoot(foundOFPath); - ofLogVerbose() << "ofPath auto-found and valid using [" << ofPath << "]"; - } - } - - if (!ofPath.empty()) { - if (!isGoodOFPath(ofPath)) { - foundOFPath = findOFPathUpwards(ofPath); - if (foundOFPath.empty()) { - ofLogNotice() << "{ \"errorMessage: \"" << "ofPath not valid. [" << ofPath << "] auto-find ofPath failed also..." << "\" }"; - return EXIT_USAGE; - } - } + ofLogVerbose() << "ofPath auto-found and valid using [" << ofPath << "]"; + } + } + + if (!ofPath.empty()) { + if (!isGoodOFPath(ofPath)) { + foundOFPath = findOFPathUpwards(ofPath); + if (foundOFPath.empty()) { + ofLogNotice() << "{ \"errorMessage: \"" << "ofPath not valid. [" << ofPath << "] auto-find ofPath failed also..." << "\" }"; + return EXIT_USAGE; + } + } // if (ofIsPathInPath(projectPath, ofPath)) { // fs::path path = fs::relative(ofPath, projectPath); // ofPath = path.string(); // } - ofPath = normalizePath(ofPath); - setOFRoot(ofPath); - } - - return EXIT_OK; + ofPath = normalizePath(ofPath); + setOFRoot(ofPath); + } + + return EXIT_OK; } void printHelp() { @@ -436,11 +432,11 @@ int main(int argc, char ** argv) { messageError("Parse error for arguments"); return 1; } - - if (options[VERBOSE].count() > 0) { - bVerbose = true; - } - + + if (options[VERBOSE].count() > 0) { + bVerbose = true; + } + if (options[BACKUP_PROJECT_FILES].count() > 0) { bBackup = true; backupProjectFiles = bBackup; @@ -459,12 +455,12 @@ int main(int argc, char ** argv) { if (options[DRYRUN].count() > 0) { bDryRun = true; } - - if (options[VERSION].count() > 0) { - printVersion(); - return EXIT_OK; - } - + + if (options[VERSION].count() > 0) { + printVersion(); + return EXIT_OK; + } + if (options[OFPATH].count() > 0) { if (options[OFPATH].arg != NULL) { setofPath(options[OFPATH].arg); @@ -495,7 +491,7 @@ int main(int argc, char ** argv) { ofLogNotice() << "{ \"ofHostPlatform\": \"" << platformsToString[ofGetTargetPlatform()] << "\" }"; return EXIT_OK; } - + if (options[TEMPLATE].count() > 0) { if (options[TEMPLATE].arg != NULL) { string templateString(options[TEMPLATE].arg); @@ -536,7 +532,7 @@ int main(int argc, char ** argv) { } } } - + #ifndef DEBUG_NO_OPTIONS if (options[HELP] || argc == 0) { printHelp(); @@ -545,7 +541,7 @@ int main(int argc, char ** argv) { } #endif - + if (parse.nonOptionsCount() > 0) { projectName = parse.nonOption(0); @@ -560,12 +556,11 @@ int main(int argc, char ** argv) { consoleSpace(); // try to get the OF_PATH as an environt variable - + if (bVerbose) { ofSetLogLevel(OF_LOG_VERBOSE); } - if (projectName == "") { printHelp(); consoleSpace(); @@ -576,12 +571,12 @@ int main(int argc, char ** argv) { fs::path projectPath = normalizePath(fs::weakly_canonical(fs::current_path() / projectName)); fs::path projectNamePath = projectPath.filename(); projectName = projectNamePath.string(); - - + + ofLogVerbose() << " projectPath path: [" << projectPath << "] root_path: [" << projectPath.root_path() << "]"; ofLogVerbose() << " ofPath path: [" << ofPath << "]"; ofLogVerbose() << " ofRoot path: [" << getOFRoot() << "]"; - + if(projectPath == projectPath.root_path()) { ofLogVerbose() << " !! projectPath == projectPath.root_path() "; } else if(normalizePath(fs::weakly_canonical( projectPath.root_path() / projectName )) == projectPath) { @@ -611,7 +606,7 @@ int main(int argc, char ** argv) { return EXIT_FAILURE; } // make folder - if (!fs::exists(projectPath)) { + if (!fs::exists(projectPath)) { try { ofLogVerbose() << " creating projectPath directory."; fs::create_directories(projectPath); @@ -620,7 +615,7 @@ int main(int argc, char ** argv) { + ex.what() + "\""); return EXIT_FAILURE; } - } else { + } else { if (fs::exists(projectPath)) { ofLogVerbose() << " The project path exists."; if (fs::is_directory(projectPath)) { @@ -629,12 +624,12 @@ int main(int argc, char ** argv) { ofLogVerbose() << " and It is a file..."; } } - } + } if (bListTemplates) { auto ret = printTemplates(); consoleSpace(); - if (ret) { + if (ret) { messageReturn("status", "EXIT_OK"); return EXIT_OK; } else { @@ -649,7 +644,7 @@ int main(int argc, char ** argv) { ofLogNotice() << "-----------------------------------------------"; ofLogNotice() << "updating an existing project"; ofLogNotice() << "target platform is: " << t; - + // MARK: - RECURSIVE UPDATE recursiveUpdate(projectPath, t); @@ -663,20 +658,23 @@ int main(int argc, char ** argv) { } else { nProjectsCreated += 1; + ofLogNotice() << "setting OF path to: [" << ofPath << "]"; + if (busingEnvVar) { + ofLogNotice() << "from PG_OF_PATH environment variable"; + } else { + ofLogNotice() << "from -o option"; + } + + for (auto & t : targets) { + consoleSpace(); ofLogNotice() << "-----------------------------------------------"; - ofLogVerbose() << "target platform is: [" << t << "]"; - ofLogVerbose() << "setting OF path to: [" << ofPath << "]"; - if (busingEnvVar) { - ofLogNotice() << "from PG_OF_PATH environment variable"; - } else { - ofLogNotice() << "from -o option"; - } - ofLogNotice() << "project path is: [" << projectPath << "]"; + ofLogNotice() << "target platform is: [" << t << "]"; +// ofLogNotice() << "project path is: [" << projectPath << "]"; if (templateName != "") { ofLogNotice() << "using additional template " << templateName; } - ofLogNotice() << "setting up new project " << projectPath; + ofLogVerbose() << "setting up new project " << projectPath; if (mode == PG_MODE_UPDATE) { // MARK: - UPDATE @@ -684,7 +682,7 @@ int main(int argc, char ** argv) { ofLogNotice() << "project updated! "; } else { if (!bDryRun) { - ofLogNotice() << "project path is: [" << projectPath << "]"; +// ofLogNotice() << "project path is: [" << projectPath << "]"; auto project = getTargetProject(t); project->create(projectPath, templateName); project->parseAddons(); @@ -700,7 +698,6 @@ int main(int argc, char ** argv) { ofLogNotice() << "project created! "; } ofLogNotice() << "-----------------------------------------------"; - consoleSpace(); } } } diff --git a/commandLine/src/projects/baseProject.cpp b/commandLine/src/projects/baseProject.cpp index 660e28aa..286974d2 100644 --- a/commandLine/src/projects/baseProject.cpp +++ b/commandLine/src/projects/baseProject.cpp @@ -126,8 +126,8 @@ bool baseProject::create(const fs::path & _path, string templateName){ // alert("path " + path.string()); // alert("path " + fs::weakly_canonical(fs::absolute(path)).string()); - cout << endl; - ofLogNotice() << "create project " << path; +// cout << endl; +// ofLogNotice() << "create project " << path; // FIXME: Rewrite here // if (ofIsPathInPath(fs::absolute(path), getOFRoot())) { @@ -165,8 +165,10 @@ bool baseProject::create(const fs::path & _path, string templateName){ try { // think of exclusions to manually merge like plist fs::copy (templatePath / p, projectDir / p, fs::copy_options::recursive | (bOverwrite ? fs::copy_options::overwrite_existing : fs::copy_options::update_existing)); - } catch(fs::filesystem_error& e) { - ofLogNotice() << "Can not copy: " << templatePath / p << " :: " <(fileFrom)), std::istreambuf_iterator()); + fileFrom.close(); + + for (auto & f : findReplaces) { + // Avoid processing empty pairs + if (empty(f.first) && empty(f.second)) { + continue; + } + replaceAll(contents, f.first, f.second); + ofLogVerbose() << "└─ Replacing " << f.first << " : " << f.second; + } + + std::ofstream fileTo(to); + try{ + fileTo << contents; + }catch(std::exception & e){ + ofLogError() << "Error saving to " << to; + ofLogError() << e.what(); + return false; + }catch(...){ + ofLogError() << "Error saving to " << to; + + return false; + } + + + } else { + // straight copy + try { + fs::copy(from, to, fs::copy_options::update_existing); + } + catch(fs::filesystem_error & e) { + ofLogError() << "error copying template file " << from << " : " << to ; + ofLogError() << e.what(); + return false; + } + } + } else { return false; } + return true; } diff --git a/commandLine/src/projects/baseProject.h b/commandLine/src/projects/baseProject.h index b094537d..c26f7bb8 100644 --- a/commandLine/src/projects/baseProject.h +++ b/commandLine/src/projects/baseProject.h @@ -132,50 +132,9 @@ class baseProject { public: fs::path from; fs::path to; - std::vector > findReplaces; + std::vector > findReplaces; - bool run() { - // needed for mingw only. maybe a ifdef here. - if (fs::exists(from)) { - if (findReplaces.size()) { - // Load file, replace contents, write to destination. - - std::ifstream fileFrom(from); - std::string contents((std::istreambuf_iterator(fileFrom)), std::istreambuf_iterator()); - fileFrom.close(); - - for (auto & f : findReplaces) { - replaceAll(contents, f.first, f.second); - } - - std::ofstream fileTo(to); - try{ - fileTo << contents; - }catch(std::exception & e){ - std::cout << "Error saving to " << to << " : " << e.what() << std::endl; - return false; - }catch(...){ - std::cout << "Error saving to " << to << std::endl; - return false; - } - - } else { - // straight copy - try { - fs::copy(from, to, fs::copy_options::update_existing); - } - catch(fs::filesystem_error & e) { - std::cout << "error copying template file " << from << " : " << to << std::endl; - std::cout << e.what() << std::endl; - return false; - } - } - } else { - return false; - } - - return true; - } + bool run(); }; vector copyTemplateFiles; diff --git a/commandLine/src/projects/visualStudioProject.cpp b/commandLine/src/projects/visualStudioProject.cpp index fd16cccd..2cc0a730 100644 --- a/commandLine/src/projects/visualStudioProject.cpp +++ b/commandLine/src/projects/visualStudioProject.cpp @@ -18,6 +18,7 @@ bool visualStudioProject::createProjectFile(){ createBackup({ projectDir / (projectName + ".vcxproj") }, projectDir); } + // FIXME: this will insert an empty pair std::pair replacementsForward, replacementsBack; if (!fs::equivalent(getOFRoot(), fs::path{ "../../.." })) { fs::path root { getOFRoot() }; diff --git a/commandLine/src/projects/xcodeProject.cpp b/commandLine/src/projects/xcodeProject.cpp index 811e26b4..3709c369 100644 --- a/commandLine/src/projects/xcodeProject.cpp +++ b/commandLine/src/projects/xcodeProject.cpp @@ -76,13 +76,14 @@ bool xcodeProject::createProjectFile(){ return false; } + // FIXME: rootReplacements can be empty. // if project is outside OF, rootReplacements is set to be used in XCode and make if (!fs::equivalent(getOFRoot(), normalizePath(fs::path{"../../.."}))) { string root { ofPathToString(getOFRoot()) }; rootReplacements = { "../../..", root }; } - - + + copyTemplateFiles.push_back({ normalizePath(templatePath / "emptyExample.xcodeproj" / "project.pbxproj"), normalizePath(xcodeProject / "project.pbxproj"), @@ -95,7 +96,7 @@ bool xcodeProject::createProjectFile(){ normalizePath(projectDir / "Project.xcconfig"), {rootReplacements} }); - + if (target == "osx" || target == "macos") { for (auto & f : {"openFrameworks-Info.plist", "of.entitlements"}) { copyTemplateFiles.push_back({normalizePath(templatePath / f), normalizePath(projectDir / f)}); @@ -115,7 +116,7 @@ bool xcodeProject::createProjectFile(){ } } } - + if (backupProjectFiles) { createBackup({ xcodeProject / "project.pbxproj" }, projectDir); createBackup({ projectDir / "openFrameworks-Info.plist" }, projectDir); @@ -125,15 +126,13 @@ bool xcodeProject::createProjectFile(){ createBackup({ projectDir / "config.make" }, projectDir); createBackup({ projectDir / "Makefile" }, projectDir); } - + saveScheme(); if(target == "osx" || target == "macos"){ saveMakefile(); } - - // Execute all file copy and replacements, including ones in saveScheme, saveMakefile for (auto & c : copyTemplateFiles) { try { @@ -143,9 +142,8 @@ bool xcodeProject::createProjectFile(){ return false; } } - + // NOW only files being copied - fs::path projectDataDir { projectDir / "bin" / "data" }; if (!fs::exists(projectDataDir)) { @@ -156,26 +154,26 @@ bool xcodeProject::createProjectFile(){ if (fs::exists(projectDataDir)) { // originally only on IOS //this is needed for 0.9.3 / 0.9.4 projects which have iOS media assets in bin/data/ - fs::path templateBinDir { templatePath / "bin" }; + fs::path templateBinDir { templatePath / "bin" }; fs::path templateDataDir { templatePath / "bin" / "data" }; if (fs::exists(templateDataDir) && fs::is_directory(templateDataDir)) { baseProject::recursiveCopyContents(templateDataDir, projectDataDir); } - if (fs::exists(templateBinDir) && fs::is_directory(templateBinDir)) { + if (fs::exists(templateBinDir) && fs::is_directory(templateBinDir)) { #ifdef TARGET_OS_MAC - try { - // extended attributes on macOS - std::string command = "xattr -w com.apple.xcode.CreatedByBuildSystem true " + templateBinDir.string(); - if (std::system(command.c_str()) != 0) { - std::cerr << "Failed to set extended attributes on " << templateBinDir.string() << std::endl; - } else { - ofLogVerbose("xcodeProject") << "xattr set correctly for /bin" << endl; - } - } catch (const std::exception& e) { - std::cout << "xcodeProject::createProjectFile() error " << e.what() << std::endl; - } + try { + // extended attributes on macOS + std::string command = "xattr -w com.apple.xcode.CreatedByBuildSystem true " + templateBinDir.string(); + if (std::system(command.c_str()) != 0) { + std::cerr << "Failed to set extended attributes on " << templateBinDir.string() << std::endl; + } else { + ofLogVerbose("xcodeProject") << "xattr set correctly for /bin" << endl; + } + } catch (const std::exception& e) { + std::cout << "xcodeProject::createProjectFile() error " << e.what() << std::endl; + } #endif - } + } } return true; } @@ -225,7 +223,7 @@ void xcodeProject::saveMakefile(){ bool xcodeProject::loadProjectFile(){ //base addCommand("Add :_OFProjectGeneratorVersion string " + getPGVersion()); - + renameProject(); // MARK: just to return something. return true; @@ -247,7 +245,7 @@ void xcodeProject::renameProject(){ //base // FIXME: Double check if isFolder is even being used. Remove it if not string xcodeProject::getFolderUUID(const fs::path & folder, bool isFolder, fs::path base) { // alert ("xcodeProject::getFolderUUID "+folder.string()+" : isfolder="+ofToString(isFolder)+" : base="+ base.string()); - + // TODO: Change key of folderUUID to base + folder, so "src" in additional source folders // doesn't get confused with "src" from project. // this can work but fullPath variable has to follow the same pattern @@ -269,7 +267,7 @@ string xcodeProject::getFolderUUID(const fs::path & folder, bool isFolder, fs::p // Iterating every folder from full path for (std::size_t a = 0; a < folders.size(); a++) { fs::path fullPath{""}; - + std::vector joinFolders; joinFolders.reserve(a + 1); // Reserve / avoid reallocations @@ -280,7 +278,7 @@ string xcodeProject::getFolderUUID(const fs::path & folder, bool isFolder, fs::p for (const auto& j : joinFolders) { fullPath /= j; } - + // Query if partial path is already stored. if not execute this following block if ( folderUUID.find(fullPath) != folderUUID.end() ) { @@ -296,30 +294,28 @@ string xcodeProject::getFolderUUID(const fs::path & folder, bool isFolder, fs::p addCommand(""); string folderName = ofPathToString(folders[a]); addCommand("Add :objects:"+thisUUID+":name string " + folderName); - - // FIXME: Inspect if this is really being used - if (isFolder) { -// alert("INSIDE " , 31); - fs::path filePath; - fs::path filePath_full { relRoot / fullPath }; - // FIXME: known issue: doesn't handle files with spaces in name. - - if (fs::exists(filePath_full)) { - filePath = filePath_full; - } - if (fs::exists(fullPath)) { - filePath = fullPath; - } - if (!filePath.empty()) { - addCommand("Add :objects:"+thisUUID+":path string " + ofPathToString(filePath)); -// alert(commands.back(), 33); - } else { -// cout << ">>>>> filePath empty " << endl; - } - } else { -// cout << "isFolder false" << endl; - } + // FIXME: Inspect if this is really being used +// if (isFolder) { +// alert("getFolderUUID, isFolder INSIDE " , 31); +// fs::path filePath; +// fs::path filePath_full { relRoot / fullPath }; +// // FIXME: known issue: doesn't handle files with spaces in name. +// +// if (fs::exists(filePath_full)) { +// filePath = filePath_full; +// } +// if (fs::exists(fullPath)) { +// filePath = fullPath; +// } +// +// if (!filePath.empty()) { +// addCommand("Add :objects:"+thisUUID+":path string " + ofPathToString(filePath)); +// } else { +// } +// } else { +// alert("getFolderUUID isFolder false", 31); +// } addCommand("Add :objects:"+thisUUID+":isa string PBXGroup"); @@ -330,6 +326,8 @@ string xcodeProject::getFolderUUID(const fs::path & folder, bool isFolder, fs::p if (lastFolderUUID == projRootUUID || lastFolder == "external_sources" || lastFolder == "local_addons") { // +// alert ("external_sources base = " + ofPathToString(base), 33); + // Base folders can be in a different depth, // so we cut folders to point to the right path fs::path base2 { base }; @@ -337,8 +335,8 @@ string xcodeProject::getFolderUUID(const fs::path & folder, bool isFolder, fs::p for (size_t x=0; xstring() == "addons" || folder.begin()->string() == "src") { - addCommand("Add :objects:"+thisUUID+":sourceTree string "); - fs::path addonFolder { fs::path(fullPath).filename() }; - addCommand("Add :objects:"+thisUUID+":path string " + ofPathToString(addonFolder)); - // alert ("group " + folder.string() + " : " + base.string() + " : " + addonFolder.string(), 32); - } else { - addCommand("Add :objects:"+thisUUID+":sourceTree string SOURCE_ROOT"); - } + + if (folder.begin()->string() == "addons" || folder.begin()->string() == "src") { + addCommand("Add :objects:"+thisUUID+":sourceTree string "); + fs::path addonFolder { fs::path(fullPath).filename() }; + addCommand("Add :objects:"+thisUUID+":path string " + ofPathToString(addonFolder)); + // alert ("group " + folder.string() + " : " + base.string() + " : " + addonFolder.string(), 32); + } else { + addCommand("Add :objects:"+thisUUID+":sourceTree string SOURCE_ROOT"); + } // Add this new folder to its parent, projRootUUID if root @@ -388,7 +386,7 @@ void xcodeProject::addSrc(const fs::path & srcFile, const fs::path & folder, Src fileProperties fp; fp.addToBuildPhase = true; fp.isSrc = true; - + if( type == DEFAULT ){ if (ext == ".h" || ext == ".hpp"){ fp.addToBuildPhase = false; @@ -414,13 +412,13 @@ void xcodeProject::addSrc(const fs::path & srcFile, const fs::path & folder, Src fp.addToBuildPhase = true; fp.addToResources = true; } - } - + } + string UUID { addFile(srcFile, folder, fp) }; - + if (ext == ".mm" || ext == ".m") { addCompileFlagsForMMFile(srcFile); } @@ -454,16 +452,16 @@ void xcodeProject::addFramework(const fs::path & path, const fs::path & folder){ // folder = the path in the addon (in case we want to add this to the file browser -- we don't do that for system libs); addCommand("# ----- addFramework path=" + ofPathToString(path) + " folder=" + ofPathToString(folder)); - + bool isSystemFramework = true; if (!folder.empty() && !ofIsStringInString(ofPathToString(path), "/System/Library/Frameworks") && target != "ios"){ isSystemFramework = false; } - + fileProperties fp; fp.absolute = isSystemFramework; - + fp.codeSignOnCopy = !isSystemFramework; fp.copyFilesBuildPhase = !isSystemFramework; fp.frameworksBuildPhase = (target != "ios" && !folder.empty()); @@ -483,19 +481,19 @@ void xcodeProject::addFramework(const fs::path & path, const fs::path & folder){ void xcodeProject::addXCFramework(const fs::path & path, const fs::path & folder) { // alert( "xcodeProject::addFramework " + path.string() + " : " + folder.string() , 33); - + // path = the full path (w name) of this framework // folder = the path in the addon (in case we want to add this to the file browser -- we don't do that for system libs); - + addCommand("# ----- addXCFramework path=" + ofPathToString(path) + " folder=" + ofPathToString(folder)); - - + + fileProperties fp; // fp.addToBuildPhase = true; fp.codeSignOnCopy = true; fp.copyFilesBuildPhase = true; fp.frameworksBuildPhase = (target != "ios" && !folder.empty()); - + string UUID { addFile(path, folder, fp) }; @@ -519,7 +517,7 @@ void xcodeProject::addDylib(const fs::path & path, const fs::path & folder){ fp.addToBuildPhase = true; fp.codeSignOnCopy = true; fp.copyFilesBuildPhase = true; - + addFile(path, folder, fp); } @@ -593,7 +591,7 @@ void xcodeProject::addAddon(ofAddon & addon){ // alert("xcodeProject addAddon string :: " + addon.name, 31); // Files listed alphabetically on XCode navigator. - + std::sort(addon.srcFiles.begin(), addon.srcFiles.end(), [](const fs::path & a, const fs::path & b) { return a.string() < b.string(); }); @@ -659,7 +657,7 @@ void xcodeProject::addAddon(ofAddon & addon){ } addFramework( "/System/Library/Frameworks/" + f + ".framework", folder); } - } + } else { if (ofIsStringInString(f, "/System/Library")){ addFramework(f, "addons/" + addon.name + "/frameworks"); @@ -685,12 +683,12 @@ void xcodeProject::addAddon(ofAddon & addon){ } // MARK: Is this ok to call .framework? addXCFramework("/System/Library/Frameworks/" + f + ".xcframework", folder); - + } else { if (ofIsStringInString(f, "/System/Library")) { - addXCFramework(f, "addons/" + addon.name + "/xcframeworks"); + addXCFramework(f, "addons/" + addon.name + "/xcframeworks"); } else { - addXCFramework(f, addon.filesToFolders[f]); + addXCFramework(f, addon.filesToFolders[f]); } } } @@ -699,17 +697,17 @@ void xcodeProject::addAddon(ofAddon & addon){ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, const fileProperties & fp) { //alert("addFile " + ofPathToString(path) + " : " + ofPathToString(folder) , 31); - + string UUID { "" }; // cout << "will check if exists " << (projectDir / path) << endl; -// if (fs::exists( projectDir / path )) +// if (fs::exists( projectDir / path )) { // cout << "OK exists" << endl; bool isFolder = false; string fileType { "file" }; fileType = extensionToFileType[path.extension()]; - + if (fileType == "") { if (fs::is_directory(path) || fp.isGroupWithoutFolder) { @@ -722,17 +720,17 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con } UUID = generateUUID(path); - + addCommand(""); addCommand("# -- addFile " + ofPathToString(path)); // encoding may be messing up for frameworks... so I switched to a pbx file ref without encoding fields - + // if (fp.reference) { // } else { // addCommand("Add :objects:"+UUID+":isa string PBXGroup"); // } - + // This is adding a file. any file. addCommand("Add :objects:"+UUID+":fileEncoding string 4"); if (fp.isGroupWithoutFolder) { @@ -742,7 +740,7 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con } addCommand("Add :objects:"+UUID+":lastKnownFileType string " + fileType); addCommand("Add :objects:"+UUID+":name string " + ofPathToString(path.filename())); - + if (fp.absolute) { addCommand("Add :objects:"+UUID+":sourceTree string SOURCE_ROOT"); @@ -752,23 +750,25 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con } else { addCommand("Add :objects:"+UUID+":sourceTree string "); } - - string folderUUID; - auto rootDir = folder.root_directory(); - if (rootDir != "addons" && rootDir != "src") { -// alert("addFile path:" + ofPathToString(path) + " folder:" + ofPathToString(folder) , 31); - auto base = path.parent_path(); - folderUUID = getFolderUUID(folder, isFolder, base); - } else { - folderUUID = getFolderUUID(folder, isFolder); - } - folderUUID = getFolderUUID(folder, isFolder); +// string folderUUID; +// auto rootDir = folder.root_directory(); +// if (rootDir != "addons" && rootDir != "src") { +//// alert("addFile path:" + ofPathToString(path) + " folder:" + ofPathToString(folder) , 31); +// auto base = path.parent_path(); +// folderUUID = getFolderUUID(folder, isFolder, base); +// +// } else { +// folderUUID = getFolderUUID(folder, isFolder); +// } + + // Eventually remove isFolder and base parameter + std::string folderUUID { getFolderUUID(folder, isFolder) }; addCommand("# ---- addFileToFolder UUID : " + ofPathToString(folder)); addCommand("Add :objects:" + folderUUID + ":children: string " + UUID); - + string buildUUID { generateUUID(ofPathToString(path) + "-build") }; // If any other option is true, add buildUUID entries. if ( @@ -776,20 +776,20 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con fp.codeSignOnCopy || fp.copyFilesBuildPhase || fp.addToBuildResource || - fp.addToResources + fp.addToResources //|| fp.frameworksBuildPhase ~ I've just removed this one, favoring -InFrameworks ) { addCommand("# ---- addToBuildPhase " + buildUUID); addCommand("Add :objects:"+buildUUID+":isa string PBXBuildFile"); addCommand("Add :objects:"+buildUUID+":fileRef string "+UUID); } - + if (fp.addToBuildPhase) { // Compile Sources // Not sure if it applies to everything, applies to srcFile. addCommand("# ---- addToBuildPhase"); addCommand("Add :objects:"+buildActionMaskUUID+":files: string " + buildUUID); } - + if (fp.copyFilesBuildPhase) { // If we are going to add xcframeworks to copy files -> destination frameworks, we should include here // if (path.extension() == ".framework" || path.extension() == ".xcframework") { @@ -804,19 +804,19 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con addCommand("Add :objects:E4A5B60F29BAAAE400C2D356:files: string " + buildUUID); } } - + if (fp.codeSignOnCopy) { addCommand("# ---- codeSignOnCopy " + buildUUID); addCommand("Add :objects:"+buildUUID+":settings:ATTRIBUTES array"); addCommand("Add :objects:"+buildUUID+":settings:ATTRIBUTES: string CodeSignOnCopy"); } - + if (fp.addToBuildResource) { string mediaAssetsUUID { "9936F60E1BFA4DEE00891288" }; addCommand("# ---- addToBuildResource"); addCommand("Add :objects:"+mediaAssetsUUID+":files: string " + UUID); } - + if (fp.addToResources) { // FIXME: test if it is working on iOS if (resourcesUUID != "") { @@ -824,7 +824,7 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con addCommand("Add :objects:"+resourcesUUID+": string " + buildUUID); } } - + if (fp.frameworksBuildPhase) { // Link Binary With Libraries auto tempUUID = generateUUID(ofPathToString(path) + "-InFrameworks"); addCommand("Add :objects:" + tempUUID + ":fileRef string " + UUID); @@ -833,7 +833,7 @@ string xcodeProject::addFile(const fs::path & path, const fs::path & folder, con addCommand("# --- PBXFrameworksBuildPhase"); addCommand("Add :objects:E4B69B590A3A1756003C02F2:files: string " + tempUUID); } - + if (path.extension() == ".framework") { addCommand("# ---- Frameworks Folder " + UUID); addCommand("Add :objects:901808C02053638E004A7774:children: string " + UUID); @@ -877,7 +877,7 @@ bool xcodeProject::saveProjectFile(){ // debugCommands = false; - + fs::path fileName { projectDir / (projectName + ".xcodeproj/project.pbxproj") }; bool usePlistBuddy = false; @@ -894,13 +894,13 @@ bool xcodeProject::saveProjectFile(){ // JSON Block - Multiplatform std::ifstream contents(fileName); - json j; - try { - j = { json::parse(contents) }; - } catch (json::parse_error& ex) { - ofLogError(xcodeProject::LOG_NAME) << "JSON parse error at byte" << ex.byte; - ofLogError(xcodeProject::LOG_NAME) << "fileName" << fileName; - } + json j; + try { + j = { json::parse(contents) }; + } catch (json::parse_error& ex) { + ofLogError(xcodeProject::LOG_NAME) << "JSON parse error at byte" << ex.byte; + ofLogError(xcodeProject::LOG_NAME) << "fileName" << fileName; + } contents.close(); @@ -914,22 +914,22 @@ bool xcodeProject::saveProjectFile(){ if (thispath.substr(thispath.length() -1) != "/") { //if (cols[0] == "Set") { - try { - json::json_pointer p { json::json_pointer(thispath) }; - if (cols[2] == "string") { - // find position after find word - auto stringStart { c.find("string ") + 7 }; - j[p] = c.substr(stringStart); - // j[p] = cols[3]; - } - else if (cols[2] == "array") { - j[p] = {}; - } - } catch (std::exception & e) { - cout << "xcodeProject saveProjectFile() first json error " << endl; - cout << e.what() << endl; - cout << " error at this path: " << thispath << endl; - } + try { + json::json_pointer p { json::json_pointer(thispath) }; + if (cols[2] == "string") { + // find position after find word + auto stringStart { c.find("string ") + 7 }; + j[p] = c.substr(stringStart); + // j[p] = cols[3]; + } + else if (cols[2] == "array") { + j[p] = {}; + } + } catch (std::exception & e) { + cout << "xcodeProject saveProjectFile() first json error " << endl; + cout << e.what() << endl; + cout << " error at this path: " << thispath << endl; + } } else { thispath = thispath.substr(0, thispath.length() -1); @@ -949,13 +949,13 @@ bool xcodeProject::saveProjectFile(){ } catch (std::exception & e) { cout << "xcodeProject saveProjectFile() json error " << endl; cout << e.what() << endl; - cout << " error at this path: " << thispath << endl; + cout << " error at this path: " << thispath << endl; } } } } - + std::ofstream jsonFile(fileName); // This is not pretty but address some differences in nlohmann json 3.11.2 to 3.11.3 auto dump = j.dump(1, ' ');