Skip to content

Commit

Permalink
[Library Ordering] Add an AutoDependenciesOrder option to projects th…
Browse files Browse the repository at this point in the history
…at will allow them to opt into ordering their ouputs in dependency order.

* This is useful on linux platforms where link order matters more.
  • Loading branch information
kudaba committed Feb 8, 2022
1 parent ccca5aa commit ef7c6bf
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
21 changes: 16 additions & 5 deletions Sharpmake/Project.Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ public void AddDependencyBuiltTargetLibraryFile(string libraryFile, int orderNum
{
if (_linkState != LinkState.Linking)
throw new Error($"Cannot add built target lib '{libraryFile}' outside of the link process of the Project.Configuration");
DependenciesBuiltTargetsLibraryFiles.Add(libraryFile, orderNumber);
DependenciesBuiltTargetsLibraryFiles.Add(libraryFile, orderNumber, OrderableStrings.OrderResolve.Greater);
}

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

internal class DependencyNode
{
internal DependencyNode(Configuration inConfiguration, DependencySetting inDependencySetting)
internal DependencyNode(Configuration inConfiguration, DependencySetting inDependencySetting, int autoDependenciesOrder = 0)
{
_configuration = inConfiguration;
_dependencySetting = inDependencySetting;
_autoDependenciesOrder = autoDependenciesOrder;
}

internal Configuration _configuration;
internal DependencySetting _dependencySetting;
internal Dictionary<DependencyNode, DependencyType> _childNodes = new Dictionary<DependencyNode, DependencyType>();
internal int _autoDependenciesOrder;
}

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

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

if (dependencySetting.HasFlag(DependencySetting.ForceUsingAssembly))
DependenciesForceUsingFiles.AddRange(dependency.ForceUsingFiles);
Expand Down Expand Up @@ -3138,8 +3141,9 @@ internal void Link(Builder builder)
if (dependencySetting.HasFlag(DependencySetting.LibraryPaths))
DependenciesOtherLibraryPaths.AddRange(dependency.LibraryPaths);

// Use dependency.TargetFileOrderNumber to make sure to group dependent libraries by their dependencies
if (dependencySetting.HasFlag(DependencySetting.LibraryFiles))
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles);
DependenciesOtherLibraryFiles.AddRange(dependency.LibraryFiles, dependency.TargetFileOrderNumber, OrderableStrings.OrderResolve.Greater);
}
}

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

Stack<DependencyNode> visiting = new Stack<DependencyNode>();
visiting.Push(rootNode);

while (visiting.Count > 0)
{
DependencyNode visitedNode = visiting.Pop();
Expand All @@ -3322,6 +3327,11 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura

visited.Add(visitedConfiguration, visitedNode);

if (visitedConfiguration.Project.AutoDependenciesOrder)
{
visitedConfiguration.TargetFileOrderNumber = Math.Max(visitedConfiguration.TargetFileOrderNumber, visitedNode._autoDependenciesOrder);
}

var unresolvedDependencies = new[] { visitedConfiguration.UnResolvedPublicDependencies, visitedConfiguration.UnResolvedPrivateDependencies };
foreach (Dictionary<Type, ITarget> dependencies in unresolvedDependencies)
{
Expand All @@ -3340,7 +3350,8 @@ static private DependencyNode BuildDependencyNodeTree(Builder builder, Configura
if (!visitedConfiguration._dependenciesSetting.TryGetValue(pair, out dependencySetting))
dependencySetting = DependencySetting.Default;

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

Expand Down
7 changes: 7 additions & 0 deletions Sharpmake/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,13 @@ public uint DependenciesOrder
set { SetProperty(ref _dependenciesOrder, value); }
}

private bool _autoDependenciesOrder = false;
public bool AutoDependenciesOrder
{
get { return _autoDependenciesOrder; }
set { SetProperty(ref _autoDependenciesOrder, value); }
}

// For projects that output both dll and lib depending on the configuration (often the case in TG projects)
// Setting this to true will force dependencies regardless of different output types.
public bool AllowInconsistentDependencies = false;
Expand Down
57 changes: 46 additions & 11 deletions Sharpmake/Strings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,14 @@ public void Add(string item)
_list.Add(new StringEntry(item));
}

public void Add(string item, int orderNumber)
public enum OrderResolve
{
None,
Less,
Greater
}

public void Add(string item, int orderNumber, OrderResolve resolveMethod = OrderResolve.None)
{
if (_hashSet.Add(item))
_list.Add(new StringEntry(item, orderNumber));
Expand All @@ -268,9 +275,22 @@ public void Add(string item, int orderNumber)
_list[i] = new StringEntry(item, orderNumber);
else if (_list[i].OrderNumber != orderNumber)
{
throw new Error(
"Cannot specify 2 different non-zero order number for \"" +
item + "\": " + _list[i].OrderNumber + " and " + orderNumber);
if (resolveMethod == OrderResolve.Less)
{
if (orderNumber < _list[i].OrderNumber)
_list[i] = new StringEntry(item, orderNumber);
}
else if (resolveMethod == OrderResolve.Greater)
{
if (orderNumber > _list[i].OrderNumber)
_list[i] = new StringEntry(item, orderNumber);
}
else
{
throw new Error(
"Cannot specify 2 different non-zero order number for \"" +
item + "\": " + _list[i].OrderNumber + " and " + orderNumber);
}
}
}
}
Expand All @@ -283,18 +303,20 @@ public void AddRange(IEnumerable<string> collection)
Add(item);
}

public void AddRange(OrderableStrings collection)
public void AddRange(OrderableStrings collection, int outerOrderNumber = 0, OrderResolve resolveMethod = OrderResolve.None)
{
List<StringEntry> existingEntriesToAdd = null;
foreach (var entry in collection._list)
{
var newEntry = new StringEntry(entry.StringValue, entry.OrderNumber + outerOrderNumber);

if (_hashSet.Add(entry.StringValue))
_list.Add(entry);
else if (entry.OrderNumber != 0) // make sure to have orderNumber
_list.Add(newEntry);
else if (newEntry.OrderNumber != 0) // make sure to have orderNumber
{
if (existingEntriesToAdd == null)
existingEntriesToAdd = new List<StringEntry>();
existingEntriesToAdd.Add(entry);
existingEntriesToAdd.Add(newEntry);
}
}
if (existingEntriesToAdd != null)
Expand All @@ -309,9 +331,22 @@ public void AddRange(OrderableStrings collection)
_list[i] = new StringEntry(_list[i].StringValue, orderNumber);
else if (_list[i].OrderNumber != orderNumber)
{
throw new Error(
"Cannot specify 2 different non-zero order number for \"" +
_list[i].StringValue + "\": " + _list[i].OrderNumber + " and " + orderNumber);
if (resolveMethod == OrderResolve.Less)
{
if (orderNumber < _list[i].OrderNumber)
_list[i] = new StringEntry(_list[i].StringValue, orderNumber);
}
else if (resolveMethod == OrderResolve.Greater)
{
if (orderNumber > _list[i].OrderNumber)
_list[i] = new StringEntry(_list[i].StringValue, orderNumber);
}
else
{
throw new Error(
"Cannot specify 2 different non-zero order number for \"" +
_list[i].StringValue + "\": " + _list[i].OrderNumber + " and " + orderNumber);
}
}
}
}
Expand Down

0 comments on commit ef7c6bf

Please sign in to comment.