Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 81aede1

Browse files
meteorcloudykatre
authored andcommitted
Reimplement whole archive on Windows
Use wrapper script to get object files if /WHOLEARCHIVE is not supported. fix bazelbuild#1978 work towards bazelbuild#1918 -- Change-Id: I675311478e65a1e1f3fa963187a5a8da531150d3 Reviewed-on: https://bazel-review.googlesource.com/#/c/6833 MOS_MIGRATED_REVID=137151817
1 parent ca99bb7 commit 81aede1

5 files changed

Lines changed: 259 additions & 0 deletions

File tree

src/test/shell/bazel/bazel_windows_example_test.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,48 @@ function test_cpp() {
6060
assert_test_fails "//examples/cpp:hello-fail_test"
6161
}
6262

63+
function test_cpp_alwayslink() {
64+
mkdir -p cpp/main
65+
cat >cpp/main/BUILD <<EOF
66+
cc_library(
67+
name = "lib",
68+
srcs = ["lib.cc"],
69+
alwayslink = 1,
70+
)
71+
cc_library(
72+
name = "main",
73+
srcs = ["main.cc"],
74+
)
75+
cc_binary(
76+
name = "bin",
77+
deps = [":main", ":lib"],
78+
)
79+
EOF
80+
81+
cat >cpp/main/lib.cc <<EOF
82+
extern int global_variable;
83+
int init() {
84+
++global_variable;
85+
return global_variable;
86+
}
87+
int x = init();
88+
int y = init();
89+
EOF
90+
91+
cat >cpp/main/main.cc <<EOF
92+
#include<stdio.h>
93+
int global_variable = 0;
94+
int main(void) {
95+
printf("global : %d\n", global_variable);
96+
return 0;
97+
}
98+
EOF
99+
assert_build //cpp/main:bin
100+
./bazel-bin/cpp/main/bin >& $TEST_log \
101+
|| fail "//cpp/main:bin execution failed"
102+
expect_log "global : 2"
103+
}
104+
63105
function test_java() {
64106
local java_pkg=examples/java-native/src/main/java/com/example/myproject
65107

tools/cpp/CROSSTOOL.tpl

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,176 @@ toolchain {
293293
}
294294
}
295295

296+
action_config {
297+
config_name: 'c++-link-executable'
298+
action_name: 'c++-link-executable'
299+
tool {
300+
tool_path: 'wrapper/bin/msvc_link.bat'
301+
}
302+
implies: 'linkstamps'
303+
implies: 'output_execpath_flags'
304+
implies: 'input_param_flags'
305+
implies: 'global_whole_archive'
306+
}
307+
308+
action_config {
309+
config_name: 'c++-link-dynamic-library'
310+
action_name: 'c++-link-dynamic-library'
311+
tool {
312+
tool_path: 'wrapper/bin/msvc_link.bat'
313+
}
314+
implies: 'shared_flag'
315+
implies: 'linkstamps'
316+
implies: 'output_execpath_flags'
317+
implies: 'input_param_flags'
318+
implies: 'global_whole_archive'
319+
implies: 'has_configured_linker_path'
320+
}
321+
322+
action_config {
323+
config_name: 'c++-link-static-library'
324+
action_name: 'c++-link-static-library'
325+
tool {
326+
tool_path: 'wrapper/bin/msvc_link.bat'
327+
}
328+
implies: 'input_param_flags'
329+
implies: 'global_whole_archive'
330+
}
331+
332+
action_config {
333+
config_name: 'c++-link-alwayslink-static-library'
334+
action_name: 'c++-link-alwayslink-static-library'
335+
tool {
336+
tool_path: 'wrapper/bin/msvc_link.bat'
337+
}
338+
implies: 'input_param_flags'
339+
implies: 'global_whole_archive'
340+
}
341+
342+
# TODO(pcloudy): The following action_config is listed in MANDATORY_LINK_TARGET_TYPES.
343+
# But do we really need them on Windows?
344+
action_config {
345+
config_name: 'c++-link-pic-static-library'
346+
action_name: 'c++-link-pic-static-library'
347+
tool {
348+
tool_path: 'wrapper/bin/msvc_link.bat'
349+
}
350+
implies: 'input_param_flags'
351+
implies: 'global_whole_archive'
352+
}
353+
354+
action_config {
355+
config_name: 'c++-link-alwayslink-pic-static-library'
356+
action_name: 'c++-link-alwayslink-pic-static-library'
357+
tool {
358+
tool_path: 'wrapper/bin/msvc_link.bat'
359+
}
360+
implies: 'input_param_flags'
361+
implies: 'global_whole_archive'
362+
}
363+
364+
action_config {
365+
config_name: 'c++-link-interface-dynamic-library'
366+
action_name: 'c++-link-interface-dynamic-library'
367+
tool {
368+
tool_path: 'wrapper/bin/msvc_link.bat'
369+
}
370+
}
371+
372+
feature {
373+
name: 'has_configured_linker_path'
374+
}
375+
376+
feature {
377+
name: 'shared_flag'
378+
flag_set {
379+
action: 'c++-link-dynamic-library'
380+
flag_group {
381+
flag: '/DLL'
382+
}
383+
}
384+
}
385+
386+
feature {
387+
name: 'linkstamps'
388+
flag_set {
389+
action: 'c++-link-executable'
390+
action: 'c++-link-dynamic-library'
391+
expand_if_all_available: 'linkstamp_paths'
392+
flag_group {
393+
flag: '%{linkstamp_paths}'
394+
}
395+
}
396+
}
397+
398+
feature {
399+
name: 'output_execpath_flags'
400+
flag_set {
401+
expand_if_all_available: 'output_execpath'
402+
action: 'c++-link-executable'
403+
action: 'c++-link-dynamic-library'
404+
flag_group {
405+
flag: '/OUT:%{output_execpath}'
406+
}
407+
}
408+
}
409+
410+
feature {
411+
name: 'input_param_flags'
412+
flag_set {
413+
expand_if_all_available: 'libopts'
414+
action: 'c++-link-executable'
415+
action: 'c++-link-dynamic-library'
416+
action: 'c++-link-static-library'
417+
action: 'c++-link-alwayslink-static-library'
418+
action: 'c++-link-pic-static-library'
419+
action: 'c++-link-alwayslink-pic-static-library'
420+
flag_group {
421+
flag: '%{libopts}'
422+
}
423+
}
424+
flag_set {
425+
expand_if_all_available: 'whole_archive_linker_params'
426+
action: 'c++-link-executable'
427+
action: 'c++-link-dynamic-library'
428+
action: 'c++-link-static-library'
429+
action: 'c++-link-alwayslink-static-library'
430+
action: 'c++-link-pic-static-library'
431+
action: 'c++-link-alwayslink-pic-static-library'
432+
flag_group {
433+
flag: '/WHOLEARCHIVE:%{whole_archive_linker_params}'
434+
}
435+
}
436+
flag_set {
437+
expand_if_all_available: 'linker_input_params'
438+
action: 'c++-link-executable'
439+
action: 'c++-link-dynamic-library'
440+
action: 'c++-link-static-library'
441+
action: 'c++-link-alwayslink-static-library'
442+
action: 'c++-link-pic-static-library'
443+
action: 'c++-link-alwayslink-pic-static-library'
444+
flag_group {
445+
flag: '%{linker_input_params}'
446+
}
447+
}
448+
}
449+
450+
feature {
451+
name: 'global_whole_archive'
452+
flag_set {
453+
expand_if_all_available: 'global_whole_archive'
454+
action: 'c++-link-executable'
455+
action: 'c++-link-dynamic-library'
456+
action: 'c++-link-static-library'
457+
action: 'c++-link-alwayslink-static-library'
458+
action: 'c++-link-pic-static-library'
459+
action: 'c++-link-alwayslink-pic-static-library'
460+
flag_group {
461+
flag: '/WHOLEARCHIVE'
462+
}
463+
}
464+
}
465+
296466
compilation_mode_flags {
297467
mode: DBG
298468
compiler_flag: "/DDEBUG=1"

tools/cpp/cc_configure.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@ def _find_env_vars(repository_ctx, vs_path):
428428
return env_map
429429

430430

431+
def _is_support_whole_archive(repository_ctx, vs_dir):
432+
"""Run MSVC linker alone to see if it supports /WHOLEARCHIVE."""
433+
result = _execute(repository_ctx, [vs_dir + "/VC/BIN/amd64/link"])
434+
return result.find("/WHOLEARCHIVE") != -1
435+
436+
431437
def _tpl(repository_ctx, tpl, substitutions={}, out=None):
432438
if not out:
433439
out = tpl
@@ -476,12 +482,19 @@ def _impl(repository_ctx):
476482
python_dir = python_binary[0:-10].replace("\\", "\\\\")
477483
include_paths = env["INCLUDE"] + (python_dir + "include")
478484
lib_paths = env["LIB"] + (python_dir + "libs")
485+
lib_tool = vs_path + "/VC/bin/amd64/lib.exe"
486+
if _is_support_whole_archive(repository_ctx, vs_path):
487+
support_whole_archive = "True"
488+
else:
489+
support_whole_archive = "False"
479490
tmp_dir = _get_env_var(repository_ctx, "TMP", "C:\\Windows\\Temp")
480491
_tpl(repository_ctx, "wrapper/bin/pydir/msvc_tools.py", {
481492
"%{tmp}": tmp_dir.replace("\\", "\\\\"),
482493
"%{path}": env["PATH"],
483494
"%{include}": include_paths,
484495
"%{lib}": lib_paths,
496+
"%{lib_tool}": lib_tool,
497+
"%{support_whole_archive}": support_whole_archive
485498
})
486499

487500
cxx_include_directories = []

tools/cpp/wrapper/bin/pydir/msvc_link.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ def Run(self, argv):
6868
# Build argument list.
6969
parser = msvc_tools.ArgParser(self, argv, LINKPATTERNS)
7070

71+
# Preprocessing arguments for linking whole archive libraries
72+
parser.WholeArchivePreprocess()
73+
7174
# Find the output file name.
7275
name = ''
7376
for arg in parser.options:

tools/cpp/wrapper/bin/pydir/msvc_tools.py.tpl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ TMP_PATH = '%{tmp}'
3131
PATH = "%{path}"
3232
INCLUDE = "%{include}"
3333
LIB = "%{lib}"
34+
LIB_TOOL = "%{lib_tool}"
3435

3536
class Error(Exception):
3637
"""Base class for all script-specific errors."""
@@ -52,8 +53,38 @@ class ArgParser(object):
5253
self.deps_file = None
5354
self.output_file = None
5455
self.params_file = None
56+
self.support_whole_archive = %{support_whole_archive}
57+
self.need_global_whole_archive = None
5558
self._ParseArgs(argv)
5659

60+
def ReplaceLibrary(self, arg):
61+
"""Do the actual replacement if necessary."""
62+
if arg == "/WHOLEARCHIVE":
63+
return []
64+
if arg.startswith("/OUT:") or os.path.splitext(arg)[1] not in ['.a', '.lo']:
65+
return [arg]
66+
if self.global_whole_archive or arg.startswith("/WHOLEARCHIVE:"):
67+
if arg.startswith("/WHOLEARCHIVE:"):
68+
arg = arg[len("/WHOLEARCHIVE:"):]
69+
output = subprocess.check_output([LIB_TOOL, "/list", arg]).decode("utf-8")
70+
object_files = []
71+
for line in output.split("\n"):
72+
line = line.strip()
73+
if line.endswith(".o"):
74+
object_files.append(line)
75+
return object_files
76+
return [arg]
77+
78+
def WholeArchivePreprocess(self):
79+
"""Replace library file with object files if /WHOLEARCHIVE is not supported."""
80+
if self.support_whole_archive:
81+
return
82+
options = []
83+
self.global_whole_archive = "/WHOLEARCHIVE" in self.options
84+
for arg in self.options:
85+
options.extend(self.ReplaceLibrary(arg))
86+
self.options = options
87+
5788
def _MatchOneArg(self, args):
5889
"""Finds a pattern which matches the beginning elements of args.
5990

0 commit comments

Comments
 (0)