9 import "OldIDESettings"
13 enum DirTypes { includes, libraries, executables };
15 define defaultCompilerName = "Default";
17 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)";
19 char * settingsDirectoryNames[DirTypes] =
26 enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings };
28 enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull };
29 PathRelationship eString_PathRelated(char * path, char * to, char * pathDiff)
31 PathRelationship result;
32 if(pathDiff) *pathDiff = '\0';
33 if(path && *path && to && *to)
35 char toPart[MAX_FILENAME], toRest[MAX_LOCATION];
36 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
38 strcpy(pathRest, path);
39 for(; toRest[0] && pathRest[0];)
41 SplitDirectory(toRest, toPart, toRest);
42 SplitDirectory(pathRest, pathPart, pathRest);
43 if(!fstrcmp(pathPart, toPart)) result = siblings;
46 if(result == siblings)
48 if(!*toRest && !*pathRest) result = identical;
49 else if(!*pathRest) result = parentPath;
50 else result = subPath;
51 if(pathDiff && result != identical) strcpy(pathDiff, *pathRest == '\0' ? toRest : pathRest);
53 else result = unrelated;
59 if(!*path && !*to) result = bothEmpty;
60 else if(!*path) result = pathEmpty;
61 else result = toEmpty;
63 else if(!path && !to) result = bothNull;
64 else if(!path) result = pathNull;
70 char * CopyValidateMakefilePath(char * path)
72 const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 7 };
73 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)", "$(TARGET_PLATFORM)",(char *)0 };
80 copy = CopyString(path);
86 Array<char *> parts { };
93 for(v=0; vars[v]; v++)
95 if(SearchString(&tmp[c], 0, vars[v], false, false) == &tmp[c])
99 parts.Add(vars[map[v]]);
100 c += strlen(vars[v]);
114 for(c=0; c<parts.count; c++) len += strlen(parts[c]);
115 copy = new char[++len];
117 for(c=0; c<parts.count; c++) strcat(copy, parts[c]);
128 CompilerConfig MakeDefaultCompiler(char * name, bool readOnly)
130 CompilerConfig defaultCompiler
135 GetRuntimePlatform(),
146 incref defaultCompiler;
147 return defaultCompiler;
150 class IDESettingsContainer : GlobalSettings
153 settingsName = "ecereIDESettingsTest";
155 settingsName = "ecereIDE";
158 virtual void OnLoad(GlobalSettingsData data);
160 char moduleLocation[MAX_LOCATION];
163 IDESettingsContainer()
165 char path[MAX_LOCATION];
167 LocateModule(null, moduleLocation);
168 strcpy(path, moduleLocation);
169 StripLastDirectory(moduleLocation, moduleLocation);
170 ChangeCh(moduleLocation, '\\', '/');
171 // PortableApps.com directory structure
172 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
174 char configFilePath[MAX_LOCATION];
175 char defaultConfigFilePath[MAX_LOCATION];
179 strcpy(configFilePath, path);
180 PathCat(configFilePath, "Data");
181 PathCat(configFilePath, "ecereIDE.ini");
183 strcpy(defaultConfigFilePath, path);
184 PathCat(defaultConfigFilePath, "App");
185 PathCat(defaultConfigFilePath, "DefaultData");
186 PathCat(defaultConfigFilePath, "ecereIDE.ini");
188 if(FileExists(defaultConfigFilePath))
190 if(!FileExists(configFilePath))
192 File f = FileOpen(defaultConfigFilePath, read);
193 f.CopyTo(configFilePath);
197 PathCat(path, "Data");
198 // the forced settings location will only be
199 // used if the running ide's path matches
200 // the PortableApps.com directory structure
201 // and the default ini file is found in
202 // the DefaultData directory
203 settingsLocation = path;
209 void OnAskReloadSettings()
211 /*if(MessageBox { type = YesNo, master = this,
212 text = "Global Settings Modified Externally",
213 contents = "The global settings were modified by another instance.\n"
214 "Would you like to reload them?" }.Modal() == Yes)*/
222 SettingsIOResult result = GlobalSettings::Load();
223 IDESettings data = (IDESettings)this.data;
224 CompilerConfig defaultCompiler = null;
227 this.data = IDESettings { };
229 *dataOwner = this.data;
231 if(result == fileNotCompatibleWithDriver)
234 OldIDESettings oldSettings { };
236 loaded = oldSettings.Load();
240 data = (IDESettings)this.data;
242 for(c : oldSettings.compilerConfigs)
243 data.compilerConfigs.Add(c.Copy());
245 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
246 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
248 data.docDir = oldSettings.docDir;
249 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
250 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
251 data.useFreeCaret = oldSettings.useFreeCaret;
252 data.showLineNumbers = oldSettings.showLineNumbers;
253 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
254 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
255 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
256 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
263 if(result == fileNotFound || !data)
265 data = (IDESettings)this.data;
266 data.useFreeCaret = true;
267 data.showLineNumbers = true;
268 data.caretFollowsScrolling = true;
271 // Ensure we have a default compiler
272 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
275 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
276 data.compilerConfigs.Add(defaultCompiler);
279 // We incref the compilers below, so reset refCount to 0
280 defaultCompiler._refCount = 0;
283 if(data.compilerConfigs)
285 for(c : data.compilerConfigs)
287 CompilerConfig compiler = c;
288 char * cxxCommand = compiler.cxxCommand;
289 if(!cxxCommand || !cxxCommand[0])
290 compiler.cxxCommand = cxxDefaultCommand;
294 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
295 data.ManagePortablePaths(moduleLocation, true);
296 data.ForcePathSeparatorStyle(true);
302 IDESettings data = (IDESettings)this.data;
303 Platform runtimePlatform = GetRuntimePlatform();
304 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
305 data.ManagePortablePaths(moduleLocation, false);
306 data.ForcePathSeparatorStyle(true);
307 if(!GlobalSettings::Save())
308 PrintLn("Error saving IDE settings");
309 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
310 data.ManagePortablePaths(moduleLocation, true);
315 class IDESettings : GlobalSettingsData
318 List<CompilerConfig> compilerConfigs { };
319 Array<String> recentFiles { };
320 Array<String> recentProjects { };
321 property char * docDir
323 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
324 get { return docDir ? docDir : ""; }
325 isset { return docDir && docDir[0]; }
327 property char * ideFileDialogLocation
329 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
330 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
331 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
333 property char * ideProjectFileDialogLocation
335 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
336 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
337 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
340 bool showLineNumbers;
341 bool caretFollowsScrolling;
342 char * displayDriver;
344 // TODO: Classify settings
345 //EditorSettings editor { };
347 property char * projectDefaultTargetDir
349 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
350 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
351 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
353 property char * projectDefaultIntermediateObjDir
355 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
356 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
357 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
360 property char * compilerConfigsDir
362 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
363 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
364 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
367 property char * defaultCompiler
369 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
370 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
371 isset { return defaultCompiler && defaultCompiler[0]; }
376 char * ideFileDialogLocation;
377 char * ideProjectFileDialogLocation;
378 char * projectDefaultTargetDir;
379 char * projectDefaultIntermediateObjDir;
380 char * compilerConfigsDir;
381 char * defaultCompiler;
383 CompilerConfig GetCompilerConfig(String compilerName)
385 char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
386 CompilerConfig compilerConfig = null;
387 for(compiler : compilerConfigs)
389 if(!strcmp(compiler.name, name))
391 compilerConfig = compiler;
395 if(!compilerConfig && compilerConfigs.count)
396 compilerConfig = compilerConfigs.firstIterator.data;
398 incref compilerConfig;
399 return compilerConfig;
404 compilerConfigs.Free();
405 delete compilerConfigs;
408 recentProjects.Free();
409 delete recentProjects;
412 delete projectDefaultTargetDir;
413 delete projectDefaultIntermediateObjDir;
414 delete compilerConfigsDir;
415 delete defaultCompiler;
417 delete ideFileDialogLocation;
418 delete ideProjectFileDialogLocation;
419 delete displayDriver;
422 void ForcePathSeparatorStyle(bool unixStyle)
426 from = '\\', to = '/';
428 from = '/', to = '\\';
429 if(compilerConfigs && compilerConfigs.count)
432 for(config : compilerConfigs)
434 if(config.includeDirs && config.includeDirs.count)
436 for(i = 0; i < config.includeDirs.count; i++)
438 if(config.includeDirs[i] && config.includeDirs[i][0])
439 ChangeCh(config.includeDirs[i], from, to);
442 if(config.libraryDirs && config.libraryDirs.count)
444 for(i = 0; i < config.libraryDirs.count; i++)
446 if(config.libraryDirs[i] && config.libraryDirs[i][0])
447 ChangeCh(config.libraryDirs[i], from, to);
450 if(config.executableDirs && config.executableDirs.count)
452 for(i = 0; i < config.executableDirs.count; i++)
454 if(config.executableDirs[i] && config.executableDirs[i][0])
455 ChangeCh(config.executableDirs[i], from, to);
460 if(recentFiles && recentFiles.count)
463 for(c = 0; c < recentFiles.count; c++)
465 if(recentFiles[c] && recentFiles[c][0])
466 ChangeCh(recentFiles[c], from, to);
469 if(recentProjects && recentProjects.count)
472 for(c = 0; c < recentProjects.count; c++)
474 if(recentProjects[c] && recentProjects[c][0])
475 ChangeCh(recentProjects[c], from, to);
478 if(docDir && docDir[0])
479 ChangeCh(docDir, from, to);
480 if(ideFileDialogLocation && ideFileDialogLocation[0])
481 ChangeCh(ideFileDialogLocation, from, to);
482 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
483 ChangeCh(ideProjectFileDialogLocation, from, to);
485 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
486 ChangeCh(projectDefaultTargetDir, from, to);
487 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
488 ChangeCh(projectDefaultIntermediateObjDir, from, to);
490 if(compilerConfigsDir && compilerConfigsDir[0])
491 ChangeCh(compilerConfigsDir, from, to);
494 void ManagePortablePaths(char * location, bool makeAbsolute)
497 if(compilerConfigs && compilerConfigs.count)
499 for(config : compilerConfigs)
502 for(t = 0; t < DirTypes::enumSize; t++)
504 Array<String> dirs = null;
505 if(t == executables) dirs = config.executableDirs;
506 else if(t == includes) dirs = config.includeDirs;
507 else if(t == libraries) dirs = config.libraryDirs;
508 if(dirs && dirs.count)
510 for(c = 0; c < dirs.count; c++)
512 if(dirs[c] && dirs[c][0])
513 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
519 if(recentFiles && recentFiles.count)
521 for(c = 0; c < recentFiles.count; c++)
523 if(recentFiles[c] && recentFiles[c][0])
524 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
527 if(recentProjects && recentProjects.count)
529 for(c = 0; c < recentProjects.count; c++)
531 if(recentProjects[c] && recentProjects[c][0])
532 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
535 if(docDir && docDir[0])
536 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
537 if(ideFileDialogLocation && ideFileDialogLocation[0])
538 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
539 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
540 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
542 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
543 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
544 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
545 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
547 if(compilerConfigsDir && compilerConfigsDir[0])
548 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
551 char * UpdatePortablePath(char * path, char * location, bool makeAbsolute)
556 char p[MAX_LOCATION];
558 PathCatSlash(p, path);
560 output = CopyString(p);
564 PathRelationship rel = eString_PathRelated(path, location, null);
565 if(rel == subPath || rel == identical)
567 char p[MAX_LOCATION];
568 MakePathRelative(path, location, p);
569 if(!*p) strcpy(p, "./");
570 else ChangeCh(p, '\\', '/');
572 output = CopyString(p);
580 void AddRecentFile(char * fileName)
583 char * filePath = CopyString(fileName);
584 ChangeCh(filePath, '\\', '/');
585 for(c = 0; c<recentFiles.count; c++)
587 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
589 recentFiles.Delete((void *)&recentFiles[c]);
593 while(recentFiles.count >= MaxRecent)
594 recentFiles.Delete(recentFiles.GetLast());
595 recentFiles.Insert(null, filePath);
596 //UpdateRecentMenus(owner);
599 void AddRecentProject(char * projectName)
602 char * filePath = CopyString(projectName);
603 ChangeCh(filePath, '\\', '/');
604 for(c = 0; c<recentProjects.count; c++)
606 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
608 recentProjects.Delete((void *)&recentProjects[c]);
612 while(recentProjects.count >= MaxRecent)
613 recentProjects.Delete(recentProjects.GetLast());
614 recentProjects.Insert(null, filePath);
615 //UpdateRecentMenus(owner);
619 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
620 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
621 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
622 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
623 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
624 // TODO: i18n with Array
625 static Array<String> compilerTypeLongNames
627 $"GNU Compiler Collection (GCC) / GNU Make",
628 $"Tiny C Compiler / GNU Make",
629 $"Portable C Compiler / GNU Make",
630 $"Microsoft Visual Studio 2005 (8.0) Compiler",
631 $"Microsoft Visual Studio 2008 (9.0) Compiler",
632 $"Microsoft Visual Studio 2010 (10.0) Compiler"
634 const CompilerType firstCompilerType = gcc;
635 const CompilerType lastCompilerType = vs10;
636 public enum CompilerType
638 gcc, tcc, pcc, vs8, vs9, vs10;
642 get { return this == vs8 || this == vs9 || this == vs10; }
647 get { return OnGetString(null, null, null); }
653 for(c = firstCompilerType; c <= lastCompilerType; c++)
654 if(!strcmpi(value, compilerTypeNames[c]))
661 property char * longName { get { return OnGetString(null, (void*)1, null); } };
662 property char * versionString { get { return OnGetString(null, (void*)2, null); } };
663 property char * yearString { get { return OnGetString(null, (void*)3, null); } };
664 property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
665 property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
667 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
669 if(this >= firstCompilerType && this <= lastCompilerType)
672 strcpy(tempString, compilerTypeNames[this]);
673 if(fieldData == null)
674 return compilerTypeNames[this];
675 else if(fieldData == (void*)1)
676 return compilerTypeLongNames[this];
677 else if(fieldData == (void*)2)
678 return compilerTypeVersionString[this];
679 else if(fieldData == (void*)3)
680 return compilerTypeYearString[this];
681 else if(fieldData == (void*)4)
682 return compilerTypeProjectFileExtension[this];
683 else if(fieldData == (void*)5)
684 return compilerTypeSolutionFileVersionString[this];
695 supportsBitDepth = true;
703 name = CopyString(value);
709 Platform targetPlatform;
711 property char * makeCommand
713 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
714 get { return makeCommand; }
715 isset { return makeCommand && makeCommand[0]; }
717 property char * ecpCommand
719 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
720 get { return ecpCommand; }
721 isset { return ecpCommand && ecpCommand[0]; }
723 property char * eccCommand
725 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
726 get { return eccCommand; }
727 isset { return eccCommand && eccCommand[0]; }
729 property char * ecsCommand
731 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
732 get { return ecsCommand; }
733 isset { return ecsCommand && ecsCommand[0]; }
735 property char * earCommand
737 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
738 get { return earCommand; }
739 isset { return earCommand && earCommand[0]; }
741 property char * cppCommand
743 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
744 get { return cppCommand; }
745 isset { return cppCommand && cppCommand[0]; }
747 property char * ccCommand
749 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
750 get { return ccCommand; }
751 isset { return ccCommand && ccCommand[0]; }
753 property char * cxxCommand
755 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
756 get { return cxxCommand; }
757 isset { return cxxCommand && cxxCommand[0]; }
759 property char * execPrefixCommand
761 set { delete execPrefixCommand; if(value && value[0]) execPrefixCommand = CopyString(value); }
762 get { return execPrefixCommand; }
763 isset { return execPrefixCommand && execPrefixCommand[0]; }
767 property bool supportsBitDepth
769 set { supportsBitDepth = value; }
770 get { return supportsBitDepth; }
771 isset { return !supportsBitDepth; }
774 property char * distccHosts
776 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
777 get { return distccHosts; }
778 isset { return distccHosts && distccHosts[0]; }
780 property char * gccPrefix
782 set { delete gccPrefix; if(value && value[0]) gccPrefix = CopyString(value); }
783 get { return gccPrefix; }
784 isset { return gccPrefix && gccPrefix[0]; }
786 property char * sysroot
788 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
789 get { return sysroot; }
790 isset { return sysroot && sysroot[0]; }
792 property Array<String> includeDirs
803 get { return includeDirs; }
804 isset { return includeDirs.count != 0; }
806 property Array<String> libraryDirs
817 get { return libraryDirs; }
818 isset { return libraryDirs.count != 0; }
820 property Array<String> executableDirs
824 executableDirs.Free();
827 delete executableDirs;
828 executableDirs = value;
831 get { return executableDirs; }
832 isset { return executableDirs.count != 0; }
834 property Array<NamedString> environmentVars
838 environmentVars.Free();
841 delete environmentVars;
842 environmentVars = value;
845 get { return environmentVars; }
846 isset { return environmentVars.count != 0; }
848 property Array<String> prepDirectives
852 prepDirectives.Free();
855 delete prepDirectives;
856 prepDirectives = value;
859 get { return prepDirectives; }
860 isset { return prepDirectives.count != 0; }
862 property Array<String> excludeLibs
873 get { return excludeLibs; }
874 isset { return excludeLibs.count != 0; }
876 property Array<String> linkerFlags
887 get { return linkerFlags; }
888 isset { return linkerFlags.count != 0; }
891 Array<String> includeDirs { };
892 Array<String> libraryDirs { };
893 Array<String> executableDirs { };
894 // TODO: Can JSON parse and serialize maps?
895 //EnvironmentVariables { };
896 Array<NamedString> environmentVars { };
897 Array<String> prepDirectives { };
898 Array<String> excludeLibs { };
899 Array<String> linkerFlags { };
909 char * execPrefixCommand;
911 bool supportsBitDepth;
916 struct { Array<String> includes, libraries, executables; };
917 Array<String> dirs[DirTypes];
931 delete execPrefixCommand;
935 if(environmentVars) environmentVars.Free();
936 if(includeDirs) { includeDirs.Free(); }
937 if(libraryDirs) { libraryDirs.Free(); }
938 if(executableDirs) { executableDirs.Free(); }
939 if(prepDirectives) { prepDirectives.Free(); }
940 if(excludeLibs) { excludeLibs.Free(); }
941 if(linkerFlags) { linkerFlags.Free(); }
943 CompilerConfig Copy()
968 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
969 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
970 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
971 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
972 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
973 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
974 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));