package VC8WorkspaceCreator;
# ************************************************************
# Description : A VC8 Workspace Creator
# Author : Johnny Willemsen
# Create Date : 4/21/2004
# ************************************************************
# ************************************************************
# Pragmas
# ************************************************************
use strict;
use VC8ProjectCreator;
use VC71WorkspaceCreator;
use vars qw(@ISA);
@ISA = qw(VC71WorkspaceCreator);
# ************************************************************
# Data Section
# ************************************************************
## NOTE: We call the constant as a function to support Perl 5.6.
my %lang_map = (Creator::cplusplus() => 'Visual C#',
Creator::csharp() => 'Visual C#',
Creator::vb() => 'Visual Basic',
Creator::java() => 'Visual J#');
# ************************************************************
# Subroutine Section
# ************************************************************
sub pre_workspace {
my($self, $fh) = @_;
my $crlf = $self->crlf();
## This identifies it as a Visual Studio 2005 file
print $fh '', $crlf,
'Microsoft Visual Studio Solution File, Format Version 9.00', $crlf;
## Optionally print the workspace comment
$self->print_workspace_comment($fh,
'# Visual Studio 2005', $crlf,
'# ', $crlf,
'#', $crlf,
'# This file was generated by MPC. Any changes made directly to', $crlf,
'# this file will be lost the next time it is generated.', $crlf,
'#', $crlf,
'# MPC Command:', $crlf,
'# ', $self->create_command_line_string($0, @ARGV), $crlf);
}
sub post_workspace {
my($self, $fh, $creator) = @_;
my $pjs = $self->get_project_info();
my @projects = $self->sort_dependencies($self->get_projects(), 0);
my %gmap;
## Store a map of the project name to project guid and whether or not
## it is suitable to be referenced. Adding a reference to a
## non-managed c++ library or a "utility" project causes a warning in
## Visual Studio 2008 and higher.
foreach my $project (@projects) {
my($name, $guid, $lang, $custom_only, $managed) =
$creator->access_pi_values($pjs, $project,
ProjectCreator::PROJECT_NAME,
ProjectCreator::PROJECT_GUID,
ProjectCreator::LANGUAGE,
ProjectCreator::CUSTOM_ONLY,
ProjectCreator::MANAGED_PROJECT);
$gmap{$name} = [$guid, !$custom_only && ($managed ||
$lang ne Creator::cplusplus)];
}
## Now go through the projects and check for the need to add external
## references.
foreach my $project (@projects) {
my $ph = new FileHandle();
my $outdir = $self->get_outdir();
my $cwd = $self->getcwd();
$outdir = $cwd if ($outdir eq '.');
my $full = $self->path_is_relative($project) ?
"$outdir/$project" : $project;
if (open($ph, $full)) {
my $write;
my @read;
my $crlf = $self->crlf();
my $lang = $$pjs{$project}->[ProjectCreator::LANGUAGE];
my $managed = $$pjs{$project}->[ProjectCreator::MANAGED_PROJECT];
while(<$ph>) {
## This is a comment found in vc8.mpd if the project contains the
## 'after' keyword setting and the 'add_references' template
## variable setting.
if (/^(\s*)get_validated_ordering($project);
foreach my $dep (@$deps) {
my $relative = $self->get_relative_dep_file($creator,
$full, $dep);
if (defined $relative) {
$relative =~ s!/!\\!g;
if ($lang eq Creator::cplusplus) {
## If the current project is not managed, then we will
## add references (although I doubt that will be useful).
## If the current project is managed, then the reference
## project must be managed or a non-c++ project.
if (!$managed || ($managed && $gmap{$dep}->[1])) {
## See if the dependency has an associated attribute.
## If it does, split it into name value pairs for use in
## the resulting generated XML.
my %attr;
my $attr = $creator->get_dependency_attribute($dep);
if (defined $attr) {
foreach my $a (split(',', $attr)) {
my @nvp = split('=', $a);
$attr{lc($nvp[0])} = $nvp[1] if (defined $nvp[0] &&
defined $nvp[1]);
}
}
push(@read, $self->cpp_proj_ref($spc, $gmap{$dep}->[0],
\%attr, $relative));
}
}
## This is a non-c++ language. So, it should not reference
## unmanaged c++ libraries. If it's a managed project or
## it's not a c++ project, it's ok to add a reference.
elsif ($gmap{$dep}->[1]) {
## There are situations where, in C#, we want a dependency
## between projects but not want them linked together (via a
## ProjectReference). There is a build dependency, i.e.,
## this project needs to be built if some other project is
## built. But, that's where the dependency ends. Setting
## the ProjectReference attribute to false allows us to do
## that.
my $attr = $creator->get_dependency_attribute($dep);
if (!defined $attr || $attr !~ /ProjectReference=false/i) {
push(@read, $spc . '' . $crlf,
$spc . ' {' . $gmap{$dep}->[0] .
'}' . $crlf,
$spc . ' ' . $dep . '' . $crlf,
$spc . '' . $crlf);
}
}
## Indicate that we need to re-write the file
$write = 1;
}
}
last if (!$write);
}
else {
push(@read, $_);
}
}
close($ph);
## If we need to re-write the file, then do so
if ($write && open($ph, ">$full")) {
foreach my $line (@read) {
print $ph $line;
}
close($ph);
}
}
}
}
sub cpp_proj_ref {
my ($self, $spc, $refguid, $attr, $relative) = @_;
my $crlf = $self->crlf();
return $spc . '' . $crlf;
}
sub adjust_names {
my($self, $name, $proj, $lang) = @_;
## For websites, the project needs to be the directory of the actual
## project file with a trailing slash. The name needs a trailing slash
## too.
if ($lang eq Creator::website) {
$proj = $self->mpc_dirname($proj);
$proj .= '\\';
$name .= '\\' if $self->website_trailing_slash();
}
## This always needs to be a path with the Windows style directory
## separator.
$proj =~ s/\//\\/g;
return $name, $proj;
}
sub website_trailing_slash {
return 1;
}
sub website_extra_props {
}
sub get_short_config_name {
#my($self, $cfg) = @_;
return $_[1];
}
sub get_solution_config_section_name {
#my $self = shift;
return 'SolutionConfigurationPlatforms';
}
sub get_project_config_section_name {
#my $self = shift;
return 'ProjectConfigurationPlatforms';
}
sub print_additional_sections {
my($self, $fh) = @_;
my $crlf = $self->crlf();
print $fh "\tGlobalSection(SolutionProperties) = preSolution$crlf",
"\t\tHideSolutionNode = FALSE$crlf",
"\tEndGlobalSection$crlf";
}
sub allow_empty_dependencies {
#my $self = shift;
return 0;
}
sub print_inner_project {
my($self, $fh, $gen, $currguid, $deps, $name, $name_to_guid_map, $proj_language, $cfgs) = @_;
## We need to perform a lot of work, but only for websites.
if ($proj_language eq Creator::website) {
my $crlf = $self->crlf();
my $directory = ($name eq '.\\' ?
$self->get_workspace_name() . '\\' : $name);
## We need the directory name with no trailing back-slash for use
## below.
my $notrail = $directory;
$notrail =~ s/\\$//;
# Print the website project.
print $fh "\tProjectSection(WebsiteProperties) = preProject", $crlf;
$self->website_extra_props($fh);
## Print out the references
my $references;
foreach my $dep (@$deps) {
if (defined $$name_to_guid_map{$dep}) {
$references = "\t\t" .
'ProjectReferences = "' if (!defined $references);
$references .= "{$$name_to_guid_map{$dep}}|$dep;";
}
}
print $fh $references, '"', $crlf if (defined $references);
## And now the configurations
my %cfg_seen;
foreach my $config (@$cfgs) {
$config =~ s/\|.*//;
if (!$cfg_seen{$config}) {
print $fh "\t\t$config.AspNetCompiler.VirtualPath = \"/$notrail\"", $crlf,
"\t\t$config.AspNetCompiler.PhysicalPath = \"$directory\"", $crlf,
"\t\t$config.AspNetCompiler.TargetPath = \"PrecompiledWeb\\$directory\"", $crlf,
"\t\t$config.AspNetCompiler.Updateable = \"true\"", $crlf,
"\t\t$config.AspNetCompiler.ForceOverwrite = \"true\"", $crlf,
"\t\t$config.AspNetCompiler.FixedNames = \"true\"", $crlf,
"\t\t$config.AspNetCompiler.Debug = \"",
($config =~ /debug/i ? 'True' : 'False'), "\"", $crlf;
$cfg_seen{$config} = 1;
}
}
print $fh "\t\tVWDPort = \"1573\"", $crlf,
"\t\tDefaultWebSiteLanguage = \"",
$lang_map{$self->get_language()}, "\"", $crlf,
"\tEndProjectSection", $crlf;
}
else {
# We can ignore this project and pass it to the
# SUPER since it's not a website.
$self->SUPER::print_inner_project($fh, $gen, $currguid, $deps,
$name, $name_to_guid_map);
}
}
1;