Update: As commented by ‘pifcnt’ this is for VS2010 files.
Today I had the daunting task of combining multiple solution files into one. The reason for this was that the project I’m working on originally started as multiple separate solutions with shared projects. Now we find it more convenient to have it in a single solution both for automated build and, at least for some, as a preferred work method.
There are 88 projects split over 22 solutions. I started the task by manually adding them to an empty solution thinking that this will take some time, but not that much. Unfortunately Visual Studio crashed early in the task. I’ve previously Googled for an application to do this and found one that didn’t work.
So I brushed off my black belt in Perl regex and 3-4 hours later I had a script that solved my problem.
It combines all Project sections, corrects relative path to projects, skips the GlobalSection(TeamFoundationVersionControl) and keeps all other GlobalSections with only unique entries on each.
Syntax: merge.pl Relative\Path\To\Solution1.sln,And\Relative\Path\To\Solution1.sln CombinedOutput.sln
Note that you want to be standing in a common root for all projects and you want to put the output file in this path. This script doesn’t check everything, it was made to solve one task – and so it did.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
#!/usr/bin/perl ## ## SETTINGS ## $HEADER = <<EOH; Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 EOH ## ## END SETTINGS ## print <<EOT; Visual Studio Solution File Merge By Tedd Hansen <tedd\@konge.net> Jan 2011 EOT if ($#ARGV <= 0) { print "Required parameters: input1.sln,input2.sln output.sln\n"; exit; } my %PROJECTS; my %GLOBALSECTIONS; my %GLOBALSECTIONSHEADER; $INPUT = @ARGV[0]; $OUTPUT = @ARGV[1]; @INPUTS = split /,/, $INPUT; print "Merging ".($#INPUTS+1)." files: ".$INPUT."\n"; print "Output: ".$OUTPUT."\n"; print "\n"; foreach my $file (@INPUTS) { &READ($file); } &WRITE($OUTPUT); sub WRITE { open (OF, "> $OUTPUT"); print OF $HEADER."\r\n"; foreach my $proj (sort keys %PROJECTS) { print OF $PROJECTS{$proj}; } print OF "Global\r\n"; foreach $glob (keys %GLOBALSECTIONS) { print OF $GLOBALSECTIONSHEADER{$glob}; my %tmp = map { $_ => 1 } split /\t/, $GLOBALSECTIONS{$glob}; foreach my $line (keys %tmp) { print OF $line; } print OF "EndGlobalSection\r\n"; } print OF "EndGlobal\r\n"; close(OF); } sub READ { #local $\ = "\r\n"; my $file = shift; open (IF, "< $file"); my $root = $file; $root =~ s/[^\\\/]+\.sln(_deploy)?$//i; while ($line = <IF>) { #$line =~ s/(\r|\n)$//mg; next if ($line =~ m/^(Microsoft Visual|# Visual Studio)/); ## ### SECTION: PROJECT ## #Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PGSA.Contracts" if ($line =~ m/^\s*Project[^=]+=\s*"([^"]+)"/) { unless (exists($PROJECTS{lc($1)})) { $in_project = lc($1); #replace file $line =~ m/(^\s*Project[^=]+=\s*"[^"]+"\s*,\s*")([^"]+)(".*)/; my $loc = $root.$2; my $p1 = $1; my $p2 = $3; $loc =~ s/\//\\/g; $loc =~ s/\\\\+/\\/g; $loc =~ s/[^\\]+\\\.\.\\//g; $line = $p1.$loc.$p2; } } $PROJECTS{$in_project} .= $line if ($in_project); undef $in_project if ($line =~ m/^\s*EndProject/); ## ### END SECTION: PROJECT ## ## ### SECTION: GLOBALSECTION ## if ($line =~ m/^\s*GlobalSection\(([^\)]+)\)/) { $in_global = lc($1); $GLOBALSECTIONSHEADER{$in_global} .= $line; } undef $in_global if ($line =~ m/^\s*EndGlobalSection/); if ($in_global) { unless ($in_global eq "teamfoundationversioncontrol") { $line =~ s/\t/ /g; $GLOBALSECTIONS{$in_global} .= "\t".$line; } } ## ### END SECTION: GLOBALSECTION ## } close(IF); } |
Too bad you forgot to mention that it only works for 2010 solution files. BAD! BAD! BAD!
Been some time since I wrote this post, but I believe it should work with other versions as well (although I haven’t tested it). There is very little change in the project files between versions. Anyway, then I presume you spent a few minutes testing it so just consider this your contribution to my contribution. 🙂