aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/cpp/AbstractCcLinkParamsStore.java
blob: 2849d55e0caa0a1146cc0e84e373d1d06bcce31c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.rules.cpp;

import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;

/**
 * A cache of C link parameters.
 *
 * <p>The cache holds instances of {@link com.google.devtools.build.lib.rules.cpp.CcLinkParams} for
 * combinations of linkingStatically and linkShared. If a requested value is not available in the
 * cache, it is computed and then stored.
 *
 * <p>Typically this class is used on targets that may be linked in as C libraries as in the
 * following example:
 *
 * <pre>
 * class SomeTarget implements CcLinkParamsStore {
 *   private final AbstractCcLinkParamsStore ccLinkParamsStore = new AbstractCcLinkParamsStore() {
 *     @Override
 *     protected void collect(CcLinkParams.Builder builder, boolean linkingStatically,
 *                            boolean linkShared) {
 *       builder.add[...]
 *     }
 *   };
 *
 *   @Override
 *   public CcLinkParams getCcLinkParams(boolean linkingStatically, boolean linkShared) {
 *     return ccLinkParamsStore.get(linkingStatically, linkShared);
 *   }
 * }
 * </pre>
 */
public abstract class AbstractCcLinkParamsStore {
  protected CcLinkParams staticSharedParams;
  protected CcLinkParams staticNoSharedParams;
  protected CcLinkParams noStaticSharedParams;
  protected CcLinkParams noStaticNoSharedParams;

  private CcLinkParams compute(boolean linkingStatically, boolean linkShared) {
    CcLinkParams.Builder builder = CcLinkParams.builder(linkingStatically, linkShared);
    collect(builder, linkingStatically, linkShared);
    return builder.build();
  }

  /**
   * Returns {@link com.google.devtools.build.lib.rules.cpp.CcLinkParams} for a combination of
   * parameters.
   *
   * <p>The {@link com.google.devtools.build.lib.rules.cpp.CcLinkParams} instance is computed lazily
   * and cached.
   */
  public synchronized CcLinkParams get(boolean linkingStatically, boolean linkShared) {
    CcLinkParams result = lookup(linkingStatically, linkShared);
    if (result == null) {
      result = compute(linkingStatically, linkShared);
      put(linkingStatically, linkShared, result);
    }
    return result;
  }

  private CcLinkParams lookup(boolean linkingStatically, boolean linkShared) {
    if (linkingStatically) {
      return linkShared ? staticSharedParams : staticNoSharedParams;
    } else {
      return linkShared ? noStaticSharedParams : noStaticNoSharedParams;
    }
  }

  private void put(boolean linkingStatically, boolean linkShared, CcLinkParams params) {
    Preconditions.checkNotNull(params);
    if (linkingStatically) {
      if (linkShared) {
        staticSharedParams = params;
      } else {
        staticNoSharedParams = params;
      }
    } else {
      if (linkShared) {
        noStaticSharedParams = params;
      } else {
        noStaticNoSharedParams = params;
      }
    }
  }

  /**
   * Hook for building the actual link params.
   *
   * <p>Users should override this method and call methods of the builder to
   * set up the actual CcLinkParams objects.
   *
   * <p>Implementations of this method must not fail or try to report errors on the
   * configured target.
   */
  protected abstract void collect(CcLinkParams.Builder builder, boolean linkingStatically,
                                  boolean linkShared);

  @AutoCodec
  @VisibleForSerialization
  static class EmptyCcLinkParamsStore extends AbstractCcLinkParamsStore {
    public static final ObjectCodec<EmptyCcLinkParamsStore> CODEC =
        new AbstractCcLinkParamsStore_EmptyCcLinkParamsStore_AutoCodec();

    @Override
    protected void collect(
        CcLinkParams.Builder builder, boolean linkingStatically, boolean linkShared) {}
  }

  /** An empty CcLinkParamStore. */
  public static final AbstractCcLinkParamsStore EMPTY = new EmptyCcLinkParamsStore();
}