Replace `find-filename-conflicts` with something more flexible

This replaces the shell script with a python script that doesn't hardcode the
paths, and changes the makefile so that it also checks plugins for filename
conflicts, since they might suffer from the same problem.

Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
pull/1155/head
Michael Richters 2 years ago
parent e3d01d25cf
commit cbf98fd70b
No known key found for this signature in database
GPG Key ID: 1288FD13E4EEF0C0

@ -98,7 +98,7 @@ build-gtest-gmock:
$(MAKE) -C testing/googletest
find-filename-conflicts:
bin/find-filename-conflicts
bin/find-filename-conflicts.py src plugins/*
.PHONY: format check-formatting cpplint cpplint-noisy shellcheck smoke-examples find-filename-conflicts prepare-virtual checkout-platform adjust-git-timestamps docker-bash docker-simulator-tests run-tests simulator-tests setup

@ -1,55 +0,0 @@
#!/usr/bin/env bash
# find-filename-conflicts - Finds cpp files with conflicting filenames
# Copyright (C) 2020 Keyboard.io, Inc.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
## When building Kaleidoscope, the compiled object files are linked together
## into a static archive. This static archive has a very simple structure, and
## only stores filenames, not paths, not even relative ones. As such, we can't
## have files with the same name, because they will conflict, and one will
## override the other.
##
## To avoid this situation, this script will find all cpp source files (we don't
## need to care about header-only things, those do not result in an object
## file), and will comb through them to find conflicting filenames.
##
## If a conflict is found, it will print all files that share the name, and will
## exit with an error at the end. It does not exit at the first duplicate, but
## will find and print all of them.
##
## If no conflict is found, the script just prints its status message and exits
## with zero.
set -e
FILE_LIST="$(find src -name '*.cpp' | sed -e 's,\(\(.*\)/\([^/]*\)\),\3 \1,')"
exit_code=0
echo -n "Looking for conflicting filenames... "
for f in $(echo "${FILE_LIST}" | cut -f1 -d" "); do
count=$(echo "${FILE_LIST}" | grep -c "^${f}")
if [ "$count" -gt 1 ]; then
echo >&2
echo " Conflict found for ${f}: " >&2
echo "${FILE_LIST}" | grep "${f}" | cut -d" " -f2 | sed -e 's,^, ,' >&2
exit_code=1
fi
done
if [ "${exit_code}" -eq 0 ]; then
echo "done."
fi
exit ${exit_code}

@ -0,0 +1,96 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
# Copyright (c) 2022 Michael Richters <gedankenexperimenter@gmail.com>
# This is free and unencumbered software released into the public domain.
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
# For more information, please refer to <http://unlicense.org/>
# ------------------------------------------------------------------------------
"""When building Kaleidoscope, the compiled object files are linked together
into a static archive. This static archive has a very simple structure, and only
stores filenames, not paths, not even relative ones. As such, we can't have
files with the same name, because they will conflict, and one will override the
other.
To avoid this situation, this script will find all cpp source files (we don't
need to care about header-only things, those do not result in an object file),
and will comb through them to find conflicting filenames.
If a conflict is found, it will print all files that share the name, and will
exit with an error at the end. It does not exit at the first duplicate, but will
find and print all of them.
If no conflict is found, the script just prints its status message and exits
with zero."""
import os
import re
import sys
cpp_regex = re.compile('.*\.cpp')
def find_duplicates(root):
"""Search for files with the same basename, but in different directories in
the tree under <root>. Prints a message for each conflict found, and
returns a count of the number of non-unique basenames."""
# Search the specified tree for matching basenames:
basenames = {}
for dir_path, dirs, files in os.walk(root):
for file_name in files:
if cpp_regex.match(file_name):
if file_name not in basenames:
basenames[file_name] = []
basenames[file_name].append(dir_path)
conflict_count = 0
for file_name, dirs in basenames.items():
# Prune unique basenames from the dict:
if len(dirs) <= 1:
continue
conflict_count += 1
# Print info about basenames with conflicts:
print(f"Conflict found for file name '{file_name}':")
for root in dirs:
path = os.path.join(root, file_name)
print(f' -> {path}')
return conflict_count
def main(args):
print('Searching for conflicting filenames...')
exit_code = 0
for path in args:
exit_code += find_duplicates(path)
if exit_code != 0:
sys.exit(exit_code)
print('No filename conflicts found.')
if __name__ == "__main__":
main(sys.argv[1:])
Loading…
Cancel
Save