Removed svn Id tag
[MPC.git] / modules / VC8WorkspaceCreator.pm
blob9d879c0b6d604e61aa7258031b701a2371764d9b
1 package VC8WorkspaceCreator;
3 # ************************************************************
4 # Description : A VC8 Workspace Creator
5 # Author : Johnny Willemsen
6 # Create Date : 4/21/2004
7 # ************************************************************
9 # ************************************************************
10 # Pragmas
11 # ************************************************************
13 use strict;
15 use VC8ProjectCreator;
16 use VC71WorkspaceCreator;
18 use vars qw(@ISA);
19 @ISA = qw(VC71WorkspaceCreator);
21 # ************************************************************
22 # Data Section
23 # ************************************************************
25 ## NOTE: We call the constant as a function to support Perl 5.6.
26 my %lang_map = (Creator::cplusplus() => 'Visual C#',
27 Creator::csharp() => 'Visual C#',
28 Creator::vb() => 'Visual Basic',
29 Creator::java() => 'Visual J#');
31 # ************************************************************
32 # Subroutine Section
33 # ************************************************************
35 sub pre_workspace {
36 my($self, $fh) = @_;
37 my $crlf = $self->crlf();
39 ## This identifies it as a Visual Studio 2005 file
40 print $fh '', $crlf,
41 'Microsoft Visual Studio Solution File, Format Version 9.00', $crlf;
43 ## Optionally print the workspace comment
44 $self->print_workspace_comment($fh,
45 '# Visual Studio 2005', $crlf,
46 '# ', $crlf,
47 '#', $crlf,
48 '# This file was generated by MPC. Any changes made directly to', $crlf,
49 '# this file will be lost the next time it is generated.', $crlf,
50 '#', $crlf,
51 '# MPC Command:', $crlf,
52 '# ', $self->create_command_line_string($0, @ARGV), $crlf);
55 sub post_workspace {
56 my($self, $fh, $creator) = @_;
57 my $pjs = $self->get_project_info();
58 my @projects = $self->sort_dependencies($self->get_projects(), 0);
59 my %gmap;
61 ## Store a map of the project name to project guid and whether or not
62 ## it is suitable to be referenced. Adding a reference to a
63 ## non-managed c++ library or a "utility" project causes a warning in
64 ## Visual Studio 2008 and higher.
65 foreach my $project (@projects) {
66 my($name, $guid, $lang, $custom_only, $managed) =
67 $creator->access_pi_values($pjs, $project,
68 ProjectCreator::PROJECT_NAME,
69 ProjectCreator::PROJECT_GUID,
70 ProjectCreator::LANGUAGE,
71 ProjectCreator::CUSTOM_ONLY,
72 ProjectCreator::MANAGED_PROJECT);
73 $gmap{$name} = [$guid, !$custom_only && ($managed ||
74 $lang ne Creator::cplusplus)];
77 ## Now go through the projects and check for the need to add external
78 ## references.
79 foreach my $project (@projects) {
80 my $ph = new FileHandle();
81 my $outdir = $self->get_outdir();
82 my $cwd = $self->getcwd();
83 $outdir = $cwd if ($outdir eq '.');
84 my $full = $self->path_is_relative($project) ?
85 "$outdir/$project" : $project;
86 if (open($ph, $full)) {
87 my $write;
88 my @read;
89 my $crlf = $self->crlf();
90 my $lang = $$pjs{$project}->[ProjectCreator::LANGUAGE];
91 my $managed = $$pjs{$project}->[ProjectCreator::MANAGED_PROJECT];
93 while(<$ph>) {
94 ## This is a comment found in vc8.mpd if the project contains the
95 ## 'after' keyword setting and the 'add_references' template
96 ## variable setting.
97 if (/^(\s*)<!\-\-\s+MPC\s+ADD\s+DEPENDENCIES/) {
98 my $spc = $1;
99 my $deps = $self->get_validated_ordering($project);
100 foreach my $dep (@$deps) {
101 my $relative = $self->get_relative_dep_file($creator,
102 $full, $dep);
103 if (defined $relative) {
104 $relative =~ s!/!\\!g;
106 if ($lang eq Creator::cplusplus) {
107 ## If the current project is not managed, then we will
108 ## add references (although I doubt that will be useful).
109 ## If the current project is managed, then the reference
110 ## project must be managed or a non-c++ project.
111 if (!$managed || ($managed && $gmap{$dep}->[1])) {
112 ## See if the dependency has an associated attribute.
113 ## If it does, split it into name value pairs for use in
114 ## the resulting generated XML.
115 my %attr;
116 my $attr = $creator->get_dependency_attribute($dep);
117 if (defined $attr) {
118 foreach my $a (split(',', $attr)) {
119 my @nvp = split('=', $a);
120 $attr{lc($nvp[0])} = $nvp[1] if (defined $nvp[0] &&
121 defined $nvp[1]);
125 push(@read, $self->cpp_proj_ref($spc, $gmap{$dep}->[0],
126 \%attr, $relative));
129 ## This is a non-c++ language. So, it should not reference
130 ## unmanaged c++ libraries. If it's a managed project or
131 ## it's not a c++ project, it's ok to add a reference.
132 elsif ($gmap{$dep}->[1]) {
133 ## There are situations where, in C#, we want a dependency
134 ## between projects but not want them linked together (via a
135 ## ProjectReference). There is a build dependency, i.e.,
136 ## this project needs to be built if some other project is
137 ## built. But, that's where the dependency ends. Setting
138 ## the ProjectReference attribute to false allows us to do
139 ## that.
140 my $attr = $creator->get_dependency_attribute($dep);
141 if (!defined $attr || $attr !~ /ProjectReference=false/i) {
142 push(@read, $spc . '<ProjectReference Include="' .
143 $relative . '">' . $crlf,
144 $spc . ' <Project>{' . $gmap{$dep}->[0] .
145 '}</Project>' . $crlf,
146 $spc . ' <Name>' . $dep . '</Name>' . $crlf,
147 $spc . '</ProjectReference>' . $crlf);
151 ## Indicate that we need to re-write the file
152 $write = 1;
155 last if (!$write);
157 else {
158 push(@read, $_);
161 close($ph);
163 ## If we need to re-write the file, then do so
164 if ($write && open($ph, ">$full")) {
165 foreach my $line (@read) {
166 print $ph $line;
168 close($ph);
174 sub cpp_proj_ref {
175 my ($self, $spc, $refguid, $attr, $relative) = @_;
176 my $crlf = $self->crlf();
177 return $spc . '<ProjectReference' . $crlf .
178 $spc . "\tReferencedProjectIdentifier=\"\{$refguid\}\"$crlf" .
179 (defined $$attr{'copylocal'}
180 ? $spc . "\tCopyLocal=\"" . $$attr{'copylocal'} . "\"$crlf"
181 : ''
183 $spc . "\tRelativePathToProject=\"$relative\"$crlf" .
184 $spc . '/>' . $crlf;
187 sub adjust_names {
188 my($self, $name, $proj, $lang) = @_;
190 ## For websites, the project needs to be the directory of the actual
191 ## project file with a trailing slash. The name needs a trailing slash
192 ## too.
193 if ($lang eq Creator::website) {
194 $proj = $self->mpc_dirname($proj);
195 $proj .= '\\';
196 $name .= '\\' if $self->website_trailing_slash();
199 ## This always needs to be a path with the Windows style directory
200 ## separator.
201 $proj =~ s/\//\\/g;
202 return $name, $proj;
205 sub website_trailing_slash {
206 return 1;
209 sub website_extra_props {
212 sub get_short_config_name {
213 #my($self, $cfg) = @_;
214 return $_[1];
217 sub get_solution_config_section_name {
218 #my $self = shift;
219 return 'SolutionConfigurationPlatforms';
222 sub get_project_config_section_name {
223 #my $self = shift;
224 return 'ProjectConfigurationPlatforms';
227 sub print_additional_sections {
228 my($self, $fh) = @_;
229 my $crlf = $self->crlf();
231 print $fh "\tGlobalSection(SolutionProperties) = preSolution$crlf",
232 "\t\tHideSolutionNode = FALSE$crlf",
233 "\tEndGlobalSection$crlf";
236 sub allow_empty_dependencies {
237 #my $self = shift;
238 return 0;
241 sub print_inner_project {
242 my($self, $fh, $gen, $currguid, $deps, $name, $name_to_guid_map, $proj_language, $cfgs) = @_;
244 ## We need to perform a lot of work, but only for websites.
245 if ($proj_language eq Creator::website) {
246 my $crlf = $self->crlf();
247 my $directory = ($name eq '.\\' ?
248 $self->get_workspace_name() . '\\' : $name);
250 ## We need the directory name with no trailing back-slash for use
251 ## below.
252 my $notrail = $directory;
253 $notrail =~ s/\\$//;
255 # Print the website project.
256 print $fh "\tProjectSection(WebsiteProperties) = preProject", $crlf;
258 $self->website_extra_props($fh);
260 ## Print out the references
261 my $references;
262 foreach my $dep (@$deps) {
263 if (defined $$name_to_guid_map{$dep}) {
264 $references = "\t\t" .
265 'ProjectReferences = "' if (!defined $references);
266 $references .= "{$$name_to_guid_map{$dep}}|$dep;";
269 print $fh $references, '"', $crlf if (defined $references);
271 ## And now the configurations
272 my %cfg_seen;
273 foreach my $config (@$cfgs) {
274 $config =~ s/\|.*//;
275 if (!$cfg_seen{$config}) {
276 print $fh "\t\t$config.AspNetCompiler.VirtualPath = \"/$notrail\"", $crlf,
277 "\t\t$config.AspNetCompiler.PhysicalPath = \"$directory\"", $crlf,
278 "\t\t$config.AspNetCompiler.TargetPath = \"PrecompiledWeb\\$directory\"", $crlf,
279 "\t\t$config.AspNetCompiler.Updateable = \"true\"", $crlf,
280 "\t\t$config.AspNetCompiler.ForceOverwrite = \"true\"", $crlf,
281 "\t\t$config.AspNetCompiler.FixedNames = \"true\"", $crlf,
282 "\t\t$config.AspNetCompiler.Debug = \"",
283 ($config =~ /debug/i ? 'True' : 'False'), "\"", $crlf;
284 $cfg_seen{$config} = 1;
287 print $fh "\t\tVWDPort = \"1573\"", $crlf,
288 "\t\tDefaultWebSiteLanguage = \"",
289 $lang_map{$self->get_language()}, "\"", $crlf,
290 "\tEndProjectSection", $crlf;
292 else {
293 # We can ignore this project and pass it to the
294 # SUPER since it's not a website.
295 $self->SUPER::print_inner_project($fh, $gen, $currguid, $deps,
296 $name, $name_to_guid_map);