Skip to content

Commit b8bf161

Browse files
committed
Add support for ftnfe to citnames
Co-authored-by: ruifm
1 parent 8d7cffa commit b8bf161

File tree

5 files changed

+271
-0
lines changed

5 files changed

+271
-0
lines changed

source/citnames/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ target_sources(citnames_a
2727
source/semantic/Parsers.cc
2828
source/semantic/Semantic.cc
2929
source/semantic/ToolAny.cc
30+
source/semantic/ToolCrayFtnfe.cc
3031
source/semantic/ToolClang.cc
3132
source/semantic/ToolCuda.cc
3233
source/semantic/ToolGcc.cc
@@ -66,6 +67,7 @@ if (ENABLE_UNIT_TESTS)
6667
add_executable(citnames_unit_test
6768
test/OutputTest.cc
6869
test/ParserTest.cc
70+
test/ToolCrayFtnfeTest.cc
6971
test/ToolClangTest.cc
7072
test/ToolGccTest.cc
7173
test/ToolIntelFortranTest.cc

source/citnames/source/semantic/Build.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "Build.h"
2121
#include "ToolAny.h"
2222
#include "ToolGcc.h"
23+
#include "ToolCrayFtnfe.h"
2324
#include "ToolClang.h"
2425
#include "ToolCuda.h"
2526
#include "ToolIntelFortran.h"
@@ -46,6 +47,7 @@ namespace {
4647
std::make_shared<cs::semantic::ToolWrapper>(),
4748
std::make_shared<cs::semantic::ToolCuda>(),
4849
std::make_shared<cs::semantic::ToolIntelFortran>(),
50+
std::make_shared<cs::semantic::ToolCrayFtnfe>(),
4951
};
5052
for (auto && compiler : cfg.compilers_to_recognize) {
5153
tools.emplace_front(std::make_shared<cs::semantic::ToolExtendingWrapper>(std::move(compiler)));
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/* Copyright (C) 2012-2024 by László Nagy
2+
This file is part of Bear.
3+
4+
Bear is a tool to generate compilation database for clang tooling.
5+
6+
Bear is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
Bear is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "ToolCrayFtnfe.h"
21+
#include "Common.h"
22+
23+
#include <regex>
24+
#include <set>
25+
26+
using namespace cs::semantic;
27+
28+
namespace {
29+
30+
Arguments create_argument_list(const Execution& execution)
31+
{
32+
Arguments input_arguments;
33+
std::copy(execution.arguments.begin(), execution.arguments.end(), std::back_inserter(input_arguments));
34+
return input_arguments;
35+
}
36+
37+
bool is_preprocessor(const CompilerFlags& flags)
38+
{
39+
return std::any_of(flags.begin(), flags.end(), [](const auto& flag) {
40+
const std::string& candidate = flag.arguments.front();
41+
static const std::set<std::string_view> NO_COMPILATION_FLAG = { "-E", "-eZ", "-e Z", "-eP", "-e P" };
42+
return ((flag.type == CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING) && (NO_COMPILATION_FLAG.find(candidate) != NO_COMPILATION_FLAG.end()))
43+
|| ((flag.type == CompilerFlagType::PREPROCESSOR_MAKE));
44+
});
45+
return false;
46+
}
47+
48+
}
49+
50+
namespace cs::semantic {
51+
52+
const FlagsByName ToolCrayFtnfe::FLAG_DEFINITION = {
53+
{ "-add-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
54+
{ "-add-rpath-shared", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
55+
{ "-add-runpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
56+
{ "-as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
57+
{ "--as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
58+
{ "-A", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
59+
{ "-b", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::KIND_OF_OUTPUT_OUTPUT } },
60+
{ "-c", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING } },
61+
{ "--custom-ld-script=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::LINKER } },
62+
{ "-d", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
63+
{ "-D", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR } },
64+
{ "-e", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
65+
{ "-E", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING } },
66+
{ "-f", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
67+
{ "-F", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
68+
{ "-g", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
69+
{ "-gcc-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
70+
{ "-G", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
71+
{ "-h", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
72+
{ "-I", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
73+
{ "-J", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
74+
{ "-K", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
75+
{ "-l", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::LINKER } },
76+
{ "-L", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH_LINKER } },
77+
{ "-m", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
78+
{ "-M", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
79+
{ "-no-add-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
80+
{ "-no-add-rpath-shared", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
81+
{ "-no-add-runpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
82+
{ "-no-as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
83+
{ "--no-as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
84+
{ "--no-custom-ld-script", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
85+
{ "-no-gcc-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
86+
{ "-N", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
87+
{ "-O", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
88+
{ "-o", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::KIND_OF_OUTPUT_OUTPUT } },
89+
{ "-p", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
90+
{ "-Q", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
91+
{ "-r", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::KIND_OF_OUTPUT } },
92+
{ "-R", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
93+
{ "-s", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
94+
{ "-S", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING } },
95+
{ "-T", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_INFO } },
96+
{ "-target-accel=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
97+
{ "-target-cpu=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
98+
{ "-target-network=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
99+
{ "-U", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR } },
100+
{ "-v", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
101+
{ "-V", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
102+
{ "-W", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
103+
{ "-x", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
104+
{ "-Y", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
105+
{ "-openmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
106+
{ "-noopenmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
107+
{ "-mp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
108+
{ "-Mnoopenmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
109+
{ "-qno-openmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
110+
{ "-dynamic", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
111+
{ "-shared", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
112+
{ "-static", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
113+
{ "-default64", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
114+
{ "-VV", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
115+
{ "-VVV", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
116+
{ "-cray", { MatchInstruction::PREFIX, CompilerFlagType::OTHER } },
117+
{ "--cray", { MatchInstruction::PREFIX, CompilerFlagType::OTHER } },
118+
};
119+
120+
rust::Result<SemanticPtr> ToolCrayFtnfe::recognize(const Execution& execution) const
121+
{
122+
if (is_compiler_call(execution.executable)) {
123+
return compilation_impl(FLAG_DEFINITION, execution, create_argument_list, is_preprocessor);
124+
}
125+
return rust::Ok(SemanticPtr());
126+
}
127+
128+
bool ToolCrayFtnfe::is_compiler_call(const fs::path& program) const
129+
{
130+
static const auto pattern = std::regex(R"(^([^-]*-)*(ftnfe)(-?\w+(\.\d+){0,2})?$)");
131+
std::cmatch m;
132+
return std::regex_match(program.filename().c_str(), m, pattern);
133+
}
134+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* Copyright (C) 2012-2024 by László Nagy
2+
This file is part of Bear.
3+
4+
Bear is a tool to generate compilation database for clang tooling.
5+
6+
Bear is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
Bear is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#pragma once
21+
22+
#include "Parsers.h"
23+
#include "Tool.h"
24+
25+
namespace cs::semantic {
26+
27+
struct ToolCrayFtnfe : public Tool {
28+
29+
[[nodiscard]]
30+
rust::Result<SemanticPtr> recognize(const Execution& execution) const override;
31+
32+
protected:
33+
[[nodiscard]] bool is_compiler_call(const fs::path& program) const;
34+
35+
static const FlagsByName FLAG_DEFINITION;
36+
};
37+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* Copyright (C) 2012-2024 by László Nagy
2+
This file is part of Bear.
3+
4+
Bear is a tool to generate compilation database for clang tooling.
5+
6+
Bear is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
Bear is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "gtest/gtest.h"
21+
22+
#include "semantic/ToolCrayFtnfe.h"
23+
24+
using namespace cs::semantic;
25+
26+
namespace {
27+
28+
TEST(ToolCrayFtnfe, is_compiler_call)
29+
{
30+
struct Expose : public ToolCrayFtnfe {
31+
using ToolCrayFtnfe::is_compiler_call;
32+
};
33+
Expose sut;
34+
EXPECT_TRUE(sut.is_compiler_call("ftnfe"));
35+
EXPECT_TRUE(sut.is_compiler_call("/usr/bin/ftnfe"));
36+
EXPECT_TRUE(sut.is_compiler_call("/opt/cray/pe/cce/18.0.0/cce/x86_64/bin/ftnfe"));
37+
EXPECT_FALSE(sut.is_compiler_call("gfortran"));
38+
EXPECT_FALSE(sut.is_compiler_call("gcc"));
39+
// `crayftn` and `ftn` are not the real Cray Fortran compiler. `crayftn`
40+
// and `ftn` are generic drivers that may call other compilers depending
41+
// on the configuration of the system. The real Cray Fortran compiler is
42+
// `ftnfe`!
43+
EXPECT_FALSE(sut.is_compiler_call("/opt/cray/pe/cce/18.0.0/bin/crayftn"));
44+
EXPECT_FALSE(sut.is_compiler_call("/opt/cray/pe/craype/2.7.32/bin/ftn"));
45+
EXPECT_FALSE(sut.is_compiler_call("crayftn"));
46+
EXPECT_FALSE(sut.is_compiler_call("ftn"));
47+
}
48+
49+
TEST(ToolCrayFtnfe, fails_on_empty)
50+
{
51+
ToolCrayFtnfe sut;
52+
EXPECT_TRUE(Tool::not_recognized(sut.recognize(Execution {})));
53+
}
54+
55+
TEST(ToolCrayFtnfe, simple)
56+
{
57+
Execution input = {
58+
"/opt/cray/pe/cce/18.0.0/cce/x86_64/bin/ftnfe",
59+
{ "ftnfe", "-b", "source_out.o", "-r", "file.listing", "source.c" },
60+
"/home/user/project",
61+
{},
62+
};
63+
SemanticPtr expected = SemanticPtr(
64+
new Compile(
65+
input.working_dir,
66+
input.executable,
67+
{ "-c", "-r", "file.listing" },
68+
{ fs::path("source.c") },
69+
{ fs::path("source_out.o") }));
70+
ToolCrayFtnfe sut;
71+
auto result = sut.recognize(input);
72+
EXPECT_TRUE(Tool::recognized_ok(result));
73+
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
74+
}
75+
76+
TEST(ToolCrayFtnfe, linker_flag_filtered)
77+
{
78+
Execution input = {
79+
"/opt/cray/pe/cce/18.0.0/cce/x86_64/bin/ftnfe",
80+
{ "ftnfe", "-L.", "-lthing", "-o", "exe", "source.c" },
81+
"/home/user/project",
82+
{},
83+
};
84+
SemanticPtr expected = SemanticPtr(
85+
new Compile(
86+
input.working_dir,
87+
input.executable,
88+
{ "-c" },
89+
{ fs::path("source.c") },
90+
{ fs::path("exe") }));
91+
ToolCrayFtnfe sut;
92+
auto result = sut.recognize(input);
93+
EXPECT_TRUE(Tool::recognized_ok(result));
94+
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
95+
}
96+
}

0 commit comments

Comments
 (0)