compile_all.py 6.94 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
    if os.path.isdir(build_dir):
Enrico Pozzobon committed
13
        raise Exception("Directory %s doesn't exist" % build_dir)
14

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
21 22 23 24 25 26
    for r, d, f in os.walk(build_dir):
        for file in f:
            with open(os.path.join(r, file), 'r') as o:
                is_generator = 'generate_test_vectors' in o.read()
            if is_generator:
                os.remove(os.path.join(r, file))
Enrico Pozzobon committed
27

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

Enrico Pozzobon committed
41
    # copy all the files from the template directory into the build directory
42 43 44 45 46 47 48 49 50 51
    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
52
    # prepare the environmental variables for the makefile
Enrico Pozzobon committed
53 54
    env = os.environ
    env['SRC_FILES'] = ' '.join(cfiles)
55
    env['ASM_FILES'] = ' '.join(sfiles)
Enrico Pozzobon committed
56
    env['HDR_FILES'] = ' '.join(hfiles)
57 58 59
    print("SRC_FILES is '%s'" % env['SRC_FILES'])
    print("ASM_FILES is '%s'" % env['ASM_FILES'])
    print("HDR_FILES is '%s'" % env['HDR_FILES'])
Enrico Pozzobon committed
60

Enrico Pozzobon committed
61
    # enter the directory and execute the makefile
Enrico Pozzobon committed
62
    wd = os.getcwd()
Enrico Pozzobon committed
63
    os.chdir(build_dir)
Enrico Pozzobon committed
64
    try:
65
        if os.path.isfile('./configure'):
66
            subprocess.check_call(["./configure"])
67

68 69 70 71 72
        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
73

74
        if os.path.isfile('./cleanup'):
75
            subprocess.check_call(["./cleanup"])
76

Enrico Pozzobon committed
77
    finally:
78 79
        sys.stdout.flush()
        sys.stderr.flush()
Enrico Pozzobon committed
80 81
        os.chdir(wd)

Enrico Pozzobon committed
82
    # if execution arrives here, the build was successful
Enrico Pozzobon committed
83
    return True
Enrico Pozzobon committed
84

Enrico Pozzobon committed
85

86 87
# Find test vectors in the test_vectors directory
def find_test_vectors(variant):
Enrico Pozzobon committed
88
    kat = None
89 90 91 92 93 94
    test_vectors_dir = os.path.join("test_vectors", variant)
    for f in os.listdir(test_vectors_dir):
        if f.startswith("LWC_AEAD_KAT_") and f.endswith(".txt"):
            if kat is not None:
                raise Exception("Multiple test vectors?")
            kat = os.path.join(test_vectors_dir, f)
Enrico Pozzobon committed
95
    return kat
Enrico Pozzobon committed
96

Enrico Pozzobon committed
97

98
def main(argv):
99
    include_list = None
100 101 102

    # Parse the arguments
    argparser = argparse.ArgumentParser(
103
        description='Compiles all LWC submissions for a given template')
104 105 106

    argparser.add_argument('-v', '--verbose', action='count')
    argparser.add_argument('-i', '--include', action='append')
107 108 109 110
    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')
111 112 113 114 115 116

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

    include_list = args.include
117
    submissions_dir = args.submissions_dir
118

119
    print("Using template %s" % template_dir)
Enrico Pozzobon committed
120 121
    subs = os.listdir(submissions_dir)

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

128
        if not os.path.isdir(variants_dir):
Enrico Pozzobon committed
129 130
            continue

131
        if "NOT ACCEPTED" in variants_dir:
Enrico Pozzobon committed
132 133 134 135 136 137
            continue

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

        c = 0
138 139 140
        for variant in os.listdir(variants_dir):
            implementations_dir = os.path.join(
                variants_dir, variant)
141 142
            if not os.path.isdir(implementations_dir):
                continue
143 144 145 146 147 148
            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))
149 150 151 152
                    c += 1

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

154 155
    if include_list is not None:
        print("Include list has %d entries" % len(include_list))
Enrico Pozzobon committed
156

157
    files = []
158 159 160 161 162
    for submission, variant, implementation in implementations:

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

164
        # Source directory d
165 166 167
        d = os.path.join(
            submissions_dir, submission, "Implementations", "crypto_aead",
            variant, implementation)
168 169
        assert os.path.isdir(d)
        print(d)
Enrico Pozzobon committed
170

171
        # Test vectors file t
172
        t = find_test_vectors(variant)
173
        print(t)
Enrico Pozzobon committed
174

175 176
        # if include_list was provided, skip elements not in the list
        if include_list is not None:
177
            if n not in include_list:
178 179
                continue

180 181 182 183 184 185 186
        # Find date of last modification in directory
        st_mtime = 0
        for root, dirs, filess in os.walk(d):
            for name in filess:
                path = os.path.join(root, name)
                st_mtime = max(st_mtime, os.stat(path).st_mtime)

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

190
    # Uncomment next line for testing, if we only want to do 1
191
    # files = files[:1]
192
    print("%d algorithms will be compiled" % len(files))
Enrico Pozzobon committed
193

194 195
    if not os.path.isdir(build_root_dir):
        os.mkdir(build_root_dir)
Enrico Pozzobon committed
196 197 198

    print()

199
    # Build all found algorithms
Enrico Pozzobon committed
200
    for t, d, name, st_mtime in files:
201 202 203 204 205
        print()
        print(d)
        try:
            build_dir = os.path.join(build_root_dir, name)

Enrico Pozzobon committed
206
            build(d, template_dir, build_dir)
207

Enrico Pozzobon committed
208
            shutil.copyfile(t, os.path.join(build_dir, 'LWC_AEAD_KAT.txt'))
209 210 211 212 213 214 215 216 217

            mdate_path = os.path.join(build_dir, 'cipher_mtime.txt')
            with open(mdate_path, 'wt') as mdate_file:
                print(int(st_mtime), file=mdate_file)

            print("COMPILATION SUCCESS FOR %s" % d)
        except Exception as ex:
            print("COMPILATION FAILED FOR %s" % d)
            print(ex)
Enrico Pozzobon committed
218

219 220
    print()

Enrico Pozzobon committed
221 222 223

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