chore: import upstream snapshot with attribution
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
This commit is contained in:
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#
|
||||
# Copyright (c) 2026, NVIDIA CORPORATION. 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.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
PYTHON_MAJOR_VERSION=${PYTHON_MAJOR_VERSION:-3}
|
||||
PYTHON_MINOR_VERSION=${PYTHON_MINOR_VERSION:-8}
|
||||
TARGET=${TARGET_ARCHITECTURE:-x86_64}
|
||||
ROOT_PATH=${TRT_OSSPATH:-/workspace/TensorRT}
|
||||
EXT_PATH=${EXT_PATH:-/tmp/external}
|
||||
WHEEL_OUTPUT_DIR=${ROOT_PATH}/python/build
|
||||
|
||||
mkdir -p ${WHEEL_OUTPUT_DIR}
|
||||
pushd ${WHEEL_OUTPUT_DIR}
|
||||
|
||||
# Generate tensorrt.so
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release \
|
||||
-DTARGET=${TARGET} \
|
||||
-DPYTHON_MAJOR_VERSION=${PYTHON_MAJOR_VERSION} \
|
||||
-DPYTHON_MINOR_VERSION=${PYTHON_MINOR_VERSION} \
|
||||
-DEXT_PATH=${EXT_PATH} \
|
||||
-DTENSORRT_ROOT=${ROOT_PATH} \
|
||||
-DTENSORRT_MODULE=${TENSORRT_MODULE} \
|
||||
-DTENSORRT_LIBPATH=${TRT_LIBPATH} \
|
||||
-DTRT_ONNXPARSER_NAME=nvonnxparser
|
||||
make -j12
|
||||
|
||||
# Generate wheel
|
||||
TRT_MAJOR=$(awk '/^\#define TRT_MAJOR_ENTERPRISE/ {print $3}' ${ROOT_PATH}/include/NvInferVersion.h)
|
||||
TRT_MINOR=$(awk '/^\#define TRT_MINOR_ENTERPRISE/ {print $3}' ${ROOT_PATH}/include/NvInferVersion.h)
|
||||
TRT_PATCH=$(awk '/^\#define TRT_PATCH_ENTERPRISE/ {print $3}' ${ROOT_PATH}/include/NvInferVersion.h)
|
||||
TRT_BUILD=$(awk '/^\#define TRT_BUILD_ENTERPRISE/ {print $3}' ${ROOT_PATH}/include/NvInferVersion.h)
|
||||
TRT_VERSION=${TRT_MAJOR}.${TRT_MINOR}.${TRT_PATCH}.${TRT_BUILD}
|
||||
TRT_MAJMINPATCH=${TRT_MAJOR}.${TRT_MINOR}.${TRT_PATCH}
|
||||
PLUGIN_DISABLED_STR="0"
|
||||
|
||||
echo "Generating python ${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION} bindings for TensorRT ${TRT_VERSION}"
|
||||
|
||||
expand_vars_cp () {
|
||||
test -f ${1} || (echo "ERROR: File: ${1} does not exist!" && exit 1); \
|
||||
sed -e "s|\#\#TENSORRT_VERSION\#\#|${TRT_VERSION}|g" \
|
||||
-e "s|\#\#TENSORRT_MAJMINPATCH\#\#|${TRT_MAJMINPATCH}|g" \
|
||||
-e "s|\#\#TENSORRT_PYTHON_VERSION\#\#|${TRT_MAJMINPATCH}|g" \
|
||||
-e "s|\#\#TENSORRT_MODULE\#\#|${TENSORRT_MODULE}|g" \
|
||||
-e "s|##TENSORRT_PLUGIN_DISABLED##|${PLUGIN_DISABLED_STR}|g" \
|
||||
${1} > ${2}
|
||||
}
|
||||
|
||||
pushd ${ROOT_PATH}/python/packaging
|
||||
for dir in $(find . -type d); do mkdir -p ${WHEEL_OUTPUT_DIR}/$dir; done
|
||||
for file in $(find . -type f); do expand_vars_cp $file ${WHEEL_OUTPUT_DIR}/${file}; done
|
||||
popd
|
||||
|
||||
# Copy required files and directories to build the bindings.
|
||||
cp tensorrt/tensorrt.so bindings_wheel/tensorrt/tensorrt.so
|
||||
mv tensorrt_build_backend bindings_wheel/
|
||||
|
||||
pushd ${WHEEL_OUTPUT_DIR}/bindings_wheel
|
||||
python -m build --no-isolation --wheel --config-setting=wheel-type=binding --config-setting=python-tag=cp${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION} --config-setting=plat-name=linux_${TARGET}
|
||||
popd
|
||||
@@ -0,0 +1,261 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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 argparse
|
||||
import onnx
|
||||
import logging
|
||||
import os
|
||||
import numpy as np
|
||||
import onnx_graphsurgeon as gs
|
||||
from onnx import helper, TensorProto, numpy_helper, version_converter
|
||||
|
||||
'''
|
||||
This script is converting TE ONNX models (cast + CustomOp Q) and (CustomOp DQ + cast) pairs to Opset19 ONNX Q/DQ
|
||||
usage:
|
||||
python3 convert_te_onnx_to_trt_onnx.py --onnx_model_path <folder/file>
|
||||
|
||||
This script requires onnx 1.14 and above
|
||||
'''
|
||||
|
||||
def find_node_by_tensor(graph, search_tensor, is_node_input, search_node_type=None):
|
||||
for idx, node in enumerate(graph.node):
|
||||
search_container = node.output
|
||||
if is_node_input:
|
||||
search_container = node.input
|
||||
for node_tensor in search_container:
|
||||
if search_node_type and node.op_type != search_node_type:
|
||||
continue
|
||||
if node_tensor == search_tensor:
|
||||
return node, idx
|
||||
|
||||
return None, None
|
||||
|
||||
def redirect_quantize_input(graph, q_node):
|
||||
assert(q_node.op_type == 'QuantizeLinear')
|
||||
q_input = q_node.input[0]
|
||||
cast_node, cast_node_idx = find_node_by_tensor(graph, q_input, False, 'Cast')
|
||||
if cast_node:
|
||||
q_node.input[0] = cast_node.input[0]
|
||||
return [cast_node_idx]
|
||||
return []
|
||||
|
||||
def redirect_dequantize_output(graph, dq_node):
|
||||
assert(dq_node.op_type == 'DequantizeLinear')
|
||||
dq_output = dq_node.output[0]
|
||||
cast_node, cast_node_idx = find_node_by_tensor(graph, dq_output, True, 'Cast')
|
||||
if cast_node:
|
||||
dq_node.output[0] = cast_node.output[0]
|
||||
return [cast_node_idx]
|
||||
return []
|
||||
|
||||
def get_attr_numpy_tensor(attr):
|
||||
assert(attr.type == onnx.AttributeProto.TENSOR)
|
||||
return numpy_helper.to_array(attr.t)
|
||||
|
||||
def get_attr(node, search_attr_name):
|
||||
for idx, attr in enumerate(node.attribute):
|
||||
if attr.name == search_attr_name:
|
||||
return attr, idx
|
||||
|
||||
return None, None
|
||||
|
||||
def cast_scale(graph, qdq_node, cast_to):
|
||||
assert(cast_to in ['fp32', 'fp16'])
|
||||
assert(qdq_node.op_type in ['QuantizeLinear', 'DequantizeLinear'])
|
||||
constant_node_idx = None
|
||||
scale_tensor = qdq_node.input[1]
|
||||
constant_node, constant_node_idx = find_node_by_tensor(graph, scale_tensor, False, 'Constant')
|
||||
scale_cast_to_dtype = None
|
||||
onnx_cast_to_dtype = None
|
||||
if cast_to == 'fp16':
|
||||
scale_cast_to_dtype = np.dtype(np.float32)
|
||||
onnx_cast_to_dtype = onnx.TensorProto.FLOAT16
|
||||
elif cast_to == 'fp32':
|
||||
scale_cast_to_dtype = np.dtype(np.float32)
|
||||
onnx_cast_to_dtype = onnx.TensorProto.FLOAT
|
||||
|
||||
if constant_node:
|
||||
scale_attr, _ = get_attr(constant_node, 'value')
|
||||
assert(scale_attr)
|
||||
numpy_scale = get_attr_numpy_tensor(scale_attr)
|
||||
logging.info(type(numpy_scale.dtype))
|
||||
logging.info(type(scale_cast_to_dtype))
|
||||
if numpy_scale.dtype != scale_cast_to_dtype:
|
||||
logging.debug(f'Change {qdq_node.name} scale from {numpy_scale.dtype} to {scale_cast_to_dtype}')
|
||||
numpy_scale = numpy_scale.astype(scale_cast_to_dtype)
|
||||
tensor_name = constant_node.name + '_casted'
|
||||
create_constant_tensor(graph, tensor_name, onnx_cast_to_dtype, numpy_scale)
|
||||
qdq_node.input[1] = tensor_name
|
||||
else:
|
||||
logging.warning(f'No constant node connected to {qdq_node} as scale')
|
||||
|
||||
if constant_node_idx:
|
||||
return [constant_node_idx]
|
||||
return []
|
||||
|
||||
def create_constant_tensor(graph, name, dtype, np_tensor):
|
||||
tensor_value_info = helper.make_tensor_value_info(name, dtype, np_tensor.shape)
|
||||
graph.input.append(tensor_value_info)
|
||||
helper.make_tensor(name, data_type=dtype, dims=(), vals=[0])
|
||||
|
||||
tensor_initializer = helper.make_tensor(name, dtype, np_tensor.shape, np_tensor.flatten().tolist())
|
||||
graph.initializer.append(tensor_initializer)
|
||||
|
||||
'''
|
||||
Convert custom operators to opset19
|
||||
'''
|
||||
def custom_op_to_opset19(graph, node, use_int32_quantization, remove_cast_before_q, remove_cast_after_dq, change_qdq_scale_precision):
|
||||
assert(node.op_type in ['TRT_FP8QuantizeLinear', 'TRT_FP8DequantizeLinear'])
|
||||
is_dq = node.op_type == 'TRT_FP8DequantizeLinear'
|
||||
logging.debug(f'Convert {node.name} to Opset19')
|
||||
orig_node_name = node.name
|
||||
new_node_name = orig_node_name + '_converted'
|
||||
|
||||
quant_to = TensorProto.FLOAT8E4M3FN
|
||||
if use_int32_quantization:
|
||||
quant_to = TensorProto.INT32
|
||||
|
||||
#add zero point to the node
|
||||
tensor_name = new_node_name + '_zero_point'
|
||||
create_constant_tensor(graph, tensor_name, quant_to, np.array([0]))
|
||||
node.input.append(tensor_name)
|
||||
|
||||
node.domain = ""
|
||||
node.op_type = "QuantizeLinear"
|
||||
|
||||
node_idxs_to_delete = []
|
||||
if is_dq:
|
||||
node.op_type = "DequantizeLinear"
|
||||
if remove_cast_after_dq:
|
||||
node_idxs_to_delete += redirect_dequantize_output(graph, node)
|
||||
if change_qdq_scale_precision:
|
||||
node_idxs_to_delete += cast_scale(graph, node, change_qdq_scale_precision)
|
||||
else:
|
||||
if remove_cast_before_q:
|
||||
node_idxs_to_delete += redirect_quantize_input(graph, node)
|
||||
if change_qdq_scale_precision:
|
||||
node_idxs_to_delete += cast_scale(graph, node, change_qdq_scale_precision)
|
||||
|
||||
node.name = new_node_name
|
||||
logging.debug(f'Convert Done\n')
|
||||
return node_idxs_to_delete
|
||||
|
||||
def check_model(graph):
|
||||
converted_qdq_ops = ['TRT_FP8QuantizeLinear', 'TRT_FP8DequantizeLinear']
|
||||
passed_check = True
|
||||
for node in graph.node:
|
||||
if node.op_type in converted_qdq_ops:
|
||||
logging.error(f'Node \"{node.name}\" of type {node.op_type} should have been removed')
|
||||
passed_check = False
|
||||
return passed_check
|
||||
|
||||
def update_quantize_node_type(model):
|
||||
graph = gs.import_onnx(model)
|
||||
for node in graph.nodes:
|
||||
if node.op == "TRT_FP8QuantizeLinear":
|
||||
for out in node.outputs:
|
||||
out.dtype = TensorProto.FLOAT8E4M3FN
|
||||
return gs.export_onnx(graph)
|
||||
|
||||
'''
|
||||
Converts onnx files from TE to TRT
|
||||
'''
|
||||
def replace_customop_qdq_with_onnx_qdq(te_onnx_files, results_path, create_netron_compatible_model, remove_cast_before_q, remove_cast_after_dq, change_qdq_scale_precision):
|
||||
# store mappings from original ONNX name to new ONNX name.
|
||||
file_mappings = {}
|
||||
for te_onnx_file in te_onnx_files:
|
||||
logging.debug('Loading model')
|
||||
model = onnx.load(te_onnx_file, load_external_data=False)
|
||||
# update QuantizeLinear output dtype
|
||||
model = update_quantize_node_type(model)
|
||||
# change model opset to 19
|
||||
model.opset_import[0].version = 19
|
||||
graph = model.graph
|
||||
logging.debug('Loading model finished')
|
||||
converted_qdq_ops = ['TRT_FP8QuantizeLinear', 'TRT_FP8DequantizeLinear']
|
||||
|
||||
try:
|
||||
node_idxs_to_delete = []
|
||||
converted = False
|
||||
for node in graph.node:
|
||||
if node.op_type in converted_qdq_ops:
|
||||
converted = True
|
||||
node_idxs_to_delete += custom_op_to_opset19(graph, node, create_netron_compatible_model, remove_cast_before_q, remove_cast_after_dq, change_qdq_scale_precision)
|
||||
|
||||
if converted:
|
||||
assert(check_model(graph))
|
||||
node_idxs_to_delete = reversed(sorted(node_idxs_to_delete))
|
||||
for node_idx in node_idxs_to_delete:
|
||||
del(graph.node[node_idx])
|
||||
suffix = '.opset19'
|
||||
if create_netron_compatible_model:
|
||||
suffix += '.netron'
|
||||
suffix += '.onnx'
|
||||
new_model_filename = os.path.join(results_path, os.path.splitext(os.path.split(te_onnx_file)[1])[0] + suffix)
|
||||
onnx.save_model(model, new_model_filename)
|
||||
logging.info(f'The converted model is saved at {new_model_filename}!')
|
||||
file_mappings[te_onnx_file] = new_model_filename
|
||||
else:
|
||||
logging.info(f'No conversion was done with {te_onnx_file}!')
|
||||
file_mappings[te_onnx_file] = te_onnx_file
|
||||
except Exception as ex:
|
||||
logging.error(f'Failed: {ex}')
|
||||
file_mappings[te_onnx_file] = None
|
||||
return file_mappings
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--onnx_model_path', required=True, help="Path of model or a folder of models. When using a folder, this script will convert all \'.onnx\' files")
|
||||
parser.add_argument('--results_path', required=False, help="Path for generated models, when not set, the generated model(s) will be next ot the origianl model(s)")
|
||||
parser.add_argument('--create_netron_compatible_model', action='store_true', required=False, help="When set, the script will use int32 quantization. "
|
||||
"This enables the user to view the graph with Netron, until it adds support for opset19. The generated model isn't TRT compatible.")
|
||||
parser.add_argument('--remove_casts', required=False, help="Controls whether to remove casts around q/dq nodes. "
|
||||
"For example, when set to \'dq\', remove casts only after dq. Default is \'keep_all\'", choices=['q', 'dq', 'qdq', 'keep_all'], default='keep_all')
|
||||
parser.add_argument('--change_qdq_scale_precision', required=False, help="When set controls q/dq nodes scales data type.", choices=['fp32', 'fp16'])
|
||||
args = parser.parse_args()
|
||||
|
||||
results_path = args.results_path
|
||||
if results_path and os.path.isdir(results_path) == False:
|
||||
logging.error(f'\'--results_path\' set to \'{results_path}\', but the folder doesn\'t exist, exiting')
|
||||
exit(-1)
|
||||
|
||||
if results_path is None:
|
||||
results_path = args.onnx_model_path
|
||||
if os.path.isfile(results_path):
|
||||
results_path = os.path.split(results_path)[0]
|
||||
|
||||
remove_cast_after_dq = False
|
||||
remove_cast_before_q = False
|
||||
if args.remove_casts == 'q':
|
||||
remove_cast_before_q = True
|
||||
elif args.remove_casts == 'dq':
|
||||
remove_cast_after_dq = True
|
||||
elif args.remove_casts == 'qdq':
|
||||
remove_cast_after_dq = True
|
||||
remove_cast_before_q = True
|
||||
|
||||
onnx_files = []
|
||||
if os.path.isdir(args.onnx_model_path):
|
||||
logging.info(f"Got folder: {args.onnx_model_path}")
|
||||
onnx_files = [os.path.join(args.onnx_model_path, filename) for filename in os.listdir(args.onnx_model_path) if filename.endswith('.onnx')==True and filename.endswith('.opset19.onnx')==False]
|
||||
|
||||
else:
|
||||
logging.info(f"Got file: {args.onnx_model_path}")
|
||||
onnx_files = [args.onnx_model_path]
|
||||
|
||||
replace_customop_qdq_with_onnx_qdq(onnx_files, results_path, args.create_netron_compatible_model, remove_cast_before_q, remove_cast_after_dq, args.change_qdq_scale_precision)
|
||||
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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 argparse
|
||||
import os
|
||||
import re
|
||||
|
||||
# Configuration
|
||||
|
||||
copyright_year = "2020"
|
||||
|
||||
extensions_p = (".py", ".sh", ".cmake", "CMakeLists")
|
||||
extensions_c = (".c", ".cpp", ".h", ".hpp", ".cu")
|
||||
|
||||
pattern_p = """#\s*
|
||||
# Copyright \(c\) ([1-2][0-9]{3}),* NVIDIA CORPORATION.*
|
||||
#\s*
|
||||
# Licensed under the Apache License, Version 2.0 \(the "License"\);\s*
|
||||
# you may not use this file except in compliance with the License.\s*
|
||||
# You may obtain a copy of the License at\s*
|
||||
#\s*
|
||||
# http://www.apache.org/licenses/LICENSE-2.0\s*
|
||||
#\s*
|
||||
# Unless required by applicable law or agreed to in writing, software\s*
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,\s*
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\s*
|
||||
# See the License for the specific language governing permissions and\s*
|
||||
# limitations under the License.\s*
|
||||
#
|
||||
"""
|
||||
|
||||
header_p = """#
|
||||
# Copyright (c) {year}, NVIDIA CORPORATION. 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.
|
||||
#
|
||||
""".format(year=copyright_year)
|
||||
|
||||
pattern_c = """/\*\s*
|
||||
\* Copyright \(c\) ([1-2][0-9]{3}),* NVIDIA CORPORATION.*
|
||||
\*\s*
|
||||
\* Licensed under the Apache License, Version 2.0 \(the "License"\);\s*
|
||||
\* you may not use this file except in compliance with the License.\s*
|
||||
\* You may obtain a copy of the License at\s*
|
||||
\*\s*
|
||||
\* http://www.apache.org/licenses/LICENSE-2.0\s*
|
||||
\*\s*
|
||||
\* Unless required by applicable law or agreed to in writing, software\s*
|
||||
\* distributed under the License is distributed on an "AS IS" BASIS,\s*
|
||||
\* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\s*
|
||||
\* See the License for the specific language governing permissions and\s*
|
||||
\* limitations under the License.\s*
|
||||
\*/
|
||||
"""
|
||||
|
||||
header_c = """/*
|
||||
* Copyright (c) {year}, NVIDIA CORPORATION. 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.
|
||||
*/
|
||||
""".format(year=copyright_year)
|
||||
|
||||
# Routines
|
||||
|
||||
def parse_args(parser):
|
||||
"""
|
||||
Parse commandline arguments.
|
||||
"""
|
||||
parser.add_argument('-d', '--dir', type=str, required=True, help='Root directory to start the scan')
|
||||
parser.add_argument('-f','--force-update', action='store_true', help='Force the header writes for all files')
|
||||
parser.add_argument('--dry-run', action='store_true', help='Just perform a dry-run')
|
||||
parser.add_argument('--max-depth', type=int,default=100, help='Maximum depth to recurse while scanning files.')
|
||||
return parser
|
||||
|
||||
def update(filename, args):
|
||||
"""
|
||||
Update copyright header for specified file
|
||||
"""
|
||||
if filename.endswith(extensions_p):
|
||||
pattern = re.compile(pattern_p)
|
||||
header = header_p
|
||||
shebang = re.compile(r'^(\#\!.*\n)', re.MULTILINE)
|
||||
elif filename.endswith(extensions_c):
|
||||
pattern = re.compile(pattern_c)
|
||||
header = header_c
|
||||
shebang = None
|
||||
else:
|
||||
return
|
||||
|
||||
with open(filename, "r+") as f:
|
||||
data = f.read()
|
||||
match = pattern.search(data)
|
||||
if match:
|
||||
year = match.group(1)
|
||||
if copyright_year == year:
|
||||
if args.force_update:
|
||||
print(filename,": FORCED")
|
||||
new_data = pattern.sub(header, data, count=1)
|
||||
else:
|
||||
print(filename,": SKIP")
|
||||
return
|
||||
else:
|
||||
print(filename,": UPDATE (",year,"->",copyright_year,")")
|
||||
new_data = pattern.sub(header, data, count=1)
|
||||
else:
|
||||
match = shebang.search(data) if shebang else None
|
||||
if match:
|
||||
print(filename,": ADD ( after",match.group(1),")")
|
||||
new_data = shebang.sub(match.group(1)+header, data, count=1)
|
||||
else:
|
||||
print(filename,": ADD ( top )")
|
||||
new_data = header+data
|
||||
|
||||
if not args.dry_run:
|
||||
with open(filename, "w") as f:
|
||||
f.write(new_data)
|
||||
|
||||
def copyright_scan(directory, depth, args, exclude_dirs=[]):
|
||||
"""
|
||||
Update copyright for TensorRT sources
|
||||
"""
|
||||
if directory in exclude_dirs:
|
||||
return
|
||||
for f in os.listdir(directory):
|
||||
filename = os.path.join(directory,f)
|
||||
if os.path.isdir(filename) and (depth > 0):
|
||||
copyright_scan(filename, depth-1, args, exclude_dirs)
|
||||
elif filename.endswith(extensions_p + extensions_c):
|
||||
update(filename, args)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='TensorRT copyright scan')
|
||||
parser = parse_args(parser)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
exclude_dirs = ["./third_party","./build","./parsers/onnx", "./include"]
|
||||
copyright_scan(args.dir, args.max_depth, args, exclude_dirs)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 1993-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# This short shell script will extract all the strong "text" symbols from the
|
||||
# shared library and create a new "stub" shared library with the same symbols.
|
||||
# The body of these functions will be empty and therefore have no dependencies.
|
||||
# This scripts uses whatever CC is defined in the user's environment.
|
||||
#
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# check arguments
|
||||
if [ $# -ne 2 ] ; then
|
||||
echo "Usage: $(basename $0) IN_LIBFILE OUT_LIBFILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IN_LIBFILE="$1"
|
||||
OUT_LIBFILE="$2"
|
||||
|
||||
# check compiler
|
||||
if [ -z "${CC}" ] ; then
|
||||
echo "Error: Environment variable 'CC' has not been defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SONAME=$(readelf -d "${IN_LIBFILE}" | grep '(SONAME)' | cut -d [ -f 2 | cut -d ] -f 1)
|
||||
|
||||
# Detect OS from /etc/os-release instead of lsb_release (which may not be installed).
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS="${ID}-${VERSION_ID}"
|
||||
else
|
||||
OS="unknown"
|
||||
fi
|
||||
|
||||
if [ "$OS" = "ubuntu-22.04" ] ; then
|
||||
EXTRA_NM_FLAG="--without-symbol-versions"
|
||||
elif [ "$OS" = "ubuntu-24.04" ] ; then
|
||||
EXTRA_NM_FLAG="--without-symbol-versions"
|
||||
fi
|
||||
|
||||
# make stub library
|
||||
# This uses the system nm in containers that compile with SCL, but the output is identical to the SCL output
|
||||
if [ -z "${CC_ARGS}" ] ; then
|
||||
nm -D "${IN_LIBFILE}" ${EXTRA_NM_FLAG} | \
|
||||
awk '{if ($2 == "T") { print "void",$3,"() {}" }}' | \
|
||||
${CC} -xc -Og -fPIC -shared -Wl,-soname=${SONAME} -Wl,--strip-all -o "${OUT_LIBFILE}" -
|
||||
else
|
||||
nm -D "${IN_LIBFILE}" ${EXTRA_NM_FLAG} | \
|
||||
awk '{if ($2 == "T") { print "void",$3,"() {}" }}' | \
|
||||
${CC} -xc -Og -fPIC -shared -Wl,-soname=${SONAME} -Wl,--strip-all -o "${OUT_LIBFILE}" "${CC_ARGS}" -
|
||||
fi
|
||||
|
||||
exit $?
|
||||
Reference in New Issue
Block a user