aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE8
-rw-r--r--build/root.build4
-rw-r--r--build2/cli/rule.cxx2
-rw-r--r--libbuild2/cc/buildfile10
-rw-r--r--libbuild2/cc/compile-rule.cxx125
-rw-r--r--libbuild2/cc/compile-rule.hxx14
-rw-r--r--libbuild2/cc/guess.cxx645
-rw-r--r--libbuild2/cc/link-rule.cxx16
-rw-r--r--libbuild2/cc/link-rule.hxx8
-rw-r--r--libbuild2/cc/msvc-setup.h1059
-rw-r--r--libbuild2/utility-installed.cxx2
-rw-r--r--libbuild2/utility.cxx6
-rw-r--r--libbuild2/utility.hxx18
-rw-r--r--libbuild2/utility.ixx12
-rw-r--r--libbuild2/utility.txx2
-rw-r--r--tests/bash/testscript2
16 files changed, 1729 insertions, 204 deletions
diff --git a/LICENSE b/LICENSE
index 215ce1d..8bebd6f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,3 +1,11 @@
+libbuild2/cc/msvc-setup.h:
+
+MIT, see the file header for details. Comes from the
+Microsoft.VisualStudio.Setup.Configuration.Native NuGet package and is
+originally named as Setup.Configuration.h.
+
+The rest:
+
Copyright (c) 2014-2019 Code Synthesis Ltd
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/build/root.build b/build/root.build
index 4929cc0..0656ab5 100644
--- a/build/root.build
+++ b/build/root.build
@@ -13,6 +13,10 @@ ixx{*}: extension = ixx
txx{*}: extension = txx
cxx{*}: extension = cxx
+# Note that we bundle some C headers (see the LICENSE file for details).
+#
+h{*}: extension = h
+
if ($cxx.target.system == 'win32-msvc')
cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx
index 4ccafc9..8bb124b 100644
--- a/build2/cli/rule.cxx
+++ b/build2/cli/rule.cxx
@@ -249,7 +249,7 @@ namespace build2
// Then the options checksum.
//
sha256 cs;
- hash_options (cs, t, "cli.options");
+ append_options (cs, t, "cli.options");
if (dd.expect (cs.string ()) != nullptr)
l4 ([&]{trace << "options mismatch forcing update of " << t;});
diff --git a/libbuild2/cc/buildfile b/libbuild2/cc/buildfile
index 50192fa..19b9fc6 100644
--- a/libbuild2/cc/buildfile
+++ b/libbuild2/cc/buildfile
@@ -11,6 +11,7 @@ include ../bin/
int_libs = ../bin/lib{build2-bin}
./: lib{build2-cc}: libul{build2-cc}: {hxx ixx txx cxx}{** -**.test...} \
+ h{msvc-setup} \
$int_libs $imp_libs
# Unit tests.
@@ -36,6 +37,13 @@ for t: cxx{**.test...}
obja{*}: cxx.poptions += -DLIBBUILD2_CC_STATIC_BUILD
objs{*}: cxx.poptions += -DLIBBUILD2_CC_SHARED_BUILD
+if ($cxx.target.class == 'windows')
+ cxx.libs += $regex.apply(advapi32 ole32 oleaut32, \
+ '(.+)', \
+ $cxx.target.system == 'mingw32' \
+ ? '-l\1' \
+ : '\1.lib')
+
# Export options.
#
lib{build2-cc}:
@@ -63,6 +71,8 @@ ver = ($version.pre_release \
lib{build2-cc}: bin.lib.version = @"-$ver"
libs{build2-cc}: bin.lib.load_suffix = "-$ver"
+h{msvc-setup}@./: install = false
+
# Install into the libbuild2/cc/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index d4ea390..9a534c7 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -186,6 +186,37 @@ namespace build2
"insufficient space");
}
+ template <typename T>
+ void compile_rule::
+ append_sys_inc_options (T& args) const
+ {
+ assert (sys_inc_dirs_extra <= sys_inc_dirs.size ());
+
+ auto b (sys_inc_dirs.begin ());
+ auto m (b + sys_inc_dirs_extra);
+ auto e (sys_inc_dirs.end ());
+
+ append_option_values (
+ args, cclass == compiler_class::msvc ? "/I" : "-I",
+ m, e,
+ [] (const dir_path& d) {return d.string ().c_str ();});
+
+ // For MSVC if we have no INCLUDE environment variable set, then we
+ // add all of them. But we want extras to come first. Note also that
+ // clang-cl takes care of this itself.
+ //
+ if (ctype == compiler_type::msvc && cvariant != "clang")
+ {
+ if (!getenv ("INCLUDE"))
+ {
+ append_option_values (
+ args, "/I",
+ b, m,
+ [] (const dir_path& d) {return d.string ().c_str ();});
+ }
+ }
+ }
+
size_t compile_rule::
append_lang_options (cstrings& args, const match_data& md) const
{
@@ -342,9 +373,10 @@ namespace build2
// Append or hash library options from a pair of *.export.* variables
// (first one is cc.export.*) recursively, prerequisite libraries first.
//
+ template <typename T>
void compile_rule::
append_lib_options (const scope& bs,
- cstrings& args,
+ T& args,
action a,
const target& t,
linfo li) const
@@ -402,59 +434,6 @@ namespace build2
}
}
- void compile_rule::
- hash_lib_options (const scope& bs,
- sha256& cs,
- action a,
- const target& t,
- linfo li) const
- {
- auto imp = [] (const file& l, bool la) {return la && l.is_a<libux> ();};
-
- auto opt = [&cs, this] (
- const file& l, const string& t, bool com, bool exp)
- {
- if (!exp)
- return;
-
- const variable& var (
- com
- ? c_export_poptions
- : (t == x
- ? x_export_poptions
- : l.ctx.var_pool[t + ".export.poptions"]));
-
- hash_options (cs, l, var);
- };
-
- // The same logic as in append_lib_options().
- //
- const function<bool (const file&, bool)> impf (imp);
- const function<void (const file&, const string&, bool, bool)> optf (opt);
-
- for (prerequisite_member p: group_prerequisite_members (a, t))
- {
- if (include (a, t, p) != include_type::normal) // Excluded/ad hoc.
- continue;
-
- if (const target* pt = p.load ())
- {
- if (const libx* l = pt->is_a<libx> ())
- pt = link_member (*l, a, li);
-
- bool la;
- if (!((la = pt->is_a<liba> ()) ||
- (la = pt->is_a<libux> ()) ||
- pt->is_a<libs> ()))
- continue;
-
- process_libraries (a, bs, li, sys_lib_dirs,
- pt->as<file> (), la, 0, // Hack: lflags unused.
- impf, nullptr, optf);
- }
- }
- }
-
// Append library prefixes based on the *.export.poptions variables
// recursively, prerequisite libraries first.
//
@@ -877,29 +856,25 @@ namespace build2
cs.append (&md.symexport, sizeof (md.symexport));
if (xlate_hdr != nullptr)
- hash_options (cs, *xlate_hdr);
+ append_options (cs, *xlate_hdr);
if (md.pp != preprocessed::all)
{
- hash_options (cs, t, c_poptions);
- hash_options (cs, t, x_poptions);
+ append_options (cs, t, c_poptions);
+ append_options (cs, t, x_poptions);
// Hash *.export.poptions from prerequisite libraries.
//
- hash_lib_options (bs, cs, a, t, li);
+ append_lib_options (bs, cs, a, t, li);
// Extra system header dirs (last).
//
- assert (sys_inc_dirs_extra <= sys_inc_dirs.size ());
- hash_option_values (
- cs, "-I",
- sys_inc_dirs.begin () + sys_inc_dirs_extra, sys_inc_dirs.end (),
- [] (const dir_path& d) {return d.string ();});
+ append_sys_inc_options (cs);
}
- hash_options (cs, t, c_coptions);
- hash_options (cs, t, x_coptions);
- hash_options (cs, tstd);
+ append_options (cs, t, c_coptions);
+ append_options (cs, t, x_coptions);
+ append_options (cs, tstd);
if (ot == otype::s)
{
@@ -2956,11 +2931,7 @@ namespace build2
// Extra system header dirs (last).
//
- assert (sys_inc_dirs_extra <= sys_inc_dirs.size ());
- append_option_values (
- args, "-I",
- sys_inc_dirs.begin () + sys_inc_dirs_extra, sys_inc_dirs.end (),
- [] (const dir_path& d) {return d.string ().c_str ();});
+ append_sys_inc_options (args);
if (md.symexport)
append_symexport_options (args, t);
@@ -4098,11 +4069,7 @@ namespace build2
append_lib_options (t.base_scope (), args, a, t, li);
- assert (sys_inc_dirs_extra <= sys_inc_dirs.size ());
- append_option_values (
- args, "-I",
- sys_inc_dirs.begin () + sys_inc_dirs_extra, sys_inc_dirs.end (),
- [] (const dir_path& d) {return d.string ().c_str ();});
+ append_sys_inc_options (args);
if (md.symexport)
append_symexport_options (args, t);
@@ -5693,11 +5660,7 @@ namespace build2
// Extra system header dirs (last).
//
- assert (sys_inc_dirs_extra <= sys_inc_dirs.size ());
- append_option_values (
- args, "-I",
- sys_inc_dirs.begin () + sys_inc_dirs_extra, sys_inc_dirs.end (),
- [] (const dir_path& d) {return d.string ().c_str ();});
+ append_sys_inc_options (args);
if (md.symexport)
append_symexport_options (args, t);
diff --git a/libbuild2/cc/compile-rule.hxx b/libbuild2/cc/compile-rule.hxx
index 93972a2..4c74016 100644
--- a/libbuild2/cc/compile-rule.hxx
+++ b/libbuild2/cc/compile-rule.hxx
@@ -58,20 +58,18 @@ namespace build2
struct match_data;
using environment = small_vector<const char*, 2>;
+ template <typename T>
+ void
+ append_sys_inc_options (T&) const;
+
+ template <typename T>
void
append_lib_options (const scope&,
- cstrings&,
+ T&,
action,
const target&,
linfo) const;
- void
- hash_lib_options (const scope&,
- sha256&,
- action,
- const target&,
- linfo) const;
-
// Mapping of include prefixes (e.g., foo in <foo/bar>) for auto-
// generated headers to directories where they will be generated.
//
diff --git a/libbuild2/cc/guess.cxx b/libbuild2/cc/guess.cxx
index 7b993f0..52c9541 100644
--- a/libbuild2/cc/guess.cxx
+++ b/libbuild2/cc/guess.cxx
@@ -4,8 +4,70 @@
#include <libbuild2/cc/guess.hxx>
+// Bootstrap build is always performed in the VC's command prompt and thus
+// doesn't require the VC search functionality.
+//
+#if defined(_WIN32) && !defined(BUILD2_BOOTSTRAP)
+# include <libbutl/win32-utility.hxx>
+
+# include <unknwn.h> // IUnknown
+# include <stdlib.h> // _MAX_PATH
+# include <oleauto.h> // SysFreeString()
+# include <guiddef.h> // CLSID, IID
+# include <objbase.h> // CoInitializeEx(), CoCreateInstance(), etc.
+
+// MinGW may lack some macro definitions used in msvc-setup.h (see below), so
+// we provide them if that's the case.
+//
+# ifndef MAXUINT
+# define MAXUINT UINT_MAX
+# endif
+
+// MinGW's sal.h (Microsoft's Source Code Annotation Language) may not contain
+// all the in/out annotation macros.
+//
+# ifndef _In_z_
+# define _In_z_
+# endif
+
+# ifndef _In_opt_z_
+# define _In_opt_z_
+# endif
+
+# ifndef _Out_opt_
+# define _Out_opt_
+# endif
+
+# ifndef _Deref_out_opt_
+# define _Deref_out_opt_
+# endif
+
+# ifndef _Out_writes_to_
+# define _Out_writes_to_(X, Y)
+# endif
+
+# ifndef _Deref_out_range_
+# define _Deref_out_range_(X, Y)
+# endif
+
+# ifndef _Outptr_result_maybenull_
+# define _Outptr_result_maybenull_
+# endif
+
+# ifndef _Reserved_
+# define _Reserved_
+# endif
+
+// API for enumerating Visual Studio setup instances and querying information
+// about them (see the LICENSE file for details).
+//
+# include <libbuild2/cc/msvc-setup.h>
+
+# include <libbuild2/filesystem.hxx>
+#endif
+
#include <map>
-#include <cstring> // strlen(), strchr()
+#include <cstring> // strlen(), strchr()
#include <libbuild2/diagnostics.hxx>
@@ -352,6 +414,291 @@ namespace build2
return pre_guess_result {invalid_compiler_type, nullopt, string::npos};
}
+ // Return the latest MSVC and Platform SDK installation information if
+ // both are discovered on the system and nullopt otherwise. In particular,
+ // don't fail on the underlying COM/OS errors returning nullopt instead.
+ // This way a broken VC setup will be silently ignored.
+ //
+ // Note that Visual Studio versions prior to 15.0 are not supported.
+ //
+ struct msvc_info
+ {
+ dir_path msvc_dir; // VC directory (...\Tools\MSVC\<ver>\).
+ string psdk_ver; // Platfor SDK directory (...\Windows Kits\<ver>\).
+ dir_path psdk_dir; // Platfor SDK version (under Include/, Lib/, etc).
+ };
+
+#if defined(_WIN32) && !defined(BUILD2_BOOTSTRAP)
+
+ // We more or less follow the logic in the Clang 'simplementation (see
+ // MSVC.cpp for details) but don't use the high level APIs (bstr_t,
+ // com_ptr_t, etc) and the VC extensions (__uuidof(), class uuid
+ // __declspecs, etc) that are poorly supported by MinGW GCC and Clang.
+ //
+ struct com_deleter
+ {
+ void operator() (IUnknown* p) const {if (p != nullptr) p->Release ();}
+ };
+
+ struct bstr_deleter
+ {
+ void operator() (BSTR p) const {if (p != nullptr) SysFreeString (p);}
+ };
+
+ // We don't use the __uuidof keyword (see above) and so define the
+ // class/interface ids manually.
+ //
+ static const CLSID msvc_setup_config_clsid {
+ 0x177F0C4A, 0x1CD3, 0x4DE7,
+ {0xA3, 0x2C, 0x71, 0xDB, 0xBB, 0x9F, 0xA3, 0x6D}};
+
+ static const IID msvc_setup_config_iid {
+ 0x26AAB78C, 0x4A60, 0x49D6,
+ {0xAF, 0x3B, 0x3C, 0x35, 0xBC, 0x93, 0x36, 0x5D}};
+
+ static const IID msvc_setup_helper_iid {
+ 0x42B21B78, 0x6192, 0x463E,
+ {0x87, 0xBF, 0xD5, 0x77, 0x83, 0x8F, 0x1D, 0x5C}};
+
+ static optional<msvc_info>
+ find_msvc ()
+ {
+ using namespace butl;
+
+ msvc_info r;
+
+ // Try to obtain the latest MSVC directory and version.
+ //
+ {
+ // Initialize the COM library for use by the current thread.
+ //
+ if (CoInitializeEx (nullptr /* pvReserved */,
+ COINIT_APARTMENTTHREADED) != S_OK)
+ return nullopt;
+
+ auto uninitializer (make_guard ([] () {CoUninitialize ();}));
+
+ // Obtain the VS information retrieval interface. Failed that, assume
+ // there is no VS installed.
+ //
+ unique_ptr<ISetupConfiguration2, com_deleter> sc;
+ {
+ ISetupConfiguration2* p;
+ if (CoCreateInstance (msvc_setup_config_clsid,
+ nullptr /* pUnkOuter */,
+ CLSCTX_ALL,
+ msvc_setup_config_iid,
+ reinterpret_cast<LPVOID*> (&p)) != S_OK)
+ return nullopt;
+
+ sc.reset (p);
+ }
+
+ // Obtain the VS instance enumerator interface.
+ //
+ unique_ptr<IEnumSetupInstances, com_deleter> ei;
+ {
+ IEnumSetupInstances* p;
+ if (sc->EnumAllInstances (&p) != S_OK)
+ return nullopt;
+
+ ei.reset (p);
+ }
+
+ // Obtain an interface that helps with the VS version parsing.
+ //
+ unique_ptr<ISetupHelper, com_deleter> sh;
+ {
+ ISetupHelper* p;
+ if (sc->QueryInterface (msvc_setup_helper_iid,
+ reinterpret_cast<LPVOID*> (&p)) != S_OK)
+ return nullopt;
+
+ sh.reset (p);
+ }
+
+ // Iterate over the VS instances and pick the latest one. Bail out
+ // if any COM interface function call fails.
+ //
+ unsigned long long vs_ver (0); // VS version numeric representation.
+ unique_ptr<ISetupInstance, com_deleter> vs;
+ HRESULT hr;
+
+ for (ISetupInstance* p;
+ (hr = ei->Next (1, &p, nullptr /* pceltFetched */)) == S_OK; )
+ {
+ unique_ptr<ISetupInstance, com_deleter> i (p);
+
+ // Note: we cannot use bstr_t due to the Clang 9.0 bug #42842.
+ //
+ BSTR iv; // For example, 16.3.29324.140.
+ if (i->GetInstallationVersion (&iv) != S_OK)
+ return nullopt;
+
+ unique_ptr<wchar_t, bstr_deleter> deleter (iv);
+
+ unsigned long long v;
+ if (sh->ParseVersion (iv, &v) != S_OK)
+ return nullopt;
+
+ if (vs == nullptr || v > vs_ver)
+ {
+ vs = move (i);
+ vs_ver = v;
+ }
+ }
+
+ // Bail out if no VS instance is found or we didn't manage to iterate
+ // through all of them successfully.
+ //
+ if (vs == nullptr || hr != S_FALSE)
+ return nullopt;
+
+ // Obtain the VC directory path.
+ //
+ {
+ BSTR p;
+ if (vs->ResolvePath (L"VC", &p) != S_OK)
+ return nullopt;
+
+ unique_ptr<wchar_t, bstr_deleter> deleter (p);
+
+ // Convert BSTR to the NULL-terminated character string and then to
+ // a path. Bail out if anything goes wrong.
+ //
+ try
+ {
+ int n (WideCharToMultiByte (CP_ACP,
+ 0 /* dwFlags */,
+ p,
+ -1, /*cchWideChar */
+ nullptr /* lpMultiByteStr */,
+ 0 /* cbMultiByte */,
+ 0 /* lpDefaultChar */,
+ 0 /* lpUsedDefaultChar */));
+
+ if (n != 0) // Note: must include the terminating NULL character.
+ {
+ vector<char> ps (n);
+ if (WideCharToMultiByte (CP_ACP,
+ 0,
+ p, -1,
+ ps.data (), n,
+ 0, 0) != 0)
+ r.msvc_dir = dir_path (ps.data ());
+ }
+ }
+ catch (const invalid_path&) {}
+
+ if (r.msvc_dir.relative ()) // Also covers the empty directory case.
+ return nullopt;
+ }
+
+ // Read the VC version from the file and bail out on error.
+ //
+ string vc_ver; // For example, 14.23.28105.
+
+ path vp (
+ r.msvc_dir /
+ path ("Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"));
+
+ try
+ {
+ ifdstream is (vp);
+ vc_ver = trim (is.read_text ());
+ }
+ catch (const io_error&) {}
+
+ // Make sure that the VC version directory exists.
+ //
+ if (!vc_ver.empty ())
+ try
+ {
+ ((r.msvc_dir /= "Tools") /= "MSVC") /= vc_ver;
+
+ if (!dir_exists (r.msvc_dir))
+ r.msvc_dir.clear ();
+ }
+ catch (const invalid_path&) {}
+ catch (const system_error&) {}
+
+ if (r.msvc_dir.empty ())
+ return nullopt;
+ }
+
+ // Try to obtain the latest Platform SDK directory and version.
+ //
+ {
+ // Read the Platform SDK directory path from the registry. Failed
+ // that, assume there is no Platform SDK installed.
+ //
+ HKEY h;
+ if (RegOpenKeyExA (
+ HKEY_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots",
+ 0 /* ulOptions */,
+ KEY_READ,
+ &h) != ERROR_SUCCESS)
+ return nullopt;
+
+ DWORD t;
+
+ // Reserve space for the terminating NULL character.
+ //
+ DWORD n (_MAX_PATH + 1);
+ char buf[_MAX_PATH + 1];
+
+ LSTATUS st (RegQueryValueExA (h,
+ "KitsRoot10",
+ nullptr,
+ &t,
+ reinterpret_cast<LPBYTE> (buf),
+ &n));
+
+ // Unlikely to fail, but we can't do much if that's the case.
+ //
+ RegCloseKey (h);
+
+ // Note that the value length includes the terminating NULL character
+ // and so cannot be zero.
+ //
+ if (st != ERROR_SUCCESS || t != REG_SZ || n == 0)
+ return nullopt;
+
+ try
+ {
+ r.psdk_dir = dir_path (buf);
+
+ if (r.psdk_dir.relative ()) // Also covers the empty directory case.
+ return nullopt;
+
+ // Obtain the latest Platform SDK version as the lexicographically
+ // greatest sub-directory name in the <psdk-dir>/Include directory.
+ //
+ for (const dir_entry& de:
+ dir_iterator (r.psdk_dir / dir_path ("Include"),
+ false /* ignore_dangling */))
+ {
+ if (de.type () == entry_type::directory)
+ {
+ const string& v (de.path ().string ());
+
+ if (v.compare (0, 3, "10.") == 0 && v > r.psdk_ver)
+ r.psdk_ver = v;
+ }
+ }
+ }
+ catch (const invalid_path&) {return nullopt;}
+ catch (const system_error&) {return nullopt;}
+
+ if (r.psdk_ver.empty ())
+ return nullopt;
+ }
+
+ return move (r);
+ }
+#endif
+
// Guess the compiler type and variant by running it. If the pre argument
// is not empty, then only "confirm" the pre-guess. Return empty result if
// unable to guess.
@@ -363,6 +710,15 @@ namespace build2
string checksum;
process_path path;
+ // Optional additional information (for example, msvc_info).
+ //
+ static void
+ null_info_deleter (void* p) { assert (p == nullptr); }
+
+ using info_ptr = unique_ptr<void, void (*) (void*)>;
+
+ info_ptr info = {nullptr, null_info_deleter};
+
guess_result () = default;
guess_result (compiler_id i, string&& s)
: id (move (i)), signature (move (s)) {}
@@ -388,9 +744,15 @@ namespace build2
using type = compiler_type;
const type invalid = invalid_compiler_type;
+ const type& pt (pre.type);
+ const optional<string>& pv (pre.variant);
+
+ using info_ptr = guess_result::info_ptr;
guess_result r;
process_path xp;
+ info_ptr search_info (nullptr, guess_result::null_info_deleter);
+ for (;;) // Breakout loop.
{
auto df = make_diag_frame (
[&xm](const diag_record& dr)
@@ -398,36 +760,93 @@ namespace build2
dr << info << "use config." << xm << " to override";
});
+ dir_path fb; // Fallback search directory.
+
+#ifdef _WIN32
// If we are running in the Visual Studio command prompt, add the
// potentially bundled Clang directory as a fallback (for some reason
// the Visual Studio prompts don't add it to PATH themselves).
//
- dir_path fallback;
-
-#ifdef _WIN32
- if (pre.type == type::clang ||
- (pre.type == type::msvc && pre.variant && *pre.variant == "clang"))
+ if (xc.simple () &&
+ (pt == type::clang ||
+ (pt == type::msvc && pv && *pv == "clang")))
{
if (optional<string> v = getenv ("VCINSTALLDIR"))
{
try
{
- fallback = ((dir_path (move (*v)) /= "Tools") /= "Llvm") /= "bin";
+ fb = ((dir_path (move (*v)) /= "Tools") /= "Llvm") /= "bin";
}
catch (const invalid_path&)
{
// Ignore it.
}
+
+ goto search;
+ }
+ }
+
+ // If we pre-guessed MSVC or Clang (including clang-cl) try the search
+ // and if not found, try to locate the MSVC installation and fallback
+ // on that.
+ //
+ if (xc.simple () &&
+ (pt == type::clang ||
+ (pt == type::msvc && (!pv || *pv == "clang"))))
+ {
+ if (!(xp = try_run_search (xc, false, dir_path (), true)).empty ())
+ break;
+
+ if (optional<msvc_info> mi = find_msvc ())
+ {
+ try
+ {
+ if (pt == type::msvc && !pv)
+ {
+ // With MSVC you get a compiler binary per target (i.e., there
+ // is nothing like -m32/-m64 or /MACHINE). Targeting 64-bit
+ // seems like as good of a default as any.
+ //
+ fb = ((dir_path (mi->msvc_dir) /= "bin") /= "Hostx64") /= "x64";
+
+ search_info = info_ptr (new msvc_info (move (*mi)),
+ [] (void* p)
+ {
+ delete static_cast<msvc_info*> (p);
+ });
+ }
+ else
+ {
+ // Get to ...\VC\Tools\ from ...\VC\Tools\MSVC\<ver>\.
+ //
+ fb = (dir_path (mi->msvc_dir) /= "..") /= "..";
+ fb.normalize ();
+ (fb /= "Llvm") /= "bin";
+
+ // Note that in this case we drop msvc_info and extract it
+ // directly from Clang later.
+ }
+ }
+ catch (const invalid_path&)
+ {
+ fb.clear (); // Ignore it.
+ }
+
+ goto search;
}
}
+
+ search:
#endif
+
// Only search in PATH (specifically, omitting the current
// executable's directory on Windows).
//
xp = run_search (xc,
- false /* init (note: result is cached) */,
- fallback,
- true /* path_only */);
+ false /* init (note: result is cached) */,
+ fb,
+ true /* path_only */);
+ break;
}
// Start with -v. This will cover gcc and clang (including clang-cl).
@@ -445,13 +864,12 @@ namespace build2
// In fact, if someone renames icpc to g++, there will be no way for
// us to detect this. Oh, well, their problem.
//
- if (r.empty () && ( pre.type == invalid ||
- pre.type == type::gcc ||
- pre.type == type::clang ||
- (pre.type == type::msvc &&
- pre.variant && *pre.variant == "clang")))
+ if (r.empty () && (pt == invalid ||
+ pt == type::gcc ||
+ pt == type::clang ||
+ (pt == type::msvc && pv && *pv == "clang")))
{
- auto f = [&xi, &pre] (string& l, bool last) -> guess_result
+ auto f = [&xi, &pt] (string& l, bool last) -> guess_result
{
if (xi)
{
@@ -525,7 +943,7 @@ namespace build2
//
if (l.find ("clang ") != string::npos)
{
- return guess_result (pre.type == type::msvc
+ return guess_result (pt == type::msvc
? compiler_id {type::msvc, "clang"}
: compiler_id {type::clang, ""},
move (l));
@@ -567,7 +985,7 @@ namespace build2
//
if (r.id.type == type::clang &&
r.id.variant == "apple" &&
- pre.type == type::gcc)
+ pt == type::gcc)
{
pre.type = type::clang;
pre.variant = "apple";
@@ -578,10 +996,10 @@ namespace build2
// Next try --version to detect icc. As well as obtain signature for
// GCC/Clang-like compilers in case -v above didn't work.
//
- if (r.empty () && (pre.type == invalid ||
- pre.type == type::icc ||
- pre.type == type::gcc ||
- pre.type == type::clang))
+ if (r.empty () && (pt == invalid ||
+ pt == type::icc ||
+ pt == type::gcc ||
+ pt == type::clang))
{
auto f = [&xi] (string& l, bool) -> guess_result
{
@@ -617,7 +1035,8 @@ namespace build2
// Finally try to run it without any options to detect msvc.
//
- if (r.empty () && (pre.type == invalid || pre.type == type::msvc))
+ if (r.empty () && (pt == invalid ||
+ pt == type::msvc))
{
auto f = [&xi] (string& l, bool) -> guess_result
{
@@ -669,9 +1088,8 @@ namespace build2
if (!r.empty ())
{
- if (pre.type != invalid &&
- (pre.type != r.id.type ||
- (pre.variant && *pre.variant != r.id.variant)))
+ if (pt != invalid &&
+ (pt != r.id.type || (pv && *pv != r.id.variant)))
{
l4 ([&]{trace << "compiler type guess mismatch"
<< ", pre-guessed " << pre
@@ -685,6 +1103,9 @@ namespace build2
<< r.signature << "'";});
r.path = move (xp);
+
+ if (search_info != nullptr && r.info == nullptr)
+ r.info = move (search_info);
}
}
else
@@ -823,6 +1244,82 @@ namespace build2
<< "' to runtime version" << endf;
}
+ // Return the MSVC system header search paths (i.e., what the Visual
+ // Studio command prompt puts into INCLUDE).
+ //
+ // Note that currently we don't add any ATL/MFC or WinRT paths (but could
+ // do that probably first checking if they exist/empty).
+ //
+ static dir_paths
+ msvc_include (const msvc_info& mi)
+ {
+ dir_paths r;
+
+ r.push_back (dir_path (mi.msvc_dir) /= "include");
+
+ // This path structure only appeared in Platform SDK 10 (if anyone wants
+ // to use anything older, they will just have to use the MSVC command
+ // prompt).
+ //
+ if (!mi.psdk_ver.empty ())
+ {
+ dir_path d ((dir_path (mi.psdk_dir) /= "Include") /= mi.psdk_ver);
+
+ r.push_back (dir_path (d) /= "ucrt" );
+ r.push_back (dir_path (d) /= "shared");
+ r.push_back (dir_path (d) /= "um" );
+ }
+
+ return r;
+ }
+
+ // Return the MSVC system library search paths (i.e., what the Visual
+ // Studio command prompt puts into LIB).
+ //
+ static dir_paths
+ msvc_lib (const msvc_info& mi, const char* cpu)
+ {
+ dir_paths r;
+
+ r.push_back ((dir_path (mi.msvc_dir) /= "lib") /= cpu);
+
+ // This path structure only appeared in Platform SDK 10 (if anyone wants
+ // to use anything older, they will just have to use the MSVC command
+ // prompt).
+ //
+ if (!mi.psdk_ver.empty ())
+ {
+ dir_path d ((dir_path (mi.psdk_dir) /= "Lib") /= mi.psdk_ver);
+
+ r.push_back ((dir_path (d) /= "ucrt") /= cpu);
+ r.push_back ((dir_path (d) /= "um" ) /= cpu);
+ }
+
+ return r;
+ }
+
+ // Return the MSVC binutils search paths (i.e., what the Visual Studio
+ // command prompt puts into PATH).
+ //
+ static string
+ msvc_bin (const msvc_info& mi, const char* cpu)
+ {
+ string r;
+
+ // Seeing that we only do 64-bit on Windows, let's always use 64-bit
+ // MSVC tools (link.exe, etc). In case of the Platform SDK, it's unclear
+ // what the CPU signifies (host, target, both).
+ //
+ r = (((dir_path (mi.msvc_dir) /= "bin") /= "Hostx64") /= cpu).
+ representation ();
+
+ r += path::traits_type::path_separator;
+
+ r += (((dir_path (mi.psdk_dir) /= "bin") /= mi.psdk_ver) /= cpu).
+ representation ();
+
+ return r;
+ }
static compiler_info
guess_msvc (const char* xm,
@@ -990,6 +1487,21 @@ namespace build2
else
ot = t = *xt;
+ // If we have the MSVC installation information, then this means we are
+ // running out of the Visual Studio command prompt and will have to
+ // supply PATH/INCLUDE/LIB equivalents ourselves.
+ //
+ optional<dir_paths> lib_dirs;
+ optional<dir_paths> inc_dirs;
+ string bpat;
+
+ if (const msvc_info* mi = static_cast<msvc_info*> (gr.info.get ()))
+ {
+ lib_dirs = msvc_lib (*mi, "x64");
+ lib_dirs = msvc_include (*mi);
+ bpat = msvc_bin (*mi, "x64");
+ }
+
// Derive the toolchain pattern.
//
// If the compiler name is/starts with 'cl' (e.g., cl.exe, cl-14),
@@ -997,7 +1509,9 @@ namespace build2
// etc.
//
string cpat (pattern (xc, "cl", nullptr, ".-"));
- string bpat (cpat); // Binutils pattern is the same as toolchain.
+
+ if (bpat.empty ())
+ bpat = cpat; // Binutils pattern is the same as toolchain.
// Runtime and standard library.
//
@@ -1025,8 +1539,8 @@ namespace build2
move (rt),
move (csl),
move (xsl),
- nullopt,
- nullopt};
+ move (lib_dirs),
+ move (inc_dirs)};
}
static compiler_info
@@ -1223,14 +1737,11 @@ namespace build2
nullopt};
}
- struct clang_msvc_info
+ struct clang_msvc_info: msvc_info
{
string triple; // cc1 -triple value
- string msvc_ver; // system version from triple
+ string msvc_ver; // Compiler version from triple.
string msvc_comp_ver; // cc1 -fms-compatibility-version value
- dir_path msvc_dir;
- string psdk_ver;
- dir_path psdk_dir;
};
static clang_msvc_info
@@ -1645,7 +2156,7 @@ namespace build2
// MSVC's.
//
optional<dir_paths> lib_dirs;
- string bin_pat;
+ string bpat;
if (tt.system == "windows-msvc")
{
@@ -1686,25 +2197,7 @@ namespace build2
// to extract this from Clang and -print-search-paths would have been
// the natural way for Clang to report it. But no luck.
//
- {
- dir_paths ds;
-
- ds.push_back ((dir_path (mi.msvc_dir) /= "lib") /= cpu);
-
- // This path structure only appeared in Platform SDK 10 (if anyone
- // wants to use anything older, they will just have to use the MSVC
- // command prompt).
- //
- if (!mi.psdk_ver.empty ())
- {
- dir_path d ((dir_path (mi.psdk_dir) /= "Lib") /= mi.psdk_ver);
-
- ds.push_back ((dir_path (d) /= "ucrt") /= cpu);
- ds.push_back ((dir_path (d) /= "um" ) /= cpu);
- }
-
- lib_dirs = move (ds);
- }
+ lib_dirs = msvc_lib (mi, cpu);
// Binutils search paths.
//
@@ -1713,17 +2206,7 @@ namespace build2
// lines. However, reliably detecting this and making sure the result
// matches Clang's is complex. So let's keep it simple for now.
//
- // Seeing that we only do 64-bit on Windows, let's always use 64-bit
- // MSVC tools (link.exe, etc). In case of the Platform SDK, it's
- // unclear what the CPU signifies (host, target, both).
- //
- bin_pat = (((dir_path (mi.msvc_dir) /= "bin") /= "Hostx64") /= cpu).
- representation ();
-
- bin_pat += path::traits_type::path_separator;
-
- bin_pat += (((dir_path (mi.psdk_dir) /= "bin") /= mi.psdk_ver) /= cpu).
- representation ();
+ bpat = msvc_bin (mi, cpu);
// If this is clang-cl, then use the MSVC compatibility version as its
// primary version.
@@ -1735,20 +2218,20 @@ namespace build2
}
}
- // Derive the toolchain pattern. Try clang/clang++, the gcc/g++ alias,
- // as well as cc/c++.
+ // Derive the compiler toolchain pattern. Try clang/clang++, the gcc/g++
+ // alias, as well as cc/c++.
//
- string pat;
+ string cpat;
if (!cl)
{
- pat = pattern (xc, xl == lang::c ? "clang" : "clang++");
+ cpat = pattern (xc, xl == lang::c ? "clang" : "clang++");
- if (pat.empty ())
- pat = pattern (xc, xl == lang::c ? "gcc" : "g++");
+ if (cpat.empty ())
+ cpat = pattern (xc, xl == lang::c ? "gcc" : "g++");
- if (pat.empty ())
- pat = pattern (xc, xl == lang::c ? "cc" : "c++");
+ if (cpat.empty ())
+ cpat = pattern (xc, xl == lang::c ? "cc" : "c++");
}
// Runtime and standard library.
@@ -1829,8 +2312,8 @@ namespace build2
move (gr.checksum), // Calculated on whole -v output.
move (t),
move (ot),
- move (pat),
- move (bin_pat),
+ move (cpat),
+ move (bpat),
move (rt),
move (csl),
move (xsl),
@@ -2154,12 +2637,12 @@ namespace build2
cs.append (static_cast<size_t> (xl));
cs.append (xc.string ());
if (xis != nullptr) cs.append (*xis);
- if (c_po != nullptr) hash_options (cs, *c_po);
- if (x_po != nullptr) hash_options (cs, *x_po);
- if (c_co != nullptr) hash_options (cs, *c_co);
- if (x_co != nullptr) hash_options (cs, *x_co);
- if (c_lo != nullptr) hash_options (cs, *c_lo);
- if (x_lo != nullptr) hash_options (cs, *x_lo);
+ if (c_po != nullptr) append_options (cs, *c_po);
+ if (x_po != nullptr) append_options (cs, *x_po);
+ if (c_co != nullptr) append_options (cs, *c_co);
+ if (x_co != nullptr) append_options (cs, *x_co);
+ if (c_lo != nullptr) append_options (cs, *c_lo);
+ if (x_lo != nullptr) append_options (cs, *x_lo);
key = cs.string ();
auto i (cache.find (key));
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index 8aedcad..f10bd42 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -1573,10 +1573,10 @@ namespace build2
}
void link_rule::
- hash_libraries (sha256& cs,
- bool& update, timestamp mt,
- const file& l, bool la, lflags lf,
- const scope& bs, action a, linfo li) const
+ append_libraries (sha256& cs,
+ bool& update, timestamp mt,
+ const file& l, bool la, lflags lf,
+ const scope& bs, action a, linfo li) const
{
struct data
{
@@ -1666,7 +1666,7 @@ namespace build2
? (exp ? x_export_loptions : x_loptions)
: l.ctx.var_pool[t + (exp ? ".export.loptions" : ".loptions")]));
- hash_options (d.cs, *g, var);
+ append_options (d.cs, *g, var);
}
};
@@ -2436,7 +2436,7 @@ namespace build2
//
if (la || ls)
{
- hash_libraries (cs, update, mt, *f, la, p.data, bs, a, li);
+ append_libraries (cs, update, mt, *f, la, p.data, bs, a, li);
f = nullptr; // Timestamp checked by hash_libraries().
}
else
@@ -2475,8 +2475,8 @@ namespace build2
//
if (!lt.static_library ())
{
- hash_options (cs, t, c_libs);
- hash_options (cs, t, x_libs);
+ append_options (cs, t, c_libs);
+ append_options (cs, t, x_libs);
}
if (dd.expect (cs.string ()) != nullptr)
diff --git a/libbuild2/cc/link-rule.hxx b/libbuild2/cc/link-rule.hxx
index 2a296a7..07e619d 100644
--- a/libbuild2/cc/link-rule.hxx
+++ b/libbuild2/cc/link-rule.hxx
@@ -131,10 +131,10 @@ namespace build2
const scope&, action, linfo) const;
void
- hash_libraries (sha256&,
- bool&, timestamp,
- const file&, bool, lflags,
- const scope&, action, linfo) const;
+ append_libraries (sha256&,
+ bool&, timestamp,
+ const file&, bool, lflags,
+ const scope&, action, linfo) const;
void
rpath_libraries (strings&,
diff --git a/libbuild2/cc/msvc-setup.h b/libbuild2/cc/msvc-setup.h
new file mode 100644
index 0000000..94f7481
--- /dev/null
+++ b/libbuild2/cc/msvc-setup.h
@@ -0,0 +1,1059 @@
+// The MIT License(MIT)
+// Copyright(C) Microsoft Corporation.All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files(the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions :
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//
+
+#pragma once
+
+// Constants
+//
+#ifndef E_NOTFOUND
+#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
+#endif
+
+#ifndef E_FILENOTFOUND
+#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
+#endif
+
+#ifndef E_NOTSUPPORTED
+#define E_NOTSUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
+#endif
+
+// Enumerations
+//
+/// <summary>
+/// The state of an instance.
+/// </summary>
+enum InstanceState
+{
+ /// <summary>
+ /// The instance state has not been determined.
+ /// </summary>
+ eNone = 0,
+
+ /// <summary>
+ /// The instance installation path exists.
+ /// </summary>
+ eLocal = 1,
+
+ /// <summary>
+ /// A product is registered to the instance.
+ /// </summary>
+ eRegistered = 2,
+
+ /// <summary>
+ /// No reboot is required for the instance.
+ /// </summary>
+ eNoRebootRequired = 4,
+
+ /// <summary>
+ /// No errors were reported for the instance.
+ /// </summary>
+ eNoErrors = 8,
+
+ /// <summary>
+ /// The instance represents a complete install.
+ /// </summary>
+ eComplete = MAXUINT,
+};
+
+// Forward interface declarations
+//
+#ifndef __ISetupInstance_FWD_DEFINED__
+#define __ISetupInstance_FWD_DEFINED__
+typedef struct ISetupInstance ISetupInstance;
+#endif
+
+#ifndef __ISetupInstance2_FWD_DEFINED__
+#define __ISetupInstance2_FWD_DEFINED__
+typedef struct ISetupInstance2 ISetupInstance2;
+#endif
+
+#ifndef __ISetupInstanceCatalog_FWD_DEFINED__
+#define __ISetupInstanceCatalog_FWD_DEFINED__
+typedef struct ISetupInstanceCatalog ISetupInstanceCatalog;
+#endif
+
+#ifndef __ISetupLocalizedProperties_FWD_DEFINED__
+#define __ISetupLocalizedProperties_FWD_DEFINED__
+typedef struct ISetupLocalizedProperties ISetupLocalizedProperties;
+#endif
+
+#ifndef __IEnumSetupInstances_FWD_DEFINED__
+#define __IEnumSetupInstances_FWD_DEFINED__
+typedef struct IEnumSetupInstances IEnumSetupInstances;
+#endif
+
+#ifndef __ISetupConfiguration_FWD_DEFINED__
+#define __ISetupConfiguration_FWD_DEFINED__
+typedef struct ISetupConfiguration ISetupConfiguration;
+#endif
+
+#ifndef __ISetupConfiguration2_FWD_DEFINED__
+#define __ISetupConfiguration2_FWD_DEFINED__
+typedef struct ISetupConfiguration2 ISetupConfiguration2;
+#endif
+
+#ifndef __ISetupPackageReference_FWD_DEFINED__
+#define __ISetupPackageReference_FWD_DEFINED__
+typedef struct ISetupPackageReference ISetupPackageReference;
+#endif
+
+#ifndef __ISetupProductReference_FWD_DEFINED__
+#define __ISetupProductReference_FWD_DEFINED__
+typedef struct ISetupProductReference ISetupProductReference;
+#endif
+
+#ifndef __ISetupProductReference2_FWD_DEFINED__
+#define __ISetupProductReference2_FWD_DEFINED__
+typedef struct ISetupProductReference2 ISetupProductReference2;
+#endif
+
+#ifndef __ISetupHelper_FWD_DEFINED__
+#define __ISetupHelper_FWD_DEFINED__
+typedef struct ISetupHelper ISetupHelper;
+#endif
+
+#ifndef __ISetupErrorInfo_FWD_DEFINED__
+#define __ISetupErrorInfo_FWD_DEFINED__
+typedef struct ISetupErrorInfo ISetupErrorInfo;
+#endif
+
+#ifndef __ISetupErrorState_FWD_DEFINED__
+#define __ISetupErrorState_FWD_DEFINED__
+typedef struct ISetupErrorState ISetupErrorState;
+#endif
+
+#ifndef __ISetupErrorState2_FWD_DEFINED__
+#define __ISetupErrorState2_FWD_DEFINED__
+typedef struct ISetupErrorState2 ISetupErrorState2;
+#endif
+
+#ifndef __ISetupErrorState3_FWD_DEFINED__
+#define __ISetupErrorState3_FWD_DEFINED__
+typedef struct ISetupErrorState3 ISetupErrorState3;
+#endif
+
+#ifndef __ISetupFailedPackageReference_FWD_DEFINED__
+#define __ISetupFailedPackageReference_FWD_DEFINED__
+typedef struct ISetupFailedPackageReference ISetupFailedPackageReference;
+#endif
+
+#ifndef __ISetupFailedPackageReference2_FWD_DEFINED__
+#define __ISetupFailedPackageReference2_FWD_DEFINED__
+typedef struct ISetupFailedPackageReference2 ISetupFailedPackageReference2;
+#endif
+
+#ifndef __ISetupFailedPackageReference3_FWD_DEFINED__
+#define __ISetupFailedPackageReference3_FWD_DEFINED__
+typedef struct ISetupFailedPackageReference3 ISetupFailedPackageReference3;
+#endif
+
+#ifndef __ISetupPropertyStore_FWD_DEFINED__
+#define __ISetupPropertyStore_FWD_DEFINED__
+typedef struct ISetupPropertyStore ISetupPropertyStore;
+#endif
+
+#ifndef __ISetupLocalizedPropertyStore_FWD_DEFINED__
+#define __ISetupLocalizedPropertyStore_FWD_DEFINED__
+typedef struct ISetupLocalizedPropertyStore ISetupLocalizedPropertyStore;
+#endif
+
+#ifndef __ISetupPolicy_FWD_DEFINED__
+#define __ISetupPolicy_FWD_DEFINED__
+typedef struct ISetupPolicy ISetupPolicy;
+#endif
+
+// Forward class declarations
+//
+#ifndef __SetupConfiguration_FWD_DEFINED__
+#define __SetupConfiguration_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class SetupConfiguration SetupConfiguration;
+#endif
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Interface definitions
+//
+EXTERN_C const IID IID_ISetupInstance;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about an instance of a product.
+/// </summary>
+struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E") DECLSPEC_NOVTABLE ISetupInstance : public IUnknown
+{
+ /// <summary>
+ /// Gets the instance identifier (should match the name of the parent instance directory).
+ /// </summary>
+ /// <param name="pbstrInstanceId">The instance identifier.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns>
+ STDMETHOD(GetInstanceId)(
+ _Out_ BSTR* pbstrInstanceId
+ ) = 0;
+
+ /// <summary>
+ /// Gets the local date and time when the installation was originally installed.
+ /// </summary>
+ /// <param name="pInstallDate">The local date and time when the installation was originally installed.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(GetInstallDate)(
+ _Out_ LPFILETIME pInstallDate
+ ) = 0;
+
+ /// <summary>
+ /// Gets the unique name of the installation, often indicating the branch and other information used for telemetry.
+ /// </summary>
+ /// <param name="pbstrInstallationName">The unique name of the installation, often indicating the branch and other information used for telemetry.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(GetInstallationName)(
+ _Out_ BSTR* pbstrInstallationName
+ ) = 0;
+
+ /// <summary>
+ /// Gets the path to the installation root of the product.
+ /// </summary>
+ /// <param name="pbstrInstallationPath">The path to the installation root of the product.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(GetInstallationPath)(
+ _Out_ BSTR* pbstrInstallationPath
+ ) = 0;
+
+ /// <summary>
+ /// Gets the version of the product installed in this instance.
+ /// </summary>
+ /// <param name="pbstrInstallationVersion">The version of the product installed in this instance.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(GetInstallationVersion)(
+ _Out_ BSTR* pbstrInstallationVersion
+ ) = 0;
+
+ /// <summary>
+ /// Gets the display name (title) of the product installed in this instance.
+ /// </summary>
+ /// <param name="lcid">The LCID for the display name.</param>
+ /// <param name="pbstrDisplayName">The display name (title) of the product installed in this instance.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(GetDisplayName)(
+ _In_ LCID lcid,
+ _Out_ BSTR* pbstrDisplayName
+ ) = 0;
+
+ /// <summary>
+ /// Gets the description of the product installed in this instance.
+ /// </summary>
+ /// <param name="lcid">The LCID for the description.</param>
+ /// <param name="pbstrDescription">The description of the product installed in this instance.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(GetDescription)(
+ _In_ LCID lcid,
+ _Out_ BSTR* pbstrDescription
+ ) = 0;
+
+ /// <summary>
+ /// Resolves the optional relative path to the root path of the instance.
+ /// </summary>
+ /// <param name="pwszRelativePath">A relative path within the instance to resolve, or NULL to get the root path.</param>
+ /// <param name="pbstrAbsolutePath">The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property is not defined.</returns>
+ STDMETHOD(ResolvePath)(
+ _In_opt_z_ LPCOLESTR pwszRelativePath,
+ _Out_ BSTR* pbstrAbsolutePath
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupInstance2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about an instance of a product.
+/// </summary>
+struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C") DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance
+{
+ /// <summary>
+ /// Gets the state of the instance.
+ /// </summary>
+ /// <param name="pState">The state of the instance.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns>
+ STDMETHOD(GetState)(
+ _Out_ InstanceState* pState
+ ) = 0;
+
+ /// <summary>
+ /// Gets an array of package references registered to the instance.
+ /// </summary>
+ /// <param name="ppsaPackages">Pointer to an array of <see cref="ISetupPackageReference"/>.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined.</returns>
+ STDMETHOD(GetPackages)(
+ _Out_ LPSAFEARRAY* ppsaPackages
+ ) = 0;
+
+ /// <summary>
+ /// Gets a pointer to the <see cref="ISetupPackageReference"/> that represents the registered product.
+ /// </summary>
+ /// <param name="ppPackage">Pointer to an instance of <see cref="ISetupPackageReference"/>. This may be NULL if <see cref="GetState"/> does not return <see cref="eComplete"/>.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the packages property is not defined.</returns>
+ STDMETHOD(GetProduct)(
+ _Outptr_result_maybenull_ ISetupPackageReference** ppPackage
+ ) = 0;
+
+ /// <summary>
+ /// Gets the relative path to the product application, if available.
+ /// </summary>
+ /// <param name="pbstrProductPath">The relative path to the product application, if available.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns>
+ STDMETHOD(GetProductPath)(
+ _Outptr_result_maybenull_ BSTR* pbstrProductPath
+ ) = 0;
+
+ /// <summary>
+ /// Gets the error state of the instance, if available.
+ /// </summary>
+ /// <param name="pErrorState">The error state of the instance, if available.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns>
+ STDMETHOD(GetErrors)(
+ _Outptr_result_maybenull_ ISetupErrorState** ppErrorState
+ ) = 0;
+
+ /// <summary>
+ /// Gets a value indicating whether the instance can be launched.
+ /// </summary>
+ /// <param name="pfIsLaunchable">Whether the instance can be launched.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ /// <remarks>
+ /// An instance could have had errors during install but still be launched. Some features may not work correctly, but others will.
+ /// </remarks>
+ STDMETHOD(IsLaunchable)(
+ _Out_ VARIANT_BOOL* pfIsLaunchable
+ ) = 0;
+
+ /// <summary>
+ /// Gets a value indicating whether the instance is complete.
+ /// </summary>
+ /// <param name="pfIsLaunchable">Whether the instance is complete.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ /// <remarks>
+ /// An instance is complete if it had no errors during install, resume, or repair.
+ /// </remarks>
+ STDMETHOD(IsComplete)(
+ _Out_ VARIANT_BOOL* pfIsComplete
+ ) = 0;
+
+ /// <summary>
+ /// Gets product-specific properties.
+ /// </summary>
+ /// <param name="ppPropeties">A pointer to an instance of <see cref="ISetupPropertyStore"/>. This may be NULL if no properties are defined.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns>
+ STDMETHOD(GetProperties)(
+ _Outptr_result_maybenull_ ISetupPropertyStore** ppProperties
+ ) = 0;
+
+ /// <summary>
+ /// Gets the directory path to the setup engine that installed the instance.
+ /// </summary>
+ /// <param name="pbstrEnginePath">The directory path to the setup engine that installed the instance.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist.</returns>
+ STDMETHOD(GetEnginePath)(
+ _Outptr_result_maybenull_ BSTR* pbstrEnginePath
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupInstanceCatalog;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about a catalog used to install an instance.
+/// </summary>
+struct DECLSPEC_UUID("9AD8E40F-39A2-40F1-BF64-0A6C50DD9EEB") DECLSPEC_NOVTABLE ISetupInstanceCatalog : public IUnknown
+{
+ /// <summary>
+ /// Gets catalog information properties.
+ /// </summary>
+ /// <param name="ppCatalogInfo">A pointer to an instance of <see cref="ISetupPropertyStore"/>.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property does not exist.</returns>
+ STDMETHOD(GetCatalogInfo)(
+ _Out_ ISetupPropertyStore** ppCatalogInfo
+ ) = 0;
+
+ /// <summary>
+ /// Gets a value indicating whether the catalog is a prerelease.
+ /// </summary>
+ /// <param name="pfIsPrerelease">Whether the catalog for the instance is a prerelease version.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the property does not exist.</returns>
+ STDMETHOD(IsPrerelease)(
+ _Out_ VARIANT_BOOL* pfIsPrerelease
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupLocalizedProperties;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Provides localized properties of an instance of a product.
+/// </summary>
+struct DECLSPEC_UUID("F4BD7382-FE27-4AB4-B974-9905B2A148B0") DECLSPEC_NOVTABLE ISetupLocalizedProperties : public IUnknown
+{
+ /// <summary>
+ /// Gets localized product-specific properties.
+ /// </summary>
+ /// <param name="ppLocalizedProperties">A pointer to an instance of <see cref="ISetupLocalizedPropertyStore"/>. This may be NULL if no properties are defined.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetLocalizedProperties)(
+ _Outptr_result_maybenull_ ISetupLocalizedPropertyStore** ppLocalizedProperties
+ ) = 0;
+
+ /// <summary>
+ /// Gets localized channel-specific properties.
+ /// </summary>
+ /// <param name="ppLocalizedChannelProperties">A pointer to an instance of <see cref="ISetupLocalizedPropertyStore"/>. This may be NULL if no channel properties are defined.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetLocalizedChannelProperties)(
+ _Outptr_result_maybenull_ ISetupLocalizedPropertyStore** ppLocalizedChannelProperties
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_IEnumSetupInstances;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// An enumerator of installed <see cref="ISetupInstance"/> objects.
+/// </summary>
+struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848") DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown
+{
+ /// <summary>
+ /// Retrieves the next set of product instances in the enumeration sequence.
+ /// </summary>
+ /// <param name="celt">The number of product instances to retrieve.</param>
+ /// <param name="rgelt">A pointer to an array of <see cref="ISetupInstance"/>.</param>
+ /// <param name="pceltFetched">A pointer to the number of product instances retrieved. If <paramref name="celt"/> is 1 this parameter may be NULL.</param>
+ /// <returns>S_OK if the number of elements were fetched, S_FALSE if nothing was fetched (at end of enumeration), E_INVALIDARG if <paramref name="celt"/> is greater than 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an <see cref="ISetupInstance"/> could not be allocated.</returns>
+ STDMETHOD(Next)(
+ _In_ ULONG celt,
+ _Out_writes_to_(celt, *pceltFetched) ISetupInstance** rgelt,
+ _Out_opt_ _Deref_out_range_(0, celt) ULONG* pceltFetched
+ ) = 0;
+
+ /// <summary>
+ /// Skips the next set of product instances in the enumeration sequence.
+ /// </summary>
+ /// <param name="celt">The number of product instances to skip.</param>
+ /// <returns>S_OK if the number of elements could be skipped; otherwise, S_FALSE;</returns>
+ STDMETHOD(Skip)(
+ _In_ ULONG celt
+ ) = 0;
+
+ /// <summary>
+ /// Resets the enumeration sequence to the beginning.
+ /// </summary>
+ /// <returns>Always returns S_OK;</returns>
+ STDMETHOD(Reset)(void) = 0;
+
+ /// <summary>
+ /// Creates a new enumeration object in the same state as the current enumeration object: the new object points to the same place in the enumeration sequence.
+ /// </summary>
+ /// <param name="ppenum">A pointer to a pointer to a new <see cref="IEnumSetupInstances"/> interface. If the method fails, this parameter is undefined.</param>
+ /// <returns>S_OK if a clone was returned; otherwise, E_OUTOFMEMORY.</returns>
+ STDMETHOD(Clone)(
+ _Deref_out_opt_ IEnumSetupInstances** ppenum
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupConfiguration;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Gets information about product instances installed on the machine.
+/// </summary>
+struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B") DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown
+{
+ /// <summary>
+ /// Enumerates all launchable product instances installed.
+ /// </summary>
+ /// <param name="ppEnumInstances">An enumeration of completed, installed product instances.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(EnumInstances)(
+ _Out_ IEnumSetupInstances** ppEnumInstances
+ ) = 0;
+
+ /// <summary>
+ /// Gets the instance for the current process path.
+ /// </summary>
+ /// <param name="ppInstance">The instance for the current process path.</param>
+ /// <returns>
+ /// The instance for the current process path, or E_NOTFOUND if not found.
+ /// The <see cref="ISetupInstance::GetState"/> may indicate the instance is invalid.
+ /// </returns>
+ /// <remarks>
+ /// The returned instance may not be launchable.
+ /// </remarks>
+STDMETHOD(GetInstanceForCurrentProcess)(
+ _Out_ ISetupInstance** ppInstance
+ ) = 0;
+
+ /// <summary>
+ /// Gets the instance for the given path.
+ /// </summary>
+ /// <param name="ppInstance">The instance for the given path.</param>
+ /// <returns>
+ /// The instance for the given path, or E_NOTFOUND if not found.
+ /// The <see cref="ISetupInstance::GetState"/> may indicate the instance is invalid.
+ /// </returns>
+ /// <remarks>
+ /// The returned instance may not be launchable.
+ /// </remarks>
+STDMETHOD(GetInstanceForPath)(
+ _In_z_ LPCWSTR wzPath,
+ _Out_ ISetupInstance** ppInstance
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupConfiguration2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Gets information about product instances.
+/// </summary>
+struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D") DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration
+{
+ /// <summary>
+ /// Enumerates all product instances.
+ /// </summary>
+ /// <param name="ppEnumInstances">An enumeration of all product instances.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(EnumAllInstances)(
+ _Out_ IEnumSetupInstances** ppEnumInstances
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupPackageReference;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a package.
+/// </summary>
+struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5") DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown
+{
+ /// <summary>
+ /// Gets the general package identifier.
+ /// </summary>
+ /// <param name="pbstrId">The general package identifier.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetId)(
+ _Out_ BSTR* pbstrId
+ ) = 0;
+
+ /// <summary>
+ /// Gets the version of the package.
+ /// </summary>
+ /// <param name="pbstrVersion">The version of the package.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetVersion)(
+ _Out_ BSTR* pbstrVersion
+ ) = 0;
+
+ /// <summary>
+ /// Gets the target process architecture of the package.
+ /// </summary>
+ /// <param name="pbstrChip">The target process architecture of the package.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetChip)(
+ _Out_ BSTR* pbstrChip
+ ) = 0;
+
+ /// <summary>
+ /// Gets the language and optional region identifier.
+ /// </summary>
+ /// <param name="pbstrLanguage">The language and optional region identifier.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetLanguage)(
+ _Out_ BSTR* pbstrLanguage
+ ) = 0;
+
+ /// <summary>
+ /// Gets the build branch of the package.
+ /// </summary>
+ /// <param name="pbstrBranch">The build branch of the package.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetBranch)(
+ _Out_ BSTR* pbstrBranch
+ ) = 0;
+
+ /// <summary>
+ /// Gets the type of the package.
+ /// </summary>
+ /// <param name="pbstrType">The type of the package.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetType)(
+ _Out_ BSTR* pbstrType
+ ) = 0;
+
+ /// <summary>
+ /// Gets the unique identifier consisting of all defined tokens.
+ /// </summary>
+ /// <param name="pbstrUniqueId">The unique identifier consisting of all defined tokens.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_UNEXPECTED if no Id was defined (required).</returns>
+ STDMETHOD(GetUniqueId)(
+ _Out_ BSTR* pbstrUniqueId
+ ) = 0;
+
+ /// <summary>
+ /// Gets a value indicating whether the package refers to an external extension.
+ /// </summary>
+ /// <param name="pfIsExtension">A value indicating whether the package refers to an external extension.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_UNEXPECTED if no Id was defined (required).</returns>
+ STDMETHOD(GetIsExtension)(
+ _Out_ VARIANT_BOOL* pfIsExtension
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupProductReference;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a product package.
+/// </summary>
+struct DECLSPEC_UUID("a170b5ef-223d-492b-b2d4-945032980685") DECLSPEC_NOVTABLE ISetupProductReference : public ISetupPackageReference
+{
+ /// <summary>
+ /// Gets a value indicating whether the product package is installed.
+ /// </summary>
+ /// <param name="pfIsInstalled">A value indicating whether the product package is installed.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_NOTSUPPORTED if the reference is not to a product, or E_UNEXPECTED if the Installed property is the wrong type.</returns>
+ STDMETHOD(GetIsInstalled)(
+ _Out_ VARIANT_BOOL* pfIsInstalled
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupProductReference2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a product package.
+/// </summary>
+struct DECLSPEC_UUID("279a5db3-7503-444b-b34d-308f961b9a06") DECLSPEC_NOVTABLE ISetupProductReference2 : public ISetupProductReference
+{
+ /// <summary>
+ /// Gets a value indicating whether the product supports extensions.
+ /// </summary>
+ /// <param name="pfSupportsExtensions">A value indicating whether the product supports extensions.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_NOTSUPPORTED if the reference is not to a product, or E_UNEXPECTED if the SupportsExtensions property is the wrong type.</returns>
+ STDMETHOD(GetSupportsExtensions)(
+ _Out_ VARIANT_BOOL* pfSupportsExtensions
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupHelper;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Helper functions.
+/// </summary>
+/// <remarks>
+/// You can query for this interface from the <see cref="SetupConfiguration"/> class.
+/// </remarks>
+struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c") DECLSPEC_NOVTABLE ISetupHelper : public IUnknown
+{
+ /// <summary>
+ /// Parses a dotted quad version string into a 64-bit unsigned integer.
+ /// </summary>
+ /// <param name="pwszVersion">The dotted quad version string to parse, e.g. 1.2.3.4.</param>
+ /// <param name="pullVersion">A 64-bit unsigned integer representing the version. You can compare this to other versions.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_INVALIDARG if the version is not valid.</returns>
+ STDMETHOD(ParseVersion)(
+ _In_ LPCOLESTR pwszVersion,
+ _Out_ PULONGLONG pullVersion
+ ) = 0;
+
+ /// <summary>
+ /// Parses a dotted quad version string into a 64-bit unsigned integer.
+ /// </summary>
+ /// <param name="pwszVersionRange">The string containing 1 or 2 dotted quad version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer.</param>
+ /// <param name="pullMinVersion">A 64-bit unsigned integer representing the minimum version, which may be 0. You can compare this to other versions.</param>
+ /// <param name="pullMaxVersion">A 64-bit unsigned integer representing the maximum version, which may be MAXULONGLONG. You can compare this to other versions.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_INVALIDARG if the version range is not valid.</returns>
+ STDMETHOD(ParseVersionRange)(
+ _In_ LPCOLESTR pwszVersionRange,
+ _Out_ PULONGLONG pullMinVersion,
+ _Out_ PULONGLONG pullMaxVersion
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupErrorInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about errors that occured during install of an instance.
+/// </summary>
+/// <remarks>
+/// Objects may also implement <see cref="IErrorInfo"/> and <see cref="ISetupPropertyStore"/>.
+/// </remarks>
+struct DECLSPEC_UUID("2A2F3292-958E-4905-B36E-013BE84E27AB") DECLSPEC_NOVTABLE ISetupErrorInfo : public IUnknown
+{
+ /// <summary>
+ /// Gets the HRESULT of the error.
+ /// </summary>
+ /// <param name="plHResult">The HRESULT of the error.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetErrorHResult)(
+ _Out_ HRESULT* plHResult
+ ) = 0;
+
+ /// <summary>
+ /// Gets the class name of the error (exception).
+ /// </summary>
+ /// <param name="pbstrClassName">The class name of the error (exception).</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetErrorClassName)(
+ _Outptr_result_maybenull_ BSTR* pbstrClassName
+ ) = 0;
+
+ /// <summary>
+ /// Gets the error message.
+ /// </summary>
+ /// <param name="pbstrMessage">The error message.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetErrorMessage)(
+ _Outptr_result_maybenull_ BSTR* pbstrMessage
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupErrorState;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about the error state of an instance.
+/// </summary>
+struct DECLSPEC_UUID("46DCCD94-A287-476A-851E-DFBC2FFDBC20") DECLSPEC_NOVTABLE ISetupErrorState : public IUnknown
+{
+ /// <summary>
+ /// Gets an array of failed package references.
+ /// </summary>
+ /// <param name="ppsaPackages">Pointer to an array of <see cref="ISetupFailedPackageReference"/>, if packages have failed.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetFailedPackages)(
+ _Outptr_result_maybenull_ LPSAFEARRAY* ppsaFailedPackages
+ ) = 0;
+
+ /// <summary>
+ /// Gets an array of skipped package references.
+ /// </summary>
+ /// <param name="ppsaPackages">Pointer to an array of <see cref="ISetupPackageReference"/>, if packages have been skipped.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetSkippedPackages)(
+ _Outptr_result_maybenull_ LPSAFEARRAY* ppsaSkippedPackages
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupErrorState2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about the error state of an instance.
+/// </summary>
+struct DECLSPEC_UUID("9871385B-CA69-48F2-BC1F-7A37CBF0B1EF") DECLSPEC_NOVTABLE ISetupErrorState2 : public ISetupErrorState
+{
+ /// <summary>
+ /// Gets the path to the error log.
+ /// </summary>
+ /// <param name="pbstrChip">The path to the error log.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetErrorLogFilePath)(
+ _Outptr_result_maybenull_ BSTR* pbstrErrorLogFilePath
+ ) = 0;
+
+ /// <summary>
+ /// Gets the path to the main setup log.
+ /// </summary>
+ /// <param name="pbstrChip">The path to the main setup log.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetLogFilePath)(
+ _Outptr_result_maybenull_ BSTR* pbstrLogFilePath
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupErrorState3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Information about the error state of an instance.
+/// </summary>
+struct DECLSPEC_UUID("290019AD-28E2-46D5-9DE5-DA4B6BCF8057") DECLSPEC_NOVTABLE ISetupErrorState3 : public ISetupErrorState2
+{
+ /// <summary>
+ /// Gets the runtime error that occured during install of an instance.
+ /// </summary>
+ /// <param name="pbstrChip">The runtime error that occured during install of an instance.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetRuntimeError)(
+ _Outptr_result_maybenull_ ISetupErrorInfo** ppErrorInfo
+ ) = 0;
+};
+#endif
+
+EXTERN_C const IID IID_ISetupFailedPackageReference;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a failed package.
+/// </summary>
+struct DECLSPEC_UUID("E73559CD-7003-4022-B134-27DC650B280F") DECLSPEC_NOVTABLE ISetupFailedPackageReference : public ISetupPackageReference
+{
+};
+
+#endif
+
+EXTERN_C const IID IID_ISetupFailedPackageReference2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a failed package.
+/// </summary>
+struct DECLSPEC_UUID("0FAD873E-E874-42E3-B268-4FE2F096B9CA") DECLSPEC_NOVTABLE ISetupFailedPackageReference2 : public ISetupFailedPackageReference
+{
+ /// <summary>
+ /// Gets the path to the optional package log.
+ /// </summary>
+ /// <param name="pbstrId">The path to the optional package log.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetLogFilePath)(
+ _Outptr_result_maybenull_ BSTR* pbstrLogFilePath
+ ) = 0;
+
+ /// <summary>
+ /// Gets the description of the package failure.
+ /// </summary>
+ /// <param name="pbstrId">The description of the package failure.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetDescription)(
+ _Outptr_result_maybenull_ BSTR* pbstrDescription
+ ) = 0;
+
+ /// <summary>
+ /// Gets the signature to use for feedback reporting.
+ /// </summary>
+ /// <param name="pbstrId">The signature to use for feedback reporting.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetSignature)(
+ _Outptr_result_maybenull_ BSTR* pbstrSignature
+ ) = 0;
+
+ /// <summary>
+ /// Gets the array of details for this package failure.
+ /// </summary>
+ /// <param name="ppsaDetails">Pointer to an array of details as BSTRs.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetDetails)(
+ _Out_ LPSAFEARRAY* ppsaDetails
+ ) = 0;
+
+ /// <summary>
+ /// Gets an array of packages affected by this package failure.
+ /// </summary>
+ /// <param name="ppsaPackages">Pointer to an array of <see cref="ISetupPackageReference"/> for packages affected by this package failure. This may be NULL.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetAffectedPackages)(
+ _Out_ LPSAFEARRAY* ppsaAffectedPackages
+ ) = 0;
+};
+
+#endif
+
+EXTERN_C const IID IID_ISetupFailedPackageReference3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// A reference to a failed package.
+/// </summary>
+struct DECLSPEC_UUID("EBC3AE68-AD15-44E8-8377-39DBF0316F6C") DECLSPEC_NOVTABLE ISetupFailedPackageReference3 : public ISetupFailedPackageReference2
+{
+ /// <summary>
+ /// Gets the action attempted when the package failed.
+ /// </summary>
+ /// <param name="pbstrAction">The action, eg: Install, Download, etc.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetAction)(
+ _Outptr_result_maybenull_ BSTR* pbstrAction
+ ) = 0;
+
+ /// <summary>
+ /// Gets the return code of the failure.
+ /// </summary>
+ /// <param name="pbstrReturnCode">The return code.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetReturnCode)(
+ _Outptr_result_maybenull_ BSTR* pbstrReturnCode
+ ) = 0;
+};
+
+#endif
+
+EXTERN_C const IID IID_ISetupPropertyStore;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Provides named properties.
+/// </summary>
+/// <remarks>
+/// You can get this from an <see cref="ISetupInstance"/>, <see cref="ISetupPackageReference"/>, or derivative.
+/// </remarks>
+struct DECLSPEC_UUID("C601C175-A3BE-44BC-91F6-4568D230FC83") DECLSPEC_NOVTABLE ISetupPropertyStore : public IUnknown
+{
+ /// <summary>
+ /// Gets an array of property names in this property store.
+ /// </summary>
+ /// <param name="ppsaNames">Pointer to an array of property names as BSTRs.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetNames)(
+ _Out_ LPSAFEARRAY* ppsaNames
+ ) = 0;
+
+ /// <summary>
+ /// Gets the value of a named property in this property store.
+ /// </summary>
+ /// <param name="pwszName">The name of the property to get.</param>
+ /// <param name="pvtValue">The value of the property.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_NOTFOUND if the property is not defined or E_NOTSUPPORTED if the property type is not supported.</returns>
+ STDMETHOD(GetValue)(
+ _In_ LPCOLESTR pwszName,
+ _Out_ LPVARIANT pvtValue
+ ) = 0;
+};
+
+#endif
+
+EXTERN_C const IID IID_ISetupLocalizedPropertyStore;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Provides localized named properties.
+/// </summary>
+/// <remarks>
+/// You can get this from an <see cref="ISetupLocalizedProperties"/>.
+/// </remarks>
+struct DECLSPEC_UUID("5BB53126-E0D5-43DF-80F1-6B161E5C6F6C") DECLSPEC_NOVTABLE ISetupLocalizedPropertyStore : public IUnknown
+{
+ /// <summary>
+ /// Gets an array of property names in this property store.
+ /// </summary>
+ /// <param name="lcid">The LCID for the property names.</param>
+ /// <param name="ppsaNames">Pointer to an array of property names as BSTRs.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetNames)(
+ _In_ LCID lcid,
+ _Out_ LPSAFEARRAY* ppsaNames
+ ) = 0;
+
+ /// <summary>
+ /// Gets the value of a named property in this property store.
+ /// </summary>
+ /// <param name="pwszName">The name of the property to get.</param>
+ /// <param name="lcid">The LCID for the property.</param>
+ /// <param name="pvtValue">The value of the property.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_NOTFOUND if the property is not defined or E_NOTSUPPORTED if the property type is not supported.</returns>
+ STDMETHOD(GetValue)(
+ _In_ LPCOLESTR pwszName,
+ _In_ LCID lcid,
+ _Out_ LPVARIANT pvtValue
+ ) = 0;
+};
+
+#endif
+
+EXTERN_C const IID IID_ISetupPolicy;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+/// <summary>
+/// Gets setup policy values.
+/// </summary>
+/// <remarks>
+/// You can get this from an <see cref="ISetupConfiguration"/>.
+/// </remarks>
+struct DECLSPEC_UUID("E1DA4CBD-64C4-4C44-821D-98FAB64C4DA7") DECLSPEC_NOVTABLE ISetupPolicy : public IUnknown
+{
+ /// <summary>
+ /// Gets the value of the SharedInstallationPath policy.
+ /// </summary>
+ /// <param name="pbstrSharedInstallationPath">The value of the SharedInstallationPath policy.</param>
+ /// <returns>Standard HRESULT indicating success or failure.</returns>
+ STDMETHOD(GetSharedInstallationPath)(
+ _Out_ BSTR* pbstrSharedInstallationPath
+ ) = 0;
+
+ /// <summary>
+ /// Gets the value of a named policy.
+ /// </summary>
+ /// <param name="pwszName">The name of the policy to get.</param>
+ /// <param name="pvtValue">The value of the named policy.</param>
+ /// <returns>Standard HRESULT indicating success or failure, including E_NOTSUPPORTED if the policy is not supported by this implementation.</returns>
+ STDMETHOD(GetValue)(
+ _In_ LPCOLESTR pwszName,
+ _Out_ LPVARIANT pvtValue
+ ) = 0;
+};
+
+#endif
+
+// Class declarations
+//
+EXTERN_C const CLSID CLSID_SetupConfiguration;
+
+#ifdef __cplusplus
+/// <summary>
+/// This class implements <see cref="ISetupConfiguration"/>, <see cref="ISetupConfiguration2"/>, and <see cref="ISetupHelper"/>.
+/// </summary>
+class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration;
+#endif
+
+// Function declarations
+//
+/// <summary>
+/// Gets an <see cref="ISetupConfiguration"/> that provides information about product instances installed on the machine.
+/// </summary>
+/// <param name="ppConfiguration">The <see cref="ISetupConfiguration"/> that provides information about product instances installed on the machine.</param>
+/// <param name="pReserved">Reserved for future use.</param>
+/// <returns>Standard HRESULT indicating success or failure.</returns>
+STDMETHODIMP GetSetupConfiguration(
+ _Out_ ISetupConfiguration** ppConfiguration,
+ _Reserved_ LPVOID pReserved
+);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libbuild2/utility-installed.cxx b/libbuild2/utility-installed.cxx
index 9135c21..c8f08b6 100644
--- a/libbuild2/utility-installed.cxx
+++ b/libbuild2/utility-installed.cxx
@@ -2,7 +2,7 @@
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
-// Bootstrap build is never condidered installed.
+// Bootstrap build is never considered installed.
//
#ifndef BUILD2_BOOTSTRAP
diff --git a/libbuild2/utility.cxx b/libbuild2/utility.cxx
index d6a32ab..10e2380 100644
--- a/libbuild2/utility.cxx
+++ b/libbuild2/utility.cxx
@@ -308,10 +308,10 @@ namespace build2
}
void
- hash_options (sha256& csum, const lookup& l)
+ append_options (sha256& csum, const lookup& l)
{
if (l)
- hash_options (csum, cast<strings> (l));
+ append_options (csum, cast<strings> (l));
}
void
@@ -345,7 +345,7 @@ namespace build2
}
void
- hash_options (sha256& csum, const strings& sv, size_t n)
+ append_options (sha256& csum, const strings& sv, size_t n)
{
for (size_t i (0); i != n; ++i)
csum.append (sv[i]);
diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx
index 980c31f..956d213 100644
--- a/libbuild2/utility.hxx
+++ b/libbuild2/utility.hxx
@@ -515,11 +515,11 @@ namespace build2
template <typename T>
void
- hash_options (sha256&, T&, const variable&);
+ append_options (sha256&, T&, const variable&);
template <typename T>
void
- hash_options (sha256&, T&, const char*);
+ append_options (sha256&, T&, const char*);
// As above but from the strings value directly.
//
@@ -533,7 +533,7 @@ namespace build2
append_options (strings&, const lookup&, const char* excl = nullptr);
LIBBUILD2_SYMEXPORT void
- hash_options (sha256&, const lookup&);
+ append_options (sha256&, const lookup&);
void
append_options (cstrings&, const strings&, const char* excl = nullptr);
@@ -542,7 +542,7 @@ namespace build2
append_options (strings&, const strings&, const char* excl = nullptr);
void
- hash_options (sha256&, const strings&);
+ append_options (sha256&, const strings&);
LIBBUILD2_SYMEXPORT void
append_options (cstrings&,
@@ -555,7 +555,7 @@ namespace build2
const char* excl = nullptr);
LIBBUILD2_SYMEXPORT void
- hash_options (sha256&, const strings&, size_t);
+ append_options (sha256&, const strings&, size_t);
// As above but append/hash option values for the specified option (e.g.,
// -I, -L).
@@ -569,10 +569,10 @@ namespace build2
template <typename I, typename F>
void
- hash_option_values (sha256&,
- const char* opt,
- I begin, I end,
- F&& get = [] (const string& s) {return s;});
+ append_option_values (sha256&,
+ const char* opt,
+ I begin, I end,
+ F&& get = [] (const string& s) {return s;});
// Check if a specified option is present in the variable or value. T is
// either target or scope.
diff --git a/libbuild2/utility.ixx b/libbuild2/utility.ixx
index 8d3f6ba..dcfd128 100644
--- a/libbuild2/utility.ixx
+++ b/libbuild2/utility.ixx
@@ -38,9 +38,9 @@ namespace build2
template <typename T>
inline void
- hash_options (sha256& csum, T& s, const variable& var)
+ append_options (sha256& csum, T& s, const variable& var)
{
- hash_options (csum, s[var]);
+ append_options (csum, s[var]);
}
template <typename T>
@@ -59,9 +59,9 @@ namespace build2
template <typename T>
inline void
- hash_options (sha256& csum, T& s, const char* var)
+ append_options (sha256& csum, T& s, const char* var)
{
- hash_options (csum, s[var]);
+ append_options (csum, s[var]);
}
inline void
@@ -79,10 +79,10 @@ namespace build2
}
inline void
- hash_options (sha256& csum, const strings& sv)
+ append_options (sha256& csum, const strings& sv)
{
if (size_t n = sv.size ())
- hash_options (csum, sv, n);
+ append_options (csum, sv, n);
}
template <typename T>
diff --git a/libbuild2/utility.txx b/libbuild2/utility.txx
index a91cb15..c183930 100644
--- a/libbuild2/utility.txx
+++ b/libbuild2/utility.txx
@@ -22,7 +22,7 @@ namespace build2
template <typename I, typename F>
void
- hash_option_values (sha256& cs, const char* o, I b, I e, F&& get)
+ append_option_values (sha256& cs, const char* o, I b, I e, F&& get)
{
for (; b != e; ++b)
{
diff --git a/tests/bash/testscript b/tests/bash/testscript
index 6a9bf1d..fd6fc05 100644
--- a/tests/bash/testscript
+++ b/tests/bash/testscript
@@ -7,7 +7,7 @@
: dummy
:
if ($test.target == $build.host && $build.host.class != 'windows')
- {
+{
buildfile = true
test.arguments =