Last active
March 1, 2021 08:31
-
-
Save jay/125191c35bbeb894444eff827651f755 to your computer and use it in GitHub Desktop.
Update curl project file templates for OpenSSL 1.1.x
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
=begin comment | |
README | |
./change_openssl_lib_names.pl | |
This script was written to update Windows project file templates in the curl | |
repo. It changes the OpenSSL libnames from 1.0.x to 1.1.x: | |
libeay32.lib -> libcrypto.lib | |
ssleay32.lib -> libssl.lib | |
Also, this script changes the include directory and adds the directory that | |
contains the libs to the list of include directories, before the standard | |
openssl include directory. That is because each individual OpenSSL | |
configuration that is built and has its own set of libs now has its own include | |
directory from the build as well. The source-located openssl include directory | |
only holds the opensslconf.h from the most recent build, which is not | |
necessarily the same for all configurations. | |
..\..\..\..\..\openssl\inc32 -> ..\..\..\..\..\openssl\include | |
And then prepend to the list: | |
..\..\..\..\..\openssl\build\ | |
Win{32,64}\VC{6..15}\{DLL,LIB} {Debug,Release}\include | |
Refer to https://github.com/curl/curl/pull/6675 | |
Copyright (C) 2021 Jay Satiro <raysatiro@yahoo.com> | |
http://curl.haxx.se/docs/copyright.html | |
https://gist.github.com/jay/125191c35bbeb894444eff827651f755 | |
=end comment | |
=cut | |
use warnings; | |
use strict; | |
# oldname => newname | |
my %libs_original = ("libeay32.lib" => "libcrypto.lib", | |
"ssleay32.lib" => "libssl.lib"); | |
# oldinc => newinc | |
my $oldinc_original = '..\..\..\..\..\openssl\inc32'; | |
my $newinc_original = '..\..\..\..\..\openssl\include'; | |
sub modify(@) { | |
local (*IN, *OUT); | |
my ($version, $infile, $outfile) = @_; | |
my $line; | |
my $linenum = 0; | |
my $config; | |
my @all; | |
open(IN, "<:raw", $infile) or return "Can't open $infile : $!"; | |
open(OUT, ">:raw", $outfile) or return "Can't open $outfile : $!"; | |
while(!eof(IN)) { | |
defined($line = readline(IN)) or return "Can't read $infile : $!"; | |
$linenum++; | |
# | |
# get current configuration | |
# | |
if($version == 6) { | |
if($line =~ /^[ \t]*!(?:ELSE)?IF[ \t]+"\Q$(CFG)\E"[ \t]+==[ \t]+ | |
"(?:curl|libcurl)\ -\ (Win32|x64)\ (.+)"/ix) { | |
$config = {}; | |
$config->{name} = $2; | |
$config->{platform} = $1; | |
} | |
} | |
elsif($version >= 7 && $version <= 9) { | |
if($line =~ /^[ \t]*Name="(.+)\|(Win32|x64)"/i) { | |
$config = {}; | |
$config->{name} = $1; | |
$config->{platform} = $2; | |
} | |
} | |
elsif($version >= 10) { | |
if($line =~ /^[ \t]*<ItemDefinitionGroup\ Condition= | |
"'\Q$(Configuration)|$(Platform)\E'== | |
'(.+)\|(Win32|x64)'">/ix) { | |
$config = {}; | |
$config->{name} = $1; | |
$config->{platform} = $2; | |
} | |
} | |
# if this is a new config then make the rest of the keys | |
if(defined($config->{name}) && !defined($config->{linenum})) { | |
$config->{infile} = $infile; | |
$config->{linenum} = $linenum; | |
# The platform must be Win32 or Win64 | |
if(lc($config->{platform}) eq "x64") { | |
$config->{platform} = "Win64"; | |
} | |
elsif(lc($config->{platform}) ne "win32") { | |
return "FATAL: Unexpected platform at line $linenum in $infile : " . | |
"$config->{platform}"; | |
} | |
# Extract OpenSSL library type, for example: | |
# "LIB Debug - DLL OpenSSL - DLL LibSSH2" | |
# static libcurl debug, dynamic openssl debug, dynamic libssh2 debug | |
# openssl lib type is DLL Debug | |
if($config->{name} =~ /^(?:DLL|LIB)\ (Debug|Release).+ | |
(DLL|LIB)\ OpenSSL/ix) { | |
$config->{openssl} = "$2 $1"; | |
#..\..\..\..\..\openssl\include\..\build\Win64\VC10\DLL Debug | |
($config->{ossllibdir} = $newinc_original) =~ s/^"|\\?"?$//g; | |
$config->{ossllibdir} .= "\\..\\build\\$config->{platform}" . | |
"\\VC$version\\$config->{openssl}\\include"; | |
} | |
elsif($config->{name} =~ /OpenSSL/i) { | |
return "FATAL: Unexpected config at line $linenum in $infile : " . | |
"$config->{name}"; | |
} | |
for my $i (0 .. $#all) { | |
#print "$i: $_=$all[$i]{$_}\n" for keys %{$all[$i]}; print "\n"; | |
if(lc($config->{name}) eq lc($all[$i]{name}) && | |
lc($config->{platform}) eq lc($all[$i]{platform})) { | |
return "FATAL: Unexpected duplicate configuration at lines " . | |
"$all[$i]{linenum} and $config->{linenum} in $infile : " . | |
"$config->{name}|$config->{platform}"; | |
} | |
} | |
#print "$_ => $config->{$_}\n" for keys %{$config}; print "\n"; | |
push @all, $config; | |
next; | |
} | |
else { | |
# die on unparseable config line otherwise wrong data could be changed | |
if($line =~ /(?:DLL|LIB) (?:Debug|Release)/i) { | |
if(($version == 6 && $line =~ /\Q$(CFG)\E/i) || | |
($version >= 7 && $version <= 9 && $line =~ /(?<![^ \t])Name=/i) || | |
($version >= 10 && | |
$line =~ /ItemDefinitionGroup.+\Q$(Configuration)\E/i)) { | |
return "FATAL: Unparseable config at line $linenum in $infile : " . | |
"$line"; | |
} | |
} | |
# skip changing lines until first config line has been parsed | |
next if !defined($config->{name}); | |
} | |
# | |
# update lib names | |
# | |
while(my ($oldlib, $newlib) = each %libs_original) { | |
# reset $line regex prev match end pos so next m//g match starts from 0 | |
pos($line) = undef; | |
$oldlib =~ s/^"|"$//g; | |
$newlib =~ s/^"|"$//g; | |
if($version == 6) { | |
if($newlib =~ / /) { | |
$newlib = "\"$newlib\""; | |
} | |
if($line =~ /^# ADD (?:BASE )?LINK32 /gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=\ ) # positive lookbehind | |
("?)\Q$oldlib\E(\3) # oldlib may be quoted | |
(?=\ |\r?$) # positive lookahead | |
) | |
/$1$newlib/gix; | |
} | |
} | |
elsif($version >= 7 && $version <= 9) { | |
if($newlib =~ / /) { | |
$newlib = ""$newlib""; | |
} | |
if($line =~ /^[ \t]*AdditionalDependencies="/gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=[ "]) | |
((?:")?)\Q$oldlib\E(\3) | |
(?=[ "]) | |
) | |
/$1$newlib/gix; | |
} | |
} | |
elsif($version >= 10) { | |
if($newlib =~ / /) { | |
$newlib = "\"$newlib\""; | |
} | |
if($line =~ /^[ \t]*<AdditionalDependencies>/gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=[;>]) | |
("?)\Q$oldlib\E(\3) | |
(?=[;<]) | |
) | |
/$1$newlib/gix; | |
} | |
} | |
} | |
# | |
# update include directory | |
# | |
pos($line) = undef; | |
(my $oldinc = $oldinc_original) =~ s/^"|"$//g; | |
(my $newinc = $newinc_original) =~ s/^"|"$//g; | |
if($version == 6) { | |
$newinc = "\"$newinc\""; # vc6 always quotes each include directory | |
if($line =~ /^# ADD (?:BASE )?CPP /gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=\/I\ ) | |
("?)\Q$oldinc\E(\3) | |
(?=\ |\r?$) | |
) | |
/$1$newinc/gix; | |
} | |
} | |
elsif($version >= 7 && $version <= 9) { | |
my $d = (($version < 8) ? "," : ";"); | |
if($line =~ /^[ \t]*AdditionalIncludeDirectories="/gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=[$d"]) | |
\Q$oldinc\E | |
(?=[$d"]) | |
) | |
/$1$newinc/gix; | |
} | |
} | |
elsif($version >= 10) { | |
if($line =~ /^[ \t]*<AdditionalIncludeDirectories>/gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=[;>]) | |
\Q$oldinc\E | |
(?=[;<]) | |
) | |
/$1$newinc/gix; | |
} | |
} | |
# | |
# prepend ossl lib dir as include dir (since it contains opensslconf.h) | |
# | |
if(defined($config->{ossllibdir})) { | |
my $libdir = $config->{ossllibdir}; | |
pos($line) = undef; | |
if($version == 6) { | |
$libdir = "\"$libdir\""; | |
if($line =~ /^# ADD (?:BASE )?CPP /gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=(?<!\/I\ \Q$libdir\E\ )\/I\ ) | |
\Q$newinc\E | |
(?=\ |\r?$) | |
) | |
/$1$libdir\ \/I\ $newinc/gix; | |
} | |
} | |
elsif($version >= 7 && $version <= 9) { | |
my $d = (($version < 8) ? "," : ";"); | |
if($line =~ /^[ \t]*AdditionalIncludeDirectories="/gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=[$d"](?<!\Q$libdir\E$d)) | |
\Q$newinc\E | |
(?=[$d"]) | |
) | |
/$1$libdir$d$newinc/gix; | |
} | |
} | |
elsif($version >= 10) { | |
if($line =~ /^[ \t]*<AdditionalIncludeDirectories>/gi) { | |
$line =~ s/\G(.*?) | |
( | |
(?<=[;>](?<!\Q$libdir\E;)) | |
\Q$newinc\E | |
(?=[;<]) | |
) | |
/$1$libdir;$newinc/gix; | |
} | |
} | |
} | |
} | |
continue { | |
if(defined($line)) { | |
print OUT $line or return "Can't write $outfile : $!"; | |
} | |
} | |
close(IN) or return "Can't close $infile : $!"; | |
close(OUT) or return "Can't close $outfile : $!"; | |
return undef; | |
} | |
# This is the max times to retry modifying each file. | |
# Modification fails if Microsoft dev git detects file changes and opens | |
# the file at the same time as this script is attempting to modify. | |
my $max_retries = 10; | |
for my $version (6, 7, 7.1, 8, 9, 10, 11, 12, 14, 15) { | |
for my $template ("src/curl.tmpl", "lib/libcurl.tmpl") { | |
my $infile = "curl/projects/Windows/VC$version/$template"; | |
my $outfile = "$infile.tmp"; | |
for(my $i = 0; $i < $max_retries; sleep($i++)) { | |
my $errmsg = modify($version, $infile, $outfile); | |
last if !defined($errmsg); | |
$errmsg =~ s/[\r\n]+$//g; | |
die $errmsg if $errmsg =~ /^FATAL: /; | |
die "FATAL: $errmsg" if $i+1 == $max_retries; | |
print STDERR "[Retrying in ${i}s] $errmsg\n"; | |
} | |
for(my $i = 0; $i < $max_retries; sleep($i++)) { | |
my $result = rename($outfile, $infile); | |
last if $result; | |
my $errmsg = "Can't rename $outfile => $infile: $!"; | |
die "FATAL: $errmsg" if $i+1 == $max_retries; | |
print STDERR "[Retrying in ${i}s] $errmsg\n"; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment