Skip to content

Commit e80ce8d

Browse files
committed
Make cc_library(alwayslink=True) apply to .a in srcs
Previously if you had an archive in the srcs of a cc_library and set alwayslink=True that was ignored. You had to have named the library .lo (arguably an implementation detail) to get the desired behavior.
1 parent 9ed3609 commit e80ce8d

File tree

6 files changed

+161
-3
lines changed

6 files changed

+161
-3
lines changed

cc/private/rules_impl/cc_library.bzl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ def _cc_library_impl(ctx):
194194
feature_configuration,
195195
ctx.fragments.cpp.force_pic(),
196196
precompiled_files,
197+
ctx.attr.alwayslink,
197198
)
198199

199200
if not cc_helper.is_compilation_outputs_empty(compilation_outputs):
@@ -373,7 +374,8 @@ def _convert_precompiled_libraries_to_library_to_link(
373374
cc_toolchain,
374375
feature_configuration,
375376
force_pic,
376-
precompiled_files):
377+
precompiled_files,
378+
alwayslink):
377379
static_libraries = _build_map_identifier_to_artifact(precompiled_files[2])
378380
pic_static_libraries = _build_map_identifier_to_artifact(precompiled_files[3])
379381
alwayslink_static_libraries = _build_map_identifier_to_artifact(precompiled_files[4])
@@ -413,7 +415,7 @@ def _convert_precompiled_libraries_to_library_to_link(
413415
static_library = static_library,
414416
pic_static_library = pic_static_library,
415417
dynamic_library = dynamic_library,
416-
alwayslink = identifier in alwayslink_static_libraries,
418+
alwayslink = alwayslink or identifier in alwayslink_static_libraries,
417419
)
418420
libraries.append(library)
419421

@@ -435,7 +437,7 @@ def _convert_precompiled_libraries_to_library_to_link(
435437
feature_configuration = feature_configuration,
436438
cc_toolchain = cc_toolchain,
437439
pic_static_library = pic_static_library,
438-
alwayslink = identifier in alwayslink_static_libraries,
440+
alwayslink = alwayslink or identifier in alwayslink_static_libraries,
439441
)
440442
libraries.append(library)
441443

tests/alwayslink_srcs/BUILD

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright 2026 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
load("//cc:cc_library.bzl", "cc_library")
16+
load("//cc:cc_test.bzl", "cc_test")
17+
18+
licenses(["notice"])
19+
20+
# Library that provides the registration state (was_registered/set_registered).
21+
cc_library(
22+
name = "registered",
23+
srcs = ["registered.c"],
24+
hdrs = ["registered.h"],
25+
)
26+
27+
# Library that registers itself via a static constructor.
28+
cc_library(
29+
name = "registerer_lib",
30+
srcs = ["registerer.c"],
31+
deps = [":registered"],
32+
)
33+
34+
# Copy the .a file produced by registerer_lib, simulates having a prebuilt .a file.
35+
genrule(
36+
name = "copy_registerer_archive",
37+
srcs = [":registerer_lib"],
38+
outs = ["libregisterer_copied.a"],
39+
cmd = "for f in $(locations :registerer_lib); do if [[ $$f == *.a ]]; then cp $$f $@; fi; done",
40+
)
41+
42+
# Library that uses the copied .a file in srcs with alwayslink=True.
43+
# Without alwayslink, the registerer would be dropped since nothing
44+
# directly references its symbols.
45+
cc_library(
46+
name = "registerer_alwayslink",
47+
srcs = [":copy_registerer_archive"],
48+
deps = [":registered"],
49+
alwayslink = True,
50+
)
51+
52+
# Test that verifies the symbol was loaded at runtime.
53+
# The test does not directly reference any symbol from registerer,
54+
# so without alwayslink the static constructor would not run.
55+
cc_test(
56+
name = "alwayslink_test",
57+
srcs = ["alwayslink_test.c"],
58+
deps = [
59+
":registered",
60+
":registerer_alwayslink",
61+
],
62+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2026 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <stdio.h>
16+
17+
#include "tests/alwayslink_srcs/registered.h"
18+
19+
int main(void) {
20+
// If alwayslink worked correctly, the registerer library should have been
21+
// linked even though nothing directly references its symbols. The static
22+
// constructor should have called set_registered().
23+
if (!was_registered()) {
24+
fprintf(stderr, "FAILED: alwayslink did not work - static constructor was not executed\n");
25+
return 1;
26+
}
27+
printf("PASSED: alwayslink worked - static constructor was executed\n");
28+
return 0;
29+
}

tests/alwayslink_srcs/registered.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2026 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "tests/alwayslink_srcs/registered.h"
16+
17+
static int g_registered = 0;
18+
19+
int was_registered(void) { return g_registered; }
20+
21+
void set_registered(void) { g_registered = 1; }

tests/alwayslink_srcs/registered.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2026 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef TESTS_ALWAYSLINK_SRCS_REGISTERED_H_
16+
#define TESTS_ALWAYSLINK_SRCS_REGISTERED_H_
17+
18+
// Returns 1 if the registerer constructor was executed.
19+
int was_registered(void);
20+
21+
// Called by the registerer's constructor.
22+
void set_registered(void);
23+
24+
#endif // TESTS_ALWAYSLINK_SRCS_REGISTERED_H_

tests/alwayslink_srcs/registerer.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2026 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "tests/alwayslink_srcs/registered.h"
16+
17+
// Static constructor that registers on load.
18+
__attribute__((constructor)) static void registerer_init(void) {
19+
set_registered();
20+
}

0 commit comments

Comments
 (0)