@@ -129,6 +129,51 @@ static std::string readEmscriptenWasm(const fs::path & configMake) {
129129 return bits;
130130}
131131
132+ // space separated list from config.make, VAR = a b / VAR += c
133+ static std::vector<std::string> readMakeList (const fs::path & configMake, const std::string & name) {
134+ std::vector<std::string> values;
135+ if (!fs::exists (configMake)) return values;
136+ for (auto & line : fileToStrings (configMake)) {
137+ auto config = ofTrim (line);
138+ if (config.empty () || config[0 ] == ' #' ) continue ;
139+ auto eq = config.find (' =' );
140+ if (eq == std::string::npos) continue ;
141+ auto var = ofTrim (config.substr (0 , eq));
142+ bool append = !var.empty () && var.back () == ' +' ;
143+ if (!var.empty () && (var.back () == ' ?' || var.back () == ' +' || var.back () == ' :' )) var = ofTrim (var.substr (0 , var.size () - 1 ));
144+ if (var != name) continue ;
145+ if (!append) values.clear ();
146+ for (auto & v : ofSplitString (ofTrim (config.substr (eq + 1 )), " " , true , true )) values.emplace_back (v);
147+ }
148+ return values;
149+ }
150+
151+ // Security.framework -> Security
152+ static std::string cleanFrameworkName (std::string name) {
153+ name = ofTrim (name);
154+ if (name.size () > 10 && name.substr (name.size () - 10 ) == " .framework" ) name = name.substr (0 , name.size () - 10 );
155+ return name;
156+ }
157+
158+ // -lsqlite3 / libsqlite3 / libsqlite3.tbd / libsqlite3.dylib -> sqlite3
159+ static std::string cleanSystemLibName (std::string name) {
160+ name = ofTrim (name);
161+ if (name.rfind (" -l" , 0 ) == 0 ) name = name.substr (2 );
162+ for (std::string ext : { " .tbd" , " .dylib" }) {
163+ if (name.size () > ext.size () && name.substr (name.size () - ext.size ()) == ext) name = name.substr (0 , name.size () - ext.size ());
164+ }
165+ if (name.rfind (" lib" , 0 ) == 0 && name.size () > 3 ) name = name.substr (3 );
166+ return name;
167+ }
168+
169+ static bool isSystemLibName (const std::string & name) {
170+ return name.rfind (" -l" , 0 ) == 0 || name.rfind (" lib" , 0 ) == 0 || ofIsStringInString (name, " .tbd" ) || ofIsStringInString (name, " .dylib" );
171+ }
172+
173+ static void addUnique (std::vector<std::string> & list, const std::string & value) {
174+ if (!value.empty () && std::find (list.begin (), list.end (), value) == list.end ()) list.emplace_back (value);
175+ }
176+
132177static const std::string OF_CMAKE_INCLUDE { " libs/openFrameworksCompiled/project/CMake/openFrameworks.cmake" };
133178
134179// set(PROJECT_EMSCRIPTEN_WASM 64) written by PG into an openFrameworks CMakeLists.txt (openFrameworks#8586)
@@ -252,6 +297,18 @@ bool baseProject::create(const fs::path & _path, string templateName){
252297 ofLogNotice () << " { \" emscriptenWasm\" : \" " << emscriptenWasm << " \" }" ;
253298 }
254299
300+ systemFrameworks.clear ();
301+ systemLibs.clear ();
302+ for (auto & f : systemFrameworksPassed ? systemFrameworksOption : readMakeList (projectDir / " config.make" , " PROJECT_FRAMEWORKS" )) {
303+ if (isSystemLibName (f)) addUnique (systemLibs, cleanSystemLibName (f));
304+ else addUnique (systemFrameworks, cleanFrameworkName (f));
305+ }
306+ for (auto & l : systemLibsPassed ? systemLibsOption : readMakeList (projectDir / " config.make" , " PROJECT_SYSTEM_LIBS" )) {
307+ addUnique (systemLibs, cleanSystemLibName (l));
308+ }
309+ if (systemFrameworks.size ()) ofLogNotice () << " { \" systemFrameworks\" : \" " << ofJoinString (systemFrameworks, " " ) << " \" }" ;
310+ if (systemLibs.size ()) ofLogNotice () << " { \" systemLibs\" : \" " << ofJoinString (systemLibs, " " ) << " \" }" ;
311+
255312 // app version / build: config.make first, then CMakeLists, Xcode, Android; the CLI value wins
256313 {
257314 std::vector<std::pair<std::string, std::pair<std::string, std::string>>> found {
@@ -427,6 +484,28 @@ bool baseProject::save(){
427484 bool bWroteWasm = false ;
428485 bool bWroteAppVersion = false ;
429486 bool bWroteAppBuild = false ;
487+ bool bWroteFrameworks = false ;
488+ bool bWroteSystemLibs = false ;
489+ auto isMakeVar = [](const std::string & line, const std::string & name) {
490+ auto config = ofTrim (line);
491+ if (config.rfind (" #" , 0 ) == 0 ) config = ofTrim (config.substr (1 ));
492+ if (config.rfind (name, 0 ) != 0 ) return false ;
493+ auto rest = ofTrim (config.substr (name.size ()));
494+ return rest.rfind (" =" , 0 ) == 0 || rest.rfind (" +=" , 0 ) == 0 || rest.rfind (" :=" , 0 ) == 0 || rest.rfind (" ?=" , 0 ) == 0 ;
495+ };
496+ // the list on the first line, commented when empty, later += lines are folded in
497+ auto writeMakeList = [&](const std::string & line, const std::string & name, const std::vector<std::string> & values, bool & bWrote) {
498+ if (bWrote) {
499+ if (ofTrim (line).rfind (" #" , 0 ) == 0 ) saveConfig << line << std::endl;
500+ return ;
501+ }
502+ if (values.empty ()) {
503+ saveConfig << (ofTrim (line).rfind (" #" , 0 ) == 0 ? line : " # " + name + " =" ) << std::endl;
504+ } else {
505+ saveConfig << name << " = " << ofJoinString (values, " " ) << std::endl;
506+ }
507+ bWrote = true ;
508+ };
430509
431510 for (auto & str : lines) {
432511 // add the of root path
@@ -472,6 +551,12 @@ bool baseProject::save(){
472551 bWroteAppBuild = true ;
473552 }
474553 }
554+ else if ( isMakeVar (str, " PROJECT_FRAMEWORKS" ) ){
555+ writeMakeList (str, " PROJECT_FRAMEWORKS" , systemFrameworks, bWroteFrameworks);
556+ }
557+ else if ( isMakeVar (str, " PROJECT_SYSTEM_LIBS" ) ){
558+ writeMakeList (str, " PROJECT_SYSTEM_LIBS" , systemLibs, bWroteSystemLibs);
559+ }
475560 else if ( emscriptenWasm == " 32" && str.rfind (" EMSCRIPTEN_MEMORY64" , 0 ) == 0 ){
476561 saveConfig << " # " << str << std::endl;
477562 } else {
@@ -490,6 +575,12 @@ bool baseProject::save(){
490575 if (!bWroteAppVersion) saveConfig << " APP_VERSION = " << appVersion << std::endl;
491576 if (!bWroteAppBuild) saveConfig << " APP_BUILD = " << appBuild << std::endl;
492577 }
578+ if ((systemFrameworks.size () && !bWroteFrameworks) || (systemLibs.size () && !bWroteSystemLibs)) {
579+ if (lines.size ()) saveConfig << std::endl;
580+ saveConfig << " # system frameworks (Security) and libraries (sqlite3 = libsqlite3.tbd / -lsqlite3)" << std::endl;
581+ if (systemFrameworks.size () && !bWroteFrameworks) saveConfig << " PROJECT_FRAMEWORKS = " << ofJoinString (systemFrameworks, " " ) << std::endl;
582+ if (systemLibs.size () && !bWroteSystemLibs) saveConfig << " PROJECT_SYSTEM_LIBS = " << ofJoinString (systemLibs, " " ) << std::endl;
583+ }
493584 saveConfig.close ();
494585 saveCMakeLists ();
495586 saveAppVersionFiles ();
@@ -1010,6 +1101,30 @@ void baseProject::parseConfigMake(){
10101101 }
10111102}
10121103
1104+ void baseProject::setSystemFrameworks (const std::vector<std::string> & frameworks, bool frameworksPassed, const std::vector<std::string> & libs, bool libsPassed) {
1105+ // "Security CoreBluetooth" is two, names have no spaces
1106+ auto splitSpaces = [](const std::vector<std::string> & list) {
1107+ std::vector<std::string> out;
1108+ for (auto & l : list) {
1109+ for (auto & v : ofSplitString (l, " " , true , true )) out.emplace_back (v);
1110+ }
1111+ return out;
1112+ };
1113+ systemFrameworksOption = splitSpaces (frameworks);
1114+ systemFrameworksPassed = frameworksPassed;
1115+ systemLibsOption = splitSpaces (libs);
1116+ systemLibsPassed = libsPassed;
1117+ }
1118+
1119+ void baseProject::addSystemFrameworks () {
1120+ for (auto & f : systemFrameworks) {
1121+ addFramework (f, " Frameworks" , true );
1122+ }
1123+ for (auto & l : systemLibs) {
1124+ addSystemLibrary (l);
1125+ }
1126+ }
1127+
10131128void baseProject::recursiveTemplateCopy (const fs::path & srcDir, const fs::path & destDir){
10141129 if (recursiveCopy (srcDir, destDir)) {
10151130 fs::path templateFile = destDir / " template.config" ;
0 commit comments