diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-08-09 11:31:53 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-08-12 17:04:22 +0200 |
commit | 9fa5f73d00905568e8979d0c93ec4a8f645c81d5 (patch) | |
tree | f2bf937fa256c0ef2c9bbe05d3655d1985719405 /build2/cc/windows-manifest.cxx | |
parent | a1b2319ff2ddc8a6f139ee364cabe236ca62e23e (diff) |
Implement support for C compilation
We now have two new modules: cc (c-common) and c.
Diffstat (limited to 'build2/cc/windows-manifest.cxx')
-rw-r--r-- | build2/cc/windows-manifest.cxx | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/build2/cc/windows-manifest.cxx b/build2/cc/windows-manifest.cxx new file mode 100644 index 0000000..0666ef5 --- /dev/null +++ b/build2/cc/windows-manifest.cxx @@ -0,0 +1,136 @@ +// file : build2/cc/windows-manifest.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <build2/scope> +#include <build2/target> +#include <build2/context> +#include <build2/variable> +#include <build2/filesystem> +#include <build2/diagnostics> + +#include <build2/cc/link> + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace cc + { + // Translate the compiler target CPU value to the processorArchitecture + // attribute value. + // + const char* + windows_manifest_arch (const string& tcpu) + { + const char* pa (tcpu == "i386" || tcpu == "i686" ? "x86" : + tcpu == "x86_64" ? "amd64" : + nullptr); + + if (pa == nullptr) + fail << "unable to translate CPU " << tcpu << " to manifest " + << "processor architecture"; + + return pa; + } + + // Generate a Windows manifest and if necessary create/update the manifest + // file corresponding to the exe{} target. Return the manifest file path. + // + path link:: + windows_manifest (file& t, bool rpath_assembly) const + { + tracer trace (x, "windows_manifest"); + + scope& rs (t.root_scope ()); + + const char* pa (windows_manifest_arch (cast<string> (rs[x_target_cpu]))); + + string m; + + m += "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n"; + m += "<assembly xmlns='urn:schemas-microsoft-com:asm.v1'\n"; + m += " manifestVersion='1.0'>\n"; + + // Program name, version, etc. + // + string name (t.path ().leaf ().string ()); + + m += " <assemblyIdentity name='"; m += name; m += "'\n"; + m += " type='win32'\n"; + m += " processorArchitecture='"; m += pa; m += "'\n"; + m += " version='0.0.0.0'/>\n"; + + // Our rpath-emulating assembly. + // + if (rpath_assembly) + { + m += " <dependency>\n"; + m += " <dependentAssembly>\n"; + m += " <assemblyIdentity name='"; m += name; m += ".dlls'\n"; + m += " type='win32'\n"; + m += " processorArchitecture='"; m += pa; m += "'\n"; + m += " language='*'\n"; + m += " version='0.0.0.0'/>\n"; + m += " </dependentAssembly>\n"; + m += " </dependency>\n"; + } + + // UAC information. Without it Windows will try to guess, which, as you + // can imagine, doesn't end well. + // + m += " <trustInfo xmlns='urn:schemas-microsoft-com:asm.v3'>\n"; + m += " <security>\n"; + m += " <requestedPrivileges>\n"; + m += " <requestedExecutionLevel level='asInvoker' uiAccess='false'/>\n"; + m += " </requestedPrivileges>\n"; + m += " </security>\n"; + m += " </trustInfo>\n"; + + m += "</assembly>\n"; + + // If the manifest file exists, compare to its content. If nothing + // changed (common case), then we can avoid any further updates. + // + // The potentially faster alternative would be to hash it and store an + // entry in depdb. This, however, gets a bit complicated since we will + // need to avoid a race between the depdb and .manifest updates. + // + path mf (t.path () + ".manifest"); + + if (file_exists (mf)) + { + try + { + ifdstream ifs (mf); + string s; + getline (ifs, s, '\0'); + + if (s == m) + return mf; + } + catch (const ifdstream::failure&) + { + // Whatever the reason we failed for , let's rewrite the file. + } + } + + if (verb >= 3) + text << "cat >" << mf; + + try + { + ofdstream ofs (mf); + ofs << m; + ofs.close (); + } + catch (const ofdstream::failure& e) + { + fail << "unable to write to " << m << ": " << e.what (); + } + + return mf; + } + } +} |