Skip to content

Commit

Permalink
Bash cpuflags (#108)
Browse files Browse the repository at this point in the history
* added bash-only script to detect cpuid flags based on g++ and/or clang

* wip bash script

* unified arch detection

* wip arch detection

* dynamic executable detection

* removed old regex

* added lscpu detection as first-choice
  • Loading branch information
alexKrauseTUD authored Sep 4, 2024
1 parent 02bf176 commit 0d2c81d
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 5 deletions.
9 changes: 4 additions & 5 deletions detect_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ def get_compile_info_from_compiler(compiler: str, arch_string: str):
return(re.findall(r' -m((?!no-)[^\s]+)', info))

def get_compile_info_from_lscpu():

if which("lscpu"):
my_env = os.environ.copy()
my_env["LANG"] = "en"
Expand Down Expand Up @@ -70,16 +69,16 @@ def get_platform():
if which("lscpu"):
flags = get_compile_info_from_lscpu()
else:

arch_string = ""
if "Apple" in get_platform() or "aarch" in arch:
arch_string = "-mcpu=native"
else:
arch_string = "-march=native"

print("Debug:", arch, get_platform())
gcc_flags = get_compile_info_from_compiler("g++", "-march=native") if which("g++") else set()
clang_flags = get_compile_info_from_compiler("clang", arch_string) if which("clang") else set()
flags = gcc_flags + clang_flags

flags.update(gcc_flags)
flags.update(clang_flags)

print(' '.join(sorted(flags)))
103 changes: 103 additions & 0 deletions detect_flags.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/bin/bash

function parse_flags {
compiler=$1
compilerinfo=$2

if [ $compiler = "clang" ]; then
regex='"-target-feature" "\+([^\"]+)"'
if [[ $compilerinfo =~ $regex ]] ; then
flag="${BASH_REMATCH[1]}"
printf "$flag "
# Remove the first regex match and parse recursively
parse_flags "$compiler" "${compilerinfo/${BASH_REMATCH[0]}/}"
fi
elif [ $compiler = "gcc" ]; then
regex=' -m([^ ]+)'
if [[ $compilerinfo =~ $regex ]] ; then
flag="${BASH_REMATCH[1]}"
# only print flags that do not start with "no-", since g++ explicitly emits unsupported flags this way.
if [[ $flag != no-* ]]; then
printf "$flag "
fi
# Remove the first regex match and parse recursively
parse_flags "$compiler" "${compilerinfo/${BASH_REMATCH[0]}/}"
fi
else
echo "Unknown compiler."
exit -1
fi
}

lscpu_exe=$(which lscpu)
if [[ ! -z ${lscpu_exe} && -f $lscpu_exe && -x $lscpu_exe ]]; then
flags=$(eval LANG=en;lscpu|grep -i flags | tr ' ' '\n' | grep -v -E '^Flags:|^$' | sort -d | tr '\n' ' ')
echo "$flags"
else
flag_set=()

gcc_exe=$(which g++)
clang_exe=$(which clang)

if [[ -f $gcc_exe && -x $gcc_exe ]]; then
gcc_output=$(eval $gcc_exe -E - -march=native -### 2>&1)
parsed_flags=$(parse_flags "gcc" "$gcc_output")
# Parse whitespace-separated string into an array
IFS=' ' read -r -a parsed_array <<< "$parsed_flags"
unset IFS
# Check for every flag if it is already contained in the flag array
for flag in "${parsed_array[@]}"
do
if [[ ! " ${flag_set[*]} " =~ [[:space:]]${flag}[[:space:]] ]]; then
flag_set+=("$flag")
fi
done
fi
if [[ -f $clang_exe && -x $clang_exe ]]; then
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [[ $(uname -i) != aarch* && $(uname -i) != arm* ]]; then
arch_string="-march=native"
else
arch_string="-mcpu=native"
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
if [[ $(uname -m) != aarch* && $(uname -m) != arm* ]]; then
arch_string="-march=native"
else
arch_string="-mcpu=native"
fi
elif [[ "$OSTYPE" == "cygwin" ]]; then
# POSIX compatibility layer and Linux environment emulation for Windows
continue
elif [[ "$OSTYPE" == "msys" ]]; then
# Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
continue
else
echo "Could not detect the current operating system. Aborting."
exit 1
fi
clang_output=$(eval $clang_exe -E - $arch_string -### 2>&1)
parsed_flags=$(parse_flags "clang" "$clang_output")
# Parse whitespace-separated string into an array
IFS=' ' read -r -a parsed_array <<< "$parsed_flags"
unset IFS
# Check for every flag if it is already contained in the flag array
for flag in "${parsed_array[@]}"
do
if [[ ! " ${flag_set[*]} " =~ [[:space:]]${flag}[[:space:]] ]]; then
flag_set+=("$flag")
fi
done
fi
IFS=$'\n' sorted=($(sort <<<"${flag_set[*]}"))
unset IFS
printf "%s " "${sorted[@]}"
printf "\n"
fi

0 comments on commit 0d2c81d

Please sign in to comment.