compile_all.py 7 KB
Newer Older
Enrico Pozzobon committed
1 2 3 4
#!/usr/bin/env python3

import os
import sys
Enrico Pozzobon committed
5
import stat
6
import argparse
Enrico Pozzobon committed
7 8 9
import shutil
import subprocess

Enrico Pozzobon committed
10

Enrico Pozzobon committed
11
def build(algo_dir, template_dir, build_dir):
12 13 14
    if os.path.isdir(build_dir):
        return None

15
    print("Building in %s" % build_dir)
16

Enrico Pozzobon committed
17
    # copy all the files from the submitted algorithm into the build directory
Enrico Pozzobon committed
18 19
    shutil.copytree(algo_dir, build_dir)

Enrico Pozzobon committed
20
    # remove the test vectors generator if it is there
Enrico Pozzobon committed
21 22 23 24
    c = os.path.join(build_dir, "genkat_aead.c")
    if os.path.exists(c):
        os.remove(c)

Enrico Pozzobon committed
25
    # find all c and h files, since they will be added to the makefile
26 27 28 29 30 31 32 33 34
    hfiles = []
    cfiles = []
    for r, d, f in os.walk(build_dir):
        for file in f:
            if file.endswith(".c"):
                cfiles.append(file)
            elif file.endswith(".h"):
                hfiles.append(file)

Enrico Pozzobon committed
35
    # copy all the files from the template directory into the build directory
36 37 38 39 40 41 42 43 44 45
    for f in os.listdir(template_dir):
        dst = os.path.join(build_dir, f)
        src = os.path.join(template_dir, f)
        if os.path.isfile(src) or os.path.islink(src):
            shutil.copy2(src, dst)
        elif os.path.isdir(src):
            shutil.copytree(src, dst)
        else:
            raise Exception("I don't know what %s is" % src)

Enrico Pozzobon committed
46
    # prepare the environmental variables for the makefile
Enrico Pozzobon committed
47 48 49 50
    env = os.environ
    env['SRC_FILES'] = ' '.join(cfiles)
    env['HDR_FILES'] = ' '.join(hfiles)

Enrico Pozzobon committed
51
    # enter the directory and execute the makefile
Enrico Pozzobon committed
52
    wd = os.getcwd()
Enrico Pozzobon committed
53
    os.chdir(build_dir)
Enrico Pozzobon committed
54
    try:
55
        if os.path.isfile('./configure'):
56
            subprocess.check_call(["./configure"])
57

58 59 60 61 62
        stdout_path = 'make.stdout.log'
        stderr_path = 'make.stderr.log'
        with open(stdout_path, 'w') as outfile, \
             open(stderr_path, 'w') as errfile:
            subprocess.check_call(['make'], stdout=outfile, stderr=errfile)
Enrico Pozzobon committed
63

64
        if os.path.isfile('./cleanup'):
65
            subprocess.check_call(["./cleanup"])
66

Enrico Pozzobon committed
67
    finally:
68 69
        sys.stdout.flush()
        sys.stderr.flush()
Enrico Pozzobon committed
70 71
        os.chdir(wd)

Enrico Pozzobon committed
72
    # if execution arrives here, the build was successful
Enrico Pozzobon committed
73 74
    return build_dir

Enrico Pozzobon committed
75 76

# Find test vectors in directory or one of the parent directories
Enrico Pozzobon committed
77 78
def find_test_vectors(d):
    kat = None
Enrico Pozzobon committed
79
    while True:
Enrico Pozzobon committed
80 81 82 83 84 85 86
        if d == '':
            raise Exception("Test vector not found")
        for f in os.listdir(d):
            if f.startswith("LWC_AEAD_KAT_") and f.endswith(".txt"):
                if kat is not None:
                    raise Exception("Multiple test vectors?")
                kat = f
Enrico Pozzobon committed
87 88 89 90
        if kat is None:
            d = os.path.split(d)[0]
        else:
            break
Enrico Pozzobon committed
91 92
    kat = os.path.join(d, kat)
    return kat
Enrico Pozzobon committed
93

Enrico Pozzobon committed
94

95
def main(argv):
96
    include_list = None
97 98 99

    # Parse the arguments
    argparser = argparse.ArgumentParser(
100
        description='Compiles all LWC submissions for a given template')
101 102 103

    argparser.add_argument('-v', '--verbose', action='count')
    argparser.add_argument('-i', '--include', action='append')
104 105 106 107
    argparser.add_argument('-t', '--template', default='templates/linux')
    argparser.add_argument('-b', '--build-dir', default='build')
    argparser.add_argument('-s', '--submissions-dir',
                           default='all-lwc-submission-files')
108 109 110 111 112 113

    args = argparser.parse_args(argv[1:])
    template_dir = args.template
    build_root_dir = args.build_dir

    include_list = args.include
114
    submissions_dir = args.submissions_dir
115

116
    print("Using template %s" % template_dir)
Enrico Pozzobon committed
117 118
    subs = os.listdir(submissions_dir)

Enrico Pozzobon committed
119
    # get all the submissions by looking for files named "api.h"
120
    implementations = []
Enrico Pozzobon committed
121
    for submission in subs:
122
        variants_dir = os.path.join(
123
            submissions_dir, submission, "Implementations", "crypto_aead")
Enrico Pozzobon committed
124

125
        if not os.path.isdir(variants_dir):
Enrico Pozzobon committed
126 127
            continue

128
        if "NOT ACCEPTED" in variants_dir:
Enrico Pozzobon committed
129 130 131 132 133 134
            continue

        print()
        print("###  %s  ###" % submission)

        c = 0
135 136 137 138 139 140 141 142 143
        for variant in os.listdir(variants_dir):
            implementations_dir = os.path.join(
                variants_dir, variant)
            for implementation in os.listdir(implementations_dir):
                implementation_dir = os.path.join(
                    implementations_dir, implementation)
                if os.path.isfile(os.path.join(implementation_dir, "api.h")):
                    implementations.append(
                        (submission, variant, implementation))
144 145 146 147
                    c += 1

        if c == 0:
            raise Exception("No implementations found")
Enrico Pozzobon committed
148

149 150
    if include_list is not None:
        print("Include list has %d entries" % len(include_list))
Enrico Pozzobon committed
151

152
    files = []
153 154 155 156 157
    for submission, variant, implementation in implementations:

        # base name n (a.k.a. cipher slug)
        n = '.'.join([submission, variant, implementation])
        print(n)
Enrico Pozzobon committed
158

159
        # Source directory d
160 161 162
        d = os.path.join(
            submissions_dir, submission, "Implementations", "crypto_aead",
            variant, implementation)
163 164
        assert os.path.isdir(d)
        print(d)
Enrico Pozzobon committed
165

166 167 168
        # Test vectors file t
        t = find_test_vectors(d)
        print(t)
Enrico Pozzobon committed
169

170 171
        # if include_list was provided, skip elements not in the list
        if include_list is not None:
172
            if n not in include_list:
173 174 175 176
                continue

        # Put all in a tuple and count
        files.append((t, d, n))
Enrico Pozzobon committed
177

178
    # For testing, we only do the first 1
179
    # files = files[:1]
180
    print("%d algorithms will be compiled" % len(files))
Enrico Pozzobon committed
181

182 183
    if not os.path.isdir(build_root_dir):
        os.mkdir(build_root_dir)
Enrico Pozzobon committed
184 185 186

    print()

Enrico Pozzobon committed
187
    # Write a script that executes all the tests one after the other
188
    test_script_path = os.path.join(build_root_dir, "test_all.sh")
Enrico Pozzobon committed
189 190
    with open(test_script_path, 'w') as test_script:
        test_script.write("#!/bin/sh\n")
Enrico Pozzobon committed
191 192
        test_script.write("mkdir -p logs\n")
        test_script.write("mkdir -p measurements\n")
Enrico Pozzobon committed
193
        for i, (t, d, name) in enumerate(files):
Enrico Pozzobon committed
194 195
            print()
            print(d)
196
            try:
197
                build_dir = os.path.join(build_root_dir, name)
Enrico Pozzobon committed
198
                b = build(d, template_dir, build_dir)
199 200
                if b is None:
                    continue
201 202 203
                test_script.write(
                    "\n\necho \"TEST NUMBER %03d: TESTING %s\"\n" % (i, d))
                test_script.write(
204
                    "python3 -u %s %s %s 2> %s | tee %s\n" % (
205
                        os.path.join(template_dir, 'test'),
206 207
                        os.path.join(b, 'LWC_AEAD_KAT.txt'),
                        b,
Enrico Pozzobon committed
208 209
                        os.path.join(b, 'test_stderr.log'),
                        os.path.join(b, 'test_stdout.log'))
210
                )
211
                shutil.copyfile(t, os.path.join(b, 'LWC_AEAD_KAT.txt'))
Enrico Pozzobon committed
212

213
                print("COMPILATION SUCCESS FOR %s" % d)
Enrico Pozzobon committed
214
            except Exception as ex:
215
                print("COMPILATION FAILED FOR %s" % d)
Enrico Pozzobon committed
216
                print(ex)
217

Enrico Pozzobon committed
218 219
    st = os.stat(test_script_path)
    os.chmod(test_script_path, st.st_mode | stat.S_IEXEC)
Enrico Pozzobon committed
220

221 222 223
    print()
    print()

Enrico Pozzobon committed
224 225 226

if __name__ == "__main__":
    sys.exit(main(sys.argv))