vcxproj: automatically initialize the vcpkg system

We just introduced a way to build Git for Windows with MSVC on the
command line using vcpkg-generated, up-to-date dependencies. Let's bring
that convenience to the Visual Studio project, too.

(The previous method, fetching NuGet packages, is fraught with problems:
as C++ libraries have to be built for every architecture and for every
toolset, the NuGet packages which we would like to consume fell behind
and are not up-to-date with the current versions of the libraries, e.g.
cURL and OpenSSL. By using vcpkg we avoid that problem, always building
the newest dependency versions.)

The trick is to initialize the VCPKG system once, and then build Git's
dependencies using it. We do that by attaching a pre-build event to the
libgit project (which is now the base project on which all others
depend, therefore no other project is built in paralleli, side-stepping
issues with vcpkg being unprepared for being run in parallel).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2017-11-28 18:29:18 +01:00
parent 5281e5899f
commit 0f4442d2ff
3 changed files with 37 additions and 56 deletions

View File

@@ -470,7 +470,7 @@ vcxproj:
# Make .vcxproj files and add them
unset QUIET_GEN QUIET_BUILT_IN; \
perl contrib/buildsystems/generate -g Vcxproj
git add -f git.sln {*,*/lib,t/helper/*}/{packages.config,*.vcxproj}
git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj
# Add command-list.h
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 command-list.h

View File

@@ -126,9 +126,12 @@ sub createProject {
$cflags =~ s/</&lt;/g;
$cflags =~ s/>/&gt;/g;
my $libs = '';
my $libs_release = "\n ";
my $libs_debug = "\n ";
if (!$static_library) {
$libs = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|libcurl\.lib|libeay32\.lib|libiconv\.lib|ssleay32\.lib|zlib\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
$libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
$libs_debug = $libs_release;
$libs_debug =~ s/zlib\.lib/zlibd\.lib/;
}
$defines =~ s/-D//g;
@@ -138,45 +141,6 @@ sub createProject {
die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
use File::Copy;
copy("$git_dir/compat/vcbuild/packages.config", "$target/packages.config");
my $needsCurl = grep(/libcurl.lib/, @{$$build_structure{"$prefix${name}_LIBS"}});
my $targetsImport = '';
my $targetsErrors = '';
my $afterTargets = '';
open F, "<$git_dir/compat/vcbuild/packages.config";
while (<F>) {
if (/<package id="([^"]+)" version="([^"]+)"/) {
if ($1 eq 'libiconv') {
# we have to link with the Release builds already because libiconv
# is only available targeting v100 and v110, see
# https://github.com/coapp-packages/libiconv/issues/2
$libs .= ";$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.$2\\build\\native\\lib\\v110\\\$(Platform)\\Release\\dynamic\\cdecl\\libiconv.lib";
$afterTargets .= "\n <Copy SourceFiles=\"$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.redist.$2\\build\\native\\bin\\v110\\\$(Platform)\\Release\\dynamic\\cdecl\\libiconv.dll\" DestinationFolder=\"\$(TargetDir)\" SkipUnchangedFiles=\"true\" />";
} elsif ($needsCurl && $1 eq 'curl') {
# libcurl is only available targeting v100 and v110
$libs .= ";$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.$2\\build\\native\\lib\\v110\\\$(Platform)\\Release\\dynamic\\libcurl.lib";
$afterTargets .= "\n <Copy SourceFiles=\"$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.redist.$2\\build\\native\\bin\\v110\\\$(Platform)\\Release\\dynamic\\libcurl.dll\" DestinationFolder=\"\$(TargetDir)\" SkipUnchangedFiles=\"true\" />";
} elsif ($needsCurl && $1 eq 'expat') {
# libexpat is only available targeting v100 and v110
$libs .= ";$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.$2\\build\\native\\lib\\v110\\\$(Platform)\\Release\\dynamic\\utf8\\libexpat.lib";
} elsif ($1 eq 'zlib') {
# zlib
$libs .= ";$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.v140.windesktop.msvcstl.dyn.rt-dyn.$2\\lib\\native\\v140\\windesktop\\msvcstl\\dyn\\rt-dyn\\x64\\RelWithDebInfo\\zlib.lib";
} elsif ($1 eq 'openssl') {
# openssl
$libs .= ";$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.v140.windesktop.msvcstl.dyn.rt-dyn.x64.$2\\lib\\native\\v140\\windesktop\\msvcstl\\dyn\\rt-dyn\\x64\\release\\libeay32.lib";
$libs .= ";$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.v140.windesktop.msvcstl.dyn.rt-dyn.x64.$2\\lib\\native\\v140\\windesktop\\msvcstl\\dyn\\rt-dyn\\x64\\release\\ssleay32.lib";
}
next if ($1 =~ /^(zlib$|openssl(?!.*(x64|x86)$))/);
my $targetsFile = "$rel_dir\\compat\\vcbuild\\GEN.PKGS\\$1.$2\\build\\native\\$1.targets";
$targetsImport .= "\n <Import Project=\"$targetsFile\" Condition=\"Exists('$targetsFile')\" />";
$targetsErrors .= "\n <Error Condition=\"!Exists('$targetsFile')\" Text=\"\$([System.String]::Format('\$(ErrorText)', '$targetsFile'))\" />";
}
}
close F;
open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
binmode F, ":crlf :utf8";
print F chr(0xFEFF);
@@ -204,6 +168,16 @@ sub createProject {
<PropertyGroup Label="Globals">
<ProjectGuid>$uuid</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch>
<VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch>
<VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory>
<VCPKGBinDirectory Condition="'\(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory>
<VCPKGLibDirectory Condition="'\(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory>
<VCPKGBinDirectory Condition="'\(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\bin</VCPKGBinDirectory>
<VCPKGLibDirectory Condition="'\(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\lib</VCPKGLibDirectory>
<VCPKGIncludeDirectory>\$(VCPKGArchDirectory)\\include</VCPKGIncludeDirectory>
<VCPKGLibs Condition="'\(Configuration)'=='Debug'">$libs_debug</VCPKGLibs>
<VCPKGLibs Condition="'\(Configuration)'!='Debug'">$libs_release</VCPKGLibs>
</PropertyGroup>
<Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'\$(Configuration)'=='Debug'" Label="Configuration">
@@ -237,7 +211,7 @@ sub createProject {
<ItemDefinitionGroup>
<ClCompile>
<AdditionalOptions>$cflags %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$includes;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$cdup;$cdup\\compat;$cdup\\compat\\regex;$cdup\\compat\\win32;$cdup\\compat\\poll;$cdup\\compat\\vcbuild\\include;\$(VCPKGIncludeDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<EnableParallelCodeGeneration />
<MinimalRebuild>true</MinimalRebuild>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
@@ -248,11 +222,22 @@ sub createProject {
<SuppressStartupBanner>true</SuppressStartupBanner>
</Lib>
<Link>
<AdditionalDependencies>$libs;\$(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions>
<ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile>
<SubSystem>Console</SubSystem>
</Link>
EOM
if ($target eq 'libgit') {
print F << "EOM";
<PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg')">
<Message>Initialize VCPKG</Message>
<Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat" </Command>
</PreBuildEvent>
EOM
}
print F << "EOM";
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'\$(Platform)'=='Win32'">
<Link>
@@ -323,21 +308,15 @@ EOM
EOM
}
print F << "EOM";
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">$targetsImport
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>$targetsErrors
</Target>
EOM
if (!$static_library && $afterTargets ne '') {
if (!$static_library) {
print F << "EOM";
<Target Name="${target}_AfterBuild" AfterTargets="AfterBuild">$afterTargets
<Target Name="${target}_AfterBuild" AfterTargets="AfterBuild">
<ItemGroup>
<DLLsAndPDBs Include="\$(VCPKGBinDirectory)\\*.dll;\$(VCPKGBinDirectory)\\*.pdb" />
</ItemGroup>
<Copy SourceFiles="@(DLLsAndPDBs)" DestinationFolder="\$(OutDir)" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />
</Target>
EOM
}

View File

@@ -347,6 +347,8 @@ sub handleLinkLine
push(@libs, "ssleay32.lib");
} elsif ("$part" eq "-lcurl") {
push(@libs, "libcurl.lib");
} elsif ("$part" eq "-lexpat") {
push(@libs, "expat.lib");
} elsif ("$part" eq "-liconv") {
push(@libs, "libiconv.lib");
} elsif ($part =~ /^[-\/]/) {