Merge pull request #10285 from flywoo/master
[inav.git] / src / utils / compiler.rb
blobfe2868acd1501e9fb28dedd5706147f5e6eeb72d
1 #!/usr/bin/env ruby
3 # This file is part of INAV.
5 # author: Alberto Garcia Hierro <alberto@garciahierro.com>
7 # This Source Code Form is subject to the terms of the Mozilla Public
8 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
9 # You can obtain one at http://mozilla.org/MPL/2.0/.
11 # Alternatively, the contents of this file may be used under the terms
12 # of the GNU General Public License Version 3, as described below:
14 # This file is free software: you may copy, redistribute and/or modify
15 # it under the terms of the GNU General Public License as published by the
16 # Free Software Foundation, either version 3 of the License, or (at your
17 # option) any later version.
19 # This file is distributed in the hope that it will be useful, but
20 # WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
22 # Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see http://www.gnu.org/licenses/.
27 require 'digest'
28 require 'open3'
29 require 'rbconfig'
30 require 'shellwords'
32 class Compiler
33     def initialize(use_host_gcc)
34         # Look for the compiler in PATH manually, since there
35         # are some issues with the built-in search by spawn()
36         # on Windows if PATH contains spaces.
37         #dirs = ((ENV["CPP_PATH"] || "") + File::PATH_SEPARATOR + (ENV["PATH"] || "")).split(File::PATH_SEPARATOR)
38         dirs = ((ENV["CPP_PATH"] || "") + File::PATH_SEPARATOR + (ENV["PATH"] || "")).split(File::PATH_SEPARATOR)
39         bin = ENV["SETTINGS_CXX"]
40         if bin.empty?
41             if use_host_gcc
42                 bin = "g++"
43             else
44                 bin = "arm-none-eabi-g++"
45             end
46         end
47         dirs.each do |dir|
48             p = File.join(dir, bin)
49             ['', '.exe'].each do |suffix|
50                 f = File.expand_path(p + suffix)
51                 if File.executable?(f)
52                     if @verbose
53                         puts "Found #{bin} at #{f}"
54                     end
55                     @path = f
56                     return
57                 end
58             end
59         end
60         raise "Could not find #{bin} in PATH, looked in #{dirs}"
61         @verbose = ENV["V"] == "1"
62     end
64     def default_args
65         cflags = Shellwords.split(ENV["CFLAGS"] || "")
66         args = [@path]
67         args << "-std=c++11"
68         cflags.each do |flag|
69             # Don't generate temporary files
70             if flag == "" || flag == "-MMD" || flag == "-MP" || flag.start_with?("-save-temps")
71                 next
72             end
73             # -Wstrict-prototypes is not valid for C++
74             if flag == "-Wstrict-prototypes"
75                 next
76             end
77             if flag.start_with? "-std="
78                 next
79             end
80             if flag.start_with? "-D'"
81                 # Cleanup flag. Done by the shell when called from
82                 # it but we must do it ourselves becase we're not
83                 # calling the compiler via shell.
84                 flag = "-D" + flag[3..-2]
85             end
86             args << flag
87         end
88         return args
89     end
91     def run(input, output, args = nil, options = { noerror: false })
92         all_args = default_args
93         if args
94             all_args.push(*args)
95         end
96         if output
97             all_args << "-o" << output
98         end
99         all_args << input
100         stdout, stderr, compile_status = Open3.capture3(join_args(all_args))
101         raise "Compiler error:\n#{all_args.join(' ')}\n#{stderr}" if not options[:noerror] and not compile_status.success?
102         return stdout, stderr
103     end
105     private
107     def join_args(args)
108         if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
109             return args.join(' ')
110         end
111         return Shellwords.join(args)
112     end