1#!/usr/bin/env python3
2
3import shutil, sys, subprocess, argparse, pathlib
4
5parser = argparse.ArgumentParser()
6
7parser.add_argument('--private-dir', required=True)
8parser.add_argument('-o', nargs='+', required=True)
9parser.add_argument('cmparr', nargs='+')
10
11contents = ['''
12int flob() {
13    return 0;
14}
15''', '''
16int flob() {
17    return 1;
18}
19''']
20
21def generate_lib_gnulike(outfile, c_file, private_dir, compiler_array):
22    if shutil.which('ar'):
23        static_linker = 'ar'
24    elif shutil.which('llvm-ar'):
25        static_linker = 'llvm-ar'
26    elif shutil.which('gcc-ar'):
27        static_linker = 'gcc-ar'
28    else:
29        sys.exit('Could not detect a static linker.')
30    o_file = c_file.with_suffix('.o')
31    compile_cmd = compiler_array + ['-c', '-g', '-O2', '-o', str(o_file), str(c_file)]
32    subprocess.check_call(compile_cmd)
33    out_file = pathlib.Path(outfile)
34    if out_file.exists():
35        out_file.unlink()
36    link_cmd = [static_linker, 'csr', outfile, str(o_file)]
37    subprocess.check_call(link_cmd)
38    return 0
39
40
41def generate_lib_msvc(outfile, c_file, private_dir, compiler_array):
42    static_linker = 'lib'
43    o_file = c_file.with_suffix('.obj')
44    compile_cmd = compiler_array + ['/MDd',
45                                    '/nologo',
46                                    '/ZI',
47                                    '/Ob0',
48                                    '/Od',
49                                    '/c',
50                                    '/Fo' + str(o_file),
51                                    str(c_file)]
52    subprocess.check_call(compile_cmd)
53    out_file = pathlib.Path(outfile)
54    if out_file.exists():
55        out_file.unlink()
56    link_cmd = [static_linker,
57                '/nologo',
58                '/OUT:' + str(outfile),
59                str(o_file)]
60    subprocess.check_call(link_cmd)
61    return 0
62
63def generate_lib(outfiles, private_dir, compiler_array):
64    private_dir = pathlib.Path(private_dir)
65    if not private_dir.exists():
66        private_dir.mkdir()
67
68    for i, content in enumerate(contents):
69        c_file = private_dir / ('flob_' + str(i + 1) + '.c')
70        c_file.write_text(content)
71        outfile = outfiles[i]
72
73        cl_found = False
74        for cl_arg in compiler_array:
75            if (cl_arg.endswith('cl') or cl_arg.endswith('cl.exe')) and 'clang-cl' not in cl_arg:
76                ret = generate_lib_msvc(outfile, c_file, private_dir, compiler_array)
77                if ret > 0:
78                    return ret
79                else:
80                    cl_found = True
81                    break
82        if not cl_found:
83            ret = generate_lib_gnulike(outfile, c_file, private_dir, compiler_array)
84            if ret > 0:
85                return ret
86    return 0
87
88if __name__ == '__main__':
89    options = parser.parse_args()
90    sys.exit(generate_lib(options.o, options.private_dir, options.cmparr))
91