diff options
Diffstat (limited to 'xmake/core/tools')
| -rw-r--r-- | xmake/core/tools/ar.lua | 114 | ||||
| -rw-r--r-- | xmake/core/tools/cat.lua | 43 | ||||
| -rw-r--r-- | xmake/core/tools/clang++.lua | 38 | ||||
| -rw-r--r-- | xmake/core/tools/clang.lua | 38 | ||||
| -rw-r--r-- | xmake/core/tools/cp.lua | 44 | ||||
| -rw-r--r-- | xmake/core/tools/dispatcher.lua | 80 | ||||
| -rw-r--r-- | xmake/core/tools/echo.lua | 44 | ||||
| -rw-r--r-- | xmake/core/tools/g++.lua | 38 | ||||
| -rwxr-xr-x | xmake/core/tools/gas-preprocessor.pl | 1025 | ||||
| -rw-r--r-- | xmake/core/tools/gcc.lua | 192 | ||||
| -rw-r--r-- | xmake/core/tools/make.lua | 82 | ||||
| -rw-r--r-- | xmake/core/tools/mkdir.lua | 46 | ||||
| -rw-r--r-- | xmake/core/tools/mv.lua | 43 | ||||
| -rw-r--r-- | xmake/core/tools/rm.lua | 46 | ||||
| -rw-r--r-- | xmake/core/tools/rmdir.lua | 46 | ||||
| -rw-r--r-- | xmake/core/tools/swiftc.lua | 117 | ||||
| -rw-r--r-- | xmake/core/tools/tools.lua | 222 | ||||
| -rw-r--r-- | xmake/core/tools/verbose.lua | 47 |
18 files changed, 2305 insertions, 0 deletions
diff --git a/xmake/core/tools/ar.lua b/xmake/core/tools/ar.lua new file mode 100644 index 000000000..75e63f83d --- /dev/null +++ b/xmake/core/tools/ar.lua @@ -0,0 +1,114 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file ar.lua +-- + +-- define module: ar +local ar = ar or {} + +-- load modules +local utils = require("base/utils") +local string = require("base/string") +local config = require("base/config") + +-- init the linker +function ar.init(self, name) + + -- save name + self.name = name or "ar" + + -- init arflags + self.arflags = { "-crs" } + +end + +-- make the link command +function ar.command_link(self, objfiles, targetfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = string.format(" > %s 2>&1", logfile) end + + -- make it + return string.format("%s %s %s %s%s", self.name, flags, targetfile, objfiles, redirect) +end + +-- extract the static library to object files +function ar.extract(self, ...) + + -- check + local args = ... + assert(#args == 2 and self.name) + + -- get library and object file path + local libfile = args[1] + local objfile = args[2] + assert(libfile and objfile) + + -- get object directory + local objdir = path.directory(objfile) + if not os.isdir(objdir) then os.mkdir(objdir) end + if not os.isdir(objdir) then + utils.error("%s not found!", objdir) + return false + end + + -- absolute the library path + libfile = path.absolute(libfile) + assert(libfile) + + -- enter the object directory + ok, errors = os.cd(objdir) + if not ok then + utils.error(errors) + return false + end + + -- extract it + local ok = self:main(string.format("%s -x %s", self.name, libfile)) + if not ok then + utils.error("extract %s to %s failed!", libfile, objdir) + return false + end + + -- leave the object directory + ok, errors = os.cd("-") + if not ok then + utils.error(errors) + return false + end + + -- ok + return true +end + + +-- the main function +function ar.main(self, cmd) + + -- execute it + local ok = os.execute(cmd) + + -- ok? + return utils.ifelse(ok == 0, true, false) +end + +-- return module: ar +return ar diff --git a/xmake/core/tools/cat.lua b/xmake/core/tools/cat.lua new file mode 100644 index 000000000..32fea4e24 --- /dev/null +++ b/xmake/core/tools/cat.lua @@ -0,0 +1,43 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file cat.lua +-- + +-- define module: cat +local cat = cat or {} + +-- load modules +local io = require("base/io") +local os = require("base/os") + +-- the main function +function cat.main(self, ...) + + -- cat all + for _, v in ipairs(...) do + if os.isfile(v) then io.cat(v) end + end + + -- ok + return true +end + +-- return module: cat +return cat diff --git a/xmake/core/tools/clang++.lua b/xmake/core/tools/clang++.lua new file mode 100644 index 000000000..37352dec4 --- /dev/null +++ b/xmake/core/tools/clang++.lua @@ -0,0 +1,38 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file clang.lua +-- + +-- load modules +local gcc = require("tools/gcc") + +-- define module: clang++ +local clangxx = clangxx or {} + +-- only copy the interfaces of gcc to clang++ +for k, v in pairs(gcc) do + if type(v) == "function" then + clangxx[k] = v + end +end + +-- return module: clang++ +return clangxx + diff --git a/xmake/core/tools/clang.lua b/xmake/core/tools/clang.lua new file mode 100644 index 000000000..280ae73a6 --- /dev/null +++ b/xmake/core/tools/clang.lua @@ -0,0 +1,38 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file clang.lua +-- + +-- load modules +local gcc = require("tools/gcc") + +-- define module: clang +local clang = clang or {} + +-- only copy the interfaces of gcc to clang +for k, v in pairs(gcc) do + if type(v) == "function" then + clang[k] = v + end +end + +-- return module: clang +return clang + diff --git a/xmake/core/tools/cp.lua b/xmake/core/tools/cp.lua new file mode 100644 index 000000000..1b3ba9843 --- /dev/null +++ b/xmake/core/tools/cp.lua @@ -0,0 +1,44 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file cp.lua +-- + +-- define module: cp +local cp = cp or {} + +-- load modules +local os = require("base/os") + +-- the main function +function cp.main(self, ...) + + -- cp it + local pathes = ... + if pathes and table.getn(pathes) == 2 then + return os.cp(pathes[1], pathes[2]) + end + + -- failed + return false + +end + +-- return module: cp +return cp diff --git a/xmake/core/tools/dispatcher.lua b/xmake/core/tools/dispatcher.lua new file mode 100644 index 000000000..d019937ec --- /dev/null +++ b/xmake/core/tools/dispatcher.lua @@ -0,0 +1,80 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file dispatcher.lua +-- + +-- define module: dispatcher +local dispatcher = dispatcher or {} + +-- load modules +local os = require("base/os") +local path = require("base/path") +local utils = require("base/utils") +local string = require("base/string") +local tools = require("tools/tools") + +-- the main function +-- +-- dispatcher toolname toolpath action arguments ... +function dispatcher.main(self, ...) + + -- check + local args = ... + assert(#args >= 2) + + -- get tool kind and action name + local tool_kind = args[1] + local action_name = args[2] + assert(tool_kind and action_name) + + -- get the tool + local tool = tools.get(tool_kind) + if tool then + + -- load action + local action = tool[action_name] + if action then + + -- init arguments for action + local action_args = {} + for i = 3, #args do + table.insert(action_args, args[i]:decode()) + end + + -- done action + if not action(tool, action_args) then + utils.error("run action %s failed!", action_name) + assert(false) + end + else + utils.error("load action %s failed!", action_name) + assert(false) + end + + else + assert(false) + end + + -- ok + return true +end + +-- return module: dispatcher +return dispatcher diff --git a/xmake/core/tools/echo.lua b/xmake/core/tools/echo.lua new file mode 100644 index 000000000..dbfa67426 --- /dev/null +++ b/xmake/core/tools/echo.lua @@ -0,0 +1,44 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file echo.lua +-- + +-- define module: echo +local echo = echo or {} + +-- load modules +local io = require("base/io") +local string = require("base/string") + +-- the main function +function echo.main(self, ...) + + -- echo all + for _, v in ipairs(...) do + io.write(string.format("%s ", v:decode())) + end + io.write("\n") + + -- ok + return true +end + +-- return module: echo +return echo diff --git a/xmake/core/tools/g++.lua b/xmake/core/tools/g++.lua new file mode 100644 index 000000000..64970b039 --- /dev/null +++ b/xmake/core/tools/g++.lua @@ -0,0 +1,38 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file g++.lua +-- + +-- load modules +local gcc = require("tools/gcc") + +-- define module: gxx +local gxx = gxx or {} + +-- only copy the interfaces of gcc to g++ +for k, v in pairs(gcc) do + if type(v) == "function" then + gxx[k] = v + end +end + +-- return module: g++ +return gxx + diff --git a/xmake/core/tools/gas-preprocessor.pl b/xmake/core/tools/gas-preprocessor.pl new file mode 100755 index 000000000..98dfe4ad9 --- /dev/null +++ b/xmake/core/tools/gas-preprocessor.pl @@ -0,0 +1,1025 @@ +#!/usr/bin/env perl +# by David Conrad +# This code is licensed under GPLv2 or later; go to gnu.org to read it +# (not that it much matters for an asm preprocessor) +# usage: set your assembler to be something like "perl gas-preprocessor.pl gcc" +use strict; + +# Apple's gas is ancient and doesn't support modern preprocessing features like +# .rept and has ugly macro syntax, among other things. Thus, this script +# implements the subset of the gas preprocessor used by x264 and ffmpeg +# that isn't supported by Apple's gas. + +my %canonical_arch = ("aarch64" => "aarch64", "arm64" => "aarch64", + "arm" => "arm", + "powerpc" => "powerpc", "ppc" => "powerpc"); + +my %comments = ("aarch64" => '//', + "arm" => '@', + "powerpc" => '#'); + +my @gcc_cmd; +my @preprocess_c_cmd; + +my $comm; +my $arch; +my $as_type = "apple-gas"; + +my $fix_unreq = $^O eq "darwin"; +my $force_thumb = 0; + +my $arm_cond_codes = "eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo"; + +my $usage_str = " +$0\n +Gas-preprocessor.pl converts assembler files using modern GNU as syntax for +Apple's ancient gas version or clang's incompatible integrated assembler. The +conversion is regularly tested for Libav, x264 and vlc. Other projects might +use different features which are not correctly handled. + +Options for this program needs to be separated with ' -- ' from the assembler +command. Following options are currently supported: + + -help - this usage text + -arch - target architecture + -as-type - one value out of {{,apple-}{gas,clang},armasm} + -fix-unreq + -no-fix-unreq + -force-thumb - assemble as thumb regardless of the input source + (note, this is incomplete and only works for sources + it explicitly was tested with) +"; + +sub usage() { + print $usage_str; +} + +while (@ARGV) { + my $opt = shift; + + if ($opt =~ /^-(no-)?fix-unreq$/) { + $fix_unreq = $1 ne "no-"; + } elsif ($opt eq "-force-thumb") { + $force_thumb = 1; + } elsif ($opt eq "-arch") { + $arch = shift; + die "unknown arch: '$arch'\n" if not exists $comments{$arch}; + } elsif ($opt eq "-as-type") { + $as_type = shift; + die "unknown as type: '$as_type'\n" if $as_type !~ /^((apple-)?(gas|clang)|armasm)$/; + } elsif ($opt eq "-help") { + usage(); + exit 0; + } elsif ($opt eq "--" ) { + @gcc_cmd = @ARGV; + } elsif ($opt =~ /^-/) { + die "option '$opt' is not known. See '$0 -help' for usage information\n"; + } else { + push @gcc_cmd, $opt, @ARGV; + } + last if (@gcc_cmd); +} + +if (grep /\.c$/, @gcc_cmd) { + # C file (inline asm?) - compile + @preprocess_c_cmd = (@gcc_cmd, "-S"); +} elsif (grep /\.[sS]$/, @gcc_cmd) { + # asm file, just do C preprocessor + @preprocess_c_cmd = (@gcc_cmd, "-E"); +} elsif (grep /-(v|-version|dumpversion)/, @gcc_cmd) { + # pass -v/--version along, used during probing. Matching '-v' might have + # uninteded results but it doesn't matter much if gas-preprocessor or + # the compiler fails. + exec(@gcc_cmd); +} else { + die "Unrecognized input filetype"; +} +if ($as_type eq "armasm") { + + $preprocess_c_cmd[0] = "cpp"; + + @preprocess_c_cmd = grep ! /^-nologo$/, @preprocess_c_cmd; + # Remove -ignore XX parameter pairs from preprocess_c_cmd + my $index = 1; + while ($index < $#preprocess_c_cmd) { + if ($preprocess_c_cmd[$index] eq "-ignore" and $index + 1 < $#preprocess_c_cmd) { + splice(@preprocess_c_cmd, $index, 2); + next; + } + $index++; + } + if (grep /^-MM$/, @preprocess_c_cmd) { + system(@preprocess_c_cmd) == 0 or die "Error running preprocessor"; + exit 0; + } +} + +# if compiling, avoid creating an output file named '-.o' +if ((grep /^-c$/, @gcc_cmd) && !(grep /^-o/, @gcc_cmd)) { + foreach my $i (@gcc_cmd) { + if ($i =~ /\.[csS]$/) { + my $outputfile = $i; + $outputfile =~ s/\.[csS]$/.o/; + push(@gcc_cmd, "-o"); + push(@gcc_cmd, $outputfile); + last; + } + } +} +# replace only the '-o' argument with '-', avoids rewriting the make dependency +# target specified with -MT to '-' +my $index = 1; +while ($index < $#preprocess_c_cmd) { + if ($preprocess_c_cmd[$index] eq "-o") { + $index++; + $preprocess_c_cmd[$index] = "-"; + } + $index++; +} + +my $tempfile; +if ($as_type ne "armasm") { + @gcc_cmd = map { /\.[csS]$/ ? qw(-x assembler -) : $_ } @gcc_cmd; +} else { + @preprocess_c_cmd = grep ! /^-c$/, @preprocess_c_cmd; + @preprocess_c_cmd = grep ! /^-m/, @preprocess_c_cmd; + + @preprocess_c_cmd = grep ! /^-G/, @preprocess_c_cmd; + @preprocess_c_cmd = grep ! /^-W/, @preprocess_c_cmd; + @preprocess_c_cmd = grep ! /^-Z/, @preprocess_c_cmd; + @preprocess_c_cmd = grep ! /^-fp/, @preprocess_c_cmd; + @preprocess_c_cmd = grep ! /^-EHsc$/, @preprocess_c_cmd; + @preprocess_c_cmd = grep ! /^-O/, @preprocess_c_cmd; + + @gcc_cmd = grep ! /^-G/, @gcc_cmd; + @gcc_cmd = grep ! /^-W/, @gcc_cmd; + @gcc_cmd = grep ! /^-Z/, @gcc_cmd; + @gcc_cmd = grep ! /^-fp/, @gcc_cmd; + @gcc_cmd = grep ! /^-EHsc$/, @gcc_cmd; + @gcc_cmd = grep ! /^-O/, @gcc_cmd; + + my @outfiles = grep /\.(o|obj)$/, @gcc_cmd; + $tempfile = $outfiles[0].".asm"; + + # Remove most parameters from gcc_cmd, which actually is the armasm command, + # which doesn't support any of the common compiler/preprocessor options. + @gcc_cmd = grep ! /^-D/, @gcc_cmd; + @gcc_cmd = grep ! /^-U/, @gcc_cmd; + @gcc_cmd = grep ! /^-m/, @gcc_cmd; + @gcc_cmd = grep ! /^-M/, @gcc_cmd; + @gcc_cmd = grep ! /^-c$/, @gcc_cmd; + @gcc_cmd = grep ! /^-I/, @gcc_cmd; + @gcc_cmd = map { /\.S$/ ? $tempfile : $_ } @gcc_cmd; +} + +# detect architecture from gcc binary name +if (!$arch) { + if ($gcc_cmd[0] =~ /(arm64|aarch64|arm|powerpc|ppc)/) { + $arch = $1; + } else { + # look for -arch flag + foreach my $i (1 .. $#gcc_cmd-1) { + if ($gcc_cmd[$i] eq "-arch" and + $gcc_cmd[$i+1] =~ /(arm64|aarch64|arm|powerpc|ppc)/) { + $arch = $1; + } + } + } +} + +# assume we're not cross-compiling if no -arch or the binary doesn't have the arch name +$arch = qx/arch/ if (!$arch); + +die "Unknown target architecture '$arch'" if not exists $canonical_arch{$arch}; + +$arch = $canonical_arch{$arch}; +$comm = $comments{$arch}; +my $inputcomm = $comm; +$comm = ";" if $as_type =~ /armasm/; + +my %ppc_spr = (ctr => 9, + vrsave => 256); + +open(INPUT, "-|", @preprocess_c_cmd) || die "Error running preprocessor"; + +if ($ENV{GASPP_DEBUG}) { + open(ASMFILE, ">&STDOUT"); +} else { + if ($as_type ne "armasm") { + open(ASMFILE, "|-", @gcc_cmd) or die "Error running assembler"; + } else { + open(ASMFILE, ">", $tempfile); + } +} + +my $current_macro = ''; +my $macro_level = 0; +my $rept_level = 0; +my %macro_lines; +my %macro_args; +my %macro_args_default; +my $macro_count = 0; +my $altmacro = 0; +my $in_irp = 0; + +my $num_repts; +my @rept_lines; + +my @irp_args; +my $irp_param; + +my @ifstack; + +my %symbols; + +my @sections; + +my %literal_labels; # for ldr <reg>, =<expr> +my $literal_num = 0; +my $literal_expr = ".word"; +$literal_expr = ".quad" if $arch eq "aarch64"; + +my $thumb = 0; + +my %thumb_labels; +my %call_targets; +my %mov32_targets; + +my %neon_alias_reg; +my %neon_alias_type; + +my $temp_label_next = 0; +my %last_temp_labels; +my %next_temp_labels; + +my %labels_seen; + +my %aarch64_req_alias; + +if ($force_thumb) { + parse_line(".thumb\n"); +} + +# pass 1: parse .macro +# note that the handling of arguments is probably overly permissive vs. gas +# but it should be the same for valid cases +while (<INPUT>) { + # remove all comments (to avoid interfering with evaluating directives) + s/(?<!\\)$inputcomm.*//x; + # Strip out windows linefeeds + s/\r$//; + # Strip out line number comments - armasm can handle them in a separate + # syntax, but since the line numbers are off they are only misleading. + s/^#\s+(\d+).*// if $as_type =~ /armasm/; + + parse_line($_); +} + +sub eval_expr { + my $expr = $_[0]; + while ($expr =~ /([A-Za-z._][A-Za-z0-9._]*)/g) { + my $sym = $1; + $expr =~ s/$sym/($symbols{$sym})/ if defined $symbols{$sym}; + } + eval $expr; +} + +sub handle_if { + my $line = $_[0]; + # handle .if directives; apple's assembler doesn't support important non-basic ones + # evaluating them is also needed to handle recursive macros + if ($line =~ /\.if(n?)([a-z]*)\s+(.*)/) { + my $result = $1 eq "n"; + my $type = $2; + my $expr = $3; + + if ($type eq "b") { + $expr =~ s/\s//g; + $result ^= $expr eq ""; + } elsif ($type eq "c") { + if ($expr =~ /(.*)\s*,\s*(.*)/) { + $result ^= $1 eq $2; + } else { + die "argument to .ifc not recognized"; + } + } elsif ($type eq "") { + $result ^= eval_expr($expr) != 0; + } elsif ($type eq "eq") { + $result = eval_expr($expr) == 0; + } elsif ($type eq "lt") { + $result = eval_expr($expr) < 0; + } else { + chomp($line); + die "unhandled .if varient. \"$line\""; + } + push (@ifstack, $result); + return 1; + } else { + return 0; + } +} + +sub parse_if_line { + my $line = $_[0]; + + # evaluate .if blocks + if (scalar(@ifstack)) { + # Don't evaluate any new if statements if we're within + # a repetition or macro - they will be evaluated once + # the repetition is unrolled or the macro is expanded. + if (scalar(@rept_lines) == 0 and $macro_level == 0) { + if ($line =~ /\.endif/) { + pop(@ifstack); + return 1; + } elsif ($line =~ /\.elseif\s+(.*)/) { + if ($ifstack[-1] == 0) { + $ifstack[-1] = !!eval_expr($1); + } elsif ($ifstack[-1] > 0) { + $ifstack[-1] = -$ifstack[-1]; + } + return 1; + } elsif ($line =~ /\.else/) { + $ifstack[-1] = !$ifstack[-1]; + return 1; + } elsif (handle_if($line)) { + return 1; + } + } + + # discard lines in false .if blocks + foreach my $i (0 .. $#ifstack) { + if ($ifstack[$i] <= 0) { + return 1; + } + } + } + return 0; +} + +sub parse_line { + my $line = $_[0]; + + return if (parse_if_line($line)); + + if (scalar(@rept_lines) == 0) { + if (/\.macro/) { + $macro_level++; + if ($macro_level > 1 && !$current_macro) { + die "nested macros but we don't have master macro"; + } + } elsif (/\.endm/) { + $macro_level--; + if ($macro_level < 0) { + die "unmatched .endm"; + } elsif ($macro_level == 0) { + $current_macro = ''; + return; + } + } + } + + if ($macro_level == 0) { + if ($line =~ /\.(rept|irp)/) { + $rept_level++; + } elsif ($line =~ /.endr/) { + $rept_level--; + } + } + + if ($macro_level > 1) { + push(@{$macro_lines{$current_macro}}, $line); + } elsif (scalar(@rept_lines) and $rept_level >= 1) { + push(@rept_lines, $line); + } elsif ($macro_level == 0) { + expand_macros($line); + } else { + if ($line =~ /\.macro\s+([\d\w\.]+)\s*(.*)/) { + $current_macro = $1; + + # commas in the argument list are optional, so only use whitespace as the separator + my $arglist = $2; + $arglist =~ s/,/ /g; + + my @args = split(/\s+/, $arglist); + foreach my $i (0 .. $#args) { + my @argpair = split(/=/, $args[$i]); + $macro_args{$current_macro}[$i] = $argpair[0]; + $argpair[0] =~ s/:vararg$//; + $macro_args_default{$current_macro}{$argpair[0]} = $argpair[1]; + } + # ensure %macro_lines has the macro name added as a key + $macro_lines{$current_macro} = []; + + } elsif ($current_macro) { + push(@{$macro_lines{$current_macro}}, $line); + } else { + die "macro level without a macro name"; + } + } +} + +sub handle_set { + my $line = $_[0]; + if ($line =~ /\.set\s+(.*),\s*(.*)/) { + $symbols{$1} = eval_expr($2); + return 1; + } + return 0; +} + +sub expand_macros { + my $line = $_[0]; + + # handle .if directives; apple's assembler doesn't support important non-basic ones + # evaluating them is also needed to handle recursive macros + if (handle_if($line)) { + return; + } + + if (/\.purgem\s+([\d\w\.]+)/) { + delete $macro_lines{$1}; + delete $macro_args{$1}; + delete $macro_args_default{$1}; + return; + } + + if ($line =~ /\.altmacro/) { + $altmacro = 1; + return; + } + + if ($line =~ /\.noaltmacro/) { + $altmacro = 0; + return; + } + + $line =~ s/\%([^,]*)/eval_expr($1)/eg if $altmacro; + + # Strip out the .set lines from the armasm output + return if (handle_set($line) and $as_type eq "armasm"); + + if ($line =~ /\.rept\s+(.*)/) { + $num_repts = $1; + @rept_lines = ("\n"); + + # handle the possibility of repeating another directive on the same line + # .endr on the same line is not valid, I don't know if a non-directive is + if ($num_repts =~ s/(\.\w+.*)//) { + push(@rept_lines, "$1\n"); + } + $num_repts = eval_expr($num_repts); + } elsif ($line =~ /\.irp\s+([\d\w\.]+)\s*(.*)/) { + $in_irp = 1; + $num_repts = 1; + @rept_lines = ("\n"); + $irp_param = $1; + + # only use whitespace as the separator + my $irp_arglist = $2; + $irp_arglist =~ s/,/ /g; + $irp_arglist =~ s/^\s+//; + @irp_args = split(/\s+/, $irp_arglist); + } elsif ($line =~ /\.irpc\s+([\d\w\.]+)\s*(.*)/) { + $in_irp = 1; + $num_repts = 1; + @rept_lines = ("\n"); + $irp_param = $1; + + my $irp_arglist = $2; + $irp_arglist =~ s/,/ /g; + $irp_arglist =~ s/^\s+//; + @irp_args = split(//, $irp_arglist); + } elsif ($line =~ /\.endr/) { + my @prev_rept_lines = @rept_lines; + my $prev_in_irp = $in_irp; + my @prev_irp_args = @irp_args; + my $prev_irp_param = $irp_param; + my $prev_num_repts = $num_repts; + @rept_lines = (); + $in_irp = 0; + @irp_args = ''; + + if ($prev_in_irp != 0) { + foreach my $i (@prev_irp_args) { + foreach my $origline (@prev_rept_lines) { + my $line = $origline; + $line =~ s/\\$prev_irp_param/$i/g; + $line =~ s/\\\(\)//g; # remove \() + parse_line($line); + } + } + } else { + for (1 .. $prev_num_repts) { + foreach my $origline (@prev_rept_lines) { + my $line = $origline; + parse_line($line); + } + } + } + } elsif ($line =~ /(\S+:|)\s*([\w\d\.]+)\s*(.*)/ && exists $macro_lines{$2}) { + handle_serialized_line($1); + my $macro = $2; + + # commas are optional here too, but are syntactically important because + # parameters can be blank + my @arglist = split(/,/, $3); + my @args; + my @args_seperator; + + my $comma_sep_required = 0; + foreach (@arglist) { + # allow arithmetic/shift operators in macro arguments + $_ =~ s/\s*(\+|-|\*|\/|<<|>>|<|>)\s*/$1/g; + + my @whitespace_split = split(/\s+/, $_); + if (!@whitespace_split) { + push(@args, ''); + push(@args_seperator, ''); + } else { + foreach (@whitespace_split) { + #print ("arglist = \"$_\"\n"); + if (length($_)) { + push(@args, $_); + my $sep = $comma_sep_required ? "," : " "; + push(@args_seperator, $sep); + #print ("sep = \"$sep\", arg = \"$_\"\n"); + $comma_sep_required = 0; + } + } + } + + $comma_sep_required = 1; + } + + my %replacements; + if ($macro_args_default{$macro}){ + %replacements = %{$macro_args_default{$macro}}; + } + + # construct hashtable of text to replace + foreach my $i (0 .. $#args) { + my $argname = $macro_args{$macro}[$i]; + my @macro_args = @{ $macro_args{$macro} }; + if ($args[$i] =~ m/=/) { + # arg=val references the argument name + # XXX: I'm not sure what the expected behaviour if a lot of + # these are mixed with unnamed args + my @named_arg = split(/=/, $args[$i]); + $replacements{$named_arg[0]} = $named_arg[1]; + } elsif ($i > $#{$macro_args{$macro}}) { + # more args given than the macro has named args + # XXX: is vararg allowed on arguments before the last? + $argname = $macro_args{$macro}[-1]; + if ($argname =~ s/:vararg$//) { + #print "macro = $macro, args[$i] = $args[$i], args_seperator=@args_seperator, argname = $argname, arglist[$i] = $arglist[$i], arglist = @arglist, args=@args, macro_args=@macro_args\n"; + #$replacements{$argname} .= ", $args[$i]"; + $replacements{$argname} .= "$args_seperator[$i] $args[$i]"; + } else { + die "Too many arguments to macro $macro"; + } + } else { + $argname =~ s/:vararg$//; + $replacements{$argname} = $args[$i]; + } + } + + my $count = $macro_count++; + + # apply replacements as regex + foreach (@{$macro_lines{$macro}}) { + my $macro_line = $_; + # do replacements by longest first, this avoids wrong replacement + # when argument names are subsets of each other + foreach (reverse sort {length $a <=> length $b} keys %replacements) { + $macro_line =~ s/\\$_/$replacements{$_}/g; + } + if ($altmacro) { + foreach (reverse sort {length $a <=> length $b} keys %replacements) { + $macro_line =~ s/\b$_\b/$replacements{$_}/g; + } + } + $macro_line =~ s/\\\@/$count/g; + $macro_line =~ s/\\\(\)//g; # remove \() + parse_line($macro_line); + } + } else { + handle_serialized_line($line); + } +} + +sub is_arm_register { + my $name = $_[0]; + if ($name eq "lr" or + $name eq "ip" or + $name =~ /^[rav]\d+$/) { + return 1; + } + return 0; +} + +sub handle_local_label { + my $line = $_[0]; + my $num = $_[1]; + my $dir = $_[2]; + my $target = "$num$dir"; + if ($dir eq "b") { + $line =~ s/$target/$last_temp_labels{$num}/g; + } else { + my $name = "temp_label_$temp_label_next"; + $temp_label_next++; + push(@{$next_temp_labels{$num}}, $name); + $line =~ s/$target/$name/g; + } + return $line; +} + +sub handle_serialized_line { + my $line = $_[0]; + + # handle .previous (only with regard to .section not .subsection) + if ($line =~ /\.(section|text|const_data)/) { + push(@sections, $line); + } elsif ($line =~ /\.previous/) { + if (!$sections[-2]) { + die ".previous without a previous section"; + } + $line = $sections[-2]; + push(@sections, $line); + } + + $thumb = 1 if $line =~ /\.code\s+16|\.thumb/; + $thumb = 0 if $line =~ /\.code\s+32|\.arm/; + + # handle ldr <reg>, =<expr> + if ($line =~ /(.*)\s*ldr([\w\s\d]+)\s*,\s*=(.*)/ and $as_type ne "armasm") { + my $label = $literal_labels{$3}; + if (!$label) { + $label = "Literal_$literal_num"; + $literal_num++; + $literal_labels{$3} = $label; + } + $line = "$1 ldr$2, $label\n"; + } elsif ($line =~ /\.ltorg/ and $as_type ne "armasm") { + $line .= ".align 2\n"; + foreach my $literal (keys %literal_labels) { + $line .= "$literal_labels{$literal}:\n $literal_expr $literal\n"; + } + %literal_labels = (); + } + + # handle GNU as pc-relative relocations for adrp/add + if ($line =~ /(.*)\s*adrp([\w\s\d]+)\s*,\s*#?:pg_hi21:([^\s]+)/) { + $line = "$1 adrp$2, ${3}\@PAGE\n"; + } elsif ($line =~ /(.*)\s*add([\w\s\d]+)\s*,([\w\s\d]+)\s*,\s*#?:lo12:([^\s]+)/) { + $line = "$1 add$2, $3, ${4}\@PAGEOFF\n"; + } + + # thumb add with large immediate needs explicit add.w + if ($thumb and $line =~ /add\s+.*#([^@]+)/) { + $line =~ s/add/add.w/ if eval_expr($1) > 255; + } + + # mach-o local symbol names start with L (no dot) + $line =~ s/(?<!\w)\.(L\w+)/$1/g; + + # recycle the '.func' directive for '.thumb_func' + if ($thumb and $as_type =~ /^apple-/) { + $line =~ s/\.func/.thumb_func/x; + } + + if ($thumb and $line =~ /^\s*(\w+)\s*:/) { + $thumb_labels{$1}++; + } + + if ($as_type =~ /^apple-/ and + $line =~ /^\s*((\w+\s*:\s*)?bl?x?(..)?(?:\.w)?|\.global)\s+(\w+)/) { + my $cond = $3; + my $label = $4; + # Don't interpret e.g. bic as b<cc> with ic as conditional code + if ($cond =~ /|$arm_cond_codes/) { + if (exists $thumb_labels{$label}) { + print ASMFILE ".thumb_func $label\n"; + } else { + $call_targets{$label}++; + } + } + } + + # @l -> lo16() @ha -> ha16() + $line =~ s/,\s+([^,]+)\@l\b/, lo16($1)/g; + $line =~ s/,\s+([^,]+)\@ha\b/, ha16($1)/g; + + # move to/from SPR + if ($line =~ /(\s+)(m[ft])([a-z]+)\s+(\w+)/ and exists $ppc_spr{$3}) { + if ($2 eq 'mt') { + $line = "$1${2}spr $ppc_spr{$3}, $4\n"; + } else { + $line = "$1${2}spr $4, $ppc_spr{$3}\n"; + } + } + + if ($line =~ /\.unreq\s+(.*)/) { + if (defined $neon_alias_reg{$1}) { + delete $neon_alias_reg{$1}; + delete $neon_alias_type{$1}; + return; + } elsif (defined $aarch64_req_alias{$1}) { + delete $aarch64_req_alias{$1}; + return; + } + } + # old gas versions store upper and lower case names on .req, + # but they remove only one on .unreq + if ($fix_unreq) { + if ($line =~ /\.unreq\s+(.*)/) { + $line = ".unreq " . lc($1) . "\n"; + $line .= ".unreq " . uc($1) . "\n"; + } + } + + if ($line =~ /(\w+)\s+\.(dn|qn)\s+(\w+)(?:\.(\w+))?(\[\d+\])?/) { + $neon_alias_reg{$1} = "$3$5"; + $neon_alias_type{$1} = $4; + return; + } + if (scalar keys %neon_alias_reg > 0 && $line =~ /^\s+v\w+/) { + # This line seems to possibly have a neon instruction + foreach (keys %neon_alias_reg) { + my $alias = $_; + # Require the register alias to match as an invididual word, not as a substring + # of a larger word-token. + if ($line =~ /\b$alias\b/) { + $line =~ s/\b$alias\b/$neon_alias_reg{$alias}/g; + # Add the type suffix. If multiple aliases match on the same line, + # only do this replacement the first time (a vfoo.bar string won't match v\w+). + $line =~ s/^(\s+)(v\w+)(\s+)/$1$2.$neon_alias_type{$alias}$3/; + } + } + } + + if ($arch eq "aarch64" or $as_type eq "armasm") { + # clang's integrated aarch64 assembler in Xcode 5 does not support .req/.unreq + if ($line =~ /\b(\w+)\s+\.req\s+(\w+)\b/) { + $aarch64_req_alias{$1} = $2; + return; + } + foreach (keys %aarch64_req_alias) { + my $alias = $_; + # recursively resolve aliases + my $resolved = $aarch64_req_alias{$alias}; + while (defined $aarch64_req_alias{$resolved}) { + $resolved = $aarch64_req_alias{$resolved}; + } + $line =~ s/\b$alias\b/$resolved/g; + } + } + if ($arch eq "aarch64") { + # fix missing aarch64 instructions in Xcode 5.1 (beta3) + # mov with vector arguments is not supported, use alias orr instead + if ($line =~ /^\s*mov\s+(v\d[\.{}\[\]\w]+),\s*(v\d[\.{}\[\]\w]+)\b\s*$/) { + $line = " orr $1, $2, $2\n"; + } + # movi 16, 32 bit shifted variant, shift is optional + if ($line =~ /^\s*movi\s+(v[0-3]?\d\.(?:2|4|8)[hsHS])\s*,\s*(#\w+)\b\s*$/) { + $line = " movi $1, $2, lsl #0\n"; + } + # Xcode 5 misses the alias uxtl. Replace it with the more general ushll. + # Clang 3.4 misses the alias sxtl too. Replace it with the more general sshll. + if ($line =~ /^\s*(s|u)xtl(2)?\s+(v[0-3]?\d\.[248][hsdHSD])\s*,\s*(v[0-3]?\d\.(?:2|4|8|16)[bhsBHS])\b\s*$/) { + $line = " $1shll$2 $3, $4, #0\n"; + } + # clang 3.4 does not automatically use shifted immediates in add/sub + if ($as_type eq "clang" and + $line =~ /^(\s*(?:add|sub)s?) ([^#l]+)#([\d\+\-\*\/ <>]+)\s*$/) { + my $imm = eval $3; + if ($imm > 4095 and not ($imm & 4095)) { + $line = "$1 $2#" . ($imm >> 12) . ", lsl #12\n"; + } + } + if ($ENV{GASPP_FIX_XCODE5}) { + if ($line =~ /^\s*bsl\b/) { + $line =~ s/\b(bsl)(\s+v[0-3]?\d\.(\w+))\b/$1.$3$2/; + $line =~ s/\b(v[0-3]?\d)\.$3\b/$1/g; + } + if ($line =~ /^\s*saddl2?\b/) { + $line =~ s/\b(saddl2?)(\s+v[0-3]?\d\.(\w+))\b/$1.$3$2/; + $line =~ s/\b(v[0-3]?\d)\.\w+\b/$1/g; + } + if ($line =~ /^\s*dup\b.*\]$/) { + $line =~ s/\bdup(\s+v[0-3]?\d)\.(\w+)\b/dup.$2$1/g; + $line =~ s/\b(v[0-3]?\d)\.[bhsdBHSD](\[\d\])$/$1$2/g; + } + } + } + + if ($as_type eq "armasm") { + # Also replace variables set by .set + foreach (keys %symbols) { + my $sym = $_; + $line =~ s/\b$sym\b/$symbols{$sym}/g; + } + + # Handle function declarations and keep track of the declared labels + if ($line =~ s/^\s*\.func\s+(\w+)/$1 PROC/) { + $labels_seen{$1} = 1; + } + + if ($line =~ s/^(\d+)://) { + # Convert local labels into unique labels. armasm (at least in + # RVCT) has something similar, but still different enough. + # By converting to unique labels we avoid any possible + # incompatibilities. + + my $num = $1; + foreach (@{$next_temp_labels{$num}}) { + $line = "$_\n" . $line; + } + @next_temp_labels{$num} = (); + my $name = "temp_label_$temp_label_next"; + $temp_label_next++; + # The matching regexp above removes the label from the start of + # the line (which might contain an instruction as well), readd + # it on a separate line above it. + $line = "$name:\n" . $line; + $last_temp_labels{$num} = $name; + } + + if ($line =~ s/^(\w+):/$1/) { + # Skip labels that have already been declared with a PROC, + # labels must not be declared multiple times. + return if (defined $labels_seen{$1}); + $labels_seen{$1} = 1; + } elsif ($line !~ /(\w+) PROC/) { + # If not a label, make sure the line starts with whitespace, + # otherwise ms armasm interprets it incorrectly. + $line =~ s/^[\.\w]/\t$&/; + } + + + # Check branch instructions + if ($line =~ /(?:^|\n)\s*(\w+\s*:\s*)?(bl?x?(..)?(\.w)?)\s+(\w+)/) { + my $instr = $2; + my $cond = $3; + my $width = $4; + my $target = $5; + # Don't interpret e.g. bic as b<cc> with ic as conditional code + if ($cond !~ /|$arm_cond_codes/) { + # Not actually a branch + } elsif ($target =~ /(\d+)([bf])/) { + # The target is a local label + $line = handle_local_label($line, $1, $2); + $line =~ s/\b$instr\b/$&.w/ if $width eq ""; + } elsif (!is_arm_register($target)) { + $call_targets{$target}++; + } + } elsif ($line =~ /^\s*.h?word.*\b\d+[bf]\b/) { + while ($line =~ /\b(\d+)([bf])\b/g) { + $line = handle_local_label($line, $1, $2); + } + } + + # ALIGN in armasm syntax is the actual number of bytes + if ($line =~ /\.align\s+(\d+)/) { + my $align = 1 << $1; + $line =~ s/\.align\s(\d+)/ALIGN $align/; + } + # Convert gas style [r0, :128] into armasm [r0@128] alignment specification + $line =~ s/\[([^\[]+),\s*:(\d+)\]/[$1\@$2]/g; + + # armasm treats logical values {TRUE} and {FALSE} separately from + # numeric values - logical operators and values can't be intermixed + # with numerical values. Evaluate !<number> and (a <> b) into numbers, + # let the assembler evaluate the rest of the expressions. This current + # only works for cases when ! and <> are used with actual constant numbers, + # we don't evaluate subexpressions here. + + # Evaluate !<number> + while ($line =~ /!\s*(\d+)/g) { + my $val = ($1 != 0) ? 0 : 1; + $line =~ s/!(\d+)/$val/; + } + # Evaluate (a > b) + while ($line =~ /\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/) { + my $val; + if ($2 eq "<") { + $val = ($1 < $3) ? 1 : 0; + } else { + $val = ($1 > $3) ? 1 : 0; + } + $line =~ s/\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/$val/; + } + + # Change a movw... #:lower16: into a mov32 pseudoinstruction + $line =~ s/^(\s*)movw(\s+\w+\s*,\s*)\#:lower16:(.*)$/$1mov32$2$3/; + # and remove the following, matching movt completely + $line =~ s/^\s*movt\s+\w+\s*,\s*\#:upper16:.*$//; + + if ($line =~ /^\s*mov32\s+\w+,\s*([a-zA-Z]\w*)/) { + $mov32_targets{$1}++; + } + + # Misc bugs/deficiencies: + # armasm seems unable to parse e.g. "vmov s0, s1" without a type + # qualifier, thus add .f32. + $line =~ s/^(\s+(?:vmov|vadd))(\s+s)/$1.f32$2/; + # armasm is unable to parse &0x - add spacing + $line =~ s/&0x/& 0x/g; + } + + if ($force_thumb) { + # Convert register post indexing to a separate add instruction. + # This converts e.g. "ldr r0, [r1], r2" into "ldr r0, [r1]", + # "add r1, r1, r2". + $line =~ s/(ldr|str)\s+(\w+),\s*\[(\w+)\],\s*(\w+)/$1 $2, [$3]\n\tadd $3, $3, $4/g; + + # Convert "mov pc, lr" into "bx lr", since the former only works + # for switching from arm to thumb (and only in armv7), but not + # from thumb to arm. + s/mov\s*pc\s*,\s*lr/bx lr/g; + + # Convert stmdb/ldmia with only one register into a plain str/ldr with post-increment/decrement + $line =~ s/stmdb\s+sp!\s*,\s*\{([^,-]+)\}/str $1, [sp, #-4]!/g; + $line =~ s/ldmia\s+sp!\s*,\s*\{([^,-]+)\}/ldr $1, [sp], #4/g; + + $line =~ s/\.arm/.thumb/x; + } + + # comment out unsupported directives + $line =~ s/\.type/$comm$&/x if $as_type =~ /^(apple-|armasm)/; + $line =~ s/\.func/$comm$&/x if $as_type =~ /^(apple-|clang)/; + $line =~ s/\.endfunc/$comm$&/x if $as_type =~ /^(apple-|clang)/; + $line =~ s/\.endfunc/ENDP/x if $as_type =~ /armasm/; + $line =~ s/\.ltorg/$comm$&/x if $as_type =~ /^(apple-|clang)/; + $line =~ s/\.ltorg/LTORG/x if $as_type eq "armasm"; + $line =~ s/\.size/$comm$&/x if $as_type =~ /^(apple-|armasm)/; + $line =~ s/\.fpu/$comm$&/x if $as_type =~ /^(apple-|armasm)/; + $line =~ s/\.arch/$comm$&/x if $as_type =~ /^(apple-|clang|armasm)/; + $line =~ s/\.object_arch/$comm$&/x if $as_type =~ /^(apple-|armasm)/; + $line =~ s/.section\s+.note.GNU-stack.*/$comm$&/x if $as_type =~ /^(apple-|armasm)/; + $line =~ s/\.hidden/$comm$&/x if $as_type =~ /^(apple-|clang|armasm)/; + + $line =~ s/\.syntax/$comm$&/x if $as_type =~ /armasm/; + + $line =~ s/\.hword/.short/x; + + if ($as_type =~ /^apple-/) { + # the syntax for these is a little different + $line =~ s/\.global/.globl/x; + # also catch .section .rodata since the equivalent to .const_data is .section __DATA,__const + $line =~ s/(.*)\.rodata/.const_data/x; + $line =~ s/\.int/.long/x; + $line =~ s/\.float/.single/x; + } + if ($as_type eq "armasm") { + $line =~ s/\.global/EXPORT/x; + $line =~ s/\.int/dcd/x; + $line =~ s/\.long/dcd/x; + $line =~ s/\.float/dcfs/x; + $line =~ s/\.word/dcd/x; + $line =~ s/\.short/dcw/x; + $line =~ s/\.byte/dcb/x; + $line =~ s/\.thumb/THUMB/x; + $line =~ s/\.arm/ARM/x; + # The alignment in AREA is the power of two, just as .align in gas + $line =~ s/\.text/AREA |.text|, CODE, READONLY, ALIGN=2, CODEALIGN/; + $line =~ s/(\s*)(.*)\.rodata/$1AREA |.rodata|, DATA, READONLY, ALIGN=5/; + + $line =~ s/fmxr/vmsr/; + $line =~ s/fmrx/vmrs/; + $line =~ s/fadds/vadd/; + } + + # catch unknown section names that aren't mach-o style (with a comma) + if ($as_type =~ /apple-/ and $line =~ /.section ([^,]*)$/) { + die ".section $1 unsupported; figure out the mach-o section name and add it"; + } + + print ASMFILE $line; +} + +if ($as_type ne "armasm") { + print ASMFILE ".text\n"; + print ASMFILE ".align 2\n"; + foreach my $literal (keys %literal_labels) { + print ASMFILE "$literal_labels{$literal}:\n $literal_expr $literal\n"; + } + + map print(ASMFILE ".thumb_func $_\n"), + grep exists $thumb_labels{$_}, keys %call_targets; +} else { + map print(ASMFILE "\tIMPORT $_\n"), + grep ! exists $labels_seen{$_}, (keys %call_targets, keys %mov32_targets); + + print ASMFILE "\tEND\n"; +} + +close(INPUT) or exit 1; +close(ASMFILE) or exit 1; +if ($as_type eq "armasm" and ! defined $ENV{GASPP_DEBUG}) { + system(@gcc_cmd) == 0 or die "Error running assembler"; +} + +END { + unlink($tempfile) if defined $tempfile; +} +#exit 1 diff --git a/xmake/core/tools/gcc.lua b/xmake/core/tools/gcc.lua new file mode 100644 index 000000000..ab5e94ccb --- /dev/null +++ b/xmake/core/tools/gcc.lua @@ -0,0 +1,192 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file gcc.lua +-- + +-- load modules +local utils = require("base/utils") +local table = require("base/table") +local string = require("base/string") +local config = require("base/config") +local platform = require("platform/platform") + +-- define module: gcc +local gcc = gcc or {} + +-- check the given flag +function gcc._check(self, flag) + + -- this flag has been checked? + self._CHECK = self._CHECK or {} + if self._CHECK[flag] then + return self._CHECK[flag] + end + + -- check it + local result = flag + if 0 ~= os.execute(string.format("%s %s -S -o %s -xc %s > %s 2>&1", self.name, flag, xmake._NULDEV, xmake._NULDEV, xmake._NULDEV)) then + result = "" + end + + -- trace + utils.verbose("checking for the compiler flags %s ... %s", flag, utils.ifelse(#result ~= 0, "ok", "no")) + + -- save it + self._CHECK[flag] = result + + -- ok? + return result +end + +-- the init function +function gcc.init(self, name) + + -- save name + self.name = name or "gcc" + + -- init mxflags + self.mxflags = { "-fmessage-length=0" + , "-pipe" + , "-fpascal-strings" + , "\"-DIBOutlet=__attribute__((iboutlet))\"" + , "\"-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))\"" + , "\"-DIBAction=void)__attribute__((ibaction)\""} + + -- init shflags + if name:find("clang") then + self.shflags = { "-dynamiclib", "-fPIC" } + else + self.shflags = { "-shared", "-fPIC" } + end + + -- init cxflags for the kind: shared + self.shared = {} + self.shared.cxflags = {"-fPIC"} + + -- suppress warning for the clang + local isclang = false + if name:find("clang") then + isclang = true + self.cxflags = self.cxflags or {} + self.mxflags = self.mxflags or {} + self.asflags = self.asflags or {} + table.join2(self.cxflags, "-Qunused-arguments") + table.join2(self.mxflags, "-Qunused-arguments") + table.join2(self.asflags, "-Qunused-arguments") + end + + -- init flags map + self.mapflags = + { + -- vectorexts + ["-mmmx"] = self._check + , ["-msse$"] = self._check + , ["-msse2"] = self._check + , ["-msse3"] = self._check + , ["-mssse3"] = self._check + , ["-mavx$"] = self._check + , ["-mavx2"] = self._check + , ["-mfpu=.*"] = self._check + + -- warnings + , ["-W1"] = "-Wall" + , ["-W2"] = "-Wall" + , ["-W3"] = "-Wall" + + -- strip + , ["-s"] = utils.ifelse(isclang, "-Wl,-S", "-s") + , ["-S"] = utils.ifelse(isclang, "-Wl,-S", "-S") + + -- others + , ["-ftrapv"] = self._check + , ["-fsanitize=address"] = self._check + } + +end + +-- make the compile command +function gcc.command_compile(self, srcfile, objfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = string.format(" > %s 2>&1", logfile) end + + -- make it + return string.format("%s -c %s -o %s %s%s", self.name, flags, objfile, srcfile, redirect) +end + +-- make the link command +function gcc.command_link(self, objfiles, targetfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = string.format(" > %s 2>&1", logfile) end + + -- make it + return string.format("%s -o %s %s %s%s", self.name, targetfile, objfiles, flags, redirect) +end + +-- make the define flag +function gcc.flag_define(self, define) + + -- make it + return "-D" .. define:gsub("\"", "\\\"") +end + +-- make the undefine flag +function gcc.flag_undefine(self, undefine) + + -- make it + return "-U" .. undefine +end + +-- make the includedir flag +function gcc.flag_includedir(self, includedir) + + -- make it + return "-I" .. includedir +end + +-- make the link flag +function gcc.flag_link(self, link) + + -- make it + return "-l" .. link +end + +-- make the linkdir flag +function gcc.flag_linkdir(self, linkdir) + + -- make it + return "-L" .. linkdir +end + +-- the main function +function gcc.main(self, cmd) + + -- execute it + local ok = os.execute(cmd) + + -- ok? + return utils.ifelse(ok == 0, true, false) +end + +-- return module: gcc +return gcc diff --git a/xmake/core/tools/make.lua b/xmake/core/tools/make.lua new file mode 100644 index 000000000..5d2d1f42b --- /dev/null +++ b/xmake/core/tools/make.lua @@ -0,0 +1,82 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file make.lua +-- + +-- load modules +local os = require("base/os") +local utils = require("base/utils") + +-- define module: make +local make = make or {} + +-- the init function +function make.init(self, name) + + -- save name + self.name = name or "make" + + -- is verbose? + self._VERBOSE = utils.ifelse(xmake._OPTIONS.verbose, "-v", "") + +end + +-- the main function +function make.main(self, mkfile, target) + + -- enable jobs? + local jobs = "" + if xmake._OPTIONS.jobs ~= nil then + if tonumber(xmake._OPTIONS.jobs) ~= 0 then + jobs = "-j" .. xmake._OPTIONS.jobs + else + jobs = "-j" + end + end + + -- make command + local cmd = nil + if mkfile and os.isfile(mkfile) then + cmd = string.format("%s -r %s -f %s %s VERBOSE=%s", self.name, jobs, mkfile, target or "", self._VERBOSE) + else + cmd = string.format("%s -r %s %s VERBOSE=%s", self.name, jobs, target or "", self._VERBOSE) + end + + -- done + local ok = os.execute(cmd) + if ok ~= 0 then + + -- attempt to execute it again for getting the error logs without jobs + if mkfile and os.isfile(mkfile) then + cmd = string.format("%s -r -f %s %s VERBOSE=%s", self.name, mkfile, target or "", self._VERBOSE) + else + cmd = string.format("%s -r %s VERBOSE=%s", self.name, target or "", self._VERBOSE) + end + + -- done + return os.execute(cmd) == 0 + end + + -- ok + return true +end + +-- return module: make +return make diff --git a/xmake/core/tools/mkdir.lua b/xmake/core/tools/mkdir.lua new file mode 100644 index 000000000..9fadb875d --- /dev/null +++ b/xmake/core/tools/mkdir.lua @@ -0,0 +1,46 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file mkdir.lua +-- + +-- define module: mkdir +local mkdir = mkdir or {} + +-- load modules +local os = require("base/os") + +-- the main function +function mkdir.main(self, ...) + + -- mkdir all + for _, dir in ipairs(...) do + if not os.exists(dir) then + if not os.mkdir(dir) then + return false + end + end + end + + -- ok + return true +end + +-- return module: mkdir +return mkdir diff --git a/xmake/core/tools/mv.lua b/xmake/core/tools/mv.lua new file mode 100644 index 000000000..7af2db9ed --- /dev/null +++ b/xmake/core/tools/mv.lua @@ -0,0 +1,43 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file mv.lua +-- + +-- define module: mv +local mv = mv or {} + +-- load modules +local os = require("base/os") + +-- the main function +function mv.main(self, ...) + + -- mv it + local pathes = ... + if pathes and table.getn(pathes) == 2 then + return os.mv(pathes[1], pathes[2]) + end + + -- failed + return false +end + +-- return module: mv +return mv diff --git a/xmake/core/tools/rm.lua b/xmake/core/tools/rm.lua new file mode 100644 index 000000000..47f57e68b --- /dev/null +++ b/xmake/core/tools/rm.lua @@ -0,0 +1,46 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file rm.lua +-- + +-- define module: rm +local rm = rm or {} + +-- load modules +local os = require("base/os") + +-- the main function +function rm.main(self, ...) + + -- rm all + for _, file_or_dir in ipairs(...) do + if os.exists(file_or_dir) then + if not os.rm(file_or_dir) then + return false + end + end + end + + -- ok + return true +end + +-- return module: rm +return rm diff --git a/xmake/core/tools/rmdir.lua b/xmake/core/tools/rmdir.lua new file mode 100644 index 000000000..cea1e28fa --- /dev/null +++ b/xmake/core/tools/rmdir.lua @@ -0,0 +1,46 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file rmdir.lua +-- + +-- define module: rmdir +local rmdir = rmdir or {} + +-- load modules +local os = require("base/os") + +-- the main function +function rmdir.main(self, ...) + + -- rmdir all + for _, dir in ipairs(...) do + if os.isdir(dir) then + if not os.rmdir(dir) then + return false + end + end + end + + -- ok + return true +end + +-- return module: rmdir +return rmdir diff --git a/xmake/core/tools/swiftc.lua b/xmake/core/tools/swiftc.lua new file mode 100644 index 000000000..39142705f --- /dev/null +++ b/xmake/core/tools/swiftc.lua @@ -0,0 +1,117 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file swiftc.lua +-- + +-- load modules +local utils = require("base/utils") +local table = require("base/table") +local string = require("base/string") +local config = require("base/config") +local platform = require("platform/platform") + +-- define module: swiftc +local swiftc = swiftc or {} + +-- the init function +function swiftc.init(self, name) + + -- save name + self.name = name or "swiftc" + + -- init flags map + self.mapflags = + { + -- symbols + ["-fvisibility=hidden"] = "" + + -- warnings + , ["-w"] = "" + , ["-W.*"] = "" + + -- optimize + , ["-O0"] = "-Onone" + , ["-Ofast"] = "-Ounchecked" + , ["-O.*"] = "-O" + + -- vectorexts + , ["-m.*"] = "" + + -- strip + , ["-s"] = "" + , ["-S"] = "" + + -- others + , ["-ftrapv"] = "" + , ["-fsanitize=address"] = "" + } + + -- init ldflags + local swift_linkdirs = config.get("__swift_linkdirs") + if swift_linkdirs then + self.ldflags = { "-L" .. swift_linkdirs } + end + +end + +-- make the compile command +function swiftc.command_compile(self, srcfile, objfile, flags, logfile) + + -- redirect + local redirect = "" + if logfile then redirect = string.format(" > %s 2>&1", logfile) end + + -- make it + return string.format("%s -c %s -o %s %s%s", self.name, flags, objfile, srcfile, redirect) +end + +-- make the includedir flag +function swiftc.flag_includedir(self, includedir) + + -- make it + return "-Xcc -I" .. includedir +end + +-- make the define flag +function swiftc.flag_define(self, define) + + -- make it + return "-Xcc -D" .. define:gsub("\"", "\\\"") +end + +-- make the undefine flag +function swiftc.flag_undefine(self, undefine) + + -- make it + return "-Xcc -U" .. undefine +end + +-- the main function +function swiftc.main(self, cmd) + + -- execute it + local ok = os.execute(cmd) + + -- ok? + return utils.ifelse(ok == 0, true, false) +end + +-- return module: swiftc +return swiftc diff --git a/xmake/core/tools/tools.lua b/xmake/core/tools/tools.lua new file mode 100644 index 000000000..a61322d3c --- /dev/null +++ b/xmake/core/tools/tools.lua @@ -0,0 +1,222 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file tools.lua +-- + +-- define module: tools +local tools = tools or {} + +-- load modules +local os = require("base/os") +local path = require("base/path") +local utils = require("base/utils") +local string = require("base/string") +local platform = require("platform/platform") + +-- match the tool name +function tools._match(name, toolname) + + -- match full? ok + if name == toolname then return 100 end + + -- match the name for windows? ok + if name:find("^" .. toolname .. "%.exe") then return 90 end + if name:find(toolname .. "%.exe") then return 85 end + + -- match the last word? ok + if name:find(toolname .. "$") then return 80 end + + -- match the partial word? ok + if name:find("%-" .. toolname) then return 60 end + + -- contains it? ok + if name:find(toolname, 1, true) then return 30 end + + -- not matched + return 0 +end + +-- find tool from the given root directory and name +function tools._find_from(root, name) + + -- attempt to get it directly first + local filepath = string.format("%s/%s.lua", root, name) + if os.isfile(filepath) then + return filepath + end + + -- make the lower name + name = name:lower() + + -- get all tool files + local file_ok = nil + local score_maxn = 0 + local files = os.match(string.format("%s/*.lua", root)) + for _, file in ipairs(files) do + + -- the tool name + local toolname = path.basename(file) + + -- found it? + if toolname and toolname ~= "tools" then + + -- match score + local score = tools._match(name, toolname:lower()) + + -- ok? + if score >= 100 then return file end + + -- select the file with the max score + if score > score_maxn then + file_ok = file + score_maxn = score + end + end + end + + -- ok? + return file_ok +end + +-- probe it's absolute path if exists from the given tool name and root directory +function tools._probe(root, name) + + -- check + assert(root and name) + + -- make the tool path + local toolpath = string.format("%s/%s", root, name) + toolpath = path.translate(toolpath) + + -- the tool exists? ok + if toolpath and os.isfile(toolpath) then + return toolpath + end +end + +-- find tool from the given name and directory (optional) +function tools.find(name, root) + + -- check + assert(name) + + -- init filename + local filepath = nil + + -- only find it from this directory if the given directory exists + if root then return tools._find_from(root, name) end + + -- attempt to find it from the current platform directory first + if not filepath then filepath = tools._find_from(platform.directory() .. "/tools", name) end + + -- attempt to find it from the script directory + if not filepath then filepath = tools._find_from(xmake._CORE_DIR .. "/tools", name) end + + -- ok? + return filepath +end + +-- load tool from the given name and directory (optional) +function tools.load(name, root) + + -- check + assert(name) + + -- get it directly from cache dirst + tools._TOOLS = tools._TOOLS or {} + if tools._TOOLS[name] then + return tools._TOOLS[name] + end + + -- find the tool file path + local toolpath = tools.find(name, root) + + -- not exists? + if not toolpath or not os.isfile(toolpath) then + return + end + + -- load script + local script, errors = loadfile(toolpath) + if script then + + -- load tool + local tool = script() + + -- init tool + if tool and tool.init then + tool:init(name) + end + + -- save tool to the cache + tools._TOOLS[name] = tool + + -- ok? + return tool + else + utils.error(errors) + utils.error("load %s failed!", toolpath) + assert(false) + end +end + +-- get the given tool script from the given kind +function tools.get(kind) + + -- get the tool name + local toolname = platform.tool(kind) + if not toolname then + utils.error("cannot get tool name for %s", kind) + return + end + + -- load it + return tools.load(toolname) +end + +-- probe it's absolute path if exists from the given tool name +function tools.probe(name, dirs) + + -- check + assert(name) + + -- attempt to run it directly first + if os.execute(string.format("%s > %s 2>&1", name, xmake._NULDEV)) ~= 0x7f00 then + return name + end + + -- attempt to get it from the given directories + if dirs then + for _, dir in ipairs(utils.wrap(dirs)) do + + -- probe it + local toolpath = tools._probe(dir, name) + + -- ok? + if toolpath and os.execute(string.format("%s > %s 2>&1", toolpath, xmake._NULDEV)) ~= 0x7f00 then + return toolpath + end + end + end +end + + +-- return module: tools +return tools diff --git a/xmake/core/tools/verbose.lua b/xmake/core/tools/verbose.lua new file mode 100644 index 000000000..b1168f29d --- /dev/null +++ b/xmake/core/tools/verbose.lua @@ -0,0 +1,47 @@ +--!The Automatic Cross-platform Build Tool +-- +-- XMake is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- +-- XMake is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with XMake; +-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> +-- +-- Copyright (C) 2009 - 2015, ruki All rights reserved. +-- +-- @author ruki +-- @file verbose.lua +-- + + +-- define module: verbose +local verbose = verbose or {} + +-- load modules +local io = require("base/io") +local string = require("base/string") + +-- the main function +function verbose.main(self, ...) + + -- verbose all + if xmake._OPTIONS.verbose then + for _, v in ipairs(...) do + io.write(string.format("%s ", v:decode())) + end + io.write("\n") + end + + -- ok + return true +end + +-- return module: verbose +return verbose |
