Skip to content

Commit dab6602

Browse files
author
jantje
committed
#1268 multiconfig seems to work (I'm surprised)
So I expect bugs but I can't find failing cases right now
1 parent 4b9e63d commit dab6602

File tree

1 file changed

+137
-51
lines changed

1 file changed

+137
-51
lines changed

io.sloeber.core/src/io/sloeber/core/api/SloeberProject.java

Lines changed: 137 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.ByteArrayInputStream;
44
import java.net.URI;
55
import java.util.HashMap;
6+
import java.util.Iterator;
67
import java.util.Map;
78
import java.util.Map.Entry;
89
import java.util.TreeMap;
@@ -14,6 +15,7 @@
1415
import org.eclipse.cdt.core.model.CoreModel;
1516
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
1617
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
18+
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
1719
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
1820
import org.eclipse.cdt.managedbuilder.core.IManagedProject;
1921
import org.eclipse.cdt.managedbuilder.core.IProjectType;
@@ -48,6 +50,7 @@
4850
import io.sloeber.core.toolchain.SloeberConfigurationVariableSupplier;
4951
import io.sloeber.core.tools.Helpers;
5052
import io.sloeber.core.tools.Libraries;
53+
import io.sloeber.core.txt.KeyValueTree;
5154
import io.sloeber.core.txt.TxtFile;
5255

5356
public class SloeberProject extends Common {
@@ -57,28 +60,26 @@ public class SloeberProject extends Common {
5760
private Map<String, OtherDescription> myOtherDescriptions = new HashMap<>();
5861
private TxtFile myCfgFile = null;
5962
private IProject myProject = null;
60-
private boolean isConfigured = false;
63+
private boolean isInMemory = false;
6164
private boolean isDirty = false; // if anything has changed
65+
private boolean myNeedToPersist = false; // Do we need to write data to disk
6266
private boolean myNeedsClean = false; // is there old sloeber data that needs cleaning
67+
private boolean myNeedsSyncWithCDT = false; // Knows CDT all configs Sloeber Knows
6368

6469
private static final String ENV_KEY_BUILD_SOURCE_PATH = BUILD + DOT + SOURCE + DOT + PATH;
6570
private static final String ENV_KEY_BUILD_GENERIC_PATH = BUILD + DOT + "generic" + DOT + PATH; //$NON-NLS-1$
6671
private static final String ENV_KEY_COMPILER_PATH = COMPILER + DOT + PATH;
6772
private static final String SLOEBER_MAKE_LOCATION = ENV_KEY_SLOEBER_START + "make_location"; //$NON-NLS-1$
68-
private static final String CONFIG_DOT = "Config.";//$NON-NLS-1$
73+
private static final String CONFIG = "Config";//$NON-NLS-1$
74+
private static final String CONFIG_DOT = CONFIG + DOT;
6975

70-
private SloeberProject(IProject project, boolean isProjectCreating) {
76+
private SloeberProject(IProject project) {
7177
myProject = project;
7278
try {
7379
project.setSessionProperty(sloeberQualifiedName, this);
7480
} catch (CoreException e) {
7581
e.printStackTrace();
7682
}
77-
if (isProjectCreating) {
78-
return;
79-
}
80-
configureProject();
81-
8283
}
8384

8485
/**
@@ -163,7 +164,7 @@ public void run(IProgressMonitor internalMonitor) throws CoreException {
163164
CCorePlugin cCorePlugin = CCorePlugin.getDefault();
164165
ICProjectDescription prjCDesc = cCorePlugin.getProjectDescription(newProjectHandle);
165166

166-
SloeberProject arduinoProjDesc = new SloeberProject(newProjectHandle, true);
167+
SloeberProject arduinoProjDesc = new SloeberProject(newProjectHandle);
167168
for (ICConfigurationDescription curConfigDesc : prjCDesc.getConfigurations()) {
168169
// Even though we use the same boardDescriptor for all configurations during
169170
// project creation
@@ -250,36 +251,60 @@ private HashMap<String, String> getEnvVars(ICConfigurationDescription confDesc)
250251
return allVars;
251252
}
252253

253-
private void configureProject() {
254+
private void configure() {
254255

255256
CCorePlugin cCorePlugin = CCorePlugin.getDefault();
256257
ICProjectDescription prjCDesc = cCorePlugin.getProjectDescription(myProject);
257-
configureProject(prjCDesc, false);
258+
configure(prjCDesc, false);
258259
}
259260

260-
private void configureProject(ICProjectDescription prjCDesc, boolean prjDescWritable) {
261-
if (isConfigured) {
261+
private void configure(ICProjectDescription prjCDesc, boolean prjDescWritable) {
262+
if (isInMemory) {
262263
if (isDirty) {
263264
createSloeberConfigFiles(prjCDesc);
264265
setEnvironmentVariables(prjCDesc);
266+
isDirty = false;
265267
}
266-
if (prjDescWritable && myNeedsClean) {
267-
cleanOldData(prjCDesc);
268+
if (myNeedToPersist) {
269+
createSloeberConfigFiles(prjCDesc);
270+
}
271+
if (prjDescWritable) {
272+
if (myNeedsSyncWithCDT) {
273+
syncWithCDT(prjCDesc, prjDescWritable);
274+
}
275+
if (myNeedsClean) {
276+
cleanOldData(prjCDesc);
277+
}
268278
}
269279
return;
270280
}
271-
// first configuration of the sloeber project
272-
if (readSloeberConfig(prjCDesc)) {
273-
// we migrated from a previous sloeber configuration
274-
myNeedsClean = true;
281+
// first read the sloeber files in memory
282+
readSloeberConfig(prjCDesc, prjDescWritable);
283+
if (myNeedToPersist || isDirty) {
275284
createSloeberConfigFiles(prjCDesc);
276-
// we need a writable project description to clean the old sloeber data
277-
if (prjDescWritable) {
285+
isDirty = false;
286+
}
287+
if (prjDescWritable) {
288+
if (myNeedsClean) {
289+
// we migrated from a previous sloeber configuration
290+
// and we can safely delete the old data
278291
cleanOldData(prjCDesc);
279292
}
293+
if (myNeedsSyncWithCDT) {
294+
syncWithCDT(prjCDesc, prjDescWritable);
295+
}
280296
}
281297
setEnvironmentVariables(prjCDesc);
282-
isConfigured = true;
298+
isInMemory = true;
299+
}
300+
301+
/**
302+
* sync the Sloeber configuration info with CDT Currently only Sloeber known
303+
* confighgurations will be created by Sloeber inside CDT
304+
*/
305+
private void syncWithCDT(ICProjectDescription prjCDesc, boolean prjDescWritable) {
306+
readSloeberConfig(prjCDesc, prjDescWritable);
307+
myNeedsSyncWithCDT = false;
283308
}
284309

285310
/**
@@ -313,22 +338,44 @@ private void cleanOldData(ICProjectDescription prjCDesc) {
313338
* @param confDesc
314339
* returns true if the config needs saving otherwise false
315340
*/
316-
private boolean readSloeberConfig(final ICProjectDescription prjCDesc) {
317-
boolean needToCreateConfigFiles = false;
341+
private void readSloeberConfig(ICProjectDescription prjCDesc, boolean prjDescWritable) {
318342
IFile file = getConfigLocalFile();
319343
if (file.exists()) {
320344
myCfgFile = new TxtFile(file.getLocation().toFile());
321345
IFile versionFile = getConfigVersionFile();
322346
if (versionFile.exists()) {
323347
myCfgFile.mergeFile(versionFile.getLocation().toFile());
324348
}
325-
for (ICConfigurationDescription confDesc : prjCDesc.getConfigurations()) {
326-
BoardDescription boardDesc = new BoardDescription(myCfgFile, getBoardPrefix(confDesc));
327-
CompileDescription compileDescription = new CompileDescription(myCfgFile, getCompilePrefix(confDesc));
328-
OtherDescription otherDesc = new OtherDescription(myCfgFile, getOtherPrefix(confDesc));
329-
myBoardDescriptions.put(confDesc.getId(), boardDesc);
330-
myCompileDescriptions.put(confDesc.getId(), compileDescription);
331-
myOtherDescriptions.put(confDesc.getId(), otherDesc);
349+
KeyValueTree allFileConfigs = myCfgFile.getData().getChild(CONFIG);
350+
for (Entry<String, KeyValueTree> curChild : allFileConfigs.getChildren().entrySet()) {
351+
String curConfName = curChild.getKey();
352+
BoardDescription boardDesc = new BoardDescription(myCfgFile, getBoardPrefix(curConfName));
353+
CompileDescription compileDescription = new CompileDescription(myCfgFile,
354+
getCompilePrefix(curConfName));
355+
OtherDescription otherDesc = new OtherDescription(myCfgFile, getOtherPrefix(curConfName));
356+
ICConfigurationDescription curConfDesc = prjCDesc.getConfigurationByName(curConfName);
357+
if (curConfDesc == null) {
358+
myNeedsSyncWithCDT = true;
359+
// I set persist because most likely this new config comes from sloeber.cfg
360+
// and it must be copied to .sproject
361+
myNeedToPersist = true;
362+
if (prjDescWritable) {
363+
String id = CDataUtil.genId(null);
364+
try {
365+
curConfDesc = prjCDesc.createConfiguration(id, curConfName,
366+
prjCDesc.getActiveConfiguration());
367+
} catch (Exception e) {
368+
// ignore as we will try again later
369+
}
370+
}
371+
}
372+
if (curConfDesc != null) {
373+
String curConfID = curConfDesc.getId();
374+
myBoardDescriptions.put(curConfID, boardDesc);
375+
myCompileDescriptions.put(curConfID, compileDescription);
376+
myOtherDescriptions.put(curConfID, otherDesc);
377+
myNeedsSyncWithCDT = false;
378+
}
332379
}
333380

334381
} else {
@@ -339,7 +386,8 @@ private boolean readSloeberConfig(final ICProjectDescription prjCDesc) {
339386
} else {
340387
// Maybe this is a old Sloeber project with the data in the eclipse build
341388
// environment variables
342-
needToCreateConfigFiles = true;
389+
myNeedToPersist = true;
390+
myNeedsClean = true;
343391
for (ICConfigurationDescription confDesc : prjCDesc.getConfigurations()) {
344392

345393
BoardDescription boardDesc = BoardDescription.getFromCDT(confDesc);
@@ -352,7 +400,6 @@ private boolean readSloeberConfig(final ICProjectDescription prjCDesc) {
352400

353401
}
354402
}
355-
return needToCreateConfigFiles;
356403
}
357404

358405
private boolean setActiveConfig(ICConfigurationDescription confDesc) {
@@ -397,12 +444,32 @@ private void createSloeberConfigFiles(final ICProjectDescription prjCDesc) {
397444
Map<String, String> versionVars = new TreeMap<>();
398445

399446
for (ICConfigurationDescription confDesc : prjCDesc.getConfigurations()) {
400-
BoardDescription boardDescription = myBoardDescriptions.get(confDesc.getId());
401-
CompileDescription compileDescription = myCompileDescriptions.get(confDesc.getId());
402-
OtherDescription otherDescription = myOtherDescriptions.get(confDesc.getId());
403-
String boardPrefix = getBoardPrefix(confDesc);
404-
String compPrefix = getCompilePrefix(confDesc);
405-
String otherPrefix = getOtherPrefix(confDesc);
447+
String confID = confDesc.getId();
448+
String confName = confDesc.getName();
449+
BoardDescription boardDescription = myBoardDescriptions.get(confID);
450+
CompileDescription compileDescription = myCompileDescriptions.get(confID);
451+
OtherDescription otherDescription = myOtherDescriptions.get(confID);
452+
// when a new configuration has been created not in project properties
453+
// the descriptions can be null
454+
// first get a config to copy from
455+
Iterator<Entry<String, BoardDescription>> iterator = myBoardDescriptions.entrySet().iterator();
456+
Entry<String, BoardDescription> actualValue = iterator.next();
457+
String copyConfID = actualValue.getKey();
458+
if (null == boardDescription) {
459+
boardDescription = new BoardDescription(myBoardDescriptions.get(copyConfID));
460+
myBoardDescriptions.put(confID, boardDescription);
461+
}
462+
if (null == compileDescription) {
463+
compileDescription = new CompileDescription(myCompileDescriptions.get(copyConfID));
464+
myCompileDescriptions.put(confID, compileDescription);
465+
}
466+
if (null == otherDescription) {
467+
otherDescription = new OtherDescription(myOtherDescriptions.get(copyConfID));
468+
myOtherDescriptions.put(confID, otherDescription);
469+
}
470+
String boardPrefix = getBoardPrefix(confName);
471+
String compPrefix = getCompilePrefix(confName);
472+
String otherPrefix = getOtherPrefix(confName);
406473

407474
configVars.putAll(boardDescription.getEnvVarsConfig(boardPrefix));
408475
configVars.putAll(compileDescription.getEnvVarsConfig(compPrefix));
@@ -418,11 +485,11 @@ private void createSloeberConfigFiles(final ICProjectDescription prjCDesc) {
418485
try {
419486
storeConfigurationFile(getConfigVersionFile(), versionVars);
420487
storeConfigurationFile(getConfigLocalFile(), configVars);
421-
isDirty = false;
422488
} catch (CoreException e) {
423489
Common.log(new Status(IStatus.ERROR, io.sloeber.core.Activator.getId(),
424490
"failed to save the sloeber config files", e)); //$NON-NLS-1$
425491
}
492+
myNeedToPersist = false;
426493

427494
}
428495

@@ -499,7 +566,7 @@ public static synchronized SloeberProject getSloeberProject(IProject project, bo
499566
e.printStackTrace();
500567
}
501568
if (!allowNull) {
502-
SloeberProject ret = new SloeberProject(project, false);
569+
SloeberProject ret = new SloeberProject(project);
503570
return ret;
504571
}
505572
}
@@ -545,21 +612,21 @@ public void setOtherDescription(ICConfigurationDescription confDesc, OtherDescri
545612
*/
546613
public BoardDescription getBoardDescription(ICConfigurationDescription confDesc, boolean allowNull) {
547614
if (!allowNull) {
548-
configureProject();
615+
configure();
549616
}
550617
return myBoardDescriptions.get(confDesc.getId());
551618
}
552619

553620
public CompileDescription getCompileDescription(ICConfigurationDescription confDesc, boolean allowNull) {
554621
if (!allowNull) {
555-
configureProject();
622+
configure();
556623
}
557624
return myCompileDescriptions.get(confDesc.getId());
558625
}
559626

560627
public OtherDescription getOtherDescription(ICConfigurationDescription confDesc, boolean allowNull) {
561628
if (!allowNull) {
562-
configureProject();
629+
configure();
563630
}
564631
return myOtherDescriptions.get(confDesc.getId());
565632
}
@@ -596,16 +663,16 @@ public String getDecoratedText(String text) {
596663
return text;
597664
}
598665

599-
private static String getBoardPrefix(ICConfigurationDescription confDesc) {
600-
return CONFIG_DOT + confDesc.getName() + DOT + "board."; //$NON-NLS-1$
666+
private static String getBoardPrefix(String confDescName) {
667+
return CONFIG_DOT + confDescName + DOT + "board."; //$NON-NLS-1$
601668
}
602669

603-
private static String getCompilePrefix(ICConfigurationDescription confDesc) {
604-
return CONFIG_DOT + confDesc.getName() + DOT + "compile."; //$NON-NLS-1$
670+
private static String getCompilePrefix(String confDescName) {
671+
return CONFIG_DOT + confDescName + DOT + "compile."; //$NON-NLS-1$
605672
}
606673

607-
private static String getOtherPrefix(ICConfigurationDescription confDesc) {
608-
return CONFIG_DOT + confDesc.getName() + DOT + "other."; //$NON-NLS-1$
674+
private static String getOtherPrefix(String confDescName) {
675+
return CONFIG_DOT + confDescName + DOT + "other."; //$NON-NLS-1$
609676
}
610677

611678
private IFile getConfigVersionFile() {
@@ -619,9 +686,28 @@ private IFile getConfigLocalFile() {
619686
public void configChangeAboutToApply(ICProjectDescription newProjDesc, ICProjectDescription oldProjDesc) {
620687
ICConfigurationDescription newActiveConfig = newProjDesc.getActiveConfiguration();
621688
ICConfigurationDescription oldActiveConfig = oldProjDesc.getActiveConfiguration();
689+
690+
// make sure the dirty flag is set when needed
691+
if (!isDirty) {
692+
// set dirty when the number of configurations changed
693+
int newNumberOfConfigs = newProjDesc.getConfigurations().length;
694+
int oldNumberOfConfigs = oldProjDesc.getConfigurations().length;
695+
if (newNumberOfConfigs != oldNumberOfConfigs) {
696+
isDirty = true;
697+
} else {
698+
// set dirty if a configname changed
699+
for (ICConfigurationDescription curConfig : newProjDesc.getConfigurations()) {
700+
if (oldProjDesc.getConfigurationByName(curConfig.getName()) == null) {
701+
isDirty = true;
702+
}
703+
}
704+
}
705+
}
706+
// in many cases we also need to set the active config
622707
boolean needsConfigSet = myNeedsClean || isDirty
623708
|| !newActiveConfig.getName().equals(oldActiveConfig.getName());
624-
configureProject(newProjDesc, true);
709+
710+
configure(newProjDesc, true);
625711
if (needsConfigSet) {
626712
setActiveConfig(newActiveConfig);
627713
}

0 commit comments

Comments
 (0)