diff options
Diffstat (limited to 'libbuild2')
-rw-r--r-- | libbuild2/cc/buildfile | 10 | ||||
-rw-r--r-- | libbuild2/cc/compile-rule.cxx | 125 | ||||
-rw-r--r-- | libbuild2/cc/compile-rule.hxx | 14 | ||||
-rw-r--r-- | libbuild2/cc/guess.cxx | 645 | ||||
-rw-r--r-- | libbuild2/cc/link-rule.cxx | 16 | ||||
-rw-r--r-- | libbuild2/cc/link-rule.hxx | 8 | ||||
-rw-r--r-- | libbuild2/cc/msvc-setup.h | 1059 | ||||
-rw-r--r-- | libbuild2/utility-installed.cxx | 2 | ||||
-rw-r--r-- | libbuild2/utility.cxx | 6 | ||||
-rw-r--r-- | libbuild2/utility.hxx | 18 | ||||
-rw-r--r-- | libbuild2/utility.ixx | 12 | ||||
-rw-r--r-- | libbuild2/utility.txx | 2 |
12 files changed, 1715 insertions, 202 deletions
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) { |