Makefiles: Add support for building Fortran intrinsics

Fixes: #21463
This commit is contained in:
Isuru Fernando 2020-11-19 11:33:23 -06:00 committed by Brad King
parent 66488d4eb3
commit fe3f846e1b
11 changed files with 110 additions and 41 deletions

View File

@ -202,6 +202,7 @@ Properties on Targets
/prop_tgt/EXPORT_NAME
/prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES
/prop_tgt/Fortran_FORMAT
/prop_tgt/Fortran_MODULE_DIRECTORY
/prop_tgt/Fortran_PREPROCESS

View File

@ -0,0 +1,14 @@
Fortran_BUILDING_INSTRINSIC_MODULES
-----------------------------------
Instructs the CMake Fortran preprocessor that the target is building
Fortran intrinsics for building a Fortran compiler.
This property is off by default and should be turned only on projects
that build a Fortran compiler. It should not be turned on for projects
that use a Fortran compiler.
Turning this property on will correctly add dependencies for building
Fortran intrinsic modules whereas turning the property off will ignore
Fortran intrinsic modules in the dependency graph as they are supplied
by the compiler itself.

View File

@ -600,12 +600,12 @@ static const yytype_int8 yytranslate[] =
static const yytype_uint8 yyrline[] =
{
0, 101, 101, 101, 104, 108, 113, 122, 128, 135,
140, 144, 149, 157, 162, 167, 172, 177, 182, 187,
192, 197, 201, 205, 209, 213, 214, 219, 219, 219,
220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
225, 225, 226, 226, 227, 227, 228, 228, 231, 232,
233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
243, 244, 245, 246, 247
140, 144, 149, 161, 166, 171, 176, 181, 186, 191,
196, 201, 205, 209, 213, 217, 218, 223, 223, 223,
224, 224, 225, 225, 226, 226, 227, 227, 228, 228,
229, 229, 230, 230, 231, 231, 232, 232, 235, 236,
237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251
};
#endif
@ -1747,142 +1747,146 @@ yyreduce:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
}
if (cmsysString_strcasecmp((yyvsp[-4].string), "intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUseIntrinsic(parser, (yyvsp[-2].string));
}
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
#line 1754 "cmFortranParser.cxx"
#line 1758 "cmFortranParser.cxx"
break;
case 13: /* stmt: INCLUDE STRING other EOSTMT */
#line 157 "cmFortranParser.y"
#line 161 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1764 "cmFortranParser.cxx"
#line 1768 "cmFortranParser.cxx"
break;
case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */
#line 162 "cmFortranParser.y"
#line 166 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1774 "cmFortranParser.cxx"
#line 1778 "cmFortranParser.cxx"
break;
case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */
#line 167 "cmFortranParser.y"
#line 171 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1784 "cmFortranParser.cxx"
#line 1788 "cmFortranParser.cxx"
break;
case 16: /* stmt: include STRING other EOSTMT */
#line 172 "cmFortranParser.y"
#line 176 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1794 "cmFortranParser.cxx"
#line 1798 "cmFortranParser.cxx"
break;
case 17: /* stmt: define WORD other EOSTMT */
#line 177 "cmFortranParser.y"
#line 181 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1804 "cmFortranParser.cxx"
#line 1808 "cmFortranParser.cxx"
break;
case 18: /* stmt: undef WORD other EOSTMT */
#line 182 "cmFortranParser.y"
#line 186 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1814 "cmFortranParser.cxx"
#line 1818 "cmFortranParser.cxx"
break;
case 19: /* stmt: ifdef WORD other EOSTMT */
#line 187 "cmFortranParser.y"
#line 191 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1824 "cmFortranParser.cxx"
#line 1828 "cmFortranParser.cxx"
break;
case 20: /* stmt: ifndef WORD other EOSTMT */
#line 192 "cmFortranParser.y"
#line 196 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
#line 1834 "cmFortranParser.cxx"
#line 1838 "cmFortranParser.cxx"
break;
case 21: /* stmt: if other EOSTMT */
#line 197 "cmFortranParser.y"
#line 201 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
#line 1843 "cmFortranParser.cxx"
#line 1847 "cmFortranParser.cxx"
break;
case 22: /* stmt: elif other EOSTMT */
#line 201 "cmFortranParser.y"
#line 205 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
#line 1852 "cmFortranParser.cxx"
#line 1856 "cmFortranParser.cxx"
break;
case 23: /* stmt: else other EOSTMT */
#line 205 "cmFortranParser.y"
#line 209 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
#line 1861 "cmFortranParser.cxx"
#line 1865 "cmFortranParser.cxx"
break;
case 24: /* stmt: endif other EOSTMT */
#line 209 "cmFortranParser.y"
#line 213 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
#line 1870 "cmFortranParser.cxx"
#line 1874 "cmFortranParser.cxx"
break;
case 48: /* misc_code: WORD */
#line 231 "cmFortranParser.y"
#line 235 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
#line 1876 "cmFortranParser.cxx"
#line 1880 "cmFortranParser.cxx"
break;
case 55: /* misc_code: STRING */
#line 238 "cmFortranParser.y"
#line 242 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
#line 1882 "cmFortranParser.cxx"
#line 1886 "cmFortranParser.cxx"
break;
#line 1886 "cmFortranParser.cxx"
#line 1890 "cmFortranParser.cxx"
default: break;
}
@ -2107,6 +2111,6 @@ yyreturn:
return yyresult;
}
#line 250 "cmFortranParser.y"
#line 254 "cmFortranParser.y"
/* End of grammar */

View File

@ -151,6 +151,10 @@ stmt:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, $5);
}
if (cmsysString_strcasecmp($3, "intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUseIntrinsic(parser, $5);
}
free($3);
free($5);
}

View File

@ -163,12 +163,17 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
}
bool building_intrinsics =
!mf->GetSafeDefinition("CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES")
.empty();
// Actually write dependencies to the streams.
using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
for (auto const& i : objInfo) {
if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir,
makeDepends, internalDepends)) {
makeDepends, internalDepends,
building_intrinsics)) {
return false;
}
}
@ -307,7 +312,8 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
std::string const& mod_dir,
std::string const& stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends)
std::ostream& internalDepends,
bool buildingIntrinsics)
{
// Get the source file for this object.
std::string const& src = info.Source;
@ -339,8 +345,13 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
makeDepends << '\n';
}
std::set<std::string> req = info.Requires;
if (buildingIntrinsics) {
req.insert(info.Intrinsics.begin(), info.Intrinsics.end());
}
// Write module requirements to the output stream.
for (std::string const& i : info.Requires) {
for (std::string const& i : req) {
// Require only modules not provided in the same source.
if (info.Provides.find(i) != info.Provides.cend()) {
continue;

View File

@ -72,7 +72,8 @@ protected:
std::string const& mod_dir,
std::string const& stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends);
std::ostream& internalDepends,
bool buildingIntrinsics);
// The source file from which to start scanning.
std::string SourceFile;

View File

@ -40,6 +40,8 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser);
/* Callbacks for parser. */
void cmFortranParser_Error(cmFortranParser* parser, const char* message);
void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name);
void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser,
const char* module_name);
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename);
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
@ -99,6 +101,9 @@ public:
std::set<std::string> Provides;
std::set<std::string> Requires;
// Set of intrinsic modules.
std::set<std::string> Intrinsics;
// Set of files included in the translation unit.
std::set<std::string> Includes;
};

View File

@ -197,6 +197,19 @@ void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name)
parser->Info.Requires.insert(parser->ModName(mod_name));
}
void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser,
const char* module_name)
{
if (parser->InPPFalseBranch) {
return;
}
// syntax: "use, intrinsic:: module_name"
// requires: "module_name.mod"
std::string const& mod_name = cmSystemTools::LowerCase(module_name);
parser->Info.Intrinsics.insert(parser->ModName(mod_name));
}
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename)
{

View File

@ -6175,6 +6175,14 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory(
return this->FortranModuleDirectory;
}
bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const
{
if (cmProp prop = this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) {
return cmIsOn(*prop);
}
return false;
}
std::string cmGeneratorTarget::CreateFortranModuleDirectory(
std::string const& working_dir) const
{

View File

@ -832,6 +832,7 @@ public:
std::string const& config) const;
std::string GetFortranModuleDirectory(std::string const& working_dir) const;
bool IsFortranBuildingInstrinsicModules() const;
const std::string& GetSourcesProperty() const;

View File

@ -1380,6 +1380,13 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "set(CMAKE_Fortran_TARGET_MODULE_DIR \""
<< this->GeneratorTarget->GetFortranModuleDirectory(working_dir)
<< "\")\n";
if (this->GeneratorTarget->IsFortranBuildingInstrinsicModules()) {
*this->InfoFileStream
<< "\n"
<< "# Fortran compiler is building intrinsic modules.\n"
<< "set(CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES ON) \n";
}
/* clang-format on */
// and now write the rule to use it