Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 35 additions & 66 deletions src/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
import sys
import re
import ctypes
import subprocess



####################################################################################################
# Validation
####################################################################################################
# Check the Python version
if sys.version_info[0] < 3 or sys.version_info[1] < 5:
raise BaseException("Python 3.5 or later is required.")
if sys.version_info[0] < 3 or sys.version_info[1] < 7:
raise BaseException("Python 3.7 or later is required.")



Expand All @@ -38,8 +39,6 @@
GAMER_CONFIG_DIR = os.path.join("..", "configs")
GAMER_MAKE_BASE = "Makefile_base"
GAMER_MAKE_OUT = "Makefile"
GAMER_LOCAL_SETTING = ".local_settings"
GAMER_GLOBAL_SETTING = os.path.expanduser("~/.config/gamer/global_settings")
GAMER_DESCRIPTION = "Prepare a customized Makefile for GAMER.\n"\
"Default values are marked by '*'.\n"\
"Use -lh to show a detailed help message.\n"
Expand Down Expand Up @@ -240,48 +239,6 @@ def print_autocomplete( self, target_option, *args, **kwargs ):

return

class SystemSetting( dict ):
"""
Store the system settings from the default setting file.

Format of the setting file:
1. Comment starts with `#`.
2. The line begins with the variable name, followed by one or multiple spaces, and then the value.
3. Only the fisrt value of the line will be loaded.
4. If a variable is defined multiple times, only the last occurrence will be used.
"""
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )

def get_default( self, key, default_val ):
return self.get( key, default_val )

def load( self, pathname ):
"""
Load the system settings from the default setting file. If a setting exists,
it will be overwritten. Return `False` if the file does not exist.

Parameters:
pathname : str - The path of the default setting file to be loaded.

Returns:
bool - Whether the file exists.
"""
if not os.path.isfile(pathname):
return False
with open( pathname, "r" ) as f:
lines = f.readlines()
for line in lines:
tokens = line.strip().split()
if len(tokens) == 0: continue # empty line
if tokens[0][0] == "#": continue # skip comment line
if len(tokens) >= 2:
self[tokens[0]] = tokens[1]
else: # key without value
self[tokens[0]] = None

return True



####################################################################################################
Expand Down Expand Up @@ -387,6 +344,23 @@ def cuda_check_error( result ):
compute_capability = cc_major.value*100 + cc_minor.value*10
return compute_capability

def get_setting( key, default_val=None ):
"""
Get the default setting from get_settings.sh.
key : The key to retrieve.
default_val : The value to return if the key is not set.
"""
GET_SCRIPT_PATH = os.path.join("..", "tool", "config", "get_settings.sh")
if not os.path.isfile(GET_SCRIPT_PATH):
raise FileNotFoundError(f"{GET_SCRIPT_PATH} does not exist. Path is relative to {os.getcwd()}")

result = subprocess.run(["sh", GET_SCRIPT_PATH, key], stdout=subprocess.PIPE, text=True)
if result.returncode == 0:
output = result.stdout.removesuffix("\n")
return output

return default_val

def string_align( string, indent_str, width, end_char ):
"""
end_char : The ending character of a word.
Expand Down Expand Up @@ -415,7 +389,7 @@ def string_align( string, indent_str, width, end_char ):
if string[i] == end_char: new_line = True
return new_str

def load_arguments( sys_setting : SystemSetting ):
def load_arguments():
parser = ArgumentParser( description = GAMER_DESCRIPTION,
formatter_class = argparse.RawTextHelpFormatter,
epilog = GAMER_EPILOG,
Expand Down Expand Up @@ -443,7 +417,7 @@ def load_arguments( sys_setting : SystemSetting ):

# machine config setup
parser.add_argument( "--machine", type=str, metavar="MACHINE",
default=sys_setting.get_default( "machine", "eureka_intel" ),
default=get_setting( "machine", "eureka_intel" ),
help="Select the *.config file from the ../configs directory. "\
"This will overwrite the default machine specified in the default setting file.\n"\
"Choice: [eureka_intel, spock_intel, ...] => "
Expand Down Expand Up @@ -1132,48 +1106,43 @@ def warning( paths, **kwargs ):
# 1. Get the execution command
command = " ".join( ["# This makefile is generated by the following command:", "\n#", sys.executable] + sys.argv + ["\n"] )

# 2. Load system settings
sys_setting = SystemSetting()
sys_setting.load(GAMER_GLOBAL_SETTING)
sys_setting.load(GAMER_LOCAL_SETTING)

# 3. Load the input arguments
args, name_table, depends, constraints, prefix_table, suffix_table = load_arguments( sys_setting )
# 2. Load the input arguments
args, name_table, depends, constraints, prefix_table, suffix_table = load_arguments()

# 4. Set the logger
# 3. Set the logger
logging.basicConfig( filename=GAMER_MAKE_OUT+'.log', filemode='w', level=logging.INFO, format=LOG_FORMAT )
ch = logging.StreamHandler()
ch.setFormatter( CustomFormatter() )
LOGGER.addHandler( ch )
LOGGER.info( " ".join( [sys.executable] + sys.argv ) )

# 5. Prepare the makefile args
# 5.1 Load the machine setup
# 4. Prepare the makefile args
# 4.1 Load the machine setup
paths, compilers, flags, gpus = load_config( os.path.join(GAMER_CONFIG_DIR, args["machine"]+".config") )

# 5.2 Validate arguments
# 4.2 Validate arguments
validation( paths, depends, constraints, **args )

warning( paths, **args )

# 5.3 Add the SIMU_OPTION
# 4.3 Add the SIMU_OPTION
LOGGER.info("========================================")
LOGGER.info("GAMER has the following setting.")
LOGGER.info("----------------------------------------")
sims = set_sims( name_table, prefix_table, suffix_table, depends, **args )

# 5.4 Set the compiler
# 4.4 Set the compiler
compiles = set_compile( paths, compilers, flags, args )

# 5.5 Set the GPU
# 4.5 Set the GPU
gpu_setup = set_gpu( gpus, flags, args )

# 6. Create Makefile
# 6.1 Read
# 5. Create Makefile
# 5.1 Read
with open( GAMER_MAKE_BASE, "r" ) as make_base:
makefile = make_base.read()

# 6.2 Replace
# 5.2 Replace
verbose_mode = "1" if args["verbose_make"] else "0"
makefile, num = re.subn(r"@@@COMPILE_VERBOSE@@@", verbose_mode, makefile)
if num == 0: raise BaseException("The string @@@COMPILE_VERBOSE@@@ is not replaced correctly.")
Expand Down Expand Up @@ -1206,7 +1175,7 @@ def warning( paths, **kwargs ):
if num == 0: raise BaseException("The string @@@%s@@@ is not replaced correctly."%key)
LOGGER.warning("@@@%s@@@ is replaced to '' since the value is not given or the related option is disabled."%key)

# 6.3 Write
# 5.3 Write
with open( GAMER_MAKE_OUT, "w") as make_out:
make_out.write( command + makefile )

Expand Down
105 changes: 105 additions & 0 deletions tool/config/get_settings.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/bash

#################### UTILITIES ####################

cd "$(dirname "$0")"
source ./settings.sh
# Variables imported from settings.sh:
# KEY_DESCRIPTIONS
# VALID_KEYS
# MAX_KEY_LENGTH

# Functions imported from settings.sh:
# print_key()
# show_valid_keys()

show_help() {
echo "Usage:"
echo " $0 [--local | --global] <key>"
echo " $0 (-h | --help)"
echo ""
echo "Options:"
echo " --local Use local settings"
echo " --global Use global settings"
echo " -h, --help Show this help message"
echo ""
show_valid_keys
}

##################### PARSER ######################

LOCAL=false
GLOBAL=false
KEY=""

while [[ "$#" -gt 0 ]]; do
case "$1" in
--local)
LOCAL=true
shift ;;
--global)
GLOBAL=true
shift ;;
-h|--help)
show_help
exit 0 ;;
-*)
echo "Error: Unknown option '$1'" >&2
show_help
exit 1 ;;
*)
if [[ -n "$KEY" ]]; then
echo "Error: Only one key can be specified." >&2
exit 1
fi
KEY="$1"
shift ;;
esac
done

#################### VALIDATION ####################

if [[ -z "$KEY" ]]; then
echo "Error: You must specify a key to retrieve." >&2
show_help
exit 1
fi

if [[ ! " ${VALID_KEYS[@]} " =~ " $KEY " ]]; then
echo "Error: Invalid key '$KEY'." >&2
show_valid_keys
exit 1
fi

################### GET SETTINGS ###################

# Helper to extract a setting from output
extract_value() {
local key="$1"
grep -E "^$key[[:space:]]+" | awk '{print $2}'
}

FOUND=false

if [ "$LOCAL" = true ] || [ "$GLOBAL" = false ]; then
local_output=$(sh ./set_settings.sh --local --list)
value=$(echo "$local_output" | extract_value "$KEY")
if [[ -n "$value" ]]; then
echo "$value"
FOUND=true
fi
fi

if [ "$FOUND" = false ] && ([ "$GLOBAL" = true ] || [ "$LOCAL" = false ]); then
global_output=$(sh ./set_settings.sh --global --list)
value=$(echo "$global_output" | extract_value "$KEY")
if [[ -n "$value" ]]; then
echo "$value"
FOUND=true
fi
fi

if [ "$FOUND" = false ]; then
echo "Key '$KEY' is not set in the requested scope(s)." >&2
exit 1
fi
44 changes: 9 additions & 35 deletions tool/config/set_settings.sh
Original file line number Diff line number Diff line change
@@ -1,41 +1,17 @@
#!/bin/bash

################### DEFINE KEYS ###################
# The keys can not contain spaces or start with `-`
declare -A KEY_DESCRIPTIONS
KEY_DESCRIPTIONS=(
["machine"]="Specify the machine name"
)
###################################################

#################### UTILITIES ####################

# List of valid keys
VALID_KEYS=("${!KEY_DESCRIPTIONS[@]}")

# For padding keys with trailing spaces to format output
MAX_KEY_LENGTH=0
for key in "${VALID_KEYS[@]}"; do
if [ ${#key} -gt $MAX_KEY_LENGTH ]; then
MAX_KEY_LENGTH=${#key}
fi
done

# Print keys in a formatted way
print_key() {
# $1 : the key name
# $2 : the key value or additional message
# $3 : indent number (optional, default 0)
printf "%${3}s" ""
printf "%-${MAX_KEY_LENGTH}s %s\n" "$1" "$2"
}
cd "$(dirname "$0")"
source ./settings.sh
# Variables imported from settings.sh:
# KEY_DESCRIPTIONS
# VALID_KEYS
# MAX_KEY_LENGTH

show_valid_keys() {
echo "Valid keys and their functionalities:"
for key in "${!KEY_DESCRIPTIONS[@]}"; do
print_key "$key" "${KEY_DESCRIPTIONS[$key]}" 2
done
}
# Functions imported from settings.sh:
# print_key()
# show_valid_keys()

show_help() {
echo "Usage:"
Expand Down Expand Up @@ -210,8 +186,6 @@ fi

################ LOAD SETTINGS FILE ###############

cd "$(dirname "$0")"

# Load if the settings file exists
declare -A EXISTING_SETTINGS
if [ -f "$SETTING_FILE" ]; then
Expand Down
38 changes: 38 additions & 0 deletions tool/config/settings.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
################### DEFINE KEYS ###################
# The keys can not contain spaces or start with `-`
declare -A KEY_DESCRIPTIONS
KEY_DESCRIPTIONS=(
["machine"]="Specify the machine name"
)
###################################################

#################### UTILITIES ####################

# List of valid keys
VALID_KEYS=("${!KEY_DESCRIPTIONS[@]}")

# For padding keys with trailing spaces to format output
MAX_KEY_LENGTH=0
for key in "${VALID_KEYS[@]}"; do
if [ ${#key} -gt $MAX_KEY_LENGTH ]; then
MAX_KEY_LENGTH=${#key}
fi
done

# Print keys in a formatted way
print_key() {
# $1 : the key name
# $2 : the key value or additional message
# $3 : indent number (optional, default 0)
printf "%${3}s" ""
printf "%-${MAX_KEY_LENGTH}s %s\n" "$1" "$2"
}

show_valid_keys() {
echo "Valid keys and their functionalities:"
for key in "${!KEY_DESCRIPTIONS[@]}"; do
print_key "$key" "${KEY_DESCRIPTIONS[$key]}" 2
done
}

###################################################