diff options
| author | ruki <[email protected]> | 2020-07-04 23:52:15 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2020-07-04 23:52:15 +0800 |
| commit | 22229713a006394d0bb5d70865850bad60898f00 (patch) | |
| tree | 3cd65734f56637e650f312d04418658c8550d689 | |
| parent | b131172723bd99c7df027e7244fc9d0cee8fffa8 (diff) | |
add gfortran compiler
| -rw-r--r-- | tests/projects/fortran/console/src/main.f90 | 3 | ||||
| -rw-r--r-- | tests/projects/fortran/console/xmake.lua | 6 | ||||
| -rw-r--r-- | xmake/languages/fortran/api.lua | 78 | ||||
| -rw-r--r-- | xmake/languages/fortran/check_main.lua | 39 | ||||
| -rw-r--r-- | xmake/languages/fortran/load.lua | 34 | ||||
| -rw-r--r-- | xmake/languages/fortran/xmake.lua | 127 | ||||
| -rw-r--r-- | xmake/modules/core/tools/dmd.lua | 28 | ||||
| -rw-r--r-- | xmake/modules/core/tools/gfortran.lua | 22 | ||||
| -rw-r--r-- | xmake/modules/detect/tools/find_gfortran.lua | 54 | ||||
| -rw-r--r-- | xmake/modules/detect/tools/gfortran/has_flags.lua | 122 | ||||
| -rw-r--r-- | xmake/platforms/linux/xmake.lua | 2 | ||||
| -rw-r--r-- | xmake/platforms/macosx/xmake.lua | 2 | ||||
| -rw-r--r-- | xmake/platforms/windows/xmake.lua | 2 | ||||
| -rw-r--r-- | xmake/rules/fortran/xmake.lua | 40 | ||||
| -rw-r--r-- | xmake/toolchains/fortran/xmake.lua | 40 |
15 files changed, 572 insertions, 27 deletions
diff --git a/tests/projects/fortran/console/src/main.f90 b/tests/projects/fortran/console/src/main.f90 new file mode 100644 index 000000000..a332e8401 --- /dev/null +++ b/tests/projects/fortran/console/src/main.f90 @@ -0,0 +1,3 @@ +program hello + print *, "Hello World!" +end program hello diff --git a/tests/projects/fortran/console/xmake.lua b/tests/projects/fortran/console/xmake.lua new file mode 100644 index 000000000..ae05d38d1 --- /dev/null +++ b/tests/projects/fortran/console/xmake.lua @@ -0,0 +1,6 @@ +add_rules("mode.debug", "mode.release") + +target("test") + set_kind("binary") + add_files("src/*.f90") + diff --git a/xmake/languages/fortran/api.lua b/xmake/languages/fortran/api.lua new file mode 100644 index 000000000..53724dd2a --- /dev/null +++ b/xmake/languages/fortran/api.lua @@ -0,0 +1,78 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file api.lua +-- + +-- get apis +function apis() + + -- init apis + _g.values = + { + -- target.add_xxx + "target.add_links" + , "target.add_syslinks" + , "target.add_dcflags" + , "target.add_ldflags" + , "target.add_arflags" + , "target.add_shflags" + , "target.add_rpathdirs" -- @note do not translate path, it's usually an absolute path or contains $ORIGIN/@loader_path + -- option.add_xxx + , "option.add_links" + , "option.add_syslinks" + , "option.add_dcflags" + , "option.add_ldflags" + , "option.add_arflags" + , "option.add_shflags" + , "option.add_rpathdirs" + -- package.add_xxx + , "package.add_links" + , "package.add_syslinks" + , "package.add_dcflags" + , "package.add_ldflags" + , "package.add_arflags" + , "package.add_shflags" + , "package.add_rpathdirs" + , "package.add_linkdirs" + , "package.add_includedirs" + -- toolchain.add_xxx + , "toolchain.add_links" + , "toolchain.add_syslinks" + , "toolchain.add_dcflags" + , "toolchain.add_ldflags" + , "toolchain.add_arflags" + , "toolchain.add_shflags" + , "toolchain.add_rpathdirs" + , "toolchain.add_linkdirs" + , "toolchain.add_includedirs" + } + _g.pathes = + { + -- target.add_xxx + "target.add_linkdirs" + , "target.add_includedirs" + -- option.add_xxx + , "option.add_linkdirs" + , "option.add_includedirs" + } + + -- ok + return _g +end + + diff --git a/xmake/languages/fortran/check_main.lua b/xmake/languages/fortran/check_main.lua new file mode 100644 index 000000000..6df61c763 --- /dev/null +++ b/xmake/languages/fortran/check_main.lua @@ -0,0 +1,39 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file check_main.lua +-- + +-- check it +function main(sourcefile) + + -- load source code + local sourcecode = io.readfile(sourcefile) + + -- remove comment first + sourcecode = sourcecode:gsub("!.-\n", "\n") + + -- find 'program xxx' + if sourcecode:find("program%s*%(.-%)") then + return true + end + + -- no main function + return false +end + + diff --git a/xmake/languages/fortran/load.lua b/xmake/languages/fortran/load.lua new file mode 100644 index 000000000..400376028 --- /dev/null +++ b/xmake/languages/fortran/load.lua @@ -0,0 +1,34 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file load.lua +-- + +-- imports +import("api") + +-- load it +function main() + + -- init apis + _g.apis = api.apis() + + -- ok + return _g +end + + diff --git a/xmake/languages/fortran/xmake.lua b/xmake/languages/fortran/xmake.lua new file mode 100644 index 000000000..8ae47ce38 --- /dev/null +++ b/xmake/languages/fortran/xmake.lua @@ -0,0 +1,127 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define language +language("fortran") + + -- set source file kinds + set_sourcekinds {fc = {".f03", ".f90", ".f95", ".for", ".f"}} + + -- set source file flags + set_sourceflags {fc = "fcflags"} + + -- set target kinds + set_targetkinds {binary = "fcld", static = "fcar", shared = "fcsh"} + + -- set target flags + set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} + + -- set language kinds + set_langkinds {fortran = "fc"} + + -- set mixing kinds + set_mixingkinds("fc", "cc", "cxx", "as") + + -- add rules + add_rules("fortran") + + -- on load + on_load("load") + + -- on check_main + on_check_main("check_main") + + -- set name flags + set_nameflags + { + object = + { + "config.includedirs" + , "target.symbols" + , "target.warnings" + , "target.optimize:check" + , "target.vectorexts:check" + , "target.includedirs" + , "toolchain.includedirs" + } + , binary = + { + "config.linkdirs" + , "target.linkdirs" + , "target.rpathdirs" + , "target.strip" + , "target.symbols" + , "option.linkdirs" + , "option.rpathdirs" + , "toolchain.linkdirs" + , "toolchain.rpathdirs" + , "config.links" + , "target.links" + , "option.links" + , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "option.syslinks" + , "toolchain.syslinks" + } + , shared = + { + "config.linkdirs" + , "target.linkdirs" + , "target.strip" + , "target.symbols" + , "option.linkdirs" + , "toolchain.linkdirs" + , "config.links" + , "target.links" + , "option.links" + , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "option.syslinks" + , "toolchain.syslinks" + } + , static = + { + "target.strip" + , "target.symbols" + } + } + + -- set menu + set_menu { + config = + { + {category = "Cross Complation Configuration/Compiler Configuration" } + , {nil, "fc", "kv", nil, "The Fortran Compiler" } + + , {category = "Cross Complation Configuration/Linker Configuration" } + , {nil, "fcld", "kv", nil, "The Fortran Linker" } + , {nil, "fcar", "kv", nil, "The Fortran Static Library Archiver"} + , {nil, "fcsh", "kv", nil, "The Fortran Shared Library Linker" } + + , {category = "Cross Complation Configuration/Builtin Flags Configuration" } + , {nil, "links", "kv", nil, "The Link Libraries" } + , {nil, "syslinks", "kv", nil, "The System Link Libraries" } + , {nil, "linkdirs", "kv", nil, "The Link Search Directories" } + , {nil, "includedirs","kv", nil, "The Include Search Directories" } + } + } + diff --git a/xmake/modules/core/tools/dmd.lua b/xmake/modules/core/tools/dmd.lua index 378c68642..2d8fe8f44 100644 --- a/xmake/modules/core/tools/dmd.lua +++ b/xmake/modules/core/tools/dmd.lua @@ -38,8 +38,6 @@ end -- make the optimize flag function nf_optimize(self, level) - - -- the maps local maps = { fast = "-O" @@ -48,42 +46,30 @@ function nf_optimize(self, level) , smallest = "-O -release -boundscheck=off" , aggressive = "-O -release -inline -boundscheck=off" } - - -- make it return maps[level] end -- make the strip flag function nf_strip(self, level) - - -- the maps local maps = { debug = "-L-S" , all = "-L-s" } - - -- make it return maps[level] end -- make the symbol flag function nf_symbol(self, level) - - -- the maps local maps = { debug = "-g -debug" } - - -- make it return maps[level] end -- make the warning flag function nf_warning(self, level) - - -- the maps local maps = { none = "-d" @@ -93,22 +79,16 @@ function nf_warning(self, level) , everything = "-w -wi" , error = "-de" } - - -- make it return maps[level] end -- make the vector extension flag function nf_vectorext(self, extension) - - -- the maps local maps = { avx = "-mcpu=avx" , avx2 = "-mcpu=avx" } - - -- make it return maps[extension] end @@ -171,17 +151,17 @@ function link(self, objectfiles, targetkind, targetfile, flags) end -- make the compile arguments list -function compargv(self, sourcefiles, objectfile, flags) - return self:program(), table.join("-c", flags, "-of" .. objectfile, sourcefiles) +function compargv(self, sourcefile, objectfile, flags) + return self:program(), table.join("-c", flags, "-of" .. objectfile, sourcefile) end -- compile the source file -function compile(self, sourcefiles, objectfile, dependinfo, flags) +function compile(self, sourcefile, objectfile, dependinfo, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) -- compile it - os.runv(compargv(self, sourcefiles, objectfile, flags)) + os.runv(compargv(self, sourcefile, objectfile, flags)) end diff --git a/xmake/modules/core/tools/gfortran.lua b/xmake/modules/core/tools/gfortran.lua new file mode 100644 index 000000000..16a6dfdb6 --- /dev/null +++ b/xmake/modules/core/tools/gfortran.lua @@ -0,0 +1,22 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file gfortran.lua +-- + +-- inherit gcc +inherit("gcc") diff --git a/xmake/modules/detect/tools/find_gfortran.lua b/xmake/modules/detect/tools/find_gfortran.lua new file mode 100644 index 000000000..1d5bec7b6 --- /dev/null +++ b/xmake/modules/detect/tools/find_gfortran.lua @@ -0,0 +1,54 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_gfortran.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find gfortran +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local gfortran = find_gfortran() +-- local gfortran, version = find_gfortran({program = "gfortran9", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "gfortran", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tools/gfortran/has_flags.lua b/xmake/modules/detect/tools/gfortran/has_flags.lua new file mode 100644 index 000000000..5f209a3fc --- /dev/null +++ b/xmake/modules/detect/tools/gfortran/has_flags.lua @@ -0,0 +1,122 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +import("lib.detect.cache") +import("core.language.language") + +-- is linker? +function _islinker(flags, opt) + + -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"? + local flags_str = table.concat(flags, " ") + if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then + return true + end + + -- the tool kind is ld or sh? + local toolkind = opt.toolkind or "" + return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("-ld") or toolkind:endswith("-sh") +end + +-- try running +function _try_running(program, argv, opt) + local errors = nil + return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors +end + +-- attempt to check it from the argument list +function _check_from_arglist(flags, opt, islinker) + + -- only for compiler + if islinker or #flags > 1 then + return + end + + -- make cache key + local key = "detect.tools.gfortran.has_flags" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local allflags = cacheinfo[flagskey] + if not allflags then + + -- get argument list + allflags = {} + local arglist = os.iorunv(opt.program, {"--help"}, {envs = opt.envs}) + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + allflags[arg] = true + end + end + + -- save cache + cacheinfo[flagskey] = allflags + cache.save(key, cacheinfo) + end + + -- ok? + return allflags[flags[1]] +end + +-- try running to check flags +function _check_try_running(flags, opt, islinker) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "gfortran_has_flags.f90") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "program hello\n print *, \"Hello World!\"\nend program hello") + end + + -- check flags for linker + if islinker then + return _try_running(opt.program, table.join(flags, "-o", os.tmpfile(), sourcefile), opt) + end + + -- check flags for compiler + -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage + return _try_running(opt.program, table.join(flags, "-S", "-o", os.tmpfile(), sourcefile), opt) +end + +-- has_flags(flags)? +-- +-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"} +-- +-- @return true or false +-- +function main(flags, opt) + + -- is linker? + local islinker = _islinker(flags, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flags, opt, islinker) then + return true + end + + -- try running to check it + return _check_try_running(flags, opt, islinker) +end + diff --git a/xmake/platforms/linux/xmake.lua b/xmake/platforms/linux/xmake.lua index a1097565b..3c98f79ce 100644 --- a/xmake/platforms/linux/xmake.lua +++ b/xmake/platforms/linux/xmake.lua @@ -50,7 +50,7 @@ platform("linux") end) -- set toolchains - set_toolchains("envs", "cross", "gcc", "clang", "yasm", "nasm", "fasm", "cuda", "dlang", "go", "rust") + set_toolchains("envs", "cross", "gcc", "clang", "yasm", "nasm", "fasm", "cuda", "dlang", "go", "rust", "fortran") -- set menu set_menu { diff --git a/xmake/platforms/macosx/xmake.lua b/xmake/platforms/macosx/xmake.lua index f643d2c80..6ca50bea7 100644 --- a/xmake/platforms/macosx/xmake.lua +++ b/xmake/platforms/macosx/xmake.lua @@ -50,7 +50,7 @@ platform("macosx") end) -- set toolchains - set_toolchains("envs", "xcode", "clang", "gcc", "yasm", "nasm", "cuda", "dlang", "rust", "go") + set_toolchains("envs", "xcode", "clang", "gcc", "yasm", "nasm", "cuda", "dlang", "rust", "go", "fortran") -- set menu set_menu { diff --git a/xmake/platforms/windows/xmake.lua b/xmake/platforms/windows/xmake.lua index 9dd8fecbd..bc5a03ea1 100644 --- a/xmake/platforms/windows/xmake.lua +++ b/xmake/platforms/windows/xmake.lua @@ -48,7 +48,7 @@ platform("windows") end) -- set toolchains - set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go") + set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go", "fortran") -- set menu set_menu { diff --git a/xmake/rules/fortran/xmake.lua b/xmake/rules/fortran/xmake.lua new file mode 100644 index 000000000..c4b630be7 --- /dev/null +++ b/xmake/rules/fortran/xmake.lua @@ -0,0 +1,40 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define rule: fortran.build +rule("fortran.build") + set_sourcekinds("fc") + on_build_files("private.action.build.object", {batch = true}) + +-- define rule: fortran +rule("fortran") + + -- add build rules + add_deps("fortran.build") + + -- inherit links and linkdirs of all dependent targets by default + add_deps("utils.inherit.links") + + -- support `add_files("src/*.o")` and `add_files("src/*.a")` to merge object and archive files to target + add_deps("utils.merge.object", "utils.merge.archive") + + -- we attempt to extract symbols to the independent file and + -- strip self-target binary if `set_symbols("debug")` and `set_strip("all")` are enabled + add_deps("utils.symbols.extract") diff --git a/xmake/toolchains/fortran/xmake.lua b/xmake/toolchains/fortran/xmake.lua new file mode 100644 index 000000000..0b3cb896f --- /dev/null +++ b/xmake/toolchains/fortran/xmake.lua @@ -0,0 +1,40 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define toolchain +toolchain("fortran") + + -- set homepage + set_homepage("https://fortran.com/") + set_description("Fortran Programming Language Compiler") + + -- set toolset + set_toolset("fc", "$(env FC)", "gfortran") + set_toolset("fcld", "$(env FC)", "gfortran") + set_toolset("fcsh", "$(env FC)", "gfortran") + set_toolset("fcar", "$(env FC)", "gfortran") + + -- on load + on_load(function (toolchain) + local march = toolchain:is_arch("x86_64", "x64") and "-m64" or "-m32" + toolchain:add("fcflags", march) + toolchain:add("fcshflags", march) + toolchain:add("fcldflags", march) + end) |
