1""" CC Link ActionConfigs for ld64.lld """
2
3load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
4load(
5    "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
6    "action_config",
7    "flag_group",
8    "flag_set",
9    "tool",
10    "variable_with_value",
11    "with_feature_set",
12)
13
14BAZEL_LINK_FLAG_SET = flag_set(
15    flag_groups = [
16        flag_group(
17            flags = ["%{linkstamp_paths}"],
18            iterate_over = "linkstamp_paths",
19            expand_if_available = "linkstamp_paths",
20        ),
21        flag_group(
22            iterate_over = "runtime_library_search_directories",
23            flag_groups = [
24                flag_group(
25                    flags = [
26                        "-Xlinker",
27                        "-rpath",
28                        "-Xlinker",
29                        "$ORIGIN/%{runtime_library_search_directories}",
30                    ],
31                ),
32            ],
33            expand_if_available =
34                "runtime_library_search_directories",
35        ),
36        flag_group(
37            flags = ["-L%{library_search_directories}"],
38            iterate_over = "library_search_directories",
39            expand_if_available = "library_search_directories",
40        ),
41        flag_group(
42            iterate_over = "libraries_to_link",
43            flag_groups = [
44                flag_group(
45                    flags = ["--start-lib"],
46                    expand_if_equal = variable_with_value(
47                        name = "libraries_to_link.type",
48                        value = "object_file_group",
49                    ),
50                ),
51                flag_group(
52                    flags = ["-whole-archive"],
53                    expand_if_true =
54                        "libraries_to_link.is_whole_archive",
55                ),
56                flag_group(
57                    flags = ["%{libraries_to_link.object_files}"],
58                    iterate_over = "libraries_to_link.object_files",
59                    expand_if_equal = variable_with_value(
60                        name = "libraries_to_link.type",
61                        value = "object_file_group",
62                    ),
63                ),
64                flag_group(
65                    flags = ["%{libraries_to_link.name}"],
66                    expand_if_equal = variable_with_value(
67                        name = "libraries_to_link.type",
68                        value = "object_file",
69                    ),
70                ),
71                flag_group(
72                    flags = ["%{libraries_to_link.name}"],
73                    expand_if_equal = variable_with_value(
74                        name = "libraries_to_link.type",
75                        value = "interface_library",
76                    ),
77                ),
78                flag_group(
79                    flags = ["%{libraries_to_link.name}"],
80                    expand_if_equal = variable_with_value(
81                        name = "libraries_to_link.type",
82                        value = "static_library",
83                    ),
84                ),
85                flag_group(
86                    flags = ["-l%{libraries_to_link.name}"],
87                    expand_if_equal = variable_with_value(
88                        name = "libraries_to_link.type",
89                        value = "dynamic_library",
90                    ),
91                ),
92                flag_group(
93                    flags = ["-l:%{libraries_to_link.name}"],
94                    expand_if_equal = variable_with_value(
95                        name = "libraries_to_link.type",
96                        value = "versioned_dynamic_library",
97                    ),
98                ),
99                flag_group(
100                    flags = ["-no-whole-archive"],
101                    expand_if_true = "libraries_to_link.is_whole_archive",
102                ),
103                flag_group(
104                    flags = ["--end-lib"],
105                    expand_if_equal = variable_with_value(
106                        name = "libraries_to_link.type",
107                        value = "object_file_group",
108                    ),
109                ),
110            ],
111            expand_if_available = "libraries_to_link",
112        ),
113        flag_group(
114            flags = ["@%{thinlto_param_file}"],
115            expand_if_true = "thinlto_param_file",
116        ),
117        flag_group(
118            flags = ["%{user_link_flags}"],
119            iterate_over = "user_link_flags",
120            expand_if_available = "user_link_flags",
121        ),
122        flag_group(
123            flags = ["-o", "%{output_execpath}"],
124            expand_if_available = "output_execpath",
125        ),
126    ],
127)
128
129def link_action_configs(
130        llvm,
131        builtin_library_directories,
132        builtin_libraries,
133        builtin_framework_directories,
134        builtin_frameworks,
135        builtin_executable_objects,
136        link_flags,
137        dbg_link_flags,
138        fastbuild_link_flags,
139        opt_link_flags):
140    """
141    Generates CC Link ActionConfigs
142
143    Args:
144        llvm (string): Path to LLVM binaries.
145        builtin_library_directories (List): List of library directories to always be passed to the linker.
146        builtin_libraries (List): List of libraries to always be passed to the linker.
147        builtin_framework_directories (List): List of Apple framework directories to always be passed to the linker.
148        builtin_frameworks (List): List of Apple frameworks to always be passed to the linker.
149        builtin_executable_objects (List): List of object files to always be passed to the linker.
150        link_flags (List): List of flags to always be passed to the linker.
151        dbg_link_flags (List): List of additional flags to always be passed to the linker in dbg configuration.
152        fastbuild_link_flags (List): List of additional flags to always be passed to the linker in fastbuild configuration.
153        opt_link_flags (List): List of additional flags to always be passed to the linker in opt configuration.
154
155    Returns:
156        List of CC Link ActionConfigs
157    """
158
159    builtin_library_directory_link_flags = []
160    for builtin_library_directory in builtin_library_directories:
161        builtin_library_directory_link_flags.append("-L")
162        builtin_library_directory_link_flags.append(builtin_library_directory)
163
164    builtin_library_link_flags = []
165    for builtin_library in builtin_libraries:
166        builtin_library_link_flags.append("-l{}".format(builtin_library))
167
168    builtin_framework_directory_link_flags = []
169    for builtin_framework_directory in builtin_framework_directories:
170        builtin_framework_directory_link_flags.append("-F")
171        builtin_framework_directory_link_flags.append(builtin_framework_directory)
172
173    builtin_framework_link_flags = []
174    for builtin_framework in builtin_frameworks:
175        builtin_framework_link_flags.append("-framework")
176        builtin_framework_link_flags.append(builtin_framework)
177
178    builtin_executable_objects_link_flags = []
179    for builtin_executable_object in builtin_executable_objects:
180        builtin_executable_objects_link_flags.append("-l{}".format(builtin_executable_object))
181
182    required_link_flags = (builtin_library_directory_link_flags +
183                           builtin_library_link_flags +
184                           builtin_framework_directory_link_flags +
185                           builtin_framework_link_flags)
186    required_link_flag_set = flag_set(
187        flag_groups = ([
188            flag_group(flags = required_link_flags),
189        ] if required_link_flags else []),
190    )
191
192    required_executable_link_flags = (builtin_executable_objects_link_flags)
193    required_executable_link_flag_set = flag_set(
194        flag_groups = ([
195            flag_group(flags = required_executable_link_flags),
196        ] if required_executable_link_flags else []),
197    )
198
199    link_flag_set = flag_set(
200        flag_groups = ([
201            flag_group(flags = link_flags),
202        ] if link_flags else []),
203    )
204
205    dbg_link_flag_set = flag_set(
206        flag_groups = ([
207            flag_group(flags = dbg_link_flags),
208        ] if dbg_link_flags else []),
209        with_features = [with_feature_set(features = ["dbg"])],
210    )
211
212    fastbuild_link_flag_set = flag_set(
213        flag_groups = ([
214            flag_group(flags = fastbuild_link_flags),
215        ] if fastbuild_link_flags else []),
216        with_features = [with_feature_set(features = ["fastbuild"])],
217    )
218
219    opt_link_flag_set = flag_set(
220        flag_groups = ([
221            flag_group(flags = opt_link_flags),
222        ] if opt_link_flags else []),
223        with_features = [with_feature_set(features = ["opt"])],
224    )
225
226    return [
227        action_config(
228            action_name = ACTION_NAMES.cpp_link_dynamic_library,
229            tools = [tool(path = "{}/bin/ld64.lld".format(llvm))],
230            flag_sets = [
231                # Mandatory, no link flags come through on command line.
232                flag_set(
233                    flag_groups = [
234                        flag_group(
235                            flags = ["@%{linker_param_file}"],
236                            expand_if_available = "linker_param_file",
237                        ),
238                    ],
239                ),
240                required_link_flag_set,
241                link_flag_set,
242                dbg_link_flag_set,
243                fastbuild_link_flag_set,
244                opt_link_flag_set,
245                BAZEL_LINK_FLAG_SET,
246                flag_set(
247                    flag_groups = [
248                        flag_group(
249                            flags = ["-dylib"],
250                        ),
251                    ],
252                ),
253            ],
254        ),
255        action_config(
256            action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library,
257            tools = [tool(path = "{}/bin/ld64.lld".format(llvm))],
258            flag_sets = [
259                # Mandatory, no link flags come through on command line.
260                flag_set(
261                    flag_groups = [
262                        flag_group(
263                            flags = ["@%{linker_param_file}"],
264                            expand_if_available = "linker_param_file",
265                        ),
266                    ],
267                ),
268                required_link_flag_set,
269                link_flag_set,
270                dbg_link_flag_set,
271                fastbuild_link_flag_set,
272                opt_link_flag_set,
273                BAZEL_LINK_FLAG_SET,
274                flag_set(
275                    flag_groups = [
276                        flag_group(
277                            flags = ["-dylib"],
278                        ),
279                    ],
280                ),
281            ],
282        ),
283        action_config(
284            action_name = ACTION_NAMES.cpp_link_executable,
285            tools = [tool(path = "{}/bin/ld64.lld".format(llvm))],
286            flag_sets = [
287                # Mandatory, no link flags come through on command line.
288                flag_set(
289                    flag_groups = [
290                        flag_group(
291                            flags = ["@%{linker_param_file}"],
292                            expand_if_available = "linker_param_file",
293                        ),
294                    ],
295                ),
296                required_link_flag_set,
297                required_executable_link_flag_set,
298                link_flag_set,
299                dbg_link_flag_set,
300                fastbuild_link_flag_set,
301                opt_link_flag_set,
302                BAZEL_LINK_FLAG_SET,
303            ],
304        ),
305    ]
306