v2 / thirdparty / stdatomic / nix / cpp / gen.v
102 lines · 87 sloc · 2.89 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1import os
2
3fn main() {
4 if os.args.len <= 1 {
5 eprintln('please specify a C++ compiler')
6 exit(1)
7 }
8 cc := os.args[1]
9 if os.execute('${os.quoted_path(cc)} -v').exit_code != 0 {
10 eprintln('please specify a valid C++ compiler')
11 exit(1)
12 }
13 cc_type, cc_version, cc_os := get_cc_info(cc)
14 triple := '${cc_type}-${cc_version}-${cc_os}'
15 println('compiler: ${triple}')
16
17 search_paths := get_search_paths(cc)
18 atomic_path := find_file(search_paths, 'atomic') or {
19 eprintln(err)
20 exit(2)
21 }
22
23 bitsatomicbase_path := find_file(search_paths, 'bits/atomic_base.h') or {
24 if cc_os == 'linux' {
25 eprintln(err)
26 exit(2)
27 }
28 'no_file' // bits/atomic_base.h is only used on linux
29 }
30
31 patch_atomic(os.join_path(os.dir(@FILE), 'atomic.h'), atomic_path) or {
32 eprintln(err)
33 exit(2)
34 }
35
36 if bitsatomicbase_path != 'no_file' {
37 patch_bitsatomicbase(os.join_path(os.dir(@FILE), 'bitsatomicbase.h'), bitsatomicbase_path) or {
38 eprintln(err)
39 exit(2)
40 }
41 }
42
43 println('${atomic_path}:::${bitsatomicbase_path}')
44}
45
46fn get_cc_info(cc string) (string, string, string) {
47 cc_type := if cc.contains('clang') {
48 'clang'
49 } else if cc.contains('g') {
50 'gcc'
51 } else {
52 eprintln('only gcc and clang are supported')
53 exit(1)
54 'none'
55 }
56
57 lines := os.execute('${os.quoted_path(cc)} -v').output.split('\n')
58
59 // gcc and clang both have the same way way to say what version they have and what the host target triple is
60 cc_version :=
61 lines.filter(it.contains('${cc_type} version '))[0].all_after('${cc_type} version ').all_before('.')
62
63 cc_os := lines.filter(it.starts_with('Target: '))[0].all_after('Target: ').split('-')[2]
64
65 return cc_type, cc_version, if cc_os.contains('darwin') {
66 'darwin' // remove 20.6.0 from darwin20.6.0
67 } else {
68 cc_os
69 }
70}
71
72fn get_search_paths(cc string) []string {
73 result := os.execute('${os.quoted_path(cc)} -v -x c++ /dev/null').output
74 lines := result.split('\n')
75 search_path := lines[lines.index('#include <...> search starts here:') + 1..lines.index('End of search list.')]
76 return search_path.map(os.real_path(it.all_before('(').trim_space()))
77}
78
79fn find_file(search_paths []string, file string) !string {
80 for search_path in search_paths {
81 if os.exists(os.join_path(search_path, file)) {
82 return os.join_path(search_path, file)
83 }
84 }
85 return error('${file} not found')
86}
87
88fn patch_atomic(outfile string, infile string) ! {
89 lines := os.read_file(infile)!.split('\n')
90 outlines := lines.filter(!it.contains('atomic(const atomic&) = delete;'))
91 outtext := outlines.join('\n').replace('#include <bits/atomic_base.h>',
92 '#include "bitsatomicbase.h"')
93 os.write_file(outfile, outtext)!
94}
95
96fn patch_bitsatomicbase(outfile string, infile string) ! {
97 lines := os.read_file(infile)!.split('\n')
98 outlines := lines.filter(!it.contains('__atomic_base(const __atomic_base&) = delete;'))
99 outtext := outlines.join('\n').replace('#include <bits/atomic_base.h>',
100 '#include "bitsatomicbase.h"')
101 os.write_file(outfile, outtext)!
102}
103