Skip to content

Commit 1794f9a

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 1794f9a

File tree

2 files changed

+69
-16
lines changed

2 files changed

+69
-16
lines changed

Sharpmake/Project.Configuration.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,13 @@ public Options.Vc.Compiler.Exceptions GetExceptionSettingForFile(string filename
10801080
return Sharpmake.Options.Vc.Compiler.Exceptions.Disable;
10811081
}
10821082

1083+
/// <summary>
1084+
/// When enabled dependendent libraries will be sorted by their dependencies. This can be
1085+
/// used to fix linker errors on linux platforms that expect libraries to be included in a
1086+
/// specific order
1087+
/// </summary>
1088+
public bool AutoDependenciesOrder = false;
1089+
10831090
/// <summary>
10841091
/// Gets a list of the search directories for static libraries.
10851092
/// </summary>
@@ -1151,7 +1158,7 @@ public void AddDependencyBuiltTargetLibraryFile(string libraryFile, int orderNum
11511158
{
11521159
if (_linkState != LinkState.Linking)
11531160
throw new Error($"Cannot add built target lib '{libraryFile}' outside of the link process of the Project.Configuration");
1154-
DependenciesBuiltTargetsLibraryFiles.Add(libraryFile, orderNumber);
1161+
DependenciesBuiltTargetsLibraryFiles.Add(libraryFile, orderNumber, OrderableStrings.OrderResolve.Greater);
11551162
}
11561163

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

28512858
internal class DependencyNode
28522859
{
2853-
internal DependencyNode(Configuration inConfiguration, DependencySetting inDependencySetting)
2860+
internal DependencyNode(Configuration inConfiguration, DependencySetting inDependencySetting, int autoDependenciesOrder = 0)
28542861
{
28552862
_configuration = inConfiguration;
28562863
_dependencySetting = inDependencySetting;
2864+
_autoDependenciesOrder = autoDependenciesOrder;
28572865
}
28582866

28592867
internal Configuration _configuration;
28602868
internal DependencySetting _dependencySetting;
28612869
internal Dictionary<DependencyNode, DependencyType> _childNodes = new Dictionary<DependencyNode, DependencyType>();
2870+
internal int _autoDependenciesOrder;
28622871
}
28632872

28642873
public class VcxprojUserFileSettings
@@ -3105,8 +3114,9 @@ internal void Link(Builder builder)
31053114
if (dependencySetting.HasFlag(DependencySetting.LibraryPaths))
31063115
DependenciesOtherLibraryPaths.AddRange(dependency.LibraryPaths);
31073116

3117+
// Use dependency.TargetFileOrderNumber to make sure to group dependent libraries by their dependencies
31083118
if (dependencySetting.HasFlag(DependencySetting.LibraryFiles))
3109-
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles);
3119+
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles, dependency.TargetFileOrderNumber, OrderableStrings.OrderResolve.Greater);
31103120

31113121
if (dependencySetting.HasFlag(DependencySetting.ForceUsingAssembly))
31123122
DependenciesForceUsingFiles.AddRange(dependency.ForceUsingFiles);
@@ -3138,8 +3148,9 @@ internal void Link(Builder builder)
31383148
if (dependencySetting.HasFlag(DependencySetting.LibraryPaths))
31393149
DependenciesOtherLibraryPaths.AddRange(dependency.LibraryPaths);
31403150

3151+
// Use dependency.TargetFileOrderNumber to make sure to group dependent libraries by their dependencies
31413152
if (dependencySetting.HasFlag(DependencySetting.LibraryFiles))
3142-
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles);
3153+
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles, dependency.TargetFileOrderNumber, OrderableStrings.OrderResolve.Greater);
31433154
}
31443155
}
31453156

@@ -3303,6 +3314,7 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
33033314

33043315
Stack<DependencyNode> visiting = new Stack<DependencyNode>();
33053316
visiting.Push(rootNode);
3317+
33063318
while (visiting.Count > 0)
33073319
{
33083320
DependencyNode visitedNode = visiting.Pop();
@@ -3322,6 +3334,11 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
33223334

33233335
visited.Add(visitedConfiguration, visitedNode);
33243336

3337+
if (visitedConfiguration.AutoDependenciesOrder)
3338+
{
3339+
visitedConfiguration.TargetFileOrderNumber = Math.Max(visitedConfiguration.TargetFileOrderNumber, visitedNode._autoDependenciesOrder);
3340+
}
3341+
33253342
var unresolvedDependencies = new[] { visitedConfiguration.UnResolvedPublicDependencies, visitedConfiguration.UnResolvedPrivateDependencies };
33263343
foreach (Dictionary<Type, ITarget> dependencies in unresolvedDependencies)
33273344
{
@@ -3340,7 +3357,8 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
33403357
if (!visitedConfiguration._dependenciesSetting.TryGetValue(pair, out dependencySetting))
33413358
dependencySetting = DependencySetting.Default;
33423359

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

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)