| 1 | import os |
| 2 | |
| 3 | fn 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 | |
| 46 | fn 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 | |
| 72 | fn 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 | |
| 79 | fn 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 | |
| 88 | fn 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 | |
| 96 | fn 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 | |