Skip to content

Commit ef7c6bf

Browse files
committed
[Library Ordering] Add an AutoDependenciesOrder option to projects that will allow them to opt into ordering their ouputs in dependency order.
* This is useful on linux platforms where link order matters more.
1 parent ccca5aa commit ef7c6bf

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

Sharpmake/Project.Configuration.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ public void AddDependencyBuiltTargetLibraryFile(string libraryFile, int orderNum
11511151
{
11521152
if (_linkState != LinkState.Linking)
11531153
throw new Error($"Cannot add built target lib '{libraryFile}' outside of the link process of the Project.Configuration");
1154-
DependenciesBuiltTargetsLibraryFiles.Add(libraryFile, orderNumber);
1154+
DependenciesBuiltTargetsLibraryFiles.Add(libraryFile, orderNumber, OrderableStrings.OrderResolve.Greater);
11551155
}
11561156

11571157
public OrderableStrings DependenciesForceUsingFiles = new OrderableStrings();
@@ -2850,15 +2850,17 @@ private static int SortConfigurationForLink(Configuration l, Configuration r)
28502850

28512851
internal class DependencyNode
28522852
{
2853-
internal DependencyNode(Configuration inConfiguration, DependencySetting inDependencySetting)
2853+
internal DependencyNode(Configuration inConfiguration, DependencySetting inDependencySetting, int autoDependenciesOrder = 0)
28542854
{
28552855
_configuration = inConfiguration;
28562856
_dependencySetting = inDependencySetting;
2857+
_autoDependenciesOrder = autoDependenciesOrder;
28572858
}
28582859

28592860
internal Configuration _configuration;
28602861
internal DependencySetting _dependencySetting;
28612862
internal Dictionary<DependencyNode, DependencyType> _childNodes = new Dictionary<DependencyNode, DependencyType>();
2863+
internal int _autoDependenciesOrder;
28622864
}
28632865

28642866
public class VcxprojUserFileSettings
@@ -3105,8 +3107,9 @@ internal void Link(Builder builder)
31053107
if (dependencySetting.HasFlag(DependencySetting.LibraryPaths))
31063108
DependenciesOtherLibraryPaths.AddRange(dependency.LibraryPaths);
31073109

3110+
// Use dependency.TargetFileOrderNumber to make sure to group dependent libraries by their dependencies
31083111
if (dependencySetting.HasFlag(DependencySetting.LibraryFiles))
3109-
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles);
3112+
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles, dependency.TargetFileOrderNumber, OrderableStrings.OrderResolve.Greater);
31103113

31113114
if (dependencySetting.HasFlag(DependencySetting.ForceUsingAssembly))
31123115
DependenciesForceUsingFiles.AddRange(dependency.ForceUsingFiles);
@@ -3138,8 +3141,9 @@ internal void Link(Builder builder)
31383141
if (dependencySetting.HasFlag(DependencySetting.LibraryPaths))
31393142
DependenciesOtherLibraryPaths.AddRange(dependency.LibraryPaths);
31403143

3144+
// Use dependency.TargetFileOrderNumber to make sure to group dependent libraries by their dependencies
31413145
if (dependencySetting.HasFlag(DependencySetting.LibraryFiles))
3142-
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles);
3146+
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles, dependency.TargetFileOrderNumber, OrderableStrings.OrderResolve.Greater);
31433147
}
31443148
}
31453149

@@ -3303,6 +3307,7 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
33033307

33043308
Stack<DependencyNode> visiting = new Stack<DependencyNode>();
33053309
visiting.Push(rootNode);
3310+
33063311
while (visiting.Count > 0)
33073312
{
33083313
DependencyNode visitedNode = visiting.Pop();
@@ -3322,6 +3327,11 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
33223327

33233328
visited.Add(visitedConfiguration, visitedNode);
33243329

3330+
if (visitedConfiguration.Project.AutoDependenciesOrder)
3331+
{
3332+
visitedConfiguration.TargetFileOrderNumber = Math.Max(visitedConfiguration.TargetFileOrderNumber, visitedNode._autoDependenciesOrder);
3333+
}
3334+
33253335
var unresolvedDependencies = new[] { visitedConfiguration.UnResolvedPublicDependencies, visitedConfiguration.UnResolvedPrivateDependencies };
33263336
foreach (Dictionary<Type, ITarget> dependencies in unresolvedDependencies)
33273337
{
@@ -3340,7 +3350,8 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
33403350
if (!visitedConfiguration._dependenciesSetting.TryGetValue(pair, out dependencySetting))
33413351
dependencySetting = DependencySetting.Default;
33423352

3343-
DependencyNode childNode = new DependencyNode(dependencyConf, dependencySetting);
3353+
// We use steps of 1000 to allow for related libraries to be grouped alongside their dependencies
3354+
DependencyNode childNode = new DependencyNode(dependencyConf, dependencySetting, visitedNode._autoDependenciesOrder + 1000);
33443355
System.Diagnostics.Debug.Assert(!visitedNode._childNodes.ContainsKey(childNode));
33453356
visitedNode._childNodes.Add(childNode, dependencyType);
33463357

Sharpmake/Project.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ public uint DependenciesOrder
254254
set { SetProperty(ref _dependenciesOrder, value); }
255255
}
256256

257+
private bool _autoDependenciesOrder = false;
258+
public bool AutoDependenciesOrder
259+
{
260+
get { return _autoDependenciesOrder; }
261+
set { SetProperty(ref _autoDependenciesOrder, value); }
262+
}
263+
257264
// For projects that output both dll and lib depending on the configuration (often the case in TG projects)
258265
// Setting this to true will force dependencies regardless of different output types.
259266
public bool AllowInconsistentDependencies = false;

Sharpmake/Strings.cs

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,14 @@ public void Add(string item)
253253
_list.Add(new StringEntry(item));
254254
}
255255

256-
public void Add(string item, int orderNumber)
256+
public enum OrderResolve
257+
{
258+
None,
259+
Less,
260+
Greater
261+
}
262+
263+
public void Add(string item, int orderNumber, OrderResolve resolveMethod = OrderResolve.None)
257264
{
258265
if (_hashSet.Add(item))
259266
_list.Add(new StringEntry(item, orderNumber));
@@ -268,9 +275,22 @@ public void Add(string item, int orderNumber)
268275
_list[i] = new StringEntry(item, orderNumber);
269276
else if (_list[i].OrderNumber != orderNumber)
270277
{
271-
throw new Error(
272-
"Cannot specify 2 different non-zero order number for \"" +
273-
item + "\": " + _list[i].OrderNumber + " and " + orderNumber);
278+
if (resolveMethod == OrderResolve.Less)
279+
{
280+
if (orderNumber < _list[i].OrderNumber)
281+
_list[i] = new StringEntry(item, orderNumber);
282+
}
283+
else if (resolveMethod == OrderResolve.Greater)
284+
{
285+
if (orderNumber > _list[i].OrderNumber)
286+
_list[i] = new StringEntry(item, orderNumber);
287+
}
288+
else
289+
{
290+
throw new Error(
291+
"Cannot specify 2 different non-zero order number for \"" +
292+
item + "\": " + _list[i].OrderNumber + " and " + orderNumber);
293+
}
274294
}
275295
}
276296
}
@@ -283,18 +303,20 @@ public void AddRange(IEnumerable<string> collection)
283303
Add(item);
284304
}
285305

286-
public void AddRange(OrderableStrings collection)
306+
public void AddRange(OrderableStrings collection, int outerOrderNumber = 0, OrderResolve resolveMethod = OrderResolve.None)
287307
{
288308
List<StringEntry> existingEntriesToAdd = null;
289309
foreach (var entry in collection._list)
290310
{
311+
var newEntry = new StringEntry(entry.StringValue, entry.OrderNumber + outerOrderNumber);
312+
291313
if (_hashSet.Add(entry.StringValue))
292-
_list.Add(entry);
293-
else if (entry.OrderNumber != 0) // make sure to have orderNumber
314+
_list.Add(newEntry);
315+
else if (newEntry.OrderNumber != 0) // make sure to have orderNumber
294316
{
295317
if (existingEntriesToAdd == null)
296318
existingEntriesToAdd = new List<StringEntry>();
297-
existingEntriesToAdd.Add(entry);
319+
existingEntriesToAdd.Add(newEntry);
298320
}
299321
}
300322
if (existingEntriesToAdd != null)
@@ -309,9 +331,22 @@ public void AddRange(OrderableStrings collection)
309331
_list[i] = new StringEntry(_list[i].StringValue, orderNumber);
310332
else if (_list[i].OrderNumber != orderNumber)
311333
{
312-
throw new Error(
313-
"Cannot specify 2 different non-zero order number for \"" +
314-
_list[i].StringValue + "\": " + _list[i].OrderNumber + " and " + orderNumber);
334+
if (resolveMethod == OrderResolve.Less)
335+
{
336+
if (orderNumber < _list[i].OrderNumber)
337+
_list[i] = new StringEntry(_list[i].StringValue, orderNumber);
338+
}
339+
else if (resolveMethod == OrderResolve.Greater)
340+
{
341+
if (orderNumber > _list[i].OrderNumber)
342+
_list[i] = new StringEntry(_list[i].StringValue, orderNumber);
343+
}
344+
else
345+
{
346+
throw new Error(
347+
"Cannot specify 2 different non-zero order number for \"" +
348+
_list[i].StringValue + "\": " + _list[i].OrderNumber + " and " + orderNumber);
349+
}
315350
}
316351
}
317352
}

0 commit comments

Comments
 (0)