blob: 6de7099cb1a4c5f022801ad39920709f7d1874f9 [file] [log] [blame]
// Copyright 2018 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lib/vc_execreq_normalizer.h"
#include "glog/logging.h"
#include "lib/clang_flags_helper.h"
#include "lib/vc_flags.h"
using std::string;
namespace devtools_goma {
ConfigurableExecReqNormalizer::Config VCExecReqNormalizer::Configure(
int id,
const std::vector<string>& args,
bool normalize_include_path,
bool is_linking,
const std::vector<string>& normalize_weak_relative_for_arg,
const std::map<string, string>& debug_prefix_map,
const ExecReq* req) const {
int keep_cwd = kOmit;
int keep_args = kNormalizeWithCwd;
int keep_pathnames_in_input = kNormalizeWithCwd;
int keep_system_include_dirs = kNormalizeWithCwd;
if (normalize_weak_relative_for_arg.empty()) {
keep_args |= kAsIs;
if (!normalize_include_path) {
keep_system_include_dirs |= kAsIs;
// TODO: check what is good for linking.
if (is_linking) {
// We preserve anything for linking but we may omit file contents.
keep_cwd |= kAsIs;
keep_args |= kAsIs;
keep_pathnames_in_input |= kAsIs;
keep_system_include_dirs |= kAsIs;
bool is_clang_cl = VCFlags::IsClangClCommand(req->command_spec().name());
FlagParser flag_parser;
FlagParser::Flag* flag_z7 = flag_parser.AddBoolFlag("Z7");
FlagParser::Flag* flag_zi = flag_parser.AddBoolFlag("Zi");
FlagParser::Flag* flag_zI = flag_parser.AddBoolFlag("ZI");
FlagParser::Flag* flag_fprofile_instr_generate =
FlagParser::Flag* flag_fcoverage_mapping =
FlagParser::Flag* flag_fc = flag_parser.AddBoolFlag("FC");
FlagParser::Flag* flag_fdiagnostics_absolute_paths =
FlagParser::Flag* flag_show_include = flag_parser.AddBoolFlag("showIncludes");
if (flag_show_include->seen()) {
// /showInclude outputs path as-is. So we need to preserve input path.
keep_pathnames_in_input |= kAsIs;
if (!is_clang_cl) {
// cl.exe seems to output pathname in absolute path even if include dir is
// given in relative form, but a file is included from the same directory
// of including file.
// We don't know a file is included from the same directory or include
// directory. So always set keep_cwd for cl.exe here.
keep_cwd |= kAsIs;
if (flag_fc->seen() || flag_fdiagnostics_absolute_paths->seen()) {
// With this option, full input path would be shown in
// stdout (/showIncludes) or stderr (compile error). We must preserve cwd
// paths.
// Currently (2018/06/19), clang-cl ignores /FC option, but it may change
// behavior. So keep cwd with /FC in clang-cl case too.
// This flag has higher priority than -fdebug-compilation-dir.
keep_cwd |= kAsIs;
absl::optional<string> fdebug_compilation_dir;
if (is_clang_cl && !(keep_cwd & kAsIs)) {
ClangFlagsHelper clang_flags_helper(args);
fdebug_compilation_dir = clang_flags_helper.fdebug_compilation_dir();
if (flag_z7->seen() || flag_zi->seen() || flag_zI->seen()) {
// If debug info option is set, we must keep args, pathnames,
// system include dirs as-is.
// But we can replace cwd when fdebug-compilation-dir is set.
if (!fdebug_compilation_dir) {
keep_cwd |= kAsIs;
keep_args |= kAsIs;
keep_pathnames_in_input |= kAsIs;
keep_system_include_dirs |= kAsIs;
if (is_clang_cl && flag_fprofile_instr_generate->seen() &&
flag_fcoverage_mapping->seen()) {
keep_cwd |= kAsIs;
keep_pathnames_in_input |= kAsIs;
// TODO: Currently the logic of keep_args is assuming args can be
// parsed with GCCFlags. Parsing command line for cl.exe (or clang-cl.exe)
// with GCCFlags is always wrong.
// Don't normalize args for cl.exe and clang-cl.exe until the code
// has fixed. Fortunately, absolute path won't appear in chrome build.
// So, the result of normalize won't change.
keep_args |= kAsIs;
Config config;
config.keep_cwd = keep_cwd;
config.keep_args = keep_args;
config.keep_pathnames_in_input = keep_pathnames_in_input;
config.keep_system_include_dirs = keep_system_include_dirs;
config.new_cwd = std::move(fdebug_compilation_dir);
// Dropping pathnames can generate same hash from different input.
CHECK(!(config.keep_pathnames_in_input & kOmit));
return config;
} // namespace devtools_goma