1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "tools/gn/substitution_type.h"
6
7#include <stdlib.h>
8
9#include "tools/gn/err.h"
10
11const char* kSubstitutionNames[SUBSTITUTION_NUM_TYPES] = {
12  "<<literal>>",  // SUBSTITUTION_LITERAL
13
14  "{{source}}",  // SUBSTITUTION_SOURCE
15  "{{output}}",  // SUBSTITUTION_OUTPUT
16
17  "{{source_name_part}}",  // SUBSTITUTION_NAME_PART
18  "{{source_file_part}}",  // SUBSTITUTION_FILE_PART
19  "{{source_dir}}",  // SUBSTITUTION_SOURCE_DIR
20  "{{source_root_relative_dir}}",  // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR
21  "{{source_gen_dir}}",  // SUBSTITUTION_SOURCE_GEN_DIR
22  "{{source_out_dir}}",  // SUBSTITUTION_SOURCE_OUT_DIR
23
24  "{{label}}",  // SUBSTITUTION_LABEL
25  "{{root_gen_dir}}",  // SUBSTITUTION_ROOT_GEN_DIR
26  "{{root_out_dir}}",  // SUBSTITUTION_ROOT_OUT_DIR
27  "{{target_gen_dir}}",  // SUBSTITUTION_TARGET_GEN_DIR
28  "{{target_out_dir}}",  // SUBSTITUTION_TARGET_OUT_DIR
29  "{{target_output_name}}",  // SUBSTITUTION_TARGET_OUTPUT_NAME
30
31  "{{cflags}}",  // SUBSTITUTION_CFLAGS
32  "{{cflags_c}}",  // SUBSTITUTION_CFLAGS_C
33  "{{cflags_cc}}",  // SUBSTITUTION_CFLAGS_CC
34  "{{cflags_objc}}",  // SUBSTITUTION_CFLAGS_OBJC
35  "{{cflags_objcc}}",  // SUBSTITUTION_CFLAGS_OBJCC
36  "{{defines}}",  // SUBSTITUTION_DEFINES
37  "{{include_dirs}}",  // SUBSTITUTION_INCLUDE_DIRS
38
39  "{{inputs}}",  // SUBSTITUTION_LINKER_INPUTS
40  "{{inputs_newline}}",  // SUBSTITUTION_LINKER_INPUTS_NEWLINE
41  "{{ldflags}}",  // SUBSTITUTION_LDFLAGS
42  "{{libs}}",  // SUBSTITUTION_LIBS
43  "{{output_extension}}",  // SUBSTITUTION_OUTPUT_EXTENSION
44  "{{solibs}}",  // SUBSTITUTION_SOLIBS
45};
46
47const char* kSubstitutionNinjaNames[SUBSTITUTION_NUM_TYPES] = {
48  NULL,  // SUBSTITUTION_LITERAL
49
50  "in",  // SUBSTITUTION_SOURCE
51  "out",  // SUBSTITUTION_OUTPUT
52
53  "source_name_part",  // SUBSTITUTION_NAME_PART
54  "source_file_part",  // SUBSTITUTION_FILE_PART
55  "source_dir",  // SUBSTITUTION_SOURCE_DIR
56  "source_root_relative_dir",  // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR
57  "source_gen_dir",  // SUBSTITUTION_SOURCE_GEN_DIR
58  "source_out_dir",  // SUBSTITUTION_SOURCE_OUT_DIR
59
60  "label",  // SUBSTITUTION_LABEL
61  "root_gen_dir",  // SUBSTITUTION_ROOT_GEN_DIR
62  "root_out_dir",  // SUBSTITUTION_ROOT_OUT_DIR
63  "target_gen_dir",  // SUBSTITUTION_TARGET_GEN_DIR
64  "target_out_dir",  // SUBSTITUTION_TARGET_OUT_DIR
65  "target_output_name",  // SUBSTITUTION_TARGET_OUTPUT_NAME
66
67  "cflags",  // SUBSTITUTION_CFLAGS
68  "cflags_c",  // SUBSTITUTION_CFLAGS_C
69  "cflags_cc",  // SUBSTITUTION_CFLAGS_CC
70  "cflags_objc",  // SUBSTITUTION_CFLAGS_OBJC
71  "cflags_objcc",  // SUBSTITUTION_CFLAGS_OBJCC
72  "defines",  // SUBSTITUTION_DEFINES
73  "include_dirs",  // SUBSTITUTION_INCLUDE_DIRS
74
75  // LINKER_INPUTS expands to the same Ninja var as SUBSTITUTION_SOURCE. These
76  // are used in different contexts and are named differently to keep things
77  // clear, but they both expand to the "set of input files" for a build rule.
78  "in",  // SUBSTITUTION_LINKER_INPUTS
79  "in_newline",  // SUBSTITUTION_LINKER_INPUTS_NEWLINE
80  "ldflags",  // SUBSTITUTION_LDFLAGS
81  "libs",  // SUBSTITUTION_LIBS
82  "output_extension",  // SUBSTITUTION_OUTPUT_EXTENSION
83  "solibs",  // SUBSTITUTION_SOLIBS
84};
85
86SubstitutionBits::SubstitutionBits() : used() {
87}
88
89void SubstitutionBits::MergeFrom(const SubstitutionBits& other) {
90  for (size_t i = 0; i < SUBSTITUTION_NUM_TYPES; i++)
91    used[i] |= other.used[i];
92}
93
94void SubstitutionBits::FillVector(std::vector<SubstitutionType>* vect) const {
95  for (size_t i = SUBSTITUTION_FIRST_PATTERN; i < SUBSTITUTION_NUM_TYPES; i++) {
96    if (used[i])
97      vect->push_back(static_cast<SubstitutionType>(i));
98  }
99}
100
101bool SubstitutionIsInOutputDir(SubstitutionType type) {
102  return type == SUBSTITUTION_SOURCE_GEN_DIR ||
103         type == SUBSTITUTION_SOURCE_OUT_DIR ||
104         type == SUBSTITUTION_ROOT_GEN_DIR ||
105         type == SUBSTITUTION_ROOT_OUT_DIR ||
106         type == SUBSTITUTION_TARGET_GEN_DIR ||
107         type == SUBSTITUTION_TARGET_OUT_DIR;
108}
109
110bool IsValidSourceSubstitution(SubstitutionType type) {
111  return type == SUBSTITUTION_LITERAL ||
112         type == SUBSTITUTION_SOURCE ||
113         type == SUBSTITUTION_SOURCE_NAME_PART ||
114         type == SUBSTITUTION_SOURCE_FILE_PART ||
115         type == SUBSTITUTION_SOURCE_DIR ||
116         type == SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR ||
117         type == SUBSTITUTION_SOURCE_GEN_DIR ||
118         type == SUBSTITUTION_SOURCE_OUT_DIR;
119}
120
121bool IsValidToolSubstutition(SubstitutionType type) {
122  return type == SUBSTITUTION_LITERAL ||
123         type == SUBSTITUTION_OUTPUT ||
124         type == SUBSTITUTION_LABEL ||
125         type == SUBSTITUTION_ROOT_GEN_DIR ||
126         type == SUBSTITUTION_ROOT_OUT_DIR ||
127         type == SUBSTITUTION_TARGET_GEN_DIR ||
128         type == SUBSTITUTION_TARGET_OUT_DIR ||
129         type == SUBSTITUTION_TARGET_OUTPUT_NAME;
130}
131
132bool IsValidCompilerSubstitution(SubstitutionType type) {
133  return IsValidToolSubstutition(type) ||
134         IsValidSourceSubstitution(type) ||
135         type == SUBSTITUTION_SOURCE ||
136         type == SUBSTITUTION_CFLAGS ||
137         type == SUBSTITUTION_CFLAGS_C ||
138         type == SUBSTITUTION_CFLAGS_CC ||
139         type == SUBSTITUTION_CFLAGS_OBJC ||
140         type == SUBSTITUTION_CFLAGS_OBJCC ||
141         type == SUBSTITUTION_DEFINES ||
142         type == SUBSTITUTION_INCLUDE_DIRS;
143}
144
145bool IsValidCompilerOutputsSubstitution(SubstitutionType type) {
146  // All tool types except "output" (which would be infinitely recursive).
147  return (IsValidToolSubstutition(type) && type != SUBSTITUTION_OUTPUT) ||
148         IsValidSourceSubstitution(type);
149}
150
151bool IsValidLinkerSubstitution(SubstitutionType type) {
152  return IsValidToolSubstutition(type) ||
153         type == SUBSTITUTION_LINKER_INPUTS ||
154         type == SUBSTITUTION_LINKER_INPUTS_NEWLINE ||
155         type == SUBSTITUTION_LDFLAGS ||
156         type == SUBSTITUTION_LIBS ||
157         type == SUBSTITUTION_OUTPUT_EXTENSION ||
158         type == SUBSTITUTION_SOLIBS;
159}
160
161bool IsValidLinkerOutputsSubstitution(SubstitutionType type) {
162  // All valid compiler outputs plus the output extension.
163  return IsValidCompilerOutputsSubstitution(type) ||
164         type == SUBSTITUTION_OUTPUT_EXTENSION;
165}
166
167bool IsValidCopySubstitution(SubstitutionType type) {
168  return IsValidToolSubstutition(type) ||
169         type == SUBSTITUTION_SOURCE;
170}
171
172bool EnsureValidSourcesSubstitutions(
173    const std::vector<SubstitutionType>& types,
174    const ParseNode* origin,
175    Err* err) {
176  for (size_t i = 0; i < types.size(); i++) {
177    if (!IsValidSourceSubstitution(types[i])) {
178      *err = Err(origin, "Invalid substitution type.",
179          "The substitution " + std::string(kSubstitutionNames[i]) +
180          " isn't valid for something\n"
181          "operating on a source file such as this.");
182      return false;
183    }
184  }
185  return true;
186}
187