xref: /aosp_15_r20/external/llvm/utils/llvm-build/llvmbuild/configutil.py (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker"""
2*9880d681SAndroid Build Coastguard WorkerDefines utilities useful for performing standard "configuration" style tasks.
3*9880d681SAndroid Build Coastguard Worker"""
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Workerimport re
6*9880d681SAndroid Build Coastguard Workerimport os
7*9880d681SAndroid Build Coastguard Worker
8*9880d681SAndroid Build Coastguard Workerdef configure_file(input_path, output_path, substitutions):
9*9880d681SAndroid Build Coastguard Worker    """configure_file(input_path, output_path, substitutions) -> bool
10*9880d681SAndroid Build Coastguard Worker
11*9880d681SAndroid Build Coastguard Worker    Given an input and output path, "configure" the file at the given input path
12*9880d681SAndroid Build Coastguard Worker    by replacing variables in the file with those given in the substitutions
13*9880d681SAndroid Build Coastguard Worker    list. Returns true if the output file was written.
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker    The substitutions list should be given as a list of tuples (regex string,
16*9880d681SAndroid Build Coastguard Worker    replacement), where the regex and replacement will be used as in 're.sub' to
17*9880d681SAndroid Build Coastguard Worker    execute the variable replacement.
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker    The output path's parent directory need not exist (it will be created).
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker    If the output path does exist and the configured data is not different than
22*9880d681SAndroid Build Coastguard Worker    it's current contents, the output file will not be modified. This is
23*9880d681SAndroid Build Coastguard Worker    designed to limit the impact of configured files on build dependencies.
24*9880d681SAndroid Build Coastguard Worker    """
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker    # Read in the input data.
27*9880d681SAndroid Build Coastguard Worker    f = open(input_path, "rb")
28*9880d681SAndroid Build Coastguard Worker    try:
29*9880d681SAndroid Build Coastguard Worker        data = f.read()
30*9880d681SAndroid Build Coastguard Worker    finally:
31*9880d681SAndroid Build Coastguard Worker        f.close()
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker    # Perform the substitutions.
34*9880d681SAndroid Build Coastguard Worker    for regex_string,replacement in substitutions:
35*9880d681SAndroid Build Coastguard Worker        regex = re.compile(regex_string)
36*9880d681SAndroid Build Coastguard Worker        data = regex.sub(replacement, data)
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker    # Ensure the output parent directory exists.
39*9880d681SAndroid Build Coastguard Worker    output_parent_path = os.path.dirname(os.path.abspath(output_path))
40*9880d681SAndroid Build Coastguard Worker    if not os.path.exists(output_parent_path):
41*9880d681SAndroid Build Coastguard Worker        os.makedirs(output_parent_path)
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker    # If the output path exists, load it and compare to the configured contents.
44*9880d681SAndroid Build Coastguard Worker    if os.path.exists(output_path):
45*9880d681SAndroid Build Coastguard Worker        current_data = None
46*9880d681SAndroid Build Coastguard Worker        try:
47*9880d681SAndroid Build Coastguard Worker            f = open(output_path, "rb")
48*9880d681SAndroid Build Coastguard Worker            try:
49*9880d681SAndroid Build Coastguard Worker                current_data = f.read()
50*9880d681SAndroid Build Coastguard Worker            except:
51*9880d681SAndroid Build Coastguard Worker                current_data = None
52*9880d681SAndroid Build Coastguard Worker            f.close()
53*9880d681SAndroid Build Coastguard Worker        except:
54*9880d681SAndroid Build Coastguard Worker            current_data = None
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker        if current_data is not None and current_data == data:
57*9880d681SAndroid Build Coastguard Worker            return False
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker    # Write the output contents.
60*9880d681SAndroid Build Coastguard Worker    f = open(output_path, "wb")
61*9880d681SAndroid Build Coastguard Worker    try:
62*9880d681SAndroid Build Coastguard Worker        f.write(data)
63*9880d681SAndroid Build Coastguard Worker    finally:
64*9880d681SAndroid Build Coastguard Worker        f.close()
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker    return True
67