2016-09-27 20:41:39 +02:00
|
|
|
# Copyright 2016 MongoDB Inc.
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
|
|
|
import SCons
|
|
|
|
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
|
2019-02-19 16:50:57 +01:00
|
|
|
|
2016-09-27 20:41:39 +02:00
|
|
|
def exists(env):
|
2020-01-07 19:48:42 +01:00
|
|
|
if not "AR" in env:
|
2016-09-27 20:41:39 +02:00
|
|
|
return False
|
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
ar = env.subst(env["AR"])
|
2016-09-27 20:41:39 +02:00
|
|
|
if not ar:
|
|
|
|
return False
|
|
|
|
|
|
|
|
# If the user has done anything confusing with ARFLAGS, bail out. We want to find
|
|
|
|
# an item in ARFLAGS of the exact form 'rc'.
|
2020-01-07 19:48:42 +01:00
|
|
|
if not "rc" in env["ARFLAGS"]:
|
2016-09-27 20:41:39 +02:00
|
|
|
return False
|
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
pipe = SCons.Action._subproc(
|
|
|
|
env,
|
|
|
|
SCons.Util.CLVar(ar) + ["--version"],
|
|
|
|
stdin="devnull",
|
|
|
|
stderr="devnull",
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
)
|
2016-09-27 20:41:39 +02:00
|
|
|
if pipe.wait() != 0:
|
|
|
|
return False
|
|
|
|
|
2018-07-01 23:15:13 +02:00
|
|
|
found = False
|
2016-09-27 20:41:39 +02:00
|
|
|
for line in pipe.stdout:
|
2018-07-01 23:15:13 +02:00
|
|
|
if found:
|
2016-09-27 20:41:39 +02:00
|
|
|
continue # consume all data
|
2020-01-07 19:48:42 +01:00
|
|
|
found = re.search(r"^GNU ar|^LLVM", line.decode("utf-8"))
|
2016-09-27 20:41:39 +02:00
|
|
|
|
2018-07-01 23:15:13 +02:00
|
|
|
return bool(found)
|
2016-09-27 20:41:39 +02:00
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
def _add_emitter(builder):
|
|
|
|
base_emitter = builder.emitter
|
2016-09-27 20:41:39 +02:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
def new_emitter(target, source, env):
|
|
|
|
for t in target:
|
|
|
|
setattr(t.attributes, "thin_archive", True)
|
|
|
|
return (target, source)
|
2016-09-27 20:41:39 +02:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
new_emitter = SCons.Builder.ListEmitter([base_emitter, new_emitter])
|
|
|
|
builder.emitter = new_emitter
|
2016-09-27 20:41:39 +02:00
|
|
|
|
2019-02-19 16:50:57 +01:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
def _add_scanner(builder):
|
|
|
|
old_scanner = builder.target_scanner
|
|
|
|
path_function = old_scanner.path_function
|
2017-05-25 14:22:58 +02:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
def new_scanner(node, env, path):
|
|
|
|
old_results = old_scanner(node, env, path)
|
2020-01-24 17:08:37 +01:00
|
|
|
|
|
|
|
# Ninja uses only timestamps for implicit dependencies so will
|
|
|
|
# always rebuild a program whose archive has been updated even
|
|
|
|
# if has the same content signature.
|
|
|
|
if env.get("GENERATING_NINJA", False):
|
|
|
|
return old_results
|
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
new_results = []
|
|
|
|
for base in old_results:
|
|
|
|
new_results.append(base)
|
|
|
|
if getattr(env.Entry(base).attributes, "thin_archive", None):
|
|
|
|
new_results.extend(base.children())
|
2020-01-24 17:08:37 +01:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
return new_results
|
2017-05-25 14:22:58 +02:00
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
builder.target_scanner = SCons.Scanner.Scanner(
|
|
|
|
function=new_scanner, path_function=path_function
|
|
|
|
)
|
2019-02-19 16:50:57 +01:00
|
|
|
|
2017-05-25 14:22:58 +02:00
|
|
|
|
2017-05-25 15:37:12 +02:00
|
|
|
def generate(env):
|
|
|
|
if not exists(env):
|
|
|
|
return
|
2016-09-27 20:41:39 +02:00
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
env["ARFLAGS"] = SCons.Util.CLVar(
|
|
|
|
[arflag if arflag != "rc" else "rcsTD" for arflag in env["ARFLAGS"]]
|
|
|
|
)
|
2016-09-27 20:41:39 +02:00
|
|
|
|
|
|
|
# Disable running ranlib, since we added 's' above
|
2020-01-07 19:48:42 +01:00
|
|
|
env["RANLIBCOM"] = ""
|
|
|
|
env["RANLIBCOMSTR"] = "Skipping ranlib for thin archive $TARGET"
|
2017-05-25 15:37:12 +02:00
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
for builder in ["StaticLibrary", "SharedArchive"]:
|
|
|
|
_add_emitter(env["BUILDERS"][builder])
|
2017-05-25 15:37:12 +02:00
|
|
|
|
2020-01-07 19:48:42 +01:00
|
|
|
for builder in ["SharedLibrary", "LoadableModule", "Program"]:
|
|
|
|
_add_scanner(env["BUILDERS"][builder])
|