#!/usr/bin/env perl use v5.10; use strict; use warnings; use autodie; use File::Spec; use File::Temp::Rename; use Getopt::Long; use IO::Handle; use UUID::Tiny qw(:std); my $force = 0; my $verbose = 0; GetOptions( 'force|f' => \$force, 'verbose|v' => \$verbose, ) and (@ARGV == 1 or @ARGV == 2) or die < [] Create a new project by copying the minimal sample .vcxproj file to the given new file and replacing the minimal.cpp with the specified new source file name (defaults to the project file name). Options: -f, --force Overwrite the file with the new name even if it exists. -v, --verbose Show more details about what the program is doing. EOF ; # Show progress messages immediately. STDOUT->autoflush(1) if $verbose; # Returns just the name of the project, i.e. the part without any path nor # extension and the full path to it, which will always have .vcxproj extension # whether it is already present in input or not. sub get_name_and_project { my ($file) = @_; # If a .filters file was passed on input by mistake, accept it as if the # project itself was given. $file =~ s/\.filters$//; my ($volume, $dir, $name) = File::Spec->splitpath($file); if ($file !~ /\.vcxproj$/) { $file .= '.vcxproj'; } else { $name =~ s/\.vcxproj$//; } return ($name, $file) } my ($orig_name, $orig_project) = ('minimal', 'samples/minimal/minimal.vcxproj'); my ($new_name, $new_project) = get_name_and_project(shift @ARGV); my $new_source_name = @ARGV ? shift @ARGV : $new_name; if (!$force && -e $new_project) { die qq{File "$new_project" already exists, not overwriting without -f.\n} } open my $fh_in, '<', $orig_project; open my $fh_out, '>', $new_project; say "Cloning $orig_project to $new_project" if $verbose; my $new_uuid = uc(create_uuid_as_string(UUID_RANDOM)); # Don't bother with parsing XML, just mangle the text directly. while (<$fh_in>) { # Note: don't use chomp to preserve the same kind of EOLs. if (m| ^ (?\s*) \{ (?[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}) \} (?\s*) $ |x) { say qq(Replacing old GUID "$+{orig_uuid}" with "$new_uuid".); $_ = "$+{leading_space}{$new_uuid}$+{trailing_space}" } else { # Replace the project name for the tags that use it. s@ ^ (\s*) \K <(?ProjectName|IntDir|\w+File(?:Name)?)> (?.*)\Q$orig_name\E(?.*) (?\s*) $ @<$+{tag}>$+{before}$new_name$+{after}$+{trailing_space}@ix; # And replace the source file name. s@@@; } print $fh_out $_; } close $fh_out; close $fh_in; say "Copying $orig_project.filters to $new_project.filters" if $verbose; open $fh_in, '<', "$orig_project.filters"; open $fh_out, '>', "$new_project.filters"; while (<$fh_in>) { s@@@; print $fh_out $_; } close $fh_out; close $fh_in; say "Adding $new_project to the solution file" if $verbose; my $solution_file = 'samples/samples_vc17.sln'; my $solution_new = File::Temp::Rename->new(FILE => $solution_file, CLOBBER => 1); open $fh_in, '<', $solution_file; open $fh_out, '>', $solution_new; (my $new_project_relative = $new_project) =~ s@^samples/@@; while (<$fh_in>) { if (/^Global\s*/) { print $fh_out <