| Index: tools/gn/target.cc
|
| diff --git a/tools/gn/target.cc b/tools/gn/target.cc
|
| index f5bdd585cd09bdd5c97c28f4313b1c9e6c4f1985..74c98db3a1b789aba2856205726a218475c1e01c 100644
|
| --- a/tools/gn/target.cc
|
| +++ b/tools/gn/target.cc
|
| @@ -39,12 +39,40 @@ void MergeAllDependentConfigsFrom(const Target* from_target,
|
| }
|
| }
|
|
|
| +Err MakeTestOnlyError(const Target* from, const Target* to) {
|
| + return Err(from->defined_from(), "Test-only dependency not allowed.",
|
| + from->label().GetUserVisibleName(false) + "\n"
|
| + "which is NOT marked testonly can't depend on\n" +
|
| + to->label().GetUserVisibleName(false) + "\n"
|
| + "which is marked testonly. Only targets with \"testonly = true\"\n"
|
| + "can depend on other test-only targets.\n"
|
| + "\n"
|
| + "Either mark it test-only or don't do this dependency.");
|
| +}
|
| +
|
| +// Inserts the given groups dependencies, starting at the given index of the
|
| +// given vector. Returns the number of items inserted.
|
| +size_t InsertGroupDeps(LabelTargetVector* vector,
|
| + size_t insert_at,
|
| + const Target* group) {
|
| + const LabelTargetVector& deps = group->deps();
|
| + vector->insert(vector->begin() + insert_at, deps.begin(), deps.end());
|
| +
|
| + // Clear the origin of each of the insertions. This marks these dependencies
|
| + // as internally generated.
|
| + for (size_t i = insert_at; i < deps.size() + insert_at; i++)
|
| + (*vector)[i].origin = NULL;
|
| +
|
| + return deps.size();
|
| +}
|
| +
|
| } // namespace
|
|
|
| Target::Target(const Settings* settings, const Label& label)
|
| : Item(settings, label),
|
| output_type_(UNKNOWN),
|
| all_headers_public_(true),
|
| + testonly_(false),
|
| hard_dep_(false),
|
| toolchain_(NULL) {
|
| }
|
| @@ -86,22 +114,11 @@ const Target* Target::AsTarget() const {
|
| return this;
|
| }
|
|
|
| -void Target::OnResolved() {
|
| +bool Target::OnResolved(Err* err) {
|
| DCHECK(output_type_ != UNKNOWN);
|
| DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
|
|
|
| - // Convert any groups we depend on to just direct dependencies on that
|
| - // group's deps. We insert the new deps immediately after the group so that
|
| - // the ordering is preserved. We need to keep the original group so that any
|
| - // flags, etc. that it specifies itself are applied to us.
|
| - for (size_t i = 0; i < deps_.size(); i++) {
|
| - const Target* dep = deps_[i].ptr;
|
| - if (dep->output_type_ == GROUP) {
|
| - // TODO(brettw) bug 403488 this should also handle datadeps.
|
| - deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end());
|
| - i += dep->deps_.size();
|
| - }
|
| - }
|
| + ExpandGroups();
|
|
|
| // Copy our own dependent configs to the list of configs applying to us.
|
| configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
|
| @@ -129,6 +146,13 @@ void Target::OnResolved() {
|
| PullRecursiveHardDeps();
|
|
|
| FillOutputFiles();
|
| +
|
| + if (!CheckVisibility(err))
|
| + return false;
|
| + if (!CheckTestonly(err))
|
| + return false;
|
| +
|
| + return true;
|
| }
|
|
|
| bool Target::IsLinkable() const {
|
| @@ -182,6 +206,19 @@ bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
|
| return false;
|
| }
|
|
|
| +void Target::ExpandGroups() {
|
| + // Convert any groups we depend on to just direct dependencies on that
|
| + // group's deps. We insert the new deps immediately after the group so that
|
| + // the ordering is preserved. We need to keep the original group so that any
|
| + // flags, etc. that it specifies itself are applied to us.
|
| + // TODO(brettw) bug 403488 this should also handle datadeps.
|
| + for (size_t i = 0; i < deps_.size(); i++) {
|
| + const Target* dep = deps_[i].ptr;
|
| + if (dep->output_type_ == GROUP)
|
| + i += InsertGroupDeps(&deps_, i + 1, dep);
|
| + }
|
| +}
|
| +
|
| void Target::PullDependentTargetInfo() {
|
| // Gather info from our dependents we need.
|
| for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) {
|
| @@ -305,3 +342,48 @@ void Target::FillOutputFiles() {
|
| NOTREACHED();
|
| }
|
| }
|
| +
|
| +bool Target::CheckVisibility(Err* err) const {
|
| + // Only check visibility when the origin of the dependency is non-null. These
|
| + // are dependencies added by the GN files. Internally added dependencies
|
| + // (expanded groups) will have a null origin. We don't want to check
|
| + // visibility for these, since the point of a group would often be to
|
| + // forward visibility.
|
| + for (size_t i = 0; i < deps_.size(); i++) {
|
| + if (deps_[i].origin &&
|
| + !Visibility::CheckItemVisibility(this, deps_[i].ptr, err))
|
| + return false;
|
| + }
|
| +
|
| + for (size_t i = 0; i < datadeps_.size(); i++) {
|
| + if (deps_[i].origin &&
|
| + !Visibility::CheckItemVisibility(this, datadeps_[i].ptr, err))
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool Target::CheckTestonly(Err* err) const {
|
| + // If there current target is marked testonly, it can include both testonly
|
| + // and non-testonly targets, so there's nothing to check.
|
| + if (testonly())
|
| + return true;
|
| +
|
| + // Verify no deps have "testonly" set.
|
| + for (size_t i = 0; i < deps_.size(); i++) {
|
| + if (deps_[i].ptr->testonly()) {
|
| + *err = MakeTestOnlyError(this, deps_[i].ptr);
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + for (size_t i = 0; i < datadeps_.size(); i++) {
|
| + if (datadeps_[i].ptr->testonly()) {
|
| + *err = MakeTestOnlyError(this, datadeps_[i].ptr);
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
|
|