Attached Files | makedepf90-2.8.8_port_cm-2.4.7.patch [^] (14,921 bytes) 2007-10-01 05:25 [Show Content] [Hide Content]diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 52b3c10..30785b3 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -29,7 +29,7 @@ OPTION(CMAKE_REGENERATE_YACCLEX
"Regenerate YACC and LEXX files" OFF)
MARK_AS_ADVANCED(CMAKE_REGENERATE_YACCLEX)
IF(CMAKE_REGENERATE_YACCLEX)
- SET(parsersLexers cmCommandArgument cmExpr)
+ SET(parsersLexers cmDependsFortran cmCommandArgument cmExpr)
FIND_PROGRAM(YACC_EXECUTABLE
NAMES yacc bison
PATHS /usr/bin
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 96452bd..505741d 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -47,6 +47,7 @@ struct cmDependsFortranFile
YY_BUFFER_STATE Buffer;
std::string Directory;
};
+
struct cmDependsFortranParser_s
{
cmDependsFortranParser_s(cmDependsFortran* self);
@@ -65,7 +66,12 @@ struct cmDependsFortranParser_s
std::string TokenString;
// Flag for whether lexer is reading from inside an interface.
- int InInterface;
+ bool InInterface;
+
+ int OldStartcond;
+ bool InPPFalseBranch;
+ std::vector<bool> SkipToEnd;
+ int StepI;
// Set of provided and required modules.
std::set<cmStdString> Provides;
@@ -351,7 +357,7 @@ cmDependsFortranParser_s::~cmDependsFortranParser_s()
}
//----------------------------------------------------------------------------
-int cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
+bool cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
const char* fname)
{
// Open the new file and push it onto the stack. Save the old
@@ -375,7 +381,7 @@ int cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
}
//----------------------------------------------------------------------------
-int cmDependsFortranParser_FilePop(cmDependsFortranParser* parser)
+bool cmDependsFortranParser_FilePop(cmDependsFortranParser* parser)
{
// Pop one file off the stack and close it. Switch the lexer back
// to the next one on the stack.
@@ -430,18 +436,31 @@ void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser,
//----------------------------------------------------------------------------
void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser,
- int in)
+ bool in)
{
parser->InInterface = in;
}
//----------------------------------------------------------------------------
-int cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser)
+bool cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser)
{
return parser->InInterface;
}
//----------------------------------------------------------------------------
+void cmDependsFortranParser_SetOldStartcond(cmDependsFortranParser* parser,
+ int arg)
+{
+ parser->OldStartcond = arg;
+}
+
+//----------------------------------------------------------------------------
+int cmDependsFortranParser_GetOldStartcond(cmDependsFortranParser* parser)
+{
+ return parser->OldStartcond;
+}
+
+//----------------------------------------------------------------------------
void cmDependsFortranParser_Error(cmDependsFortranParser*, const char*)
{
// If there is a parser error just ignore it. The source will not
@@ -453,7 +472,7 @@ void cmDependsFortranParser_Error(cmDependsFortranParser*, const char*)
void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser,
const char* name)
{
- parser->Requires.insert(name);
+ parser->Requires.insert(cmSystemTools::LowerCase(name) );
}
//----------------------------------------------------------------------------
@@ -486,7 +505,7 @@ void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
const char* name)
{
- parser->Provides.insert(name);
+ parser->Provides.insert(cmSystemTools::LowerCase(name) );
}
//----------------------------------------------------------------------------
diff --git a/Source/cmDependsFortranLexer.in.l b/Source/cmDependsFortranLexer.in.l
index 8298000..a2844e4 100644
--- a/Source/cmDependsFortranLexer.in.l
+++ b/Source/cmDependsFortranLexer.in.l
@@ -64,6 +64,7 @@ Modify cmDependsFortranLexer.h:
/*--------------------------------------------------------------------------*/
%}
+
%option reentrant
%option noyywrap
%pointer
@@ -75,16 +76,19 @@ Modify cmDependsFortranLexer.h:
\" {
cmDependsFortranParser_StringStart(yyextra);
+ cmDependsFortranParser_SetOldStartcond(yyextra, YY_START);
BEGIN(str_dq);
}
' {
cmDependsFortranParser_StringStart(yyextra);
+ cmDependsFortranParser_SetOldStartcond(yyextra, YY_START);
BEGIN(str_sq);
}
<str_dq>\" |
<str_sq>' {
+ BEGIN(cmDependsFortranParser_GetOldStartcond(yyextra) );
yylvalp->string = strdup(cmDependsFortranParser_StringEnd(yyextra));
return STRING;
}
@@ -92,7 +96,15 @@ Modify cmDependsFortranLexer.h:
<str_dq,str_sq>&[ \t]*\n |
<str_dq,str_sq>&[ \t]*\n[ \t]*& /* Ignore (continued strings, free fmt) */
-<fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] /*Ignore (cont. strings, fixed fmt) */
+<fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] {
+ if (cmDependsFortranParser_GetOldStartcond(yyextra) == fixed_fmt)
+ ; /* Ignore (cont. strings, fixed fmt) */
+ else
+ {
+ unput(yytext[strlen(yytext)-1]);
+ }
+}
+
<str_dq,str_sq>\n {
unput ('\n');
@@ -110,23 +122,6 @@ Modify cmDependsFortranLexer.h:
#[ \t]*include { return CPP_INCLUDE; }
\$[ \t]*include { return F90PPR_INCLUDE; }
\?\?[ \t]*include { return COCO_INCLUDE; }
-INCLUDE { return F_INCLUDE; }
-USE { return USE; }
-
-END" "*INTERFACE {
- cmDependsFortranParser_SetInInterface(yyextra, 0);
-}
-INTERFACE {
- cmDependsFortranParser_SetInInterface(yyextra, 1);
-}
-
-END" "*MODULE /* Ignore */
-MODULE {
- if(!cmDependsFortranParser_GetInInterface(yyextra))
- {
- return MODULE;
- }
-}
#[ \t]*define { return CPP_DEFINE; }
\$[ \t]*DEFINE { return F90PPR_DEFINE; }
@@ -148,23 +143,34 @@ $[ \t]*elif { return F90PPR_ELIF; }
$[ \t]*else { return F90PPR_ELSE; }
$[ \t]*endif { return F90PPR_ENDIF; }
-&[ \t]*\n |
-&[ \t]*\n[ \t]*& /* Ignore */
+ /* Line continuations, possible involving comments. */
+&([ \t\n]*|!.*)*
+&([ \t\n]*|!.*)*&
+
+<fixed_fmt>\n[ ]{5}[^ ] { return GARBAGE; }
+
+=|=> { return ASSIGNMENT_OP; }
+
+[a-zA-Z_][a-zA-Z_0-9]* {
+ yylvalp->string = strdup(yytext);
+ return WORD;
+}
+[^ \t\n\r;,!'"a-zA-Z=&]+ { return GARBAGE; }
-[^ \t\n\r;,!'""']+ { yylvalp->string = strdup(yytext); return WORD; }
+;|\n { return EOSTMT; }
-;|\n { return EOSTMT; }
[ \t\r,] /* Ignore */
+\\[ \t]*\n /* Ignore line-endings preceeded by \ */
-. { return *yytext; }
+. { return *yytext; }
<<EOF>> {
- if(!cmDependsFortranParser_FilePop(yyextra))
- {
- return YY_NULL;
- }
+ if(!cmDependsFortranParser_FilePop(yyextra) )
+ {
+ return YY_NULL;
+ }
}
%%
diff --git a/Source/cmDependsFortranParser.h b/Source/cmDependsFortranParser.h
index d0306a9..a9ba01a 100644
--- a/Source/cmDependsFortranParser.h
+++ b/Source/cmDependsFortranParser.h
@@ -23,20 +23,33 @@
typedef struct cmDependsFortranParser_s cmDependsFortranParser;
/* Functions to enter/exit #include'd files in order. */
-int cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
+bool cmDependsFortranParser_FilePush(cmDependsFortranParser* parser,
const char* fname);
-int cmDependsFortranParser_FilePop(cmDependsFortranParser* parser);
+bool cmDependsFortranParser_FilePop(cmDependsFortranParser* parser);
/* Callbacks for lexer. */
int cmDependsFortranParser_Input(cmDependsFortranParser* parser,
char* buffer, size_t bufferSize);
+
+
void cmDependsFortranParser_StringStart(cmDependsFortranParser* parser);
const char* cmDependsFortranParser_StringEnd(cmDependsFortranParser* parser);
void cmDependsFortranParser_StringAppend(cmDependsFortranParser* parser,
char c);
+
void cmDependsFortranParser_SetInInterface(cmDependsFortranParser* parser,
- int in);
-int cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser);
+ bool is_in);
+bool cmDependsFortranParser_GetInInterface(cmDependsFortranParser* parser);
+
+
+void cmDependsFortranParser_SetInPPFalseBranch(cmDependsFortranParser* parser,
+ bool is_in);
+bool cmDependsFortranParser_GetInPPFalseBranch(cmDependsFortranParser* parser);
+
+
+void cmDependsFortranParser_SetOldStartcond(cmDependsFortranParser* parser,
+ int arg);
+int cmDependsFortranParser_GetOldStartcond(cmDependsFortranParser* parser);
/* Callbacks for parser. */
void cmDependsFortranParser_Error(cmDependsFortranParser* parser,
diff --git a/Source/cmDependsFortranParser.y b/Source/cmDependsFortranParser.y
index b4b3a04..0b01817 100644
--- a/Source/cmDependsFortranParser.y
+++ b/Source/cmDependsFortranParser.y
@@ -76,7 +76,7 @@ static void cmDependsFortranError(yyscan_t yyscanner, const char* message)
%}
/* Generate a reentrant parser object. */
-%pure_parser
+%pure-parser
%union {
char* string;
@@ -84,90 +84,128 @@ static void cmDependsFortranError(yyscan_t yyscanner, const char* message)
/*-------------------------------------------------------------------------*/
/* Tokens */
-%token USE F_INCLUDE MODULE EOSTMT
+%token EOSTMT ASSIGNMENT_OP GARBAGE
%token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
%token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
%token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
%token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
-%token UNTERMINATED_STRING
-%token <string> CPP_TOENDL STRING WORD
+%token <string> CPP_TOENDL
+%token <number> UNTERMINATED_STRING
+%token <string> STRING WORD
/*-------------------------------------------------------------------------*/
/* grammar */
%%
-code: /* empty */ | code stmt ;
+code: /* empty */ | code stmt;
-stmt:
- USE WORD other eostmt
+stmt: keyword_stmt | assignment_stmt;
+
+assignment_stmt: WORD ASSIGNMENT_OP other EOSTMT /* Ignore */
+
+keyword_stmt:
+ WORD EOSTMT
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleUse(parser, $2);
- free($2);
+ if (strcasecmp($1, "interface") == 0)
+ {
+ cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+ cmDependsFortranParser_SetInInterface(parser, true);
+ }
+ free($1);
}
-| include STRING other eostmt
+| WORD WORD other EOSTMT
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleInclude(parser, $2);
- free($2);
+ if (strcasecmp($1, "use") == 0)
+ {
+ cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+ cmDependsFortranParser_RuleUse(parser, $2);
+ free($2);
+ }
+ else if (strcasecmp($1, "module") == 0)
+ {
+ cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+ cmDependsFortranParser_RuleModule(parser, $2);
+ free($2);
+ }
+ else if (strcasecmp($1, "interface") == 0)
+ {
+ cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+ cmDependsFortranParser_SetInInterface(parser, true);
+ free($2);
+ }
+ else if (strcasecmp($2, "interface") == 0 && strcasecmp($1, "end") == 0)
+ {
+ cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+ cmDependsFortranParser_SetInInterface(parser, false);
+ free($2);
+ }
+ free($1);
}
-| CPP_INCLUDE WORD other eostmt /* Ignore */
-| MODULE WORD eostmt
+| WORD STRING other EOSTMT
{
- cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
- cmDependsFortranParser_RuleModule(parser, $2);
+ if (strcasecmp($1, "include") == 0)
+ {
+ cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
+ cmDependsFortranParser_RuleInclude(parser, $2);
+ }
+ free($1);
free($2);
}
-| define WORD other eostmt
+| CPP_INCLUDE WORD other EOSTMT /* Ignore */
+| define WORD other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleDefine(parser, $2);
free($2);
}
-| undef WORD other eostmt
+| undef WORD other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleUndef(parser, $2);
free($2);
}
-| ifdef WORD other eostmt
+| ifdef WORD other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleIfdef(parser, $2);
free($2);
}
-| ifndef WORD other eostmt
+| ifndef WORD other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleIfndef(parser, $2);
free($2);
}
-| if other eostmt
+| if other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleIf(parser);
}
-| elif other eostmt
+| elif other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleElif(parser);
}
-| else other eostmt
+| else other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleElse(parser);
}
-| endif other eostmt
+| endif other EOSTMT
{
cmDependsFortranParser* parser = cmDependsFortran_yyget_extra(yyscanner);
cmDependsFortranParser_RuleEndif(parser);
}
-| other eostmt /* Ignore */
+| WORD GARBAGE other EOSTMT /* Ignore */
+| GARBAGE other EOSTMT
+| EOSTMT
+| error
;
-eostmt: /* empty */ | EOSTMT ;
-include: F_INCLUDE | CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
-define: CPP_DEFINE | F90PPR_DEFINE ;
+
+
+include: CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
+define: CPP_DEFINE | F90PPR_DEFINE;
undef: CPP_UNDEF | F90PPR_UNDEF ;
ifdef: CPP_IFDEF | F90PPR_IFDEF ;
ifndef: CPP_IFNDEF | F90PPR_IFNDEF ;
@@ -180,6 +218,8 @@ other: /* empty */ | other misc_code ;
misc_code:
WORD { free ($1); }
| STRING { free ($1); }
+| GARBAGE
+| ASSIGNMENT_OP
| UNTERMINATED_STRING
;
lib_dep_example.tar.gz [^] (527 bytes) 2007-10-01 06:37
missing_mod_dep.tar.gz [^] (318 bytes) 2007-10-01 14:46
test_use_in_comment.patch [^] (1,337 bytes) 2007-10-06 15:23 [Show Content] [Hide Content]diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt
index 99132de..5229add 100755
--- a/Tests/Fortran/CMakeLists.txt
+++ b/Tests/Fortran/CMakeLists.txt
@@ -7,6 +7,9 @@ MESSAGE("CMAKE_Fortran_COMPILER = ${CMAKE_Fortran_COMPILER}")
MESSAGE("CMAKE_Fortran_FLAGS = ${CMAKE_Fortran_FLAGS}")
ADD_EXECUTABLE(testf hello.f)
+ADD_EXECUTABLE(test_use_in_comment_fixedform test_use_in_comment_fixedform.f)
+ADD_EXECUTABLE(test_use_in_comment_freeform test_use_in_comment_freeform.f90)
+
IF(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
ADD_EXECUTABLE(test_module
test_module_main.f90
diff --git a/Tests/Fortran/test_use_in_comment_fixedform.f b/Tests/Fortran/test_use_in_comment_fixedform.f
new file mode 100644
index 0000000..e670939
--- /dev/null
+++ b/Tests/Fortran/test_use_in_comment_fixedform.f
@@ -0,0 +1,7 @@
+ PROGRAM foo
+C USE bar
+C use bar
+C Use bar
+
+ WRITE(*,*) 'Hello, Fortran world.'
+ END PROGRAM
diff --git a/Tests/Fortran/test_use_in_comment_freeform.f90 b/Tests/Fortran/test_use_in_comment_freeform.f90
new file mode 100644
index 0000000..c992a04
--- /dev/null
+++ b/Tests/Fortran/test_use_in_comment_freeform.f90
@@ -0,0 +1,7 @@
+PROGRAM foo
+! USE bar
+! use bar
+! Use bar
+
+ WRITE(*,*) 'Hello, Fortran world.'
+END PROGRAM
example_simpleProgram.tar.gz [^] (541 bytes) 2007-10-08 08:24
examples_using_Makefiles.tar.gz [^] (4,189 bytes) 2007-10-08 10:41
in_interface.patch [^] (669 bytes) 2007-10-09 13:49 [Show Content] [Hide Content]diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 4516ea9..28dc350 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -504,7 +504,10 @@ void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
const char* name)
{
- parser->Provides.insert(cmSystemTools::LowerCase(name) );
+ if(!cmDependsFortranParser_GetInInterface(parser) )
+ {
+ parser->Provides.insert(cmSystemTools::LowerCase(name) );
+ }
}
//----------------------------------------------------------------------------
in_interface.patch2 [^] (643 bytes) 2007-10-10 02:04
Tests_Fortran.patch [^] (2,268 bytes) 2007-10-10 07:14 [Show Content] [Hide Content]diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt
index 99132de..01a1c57 100755
--- a/Tests/Fortran/CMakeLists.txt
+++ b/Tests/Fortran/CMakeLists.txt
@@ -7,9 +7,21 @@ MESSAGE("CMAKE_Fortran_COMPILER = ${CMAKE_Fortran_COMPILER}")
MESSAGE("CMAKE_Fortran_FLAGS = ${CMAKE_Fortran_FLAGS}")
ADD_EXECUTABLE(testf hello.f)
+
+
IF(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
ADD_EXECUTABLE(test_module
test_module_main.f90
test_module_implementation.f90
test_module_interface.f90)
+
+ ADD_EXECUTABLE(test_use_in_comment_fixedform
+ test_use_in_comment_fixedform.f)
+ ADD_EXECUTABLE(test_use_in_comment_freeform
+ test_use_in_comment_freeform.f90)
+
+ ADD_EXECUTABLE(test_in_interface
+ in_interface/main.f90
+ in_interface/module.f90)
+
ENDIF(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
diff --git a/Tests/Fortran/in_interface/main.f90 b/Tests/Fortran/in_interface/main.f90
new file mode 100644
index 0000000..28bcf36
--- /dev/null
+++ b/Tests/Fortran/in_interface/main.f90
@@ -0,0 +1,3 @@
+program hello
+ use test_interface
+end program hello
diff --git a/Tests/Fortran/in_interface/module.f90 b/Tests/Fortran/in_interface/module.f90
new file mode 100644
index 0000000..1064d74
--- /dev/null
+++ b/Tests/Fortran/in_interface/module.f90
@@ -0,0 +1,12 @@
+module test_interface
+
+ interface dummy
+ module procedure module_function
+ end interface
+
+contains
+
+ subroutine module_function
+ end subroutine
+
+end module test_interface
\ No newline at end of file
diff --git a/Tests/Fortran/test_use_in_comment_fixedform.f b/Tests/Fortran/test_use_in_comment_fixedform.f
new file mode 100644
index 0000000..e670939
--- /dev/null
+++ b/Tests/Fortran/test_use_in_comment_fixedform.f
@@ -0,0 +1,7 @@
+ PROGRAM foo
+C USE bar
+C use bar
+C Use bar
+
+ WRITE(*,*) 'Hello, Fortran world.'
+ END PROGRAM
diff --git a/Tests/Fortran/test_use_in_comment_freeform.f90 b/Tests/Fortran/test_use_in_comment_freeform.f90
new file mode 100644
index 0000000..c992a04
--- /dev/null
+++ b/Tests/Fortran/test_use_in_comment_freeform.f90
@@ -0,0 +1,7 @@
+PROGRAM foo
+! USE bar
+! use bar
+! Use bar
+
+ WRITE(*,*) 'Hello, Fortran world.'
+END PROGRAM
conservative_full_fortran_support_rev0.patch [^] (44,113 bytes) 2007-12-22 18:55 [Show Content] [Hide Content]diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index e821f91..97449f7 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -121,6 +121,8 @@ SET(SRCS
cmExtraEclipseCDT4Generator.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
+ cmFortranDependInfos.cxx
+ cmFortranDependInfos.h
cmGeneratedFileStream.cxx
cmGlobalGenerator.cxx
cmGlobalGenerator.h
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index cb0b6af..af9fc89 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -101,21 +101,15 @@ cmDependsFortran::~cmDependsFortran()
{
}
-//----------------------------------------------------------------------------
-bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
- std::ostream& makeDepends, std::ostream& internalDepends)
+bool cmDependsFortran::ModuleScan(const char *src,
+ cmFortranSourceDependInfo& dinfo)
{
- // Make sure this is a scanning instance.
+
if(!src || src[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
}
- if(!obj || obj[0] == '\0')
- {
- cmSystemTools::Error("Cannot scan dependencies without an object file.");
- return false;
- }
if(!this->IncludePath)
{
cmSystemTools::Error("Cannot scan dependencies without an include path.");
@@ -123,8 +117,8 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
}
// Get the directory in which stamp files will be stored.
- std::string mod_dir =
- this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
+ std::string stamp_dir =
+ this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
// Create the parser object.
cmDependsFortranParser parser(this);
@@ -133,203 +127,169 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
cmDependsFortranParser_FilePush(&parser, src);
// Parse the translation unit.
- if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+ if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+ {
+ // Failed to parse the file. Report failure to write dependencies.
+ return false;
+ }
+
+ std::copy(parser.Requires.begin(), parser.Requires.end(),
+ std::back_inserter(dinfo.Requires) );
+
+ std::copy(parser.Provides.begin(), parser.Provides.end(),
+ std::back_inserter(dinfo.Provides) );
+
+ std::copy(parser.Includes.begin(), parser.Includes.end(),
+ std::back_inserter(dinfo.Includes) );
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------
+bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
+ std::ostream& makeDepends, std::ostream& internalDepends)
+{
+ // Make sure this is a scanning instance.
+ if(!src || src[0] == '\0')
+ {
+ cmSystemTools::Error("Cannot scan dependencies without an source file.");
+ return false;
+ }
+ if(!obj || obj[0] == '\0')
+ {
+ cmSystemTools::Error("Cannot scan dependencies without an object file.");
+ return false;
+ }
+ if(!this->IncludePath)
{
- // Failed to parse the file. Report failure to write dependencies.
+ cmSystemTools::Error("Cannot scan dependencies without an include path.");
return false;
}
- // Write the include dependencies to the output stream.
+ cmFortranDependInfos* fDInfos =
+ this->LocalGenerator->GetFortranDependInfos();
+
+ std::string targetName =
+ this->LocalGenerator->Convert(this->TargetDirectory.c_str(),
+ cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
+
+
+ cmFortranTargetDependInfo targetInfo;
+ fDInfos->GetModuleInfoOfTarget(targetName.c_str(), targetInfo);
+ cmFortranSourceDependInfo sourceInfo;
+ targetInfo.GetModuleInfoOfSource(src, sourceInfo);
+
+
+ // Write the include dependencies, module requirements and provided modules
+ // to the output stream.
+
internalDepends << obj << std::endl;
- internalDepends << " " << src << std::endl;
- for(std::set<cmStdString>::const_iterator i = parser.Includes.begin();
- i != parser.Includes.end(); ++i)
+
+ for(std::vector<std::string>::const_iterator
+ itI = sourceInfo.Includes.begin(); itI != sourceInfo.Includes.end();
+ ++itI )
{
- makeDepends << obj << ": "
- << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
- << std::endl;
- internalDepends << " " << i->c_str() << std::endl;
+ for(std::vector<std::string>::const_iterator
+ itIP = this->IncludePath->begin(); itIP != this->IncludePath->end();
+ ++itIP)
+ {
+ std::string tempPathStr = "";
+
+ // Construct the name of the file as if it were in the current
+ // include directory. Avoid using a leading "./".
+ if((*itI) == ".")
+ {
+ tempPathStr += *itIP;
+ }
+ else
+ {
+ tempPathStr += *itIP + "/" + *itI;
+ }
+
+ // Look for the file in this location.
+ if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
+ {
+ makeDepends << obj << ": " << " " << tempPathStr << std::endl;
+ internalDepends << " " << tempPathStr << std::endl;
+ break;
+ }
+ }
+
}
makeDepends << std::endl;
- // Write module requirements to the output stream.
- for(std::set<cmStdString>::const_iterator i = parser.Requires.begin();
- i != parser.Requires.end(); ++i)
+ bool depends_on_FortranModuleInfos_cmake = false;
+
+ for(std::vector<std::string>::const_iterator
+ itR = sourceInfo.Requires.begin(); itR != sourceInfo.Requires.end();
+ ++itR )
{
- // Require only modules not provided in the same source.
- if(parser.Provides.find(*i) == parser.Provides.end())
+ // is module provided by the same target?
+ if(targetInfo.Provides(itR->c_str()))
+ {
+ makeDepends << obj << ": " << *itR << ".mod" << std::endl;
+
+ if(!depends_on_FortranModuleInfos_cmake)
+ {
+ internalDepends << " " << "FortranModuleInfos.cmake" << std::endl;
+ depends_on_FortranModuleInfos_cmake = true;
+ }
+ }
+ // is module provided by the some target in the sourcetree?
+ else if(fDInfos->Provides(itR->c_str()))
{
- std::string proxy = mod_dir;
- proxy += "/";
- proxy += *i;
- proxy += ".mod.proxy";
- proxy = this->LocalGenerator->Convert(proxy.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
-
- // since we require some things add them to our list of requirements
- makeDepends << obj << ".requires: " << proxy << std::endl;
-
- // create an empty proxy in case no other source provides it
- makeDepends << proxy << ":" << std::endl;
-
- // The object file should depend on timestamped files for the
- // modules it uses.
- std::string m = cmSystemTools::LowerCase(*i);
- std::string stampFile = mod_dir;
- stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
- stampFile =
- this->LocalGenerator->Convert(stampFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- makeDepends << obj << ": " << stampFile << "\n";
-
- // Create a dummy timestamp file for the module.
- std::string fullPath = mod_dir;
- fullPath += "/";
- fullPath += m;
- fullPath += ".mod.stamp";
- if(!cmSystemTools::FileExists(fullPath.c_str(), true))
+ /* this may be invalid in the future, due to a real module output path
+ mechanism which should be introduces */
+ std::string modPath =
+ this->LocalGenerator->GetMakefile()->GetHomeOutputDirectory();
+ modPath += *itR + ".mod";
+ makeDepends << obj << ": " << " " << modPath << std::endl;
+
+ if(!depends_on_FortranModuleInfos_cmake)
{
- std::ofstream dummy(fullPath.c_str());
- dummy
- << "This is a fake module timestamp file created by CMake because\n"
- << " " << src << "\n"
- << "requires the module and\n"
- << " " << obj << "\n"
- << "depends on this timestamp file.\n"
- << "\n"
- << "If another source in the same directory provides the module\n"
- << "this file will be overwritten with a real module timestamp\n"
- << "that is updated when the module is rebuilt.\n"
- << "\n"
- << "If no source in the directory provides the module at least\n"
- << "the project will build without failing to find the module\n"
- << "timestamp.\n"
- << "\n"
- << "In the future CMake may be able to locate modules in other\n"
- << "directories or outside the project and update this timestamp\n"
- << "file as necessary.\n"
- ;
+ internalDepends << " " << "FortranModuleInfos.cmake" << std::endl;
+ depends_on_FortranModuleInfos_cmake = true;
+ }
+ }
+ // module may be provided by a prebuild library
+ else
+ {
+ for(std::vector<std::string>::const_iterator
+ itIP = this->IncludePath->begin(); itIP != this->IncludePath->end();
+ ++itIP)
+ {
+ std::string tempPathStr = "";
+
+ // Construct the name of the file as if it were in the current
+ // include directory. Avoid using a leading "./".
+ if((*itR) == ".")
+ {
+ tempPathStr += *itIP;
+ }
+ else
+ {
+ tempPathStr += *itIP + "/" + *itR + ".mod" ;
+ }
+
+ if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
+ {
+ makeDepends << obj << ": " << " " << tempPathStr << std::endl;
+ internalDepends << " " << tempPathStr << std::endl;
+ break;
+ }
}
}
}
- // Write provided modules to the output stream.
- for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
- i != parser.Provides.end(); ++i)
+ for(std::vector<std::string>::const_iterator
+ itP = sourceInfo.Provides.begin(); itP != sourceInfo.Provides.end();
+ ++itP )
{
- std::string proxy = mod_dir;
- proxy += "/";
- proxy += *i;
- proxy += ".mod.proxy";
- proxy = this->LocalGenerator->Convert(proxy.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << proxy << ": " << obj << ".provides" << std::endl;
- }
-
- // If any modules are provided then they must be converted to stamp files.
- if(!parser.Provides.empty())
- {
- // Create a target to copy the module after the object file
- // changes.
- makeDepends << obj << ".provides.build:\n";
- for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
- i != parser.Provides.end(); ++i)
- {
- // Always use lower case for the mod stamp file name. The
- // cmake_copy_f90_mod will call back to this class, which will
- // try various cases for the real mod file name.
- std::string m = cmSystemTools::LowerCase(*i);
- std::string modFile = mod_dir;
- modFile += "/";
- modFile += *i;
- modFile =
- this->LocalGenerator->Convert(modFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- std::string stampFile = mod_dir;
- stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
- stampFile =
- this->LocalGenerator->Convert(stampFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod "
- << modFile << " " << stampFile << "\n";
- }
- // After copying the modules update the timestamp file so that
- // copying will not be done again until the source rebuilds.
- makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj
- << ".provides.build\n";
-
- // Make sure the module timestamp rule is evaluated by the time
- // the target finishes building.
- std::string driver = this->TargetDirectory;
- driver += "/build";
- driver = this->LocalGenerator->Convert(driver.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << driver << ": " << obj << ".provides.build\n";
+ makeDepends << *itP << ".mod: " << obj << std::endl;
}
- /*
- // TODO:
- What about .mod files provided in another directory and found with a
- -M search path? The stamp file will not be updated, so things might
- not rebuild. Possible solutions (not all thought through):
-
- Solution 1: Have all the .o.requires in a directory depend on a
- single .outside.requires that searches for .mod files in another
- directory of the build tree and uses copy-if-different to produce
- the local directory's stamp files. (won't work because the single
- rule cannot know about the modules)
-
- Solution 2: When the dependency is detected search the module
- include path for a mark file indicating the module is provided. If
- not found just write the dummy stamp file. If found, we need a rule
- to copy-if-different the module file. When a module is provided,
- write this mark file.
-
- Solution 3: Use a set of make rules like this:
-
- # When required:
- foo.mod.proxy: foo.mod.default
- foo.mod.default:: foo.mod.hack
- @echo foo.mod.default2 # Search for and copy-if-different the mod file.
- foo.mod.hack:
-
- # When provided:
- foo.mod.proxy: foo.o.requires
- @rm -f foo.mod.hack foo.mod.default
- foo.o.requires: foo.mod.hack
- @echo foo.o.requires
- foo.mod.hack:
- @touch foo.mod.hack
- @touch foo.mod.default
-
- Solution 4:
-
- When scanning dependencies and providing a module:
- - Create a .mod.provided.
- - Add .mod.proxy rule depending on corresponding .o.requires.
-
- When scanning dependencies and requiring a module:
- - Search the module path for a .mod.provided or a .mod.
- - If a .mod.provided is found depend on the corresponding .mod.stamp
- (it is provided by CMake in another directory)
- - Else, if a .mod is found depend on it directly
- (it is provided in another directory by a non-CMake project)
- - Else:
- - Add the empty proxy rule (if it is provided locally this will hook it)
- - Depend on a local .mod.stamp (it might be provided locally)
- - Create the dummy local .mod.stamp (it might not be provided locally)
-
- */
+ internalDepends << std::endl;
return true;
}
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index 80072c7..b2ab161 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -18,6 +18,7 @@
#define cmDependsFortran_h
#include "cmDepends.h"
+#include "cmFortranDependInfos.h"
/** \class cmDependsFortran
* \brief Dependency scanner for Fortran object files.
@@ -43,6 +44,8 @@ public:
by a Fortran90 compiler to copy the .mod file to the
corresponding stamp file. */
static bool CopyModule(const std::vector<std::string>& args);
+
+ bool ModuleScan(const char *src, cmFortranSourceDependInfo&);
/** Method to find an included file in the include path. Fortran
always searches the directory containing the including source
diff --git a/Source/cmFortranDependInfos.cxx b/Source/cmFortranDependInfos.cxx
new file mode 100644
index 0000000..6f41ed5
--- /dev/null
+++ b/Source/cmFortranDependInfos.cxx
@@ -0,0 +1,270 @@
+#include "cmFortranDependInfos.h"
+#include "cmSystemTools.h"
+#include "cmGeneratedFileStream.h"
+#include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmake.h"
+
+#include <fstream>
+#include <memory>
+#include <algorithm>
+
+char const* cmFortranDependInfos::ArchiveName = "FortranModuleInfos.cmake";
+
+void cmFortranTargetDependInfo
+::GetModuleInfoOfSource(char const* src_, cmFortranSourceDependInfo& fSDinfo)
+ const
+{
+ bool found = false;
+ std::string src = src_;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it = Sources.begin(); it != Sources.end() && !found; ++it)
+ {
+ if(it->Name == src )
+ {
+ fSDinfo = *it;
+ found = true;
+ }
+ }
+
+ if(!found)
+ fSDinfo.Name = "NotFound";
+}
+
+bool cmFortranTargetDependInfo::Provides(char const* mod) const
+{
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it = Sources.begin(); it != Sources.end(); ++it)
+ {
+ if(find(it->Provides.begin() , it->Provides.end(), mod)
+ != it->Provides.end() )
+ return true;
+
+ }
+ return false;
+}
+
+
+
+cmFortranDependInfos::~cmFortranDependInfos()
+{
+}
+
+void cmFortranDependInfos
+::InsertSourceDependInfo(char const* targetName,
+ cmFortranSourceDependInfo const& sourceInfo)
+{
+ cmFortranTargetDependInfo& target = Targets[std::string(targetName)];
+ target.Name = targetName;
+ target.Sources.insert(sourceInfo);
+}
+
+void cmFortranDependInfos
+::GetModuleInfoOfTarget(char const* targetName_,
+ cmFortranTargetDependInfo& targetInfo) const
+{
+ std::string targetName = targetName_;
+ targets_type::const_iterator match = Targets.find(targetName);
+ if(match != Targets.end())
+ targetInfo = match->second;
+}
+
+void cmFortranDependInfos
+::SetLocalGenerator(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+}
+
+
+bool cmFortranDependInfos
+::Provides(char const* mod_)
+{
+ std::string mod = mod_;
+ return std::find(ProvidedModules.begin(), ProvidedModules.end(), mod)
+ != ProvidedModules.end();
+}
+
+void cmFortranDependInfos
+::Save()
+{
+// std::ofstream ofs(archive.c_str());
+// boost::archive::text_oarchive oa(ofs);
+// oa & Targets;
+
+ cmake* cm = this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance();
+ std::string archive = cm->GetHomeOutputDirectory();
+ archive += "/";
+ archive += cmFortranDependInfos::ArchiveName;
+
+ cmGeneratedFileStream ofs(archive.c_str());
+ ofs << "SET(CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_mapkeys\n";
+ for(targets_type::const_iterator
+ it = this->Targets.begin(); it != this->Targets.end(); ++it)
+ {
+ ofs << " " << it->first << "\n";
+ }
+ ofs << ")\n\n";
+
+
+ std::size_t target_cnt = 0;
+ for(targets_type::const_iterator
+ it = this->Targets.begin(); it != this->Targets.end(); ++it, ++target_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_TARGET" << target_cnt
+ << "\n";
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = it->second.Sources.begin(); it_s != it->second.Sources.end();
+ ++it_s)
+ {
+ ofs << " " << it_s->Name << "\n";
+ }
+ ofs << ")\n\n";
+ }
+
+ // .._REQUIRES
+ target_cnt = 0;
+ for(targets_type::const_iterator
+ it = this->Targets.begin(); it != this->Targets.end(); ++it, ++target_cnt)
+ {
+ std::size_t src_cnt = 0;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = it->second.Sources.begin(); it_s != it->second.Sources.end();
+ ++it_s, ++src_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_TARGET" << target_cnt
+ << "_SRC" << src_cnt
+ << "_REQUIRES" << "\n";
+
+ for(std::vector<std::string>::const_iterator
+ itR = it_s->Requires.begin(); itR != it_s->Requires.end(); ++itR)
+ {
+ ofs << " " << *itR << "\n";
+ }
+ ofs << ")\n\n";
+ }
+ }
+
+
+ // .._PROVIDES
+ target_cnt = 0;
+ for(targets_type::const_iterator
+ it = this->Targets.begin(); it != this->Targets.end(); ++it, ++target_cnt)
+ {
+ std::size_t src_cnt = 0;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = it->second.Sources.begin(); it_s != it->second.Sources.end();
+ ++it_s, ++src_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_TARGET" << target_cnt
+ << "_SRC" << src_cnt
+ << "_PROVIDES" << "\n";
+
+ for(std::vector<std::string>::const_iterator
+ itP = it_s->Provides.begin(); itP != it_s->Provides.end(); ++itP)
+ {
+ ofs << " " << *itP << "\n";
+ }
+ ofs << ")\n\n";
+ }
+ }
+
+ // .._INCLUDES
+ target_cnt = 0;
+ for(targets_type::const_iterator
+ it = this->Targets.begin(); it != this->Targets.end(); ++it, ++target_cnt)
+ {
+ std::size_t src_cnt = 0;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = it->second.Sources.begin(); it_s != it->second.Sources.end();
+ ++it_s, ++src_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_TARGET" << target_cnt
+ << "_SRC" << src_cnt
+ << "_INCLUDES" << "\n";
+
+ for(std::vector<std::string>::const_iterator
+ itI = it_s->Includes.begin(); itI != it_s->Includes.end(); ++itI)
+ {
+ ofs << " " << *itI << "\n";
+ }
+ ofs << ")\n\n";
+ }
+ }
+
+}
+
+void cmFortranDependInfos::Load()
+{
+ cmake* cm = this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance();
+ std::string archive = cm->GetHomeOutputDirectory();
+ archive += "/";
+ archive += cmFortranDependInfos::ArchiveName;
+
+ typedef std::vector<std::string>::const_iterator cit_type;
+
+ // Read the directory information file.
+ std::auto_ptr<cmMakefile> mf(new cmMakefile);
+ mf->SetLocalGenerator(this->LocalGenerator);
+ if(! mf->ReadListFile(0, archive.c_str()) )
+ return;
+
+
+ char const* c_targetsMapKeys=
+ mf->GetSafeDefinition("CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_mapkeys");
+ std::vector<std::string> targetsMapKeys;
+ cmSystemTools::ExpandListArgument(c_targetsMapKeys, targetsMapKeys);
+
+ std::size_t target_cnt = 0;
+ cmOStringStream var;
+ for(cit_type itT = targetsMapKeys.begin(); itT != targetsMapKeys.end();
+ ++itT, ++target_cnt)
+ {
+ cmFortranTargetDependInfo targetInfo;
+ targetInfo.Name = *itT;
+
+ var.str("");
+ var << "CMAKE_FORTRAN_DEPEND_INFOS_TARGETS_TARGET" << target_cnt;
+ std::string target_def = var.str();
+ char const* c_sources=
+ mf->GetSafeDefinition(target_def.c_str());
+ std::vector<std::string> sources;
+ cmSystemTools::ExpandListArgument(c_sources, sources);
+ std::size_t src_cnt = 0;
+ for(cit_type it_s = sources.begin(); it_s != sources.end();
+ ++it_s, ++ src_cnt)
+ {
+ cmFortranSourceDependInfo sourceInfo;
+ sourceInfo.Name = *it_s;
+
+ var.str("");
+ var << target_def << "_SRC" << src_cnt;
+
+ {
+ std::string def = var.str() + "_PROVIDES";
+ char const* def_value = mf->GetSafeDefinition(def.c_str());
+ cmSystemTools::ExpandListArgument(def_value, sourceInfo.Provides);
+ std::copy(sourceInfo.Provides.begin(), sourceInfo.Provides.end(),
+ std::back_inserter(ProvidedModules));
+ }
+ {
+ std::string def = var.str() + "_REQUIRES";
+ char const* def_value = mf->GetSafeDefinition(def.c_str());
+ cmSystemTools::ExpandListArgument(def_value, sourceInfo.Requires);
+ }
+ {
+ std::string def = var.str() + "_INCLUDES";
+ char const* def_value = mf->GetSafeDefinition(def.c_str());
+ cmSystemTools::ExpandListArgument(def_value, sourceInfo.Includes);
+ }
+
+ targetInfo.Sources.insert(sourceInfo);
+ }
+
+ this->Targets[*itT] = targetInfo;
+
+ }
+
+}
+
+
diff --git a/Source/cmFortranDependInfos.h b/Source/cmFortranDependInfos.h
new file mode 100644
index 0000000..75d6c05
--- /dev/null
+++ b/Source/cmFortranDependInfos.h
@@ -0,0 +1,61 @@
+#ifndef CMFORTRANMODULEINFOS_H_
+#define CMFORTRANMODULEINFOS_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+
+
+class cmLocalGenerator;
+
+struct cmFortranSourceDependInfo
+{
+ std::string Name;
+ std::vector<std::string> Requires;
+ std::vector<std::string> Provides;
+ std::vector<std::string> Includes;
+
+ bool operator<(cmFortranSourceDependInfo const& rhs) const
+ {
+ return this->Name < rhs.Name;
+ }
+};
+struct cmFortranTargetDependInfo
+{
+ std::string Name;
+ std::set<cmFortranSourceDependInfo> Sources;
+ void GetModuleInfoOfSource(char const* src, cmFortranSourceDependInfo&) const;
+ bool Provides(char const* mod) const;
+};
+
+class cmFortranDependInfos
+{
+public:
+ typedef std::map<std::string, cmFortranTargetDependInfo > targets_type;
+
+// cmFortranDependInfos();
+ virtual ~cmFortranDependInfos();
+
+ void InsertSourceDependInfo(char const* targetName,
+ cmFortranSourceDependInfo const&);
+
+ void GetModuleInfoOfTarget(char const* targetName,
+ cmFortranTargetDependInfo&) const;
+
+ void SetLocalGenerator(cmLocalGenerator* lg);
+ bool Provides(char const* mod);
+
+ void Save();
+ void Load();
+
+private:
+ static char const* ArchiveName;
+ targets_type Targets;
+ cmLocalGenerator* LocalGenerator;
+
+ // for speed improvements when this->Prvides is called
+ std::vector<std::string> ProvidedModules;
+};
+
+#endif /*CMFORTRANMODULEINFOS_H_*/
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index b7f7f6d..39328b3 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -842,6 +842,30 @@ cmGlobalUnixMakefileGenerator3
depends.push_back(makeTargetName);
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
"clean", depends, commands, true);
+
+ std::set<cmStdString> langs;
+ t->second.GetLanguages(langs);
+ if(std::find(langs.begin(), langs.end(), "Fortran") != langs.end())
+ {
+ commands.clear();
+ depends.clear();
+
+ makeTargetName = localName;
+ makeTargetName += "/fortran_module_scan";
+
+ depends.push_back(makeTargetName);
+
+ lg->WriteMakeRule(ruleFileStream,
+ "add target to fortran module scan target",
+ "fortran_module_scan", depends, commands, true);
+
+ depends.clear();
+ commands.push_back(lg->GetRecursiveMakeCall
+ (makefileName.c_str(),makeTargetName.c_str()));
+
+ lg->WriteMakeRule(ruleFileStream, "fortran module scan for target",
+ makeTargetName.c_str(), depends, commands, true);
+ }
}
}
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4a81404..35e22cf 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -31,6 +31,7 @@
#if defined(CMAKE_BUILD_WITH_CMAKE)
# define CM_LG_ENCODE_OBJECT_NAMES
# include <cmsys/MD5.h>
+# include "cmFortranDependInfos.h"
#endif
#include <cmsys/System.h>
@@ -2474,6 +2475,14 @@ cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
}
//----------------------------------------------------------------------------
+#ifdef CMAKE_BUILD_WITH_CMAKE
+void cmLocalGenerator::SetFortranDependInfos(cmFortranDependInfos* fDInfos)
+{
+ this->FortranDependInfos = fDInfos;
+}
+#endif
+
+//----------------------------------------------------------------------------
void
cmLocalGenerator
::GenerateTargetInstallRules(
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 4c83de4..4ce3c54 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -26,6 +26,10 @@ class cmTargetManifest;
class cmSourceFile;
class cmCustomCommand;
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ class cmFortranDependInfos;
+#endif
+
/** \class cmLocalGenerator
* \brief Create required build files for a directory.
*
@@ -157,6 +161,18 @@ public:
///! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(const char* p);
+#ifdef CMAKE_BUILD_WITH_CMAKE
+
+ void SetFortranDependInfos(cmFortranDependInfos* fDInfos);
+ cmFortranDependInfos* GetFortranDependInfos()
+ { return this->FortranDependInfos; }
+
+ /** Called from command-line. A hook to scan for fortran modules. */
+ virtual bool FortranModuleScan(char const* /* depInfoFile */)
+ { return true; }
+
+#endif
+
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* /* mf */,
bool /* verbose */) {}
@@ -343,6 +359,10 @@ protected:
std::string RelativePathTopBinary;
bool RelativePathsConfigured;
bool PathConversionsSetup;
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmFortranDependInfos* FortranDependInfos;
+#endif
};
#endif
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 46078a0..5306d02 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1277,6 +1277,132 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
}
//----------------------------------------------------------------------------
+#ifdef CMAKE_BUILD_WITH_CMAKE
+bool cmLocalUnixMakefileGenerator3::FortranModuleScan(char const* depInfoFile_)
+{
+
+ // The info file for this target
+ std::string depInfoFile = depInfoFile_;
+
+ // Read the directory information file.
+ cmMakefile* mf = this->Makefile;
+ bool haveDirectoryInfo = false;
+ std::string dirInfoFile = this->Makefile->GetStartOutputDirectory();
+ dirInfoFile += cmake::GetCMakeFilesDirectory();
+ dirInfoFile += "/CMakeDirectoryInformation.cmake";
+ if(mf->ReadListFile(0, dirInfoFile.c_str()) &&
+ !cmSystemTools::GetErrorOccuredFlag())
+ {
+ haveDirectoryInfo = true;
+ }
+
+ // read in the target info file
+ if(!mf->ReadListFile(0, depInfoFile.c_str()) ||
+ cmSystemTools::GetErrorOccuredFlag())
+ {
+ cmSystemTools::Error("Target DependInfo.cmake file not found");
+ }
+
+
+ // Lookup useful directory information.
+ if(haveDirectoryInfo)
+ {
+ // Test whether we need to force Unix paths.
+ if(const char* force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS"))
+ {
+ if(!cmSystemTools::IsOff(force))
+ {
+ cmSystemTools::SetForceUnixPaths(true);
+ }
+ }
+
+ // Setup relative path top directories.
+ this->RelativePathsConfigured = true;
+ if(const char* relativePathTopSource =
+ mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"))
+ {
+ this->RelativePathTopSource = relativePathTopSource;
+ }
+ if(const char* relativePathTopBinary =
+ mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"))
+ {
+ this->RelativePathTopBinary = relativePathTopBinary;
+ }
+ }
+ else
+ {
+ cmSystemTools::Error("Directory Information file not found");
+ }
+
+ // Get the set of include directories.
+ std::vector<std::string> includes;
+ if(haveDirectoryInfo)
+ {
+ std::string includePathVar = "CMAKE_";
+ includePathVar += "Fortran";
+ includePathVar += "_INCLUDE_PATH";
+ if(const char* includePath = mf->GetDefinition(includePathVar.c_str()))
+ {
+ cmSystemTools::ExpandListArgument(includePath, includes);
+ }
+ }
+
+ std::string dir = cmSystemTools::GetFilenamePath(depInfoFile);
+ std::auto_ptr<cmDependsFortran> scanner (new cmDependsFortran(includes, dir));
+
+
+ if(scanner.get())
+ {
+ std::string targetName = cmSystemTools::GetFilenameName(dir);
+ targetName = targetName.substr(0, targetName.length()-4);
+ std::string message = "fortran module scan for target " + targetName;
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta
+ | cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, true);
+
+ std::string homeDir = this->Makefile->GetHomeDirectory();
+ std::string homeOutputDir = this->Makefile->GetHomeOutputDirectory();
+ cmFortranDependInfos* fortranDependInfos =
+ this->GetFortranDependInfos();
+
+ scanner->SetLocalGenerator(this);
+ scanner->SetFileComparison(
+ this->GlobalGenerator->GetCMakeInstance()->GetFileComparison());
+
+ std::string srcLang = "CMAKE_DEPENDS_CHECK_Fortran";
+ const char *srcStr = mf->GetSafeDefinition(srcLang.c_str());
+ std::vector<std::string> srcs;
+ cmSystemTools::ExpandListArgument(srcStr, srcs);
+
+ for(std::vector<std::string>::iterator
+ si = srcs.begin(); si != srcs.end(); ++si)
+ {
+ std::string &src = *si;
+ std::string obj = *(++si);
+ cmFortranSourceDependInfo dinfo;
+
+ // make sure the object file is relative to home output
+ obj = this->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE);
+
+ dinfo.Name = src;
+ scanner->ModuleScan(src.c_str(), dinfo);
+ std::string relDir = this->Convert(dir.c_str(),HOME_OUTPUT,MAKEFILE);
+ fortranDependInfos->InsertSourceDependInfo(relDir.c_str(), dinfo);
+ }
+
+ fortranDependInfos->Save();
+
+ // scan for this target is complete, so touch the mark file
+ std::ofstream fmark((dir + "/fortran_module_scan.mark").c_str());
+ fmark << "fortran module scan updated>" << std::endl;
+ }
+
+
+ return true;
+}
+#endif // CMAKE_BUILD_WITH_CMAKE
+
+//----------------------------------------------------------------------------
bool
cmLocalUnixMakefileGenerator3
::ScanDependencies(const char* targetDir)
@@ -1619,8 +1745,16 @@ void cmLocalUnixMakefileGenerator3
}
std::string mf2Dir = cmake::GetCMakeFilesDirectoryPostSlash();
mf2Dir += "Makefile2";
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ std::string scanTarget = this->Makefile->GetStartOutputDirectory();
+ scanTarget += "/fortran_module_scan";
commands.push_back(this->GetRecursiveMakeCall(mf2Dir.c_str(),
- recursiveTarget.c_str()));
+ scanTarget.c_str()));
+#endif
+
+ commands.push_back(this->GetRecursiveMakeCall(mf2Dir.c_str(),
+ recursiveTarget.c_str()));
this->CreateCDCommand(commands,
this->Makefile->GetHomeOutputDirectory(),
this->Makefile->GetStartOutputDirectory());
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 364b890..dcfec5c 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -203,6 +203,11 @@ public:
virtual bool UpdateDependencies(const char* tgtInfo,
bool verbose, bool color);
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ /** Called from command-line. A hook to scan for fortran modules. */
+ virtual bool FortranModuleScan(char const* depInfoFile);
+#endif
+
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* mf, bool verbose);
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index c25b1ed..db9a53e 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -45,6 +45,11 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// write the per-target per-language flags
this->WriteTargetLanguageFlags();
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // Write the dependency generation rule.
+ this->WriteTargetFortranModuleScanRules();
+#endif
+
// write the link rules
this->WriteExecutableRule(false);
if(this->Target->NeedRelinkBeforeInstall())
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index c395682..2bddd7b 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -47,6 +47,12 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
// write the per-target per-language flags
this->WriteTargetLanguageFlags();
+ // MAIKS_ANNOTATION
+ #ifdef CMAKE_BUILD_WITH_CMAKE
+ // Write the dependency generation rule.
+ this->WriteTargetFortranModuleScanRules();
+ #endif
+
// write the link rules
// Write the rule for this target type.
switch(this->Target->GetType())
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index f954d0a..535fb10 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -731,6 +731,88 @@ void cmMakefileTargetGenerator::WriteTargetRequiresRules()
}
//----------------------------------------------------------------------------
+#ifdef CMAKE_BUILD_WITH_CMAKE
+void cmMakefileTargetGenerator::WriteTargetFortranModuleScanRules()
+{
+
+
+
+ std::vector<std::string> depends;
+ std::vector<std::string> no_commands, commands;
+
+ std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
+ this->InfoFileNameFull = dir;
+ this->InfoFileNameFull += "/DependInfo.cmake";
+
+ // Construct the name of the dependency generation target.
+ std::string depTargetDir =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ depTargetDir += "/fortran_module_scan";
+ std::string depTarget = depTargetDir + ".mark";
+
+ // This target drives dependency generation for all object files.
+ std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string pathTarget = this->LocalGenerator->GetTargetDirectory(*(this->Target));
+ std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
+
+
+
+
+ for(std::vector<cmSourceFile*>::const_iterator it = sources.begin();
+ it != sources.end(); ++it)
+ {
+ std::string srcRelPath = (*it)->GetFullPath();
+ srcRelPath = this->Convert(srcRelPath.c_str(), cmLocalGenerator::FULL);
+ depends.push_back(srcRelPath);
+ }
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTarget.c_str(),
+ depends, no_commands, true);
+ depends.clear();
+
+ {
+ cmOStringStream depCmd;
+ // Generate a call this signature:
+ //
+ // -E cmake_fortran_module_scan <generator>
+ // <home-src-dir> <start-src-dir>
+ // <home-out-dir> <start-out-dir>
+ // <dep-info>
+ depCmd << "$(CMAKE_COMMAND) -E cmake_fortran_module_scan \""
+ << this->GlobalGenerator->GetName() << "\" "
+ << this->Convert(this->Makefile->GetHomeDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->Makefile->GetStartDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->Makefile->GetHomeOutputDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->Makefile->GetStartOutputDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->InfoFileNameFull.c_str(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
+
+ std::string command = depCmd.str();
+ commands.push_back(command.c_str());
+ }
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTarget.c_str(),
+ depends, commands, true);
+
+ depends.clear();
+ depends.push_back(depTarget);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTargetDir.c_str(),
+ depends, no_commands, true);
+
+}
+#endif // CMAKE_BUILD_WITH_CMAKE
+
+
+//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetCleanRules()
{
std::vector<std::string> depends;
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index fac9597..76b3056 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -76,6 +76,11 @@ protected:
// write the provide require rules for this target
void WriteTargetRequiresRules();
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // write the fortran scan rules for this target
+ void WriteTargetFortranModuleScanRules();
+#endif
+
// write the clean rules for this target
void WriteTargetCleanRules();
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 1eb087f..6e910d0 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1427,13 +1427,75 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
lgd->GetMakefile()->MakeStartDirectoriesCurrent();
+ cmFortranDependInfos* fdinfos = new cmFortranDependInfos;
+ fdinfos->SetLocalGenerator(lgd.get());
+ lgd->SetFortranDependInfos(fdinfos);
+ fdinfos->Load();
+
// Actually scan dependencies.
return lgd->UpdateDependencies(depInfo.c_str(),
verbose, color)? 0 : 2;
}
return 1;
}
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // This command looks almost the same as cmake_depends
+ else if (args[1] == "cmake_fortran_module_scan" && args.size() >= 6)
+ {
+ // Create a cmake object instance to process dependencies.
+ cmake cm;
+ // signature:
+ //
+ // -E cmake_fortran_module_scan <generator>
+ // <home-src-dir> <start-src-dir>
+ // <home-out-dir> <start-out-dir>
+ // <dep-info>
+ std::string gen = args[2];
+ std::string homeDir = args[3];
+ std::string startDir = args[4];
+ std::string homeOutDir = args[5];
+ std::string startOutDir = args[6];
+ std::string depInfo = args[7];
+
+ // Create a local generator configured for the directory in
+ // which dependencies will be scanned.
+ homeDir = cmSystemTools::CollapseFullPath(homeDir.c_str());
+ startDir = cmSystemTools::CollapseFullPath(startDir.c_str());
+ homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir.c_str());
+ startOutDir = cmSystemTools::CollapseFullPath(startOutDir.c_str());
+ cm.SetHomeDirectory(homeDir.c_str());
+ cm.SetStartDirectory(startDir.c_str());
+ cm.SetHomeOutputDirectory(homeOutDir.c_str());
+ cm.SetStartOutputDirectory(startOutDir.c_str());
+ if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
+ {
+ cm.SetGlobalGenerator(ggd);
+ std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
+ lgd->SetGlobalGenerator(ggd);
+
+ lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
+ lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
+ lgd->GetMakefile()->MakeStartDirectoriesCurrent();
+
+ cmFortranDependInfos* fdinfos = new cmFortranDependInfos;
+ fdinfos->SetLocalGenerator(lgd.get());
+ lgd->SetFortranDependInfos(fdinfos);
+ fdinfos->Load();
+
+ // Scan for fortran modules.
+ bool success = lgd->FortranModuleScan(depInfo.c_str());
+ if(success)
+ {
+ fdinfos->Save();
+ return 0;
+ }
+ else
+ return 2;
+ }
+ return 1;
+ }
+#endif
// Internal CMake link script support.
else if (args[1] == "cmake_link_script" && args.size() >= 3)
{
full_fortran_support_rev0.patch [^] (43,671 bytes) 2007-12-23 13:56 [Show Content] [Hide Content]diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index e821f91..97449f7 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -121,6 +121,8 @@ SET(SRCS
cmExtraEclipseCDT4Generator.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
+ cmFortranDependInfos.cxx
+ cmFortranDependInfos.h
cmGeneratedFileStream.cxx
cmGlobalGenerator.cxx
cmGlobalGenerator.h
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index abfc7b1..4e336ee 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -29,6 +29,25 @@
// use lower case and some always use upper case. I do not know if any
// use the case from the source code.
+
+
+static inline std::string targetOutputDirOf(char const* targetDir_)
+{
+ std::string targetDir = targetDir_;
+ typedef std::string::iterator it_type;
+ typedef std::string::reverse_iterator rit_type;
+
+ rit_type rlast = std::find(targetDir.rbegin(), targetDir.rend(), '/');
+ rit_type rprelast = std::find(rlast+1, targetDir.rend() , '/') ;
+
+ it_type last = rlast.base();
+ it_type prelast = rprelast.base();
+
+ std::string ret(targetDir.begin(), prelast-1);
+
+ return ret;
+}
+
//----------------------------------------------------------------------------
// Parser methods not included in generated interface.
@@ -100,21 +119,15 @@ cmDependsFortran::~cmDependsFortran()
{
}
-//----------------------------------------------------------------------------
-bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
- std::ostream& makeDepends, std::ostream& internalDepends)
+bool cmDependsFortran::ModuleScan(const char *src,
+ cmFortranSourceDependInfo& dinfo)
{
- // Make sure this is a scanning instance.
+
if(!src || src[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
}
- if(!obj || obj[0] == '\0')
- {
- cmSystemTools::Error("Cannot scan dependencies without an object file.");
- return false;
- }
if(!this->IncludePath)
{
cmSystemTools::Error("Cannot scan dependencies without an include path.");
@@ -122,8 +135,8 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
}
// Get the directory in which stamp files will be stored.
- std::string mod_dir =
- this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
+ std::string stamp_dir =
+ this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
// Create the parser object.
cmDependsFortranParser parser(this);
@@ -132,203 +145,175 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
cmDependsFortranParser_FilePush(&parser, src);
// Parse the translation unit.
- if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+ if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+ {
+ // Failed to parse the file. Report failure to write dependencies.
+ return false;
+ }
+
+ std::copy(parser.Requires.begin(), parser.Requires.end(),
+ std::back_inserter(dinfo.Requires) );
+
+ std::copy(parser.Provides.begin(), parser.Provides.end(),
+ std::back_inserter(dinfo.Provides) );
+
+ std::copy(parser.Includes.begin(), parser.Includes.end(),
+ std::back_inserter(dinfo.Includes) );
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------
+bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
+ std::ostream& makeDepends, std::ostream& internalDepends)
+{
+ // Make sure this is a scanning instance.
+ if(!src || src[0] == '\0')
{
- // Failed to parse the file. Report failure to write dependencies.
+ cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
}
-
- // Write the include dependencies to the output stream.
- internalDepends << obj << std::endl;
- internalDepends << " " << src << std::endl;
- for(std::set<cmStdString>::const_iterator i = parser.Includes.begin();
- i != parser.Includes.end(); ++i)
+ if(!obj || obj[0] == '\0')
{
- makeDepends << obj << ": "
- << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
- << std::endl;
- internalDepends << " " << i->c_str() << std::endl;
+ cmSystemTools::Error("Cannot scan dependencies without an object file.");
+ return false;
}
- makeDepends << std::endl;
+ if(!this->IncludePath)
+ {
+ cmSystemTools::Error("Cannot scan dependencies without an include path.");
+ return false;
+ }
+
+ cmFortranDependInfos* fDInfos =
+ this->LocalGenerator->GetFortranDependInfos();
+
+// std::string targetName =
+// this->LocalGenerator->Convert(this->TargetDirectory.c_str(),
+// cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
+ std::string targetName = this->TargetDirectory;
- // Write module requirements to the output stream.
- for(std::set<cmStdString>::const_iterator i = parser.Requires.begin();
- i != parser.Requires.end(); ++i)
+ cmFortranTargetDependInfo targetInfo;
+ fDInfos->GetModuleInfoOfTarget(targetName.c_str(), targetInfo);
+ cmFortranSourceDependInfo sourceInfo;
+ targetInfo.GetModuleInfoOfSource(src, sourceInfo);
+
+
+ // Write the include dependencies, module requirements and provided modules
+ // to the output stream.
+
+ internalDepends << obj << std::endl;
+
+ for(std::vector<std::string>::const_iterator
+ itI = sourceInfo.Includes.begin(); itI != sourceInfo.Includes.end();
+ ++itI )
{
- // Require only modules not provided in the same source.
- if(parser.Provides.find(*i) == parser.Provides.end())
+ for(std::vector<std::string>::const_iterator
+ itIP = this->IncludePath->begin(); itIP != this->IncludePath->end();
+ ++itIP)
{
- std::string proxy = mod_dir;
- proxy += "/";
- proxy += *i;
- proxy += ".mod.proxy";
- proxy = this->LocalGenerator->Convert(proxy.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
-
- // since we require some things add them to our list of requirements
- makeDepends << obj << ".requires: " << proxy << std::endl;
-
- // create an empty proxy in case no other source provides it
- makeDepends << proxy << ":" << std::endl;
-
- // The object file should depend on timestamped files for the
- // modules it uses.
- std::string m = cmSystemTools::LowerCase(*i);
- std::string stampFile = mod_dir;
- stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
- stampFile =
- this->LocalGenerator->Convert(stampFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- makeDepends << obj << ": " << stampFile << "\n";
-
- // Create a dummy timestamp file for the module.
- std::string fullPath = mod_dir;
- fullPath += "/";
- fullPath += m;
- fullPath += ".mod.stamp";
- if(!cmSystemTools::FileExists(fullPath.c_str(), true))
+ std::string tempPathStr = "";
+
+ // Construct the name of the file as if it were in the current
+ // include directory. Avoid using a leading "./".
+ if((*itI) == ".")
+ {
+ tempPathStr += *itIP;
+ }
+ else
+ {
+ tempPathStr += *itIP + "/" + *itI;
+ }
+
+ // Look for the file in this location.
+ if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
{
- std::ofstream dummy(fullPath.c_str());
- dummy
- << "This is a fake module timestamp file created by CMake because\n"
- << " " << src << "\n"
- << "requires the module and\n"
- << " " << obj << "\n"
- << "depends on this timestamp file.\n"
- << "\n"
- << "If another source in the same directory provides the module\n"
- << "this file will be overwritten with a real module timestamp\n"
- << "that is updated when the module is rebuilt.\n"
- << "\n"
- << "If no source in the directory provides the module at least\n"
- << "the project will build without failing to find the module\n"
- << "timestamp.\n"
- << "\n"
- << "In the future CMake may be able to locate modules in other\n"
- << "directories or outside the project and update this timestamp\n"
- << "file as necessary.\n"
- ;
+ makeDepends << obj << ": " << " " << tempPathStr << std::endl;
+ internalDepends << " " << tempPathStr << std::endl;
+ break;
}
}
+
}
+ makeDepends << std::endl;
- // Write provided modules to the output stream.
- for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
- i != parser.Provides.end(); ++i)
+ bool depends_on_FortranDependInfo_cmake = false;
+ std::string thisModPath = targetOutputDirOf(this->TargetDirectory.c_str());
+ thisModPath += "/";
+ if((thisModPath) == "/")
{
- std::string proxy = mod_dir;
- proxy += "/";
- proxy += *i;
- proxy += ".mod.proxy";
- proxy = this->LocalGenerator->Convert(proxy.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << proxy << ": " << obj << ".provides" << std::endl;
+ thisModPath = "";
}
- // If any modules are provided then they must be converted to stamp files.
- if(!parser.Provides.empty())
+ for(std::vector<std::string>::const_iterator
+ itR = sourceInfo.Requires.begin(); itR != sourceInfo.Requires.end();
+ ++itR )
{
- // Create a target to copy the module after the object file
- // changes.
- makeDepends << obj << ".provides.build:\n";
- for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
- i != parser.Provides.end(); ++i)
+ // is module provided by the same target?
+ if(targetInfo.Provides(itR->c_str()))
+ {
+ makeDepends << obj << ": " << thisModPath << *itR << ".mod"
+ << std::endl;
+
+ if(!depends_on_FortranDependInfo_cmake)
+ {
+ internalDepends << " " << this->TargetDirectory
+ << "/FortranDependInfo.cmake" << std::endl;
+ depends_on_FortranDependInfo_cmake = true;
+ }
+ }
+ // is module provided by the some target in the sourcetree?
+ else if(char const* target = fDInfos->ProvidedByTarget(itR->c_str()))
{
- // Always use lower case for the mod stamp file name. The
- // cmake_copy_f90_mod will call back to this class, which will
- // try various cases for the real mod file name.
- std::string m = cmSystemTools::LowerCase(*i);
- std::string modFile = mod_dir;
- modFile += "/";
- modFile += *i;
- modFile =
- this->LocalGenerator->Convert(modFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- std::string stampFile = mod_dir;
- stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
- stampFile =
- this->LocalGenerator->Convert(stampFile.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::SHELL);
- makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod "
- << modFile << " " << stampFile << "\n";
+ /* this may be invalid in the future, due to a real module output path
+ mechanism which should be introduces */
+ std::string modPath = targetOutputDirOf(target);
+ modPath += "/";
+ modPath += *itR + ".mod";
+ makeDepends << obj << ": " << " " << modPath << std::endl;
+
+ internalDepends << " " << target
+ << "/FortranDependInfo.cmake" << std::endl;
+
}
- // After copying the modules update the timestamp file so that
- // copying will not be done again until the source rebuilds.
- makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj
- << ".provides.build\n";
-
- // Make sure the module timestamp rule is evaluated by the time
- // the target finishes building.
- std::string driver = this->TargetDirectory;
- driver += "/build";
- driver = this->LocalGenerator->Convert(driver.c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- makeDepends << driver << ": " << obj << ".provides.build\n";
+ // module may be provided by a prebuild library
+ else
+ {
+ for(std::vector<std::string>::const_iterator
+ itIP = this->IncludePath->begin(); itIP != this->IncludePath->end();
+ ++itIP)
+ {
+ std::string tempPathStr = "";
+
+ // Construct the name of the file as if it were in the current
+ // include directory. Avoid using a leading "./".
+ if((*itR) == ".")
+ {
+ tempPathStr += *itIP;
+ }
+ else
+ {
+ tempPathStr += *itIP + "/" + *itR + ".mod" ;
+ }
+
+ if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
+ {
+ makeDepends << obj << ": " << " " << tempPathStr << std::endl;
+ internalDepends << " " << tempPathStr << std::endl;
+ break;
+ }
+ }
+ }
+ }
+
+ for(std::vector<std::string>::const_iterator
+ itP = sourceInfo.Provides.begin(); itP != sourceInfo.Provides.end();
+ ++itP )
+ {
+ makeDepends << thisModPath << *itP << ".mod: " << obj << std::endl;
}
- /*
- // TODO:
- What about .mod files provided in another directory and found with a
- -M search path? The stamp file will not be updated, so things might
- not rebuild. Possible solutions (not all thought through):
-
- Solution 1: Have all the .o.requires in a directory depend on a
- single .outside.requires that searches for .mod files in another
- directory of the build tree and uses copy-if-different to produce
- the local directory's stamp files. (won't work because the single
- rule cannot know about the modules)
-
- Solution 2: When the dependency is detected search the module
- include path for a mark file indicating the module is provided. If
- not found just write the dummy stamp file. If found, we need a rule
- to copy-if-different the module file. When a module is provided,
- write this mark file.
-
- Solution 3: Use a set of make rules like this:
-
- # When required:
- foo.mod.proxy: foo.mod.default
- foo.mod.default:: foo.mod.hack
- @echo foo.mod.default2 # Search for and copy-if-different the mod file.
- foo.mod.hack:
-
- # When provided:
- foo.mod.proxy: foo.o.requires
- @rm -f foo.mod.hack foo.mod.default
- foo.o.requires: foo.mod.hack
- @echo foo.o.requires
- foo.mod.hack:
- @touch foo.mod.hack
- @touch foo.mod.default
-
- Solution 4:
-
- When scanning dependencies and providing a module:
- - Create a .mod.provided.
- - Add .mod.proxy rule depending on corresponding .o.requires.
-
- When scanning dependencies and requiring a module:
- - Search the module path for a .mod.provided or a .mod.
- - If a .mod.provided is found depend on the corresponding .mod.stamp
- (it is provided by CMake in another directory)
- - Else, if a .mod is found depend on it directly
- (it is provided in another directory by a non-CMake project)
- - Else:
- - Add the empty proxy rule (if it is provided locally this will hook it)
- - Depend on a local .mod.stamp (it might be provided locally)
- - Create the dummy local .mod.stamp (it might not be provided locally)
-
- */
+ internalDepends << std::endl;
return true;
}
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index 4e1226c..6be0514 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -18,6 +18,7 @@
#define cmDependsFortran_h
#include "cmDepends.h"
+#include "cmFortranDependInfos.h"
/** \class cmDependsFortran
* \brief Dependency scanner for Fortran object files.
@@ -43,6 +44,8 @@ public:
corresponding stamp file. */
static bool CopyModule(const std::vector<std::string>& args);
+ bool ModuleScan(const char *src, cmFortranSourceDependInfo&);
+
/** Method to find an included file in the include path. Fortran
always searches the directory containing the including source
first. */
diff --git a/Source/cmFortranDependInfos.cxx b/Source/cmFortranDependInfos.cxx
new file mode 100644
index 0000000..2a12063
--- /dev/null
+++ b/Source/cmFortranDependInfos.cxx
@@ -0,0 +1,226 @@
+#include "cmFortranDependInfos.h"
+#include "cmSystemTools.h"
+#include "cmGeneratedFileStream.h"
+#include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmake.h"
+
+#include <fstream>
+#include <memory>
+#include <algorithm>
+
+char const* cmFortranDependInfos::ArchiveName = "FortranModuleInfos.cmake";
+
+void cmFortranTargetDependInfo
+::GetModuleInfoOfSource(char const* src_, cmFortranSourceDependInfo& fSDinfo)
+ const
+{
+ bool found = false;
+ std::string src = src_;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it = Sources.begin(); it != Sources.end() && !found; ++it)
+ {
+ if(it->Name == src )
+ {
+ fSDinfo = *it;
+ found = true;
+ }
+ }
+
+ if(!found)
+ fSDinfo.Name = "NotFound";
+}
+
+bool cmFortranTargetDependInfo::Provides(char const* mod) const
+{
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it = Sources.begin(); it != Sources.end(); ++it)
+ {
+ if(find(it->Provides.begin() , it->Provides.end(), mod)
+ != it->Provides.end() )
+ return true;
+
+ }
+ return false;
+}
+
+
+
+cmFortranDependInfos::~cmFortranDependInfos()
+{
+}
+
+void cmFortranDependInfos
+::InsertTargetDependInfo(cmFortranTargetDependInfo const& targetInfo)
+{
+ Targets[targetInfo.Name] = targetInfo;
+
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it = targetInfo.Sources.begin(); it != targetInfo.Sources.end(); ++it)
+ {
+ for(std::vector<std::string>::const_iterator
+ itP = it->Provides.begin(); itP != it->Provides.end(); ++itP)
+ {
+ this->ProvidedModules[*itP] = targetInfo.Name;
+ }
+ }
+}
+
+void cmFortranDependInfos
+::GetModuleInfoOfTarget(char const* targetName_,
+ cmFortranTargetDependInfo& targetInfo) const
+{
+ std::string targetName = targetName_;
+ targets_type::const_iterator match = Targets.find(targetName);
+ if(match != Targets.end())
+ targetInfo = match->second;
+}
+
+void cmFortranDependInfos
+::SetLocalGenerator(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+}
+
+
+char const* cmFortranDependInfos
+::ProvidedByTarget(char const* mod_)
+{
+ std::string mod = mod_;
+ char const* target = 0;
+ std::map<std::string, std::string>::const_iterator match =
+ this->ProvidedModules.find(mod);
+ if(match != this->ProvidedModules.end())
+ target = match->second.c_str();
+
+ return target;
+}
+
+void cmFortranTargetDependInfo
+::Save(char const* archive)
+{
+// std::ofstream ofs(archive.c_str());
+// boost::archive::text_oarchive oa(ofs);
+// oa & Targets;
+
+ cmGeneratedFileStream ofs(archive);
+
+ ofs << "SET(CMAKE_FORTRAN_TARGET_DEPEND_INFO_SOURCES"
+ << "\n";
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = this->Sources.begin(); it_s != this->Sources.end();
+ ++it_s)
+ {
+ ofs << " " << it_s->Name << "\n";
+ }
+ ofs << ")\n\n";
+
+
+ // .._REQUIRES
+ std::size_t src_cnt = 0;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = this->Sources.begin(); it_s != this->Sources.end();
+ ++it_s, ++src_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_TARGET_DEPEND_INFO" << "_SRC" << src_cnt
+ << "_REQUIRES" << "\n";
+
+ for(std::vector<std::string>::const_iterator
+ itR = it_s->Requires.begin(); itR != it_s->Requires.end(); ++itR)
+ {
+ ofs << " " << *itR << "\n";
+ }
+ ofs << ")\n\n";
+ }
+
+
+
+ // .._PROVIDES
+ src_cnt = 0;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = this->Sources.begin(); it_s != this->Sources.end();
+ ++it_s, ++src_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_TARGET_DEPEND_INFO" << "_SRC" << src_cnt
+ << "_PROVIDES" << "\n";
+
+ for(std::vector<std::string>::const_iterator
+ itP = it_s->Provides.begin(); itP != it_s->Provides.end(); ++itP)
+ {
+ ofs << " " << *itP << "\n";
+ }
+ ofs << ")\n\n";
+ }
+
+
+ // .._INCLUDES
+ src_cnt = 0;
+ for(std::set<cmFortranSourceDependInfo>::const_iterator
+ it_s = this->Sources.begin(); it_s != this->Sources.end();
+ ++it_s, ++src_cnt)
+ {
+ ofs << "SET(CMAKE_FORTRAN_TARGET_DEPEND_INFO" << "_SRC" << src_cnt
+ << "_INCLUDES" << "\n";
+
+ for(std::vector<std::string>::const_iterator
+ itI = it_s->Includes.begin(); itI != it_s->Includes.end(); ++itI)
+ {
+ ofs << " " << *itI << "\n";
+ }
+ ofs << ")\n\n";
+ }
+
+
+}
+
+void cmFortranTargetDependInfo::Load(char const* archive)
+{
+
+ typedef std::vector<std::string>::const_iterator cit_type;
+
+ this->Name = cmSystemTools::GetFilenamePath(archive);
+
+ // Read the directory information file.
+ std::auto_ptr<cmMakefile> mf(new cmMakefile);
+ mf->SetLocalGenerator(this->LocalGenerator);
+ if(! mf->ReadListFile(0, archive) )
+ return;
+
+ char const* c_sourceNames =
+ mf->GetSafeDefinition("CMAKE_FORTRAN_TARGET_DEPEND_INFO_SOURCES");
+ std::vector<std::string> sourceNames;
+ cmSystemTools::ExpandListArgument(c_sourceNames, sourceNames);
+
+ std::size_t src_cnt = 0;
+ for(cit_type it_s = sourceNames.begin(); it_s != sourceNames.end();
+ ++it_s, ++src_cnt)
+ {
+ cmOStringStream var;
+ var << "CMAKE_FORTRAN_TARGET_DEPEND_INFO_SRC" << src_cnt;
+
+ cmFortranSourceDependInfo sourceInfo;
+ sourceInfo.Name = *it_s;
+
+ {
+ std::string def = var.str() + "_PROVIDES";
+ char const* def_value = mf->GetSafeDefinition(def.c_str());
+ cmSystemTools::ExpandListArgument(def_value, sourceInfo.Provides);
+ }
+ {
+ std::string def = var.str() + "_REQUIRES";
+ char const* def_value = mf->GetSafeDefinition(def.c_str());
+ cmSystemTools::ExpandListArgument(def_value, sourceInfo.Requires);
+ }
+ {
+ std::string def = var.str() + "_INCLUDES";
+ char const* def_value = mf->GetSafeDefinition(def.c_str());
+ cmSystemTools::ExpandListArgument(def_value, sourceInfo.Includes);
+ }
+
+ this->Sources.insert(sourceInfo);
+ }
+
+}
+
+
diff --git a/Source/cmFortranDependInfos.h b/Source/cmFortranDependInfos.h
new file mode 100644
index 0000000..fe7b733
--- /dev/null
+++ b/Source/cmFortranDependInfos.h
@@ -0,0 +1,62 @@
+#ifndef CMFORTRANMODULEINFOS_H_
+#define CMFORTRANMODULEINFOS_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+
+
+class cmLocalGenerator;
+
+struct cmFortranSourceDependInfo
+{
+ std::string Name;
+ std::vector<std::string> Requires;
+ std::vector<std::string> Provides;
+ std::vector<std::string> Includes;
+
+ bool operator<(cmFortranSourceDependInfo const& rhs) const
+ {
+ return this->Name < rhs.Name;
+ }
+};
+struct cmFortranTargetDependInfo
+{
+ std::string Name;
+ std::set<cmFortranSourceDependInfo> Sources;
+ void GetModuleInfoOfSource(char const* src, cmFortranSourceDependInfo&) const;
+ bool Provides(char const* mod) const;
+
+ void Save(char const* archive);
+ void Load(char const* archive);
+
+ cmLocalGenerator* LocalGenerator;
+};
+
+class cmFortranDependInfos
+{
+public:
+ typedef std::map<std::string, cmFortranTargetDependInfo > targets_type;
+
+// cmFortranDependInfos();
+ virtual ~cmFortranDependInfos();
+
+ void InsertTargetDependInfo(cmFortranTargetDependInfo const&);
+
+ void GetModuleInfoOfTarget(char const* targetName,
+ cmFortranTargetDependInfo&) const;
+
+ void SetLocalGenerator(cmLocalGenerator* lg);
+ char const* ProvidedByTarget(char const* mod);
+
+private:
+ static char const* ArchiveName;
+ targets_type Targets;
+ cmLocalGenerator* LocalGenerator;
+
+ // for speed improvements when this->Prvides is called
+ std::map<std::string, std::string> ProvidedModules;
+};
+
+#endif /*CMFORTRANMODULEINFOS_H_*/
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index b7f7f6d..0c3bcb6 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -698,6 +698,17 @@ cmGlobalUnixMakefileGenerator3
<< localName << "\n\n";
commands.clear();
+
+ std::set<cmStdString> langs;
+ t->second.GetLanguages(langs);
+ if(std::find(langs.begin(), langs.end(), "Fortran") != langs.end())
+ {
+ makeTargetName = localName;
+ makeTargetName += "/fortran_module_scan";
+ commands.push_back(lg->GetRecursiveMakeCall
+ (makefileName.c_str(),makeTargetName.c_str()));
+ }
+
makeTargetName = localName;
makeTargetName += "/depend";
commands.push_back(lg->GetRecursiveMakeCall
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4a81404..35e22cf 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -31,6 +31,7 @@
#if defined(CMAKE_BUILD_WITH_CMAKE)
# define CM_LG_ENCODE_OBJECT_NAMES
# include <cmsys/MD5.h>
+# include "cmFortranDependInfos.h"
#endif
#include <cmsys/System.h>
@@ -2474,6 +2475,14 @@ cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
}
//----------------------------------------------------------------------------
+#ifdef CMAKE_BUILD_WITH_CMAKE
+void cmLocalGenerator::SetFortranDependInfos(cmFortranDependInfos* fDInfos)
+{
+ this->FortranDependInfos = fDInfos;
+}
+#endif
+
+//----------------------------------------------------------------------------
void
cmLocalGenerator
::GenerateTargetInstallRules(
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 4c83de4..4ce3c54 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -26,6 +26,10 @@ class cmTargetManifest;
class cmSourceFile;
class cmCustomCommand;
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ class cmFortranDependInfos;
+#endif
+
/** \class cmLocalGenerator
* \brief Create required build files for a directory.
*
@@ -157,6 +161,18 @@ public:
///! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(const char* p);
+#ifdef CMAKE_BUILD_WITH_CMAKE
+
+ void SetFortranDependInfos(cmFortranDependInfos* fDInfos);
+ cmFortranDependInfos* GetFortranDependInfos()
+ { return this->FortranDependInfos; }
+
+ /** Called from command-line. A hook to scan for fortran modules. */
+ virtual bool FortranModuleScan(char const* /* depInfoFile */)
+ { return true; }
+
+#endif
+
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* /* mf */,
bool /* verbose */) {}
@@ -343,6 +359,10 @@ protected:
std::string RelativePathTopBinary;
bool RelativePathsConfigured;
bool PathConversionsSetup;
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmFortranDependInfos* FortranDependInfos;
+#endif
};
#endif
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index a09110f..933e3ab 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1277,6 +1277,134 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
}
//----------------------------------------------------------------------------
+#ifdef CMAKE_BUILD_WITH_CMAKE
+bool cmLocalUnixMakefileGenerator3::FortranModuleScan(char const* depInfoFile_)
+{
+
+ // The info file for this target
+ std::string depInfoFile = depInfoFile_;
+
+ // Read the directory information file.
+ cmMakefile* mf = this->Makefile;
+ bool haveDirectoryInfo = false;
+ std::string dirInfoFile = this->Makefile->GetStartOutputDirectory();
+ dirInfoFile += cmake::GetCMakeFilesDirectory();
+ dirInfoFile += "/CMakeDirectoryInformation.cmake";
+ if(mf->ReadListFile(0, dirInfoFile.c_str()) &&
+ !cmSystemTools::GetErrorOccuredFlag())
+ {
+ haveDirectoryInfo = true;
+ }
+
+ // read in the target info file
+ if(!mf->ReadListFile(0, depInfoFile.c_str()) ||
+ cmSystemTools::GetErrorOccuredFlag())
+ {
+ cmSystemTools::Error("Target DependInfo.cmake file not found");
+ }
+
+
+ // Lookup useful directory information.
+ if(haveDirectoryInfo)
+ {
+ // Test whether we need to force Unix paths.
+ if(const char* force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS"))
+ {
+ if(!cmSystemTools::IsOff(force))
+ {
+ cmSystemTools::SetForceUnixPaths(true);
+ }
+ }
+
+ // Setup relative path top directories.
+ this->RelativePathsConfigured = true;
+ if(const char* relativePathTopSource =
+ mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE"))
+ {
+ this->RelativePathTopSource = relativePathTopSource;
+ }
+ if(const char* relativePathTopBinary =
+ mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY"))
+ {
+ this->RelativePathTopBinary = relativePathTopBinary;
+ }
+ }
+ else
+ {
+ cmSystemTools::Error("Directory Information file not found");
+ }
+
+ // Get the set of include directories.
+ std::vector<std::string> includes;
+ if(haveDirectoryInfo)
+ {
+ std::string includePathVar = "CMAKE_";
+ includePathVar += "Fortran";
+ includePathVar += "_INCLUDE_PATH";
+ if(const char* includePath = mf->GetDefinition(includePathVar.c_str()))
+ {
+ cmSystemTools::ExpandListArgument(includePath, includes);
+ }
+ }
+
+ std::string dir = cmSystemTools::GetFilenamePath(depInfoFile);
+ std::auto_ptr<cmDependsFortran> scanner (new cmDependsFortran(includes));
+
+
+ if(scanner.get())
+ {
+ std::string targetName = cmSystemTools::GetFilenameName(dir);
+
+ targetName = targetName.substr(0, targetName.length()-4);
+ std::string message = "fortran module scan for target " + targetName;
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta
+ | cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, true);
+
+ std::string homeDir = this->Makefile->GetHomeDirectory();
+ std::string homeOutputDir = this->Makefile->GetHomeOutputDirectory();
+ cmFortranTargetDependInfo fortranTargetDependInfo;
+
+ scanner->SetLocalGenerator(this);
+ scanner->SetFileComparison(
+ this->GlobalGenerator->GetCMakeInstance()->GetFileComparison());
+
+ std::string srcLang = "CMAKE_DEPENDS_CHECK_Fortran";
+ const char *srcStr = mf->GetSafeDefinition(srcLang.c_str());
+ std::vector<std::string> srcs;
+ cmSystemTools::ExpandListArgument(srcStr, srcs);
+
+ for(std::vector<std::string>::iterator
+ si = srcs.begin(); si != srcs.end(); ++si)
+ {
+ std::string &src = *si;
+ std::string obj = *(++si);
+ cmFortranSourceDependInfo dinfo;
+
+ // make sure the object file is relative to home output
+ obj = this->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE);
+
+ dinfo.Name = src;
+ scanner->ModuleScan(src.c_str(), dinfo);
+ std::string relDir = this->Convert(dir.c_str(),HOME_OUTPUT,MAKEFILE);
+ fortranTargetDependInfo.Sources.insert(dinfo);
+ }
+ std::string archive = dir;
+ archive += "/FortranDependInfo.cmake";
+ fortranTargetDependInfo.Save(archive.c_str());
+
+ // scan for this target is complete, so touch the mark file
+ std::string mark = dir + "/fortran_module_scan.mark";
+ std::ofstream fmark(mark.c_str());
+ fmark << "fortran module scan updated>" << std::endl;
+ }
+
+
+ return true;
+}
+#endif // CMAKE_BUILD_WITH_CMAKE
+
+//----------------------------------------------------------------------------
bool
cmLocalUnixMakefileGenerator3
::ScanDependencies(const char* targetDir)
@@ -1394,6 +1522,9 @@ cmLocalUnixMakefileGenerator3
}
}
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ std::auto_ptr<cmFortranDependInfos> fdinfos;
+#endif
// Create the scanner for this language
cmDepends *scanner = 0;
if(lang == "C" || lang == "CXX" || lang == "RC")
@@ -1413,6 +1544,31 @@ cmLocalUnixMakefileGenerator3
else if(lang == "Fortran")
{
scanner = new cmDependsFortran(includes);
+ fdinfos.reset(new cmFortranDependInfos);
+ this->SetFortranDependInfos(fdinfos.get());
+
+ {
+ cmFortranTargetDependInfo fortranTargetDependInfo;
+ fortranTargetDependInfo.LocalGenerator = this;
+ std::string archive = dir + "/FortranDependInfo.cmake";
+ fortranTargetDependInfo.Load(archive.c_str());
+ fdinfos->InsertTargetDependInfo(fortranTargetDependInfo);
+ }
+ char const* c_dependees =
+ mf->GetSafeDefinition("CMAKE_DEPENDS_DEPENDEES");
+ std::vector<std::string> dependees;
+ cmSystemTools::ExpandListArgument(c_dependees, dependees);
+
+ for(std::vector<std::string>::const_iterator
+ it = dependees.begin(); it != dependees.end(); ++it)
+ {
+ cmFortranTargetDependInfo fortranTargetDependInfo;
+ std::string archive = *it + "/FortranDependInfo.cmake";
+ fortranTargetDependInfo.LocalGenerator = this;
+ fortranTargetDependInfo.Load(archive.c_str());
+ fdinfos->InsertTargetDependInfo(fortranTargetDependInfo);
+ }
+
}
else if(lang == "Java")
{
@@ -1760,6 +1916,22 @@ void cmLocalUnixMakefileGenerator3
}
cmakefileStream << " )\n";
}
+
+ cmakefileStream << "SET(CMAKE_DEPENDS_DEPENDEES\n";
+ cmTarget::LinkLibraryVectorType linkLibs = target.GetLinkLibraries();
+ for(cmTarget::LinkLibraryVectorType::const_iterator
+ itL = linkLibs.begin(); itL != linkLibs.end(); ++itL)
+ {
+ if(cmTarget* libTarget =
+ this->GetGlobalGenerator()-> FindTarget(0, itL->first.c_str(), true))
+ {
+ std::string targetDir = libTarget->GetDirectory();
+ targetDir += "/";
+ targetDir += this->GetTargetDirectory(*libTarget);
+ cmakefileStream << " \"" << targetDir << "\"\n";
+ }
+ }
+ cmakefileStream << " )\n";
}
//----------------------------------------------------------------------------
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 364b890..dcfec5c 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -203,6 +203,11 @@ public:
virtual bool UpdateDependencies(const char* tgtInfo,
bool verbose, bool color);
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ /** Called from command-line. A hook to scan for fortran modules. */
+ virtual bool FortranModuleScan(char const* depInfoFile);
+#endif
+
/** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* mf, bool verbose);
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index c25b1ed..db9a53e 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -45,6 +45,11 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// write the per-target per-language flags
this->WriteTargetLanguageFlags();
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // Write the dependency generation rule.
+ this->WriteTargetFortranModuleScanRules();
+#endif
+
// write the link rules
this->WriteExecutableRule(false);
if(this->Target->NeedRelinkBeforeInstall())
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index c395682..2bddd7b 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -47,6 +47,12 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
// write the per-target per-language flags
this->WriteTargetLanguageFlags();
+ // MAIKS_ANNOTATION
+ #ifdef CMAKE_BUILD_WITH_CMAKE
+ // Write the dependency generation rule.
+ this->WriteTargetFortranModuleScanRules();
+ #endif
+
// write the link rules
// Write the rule for this target type.
switch(this->Target->GetType())
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index f954d0a..b3d18e6 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -731,6 +731,89 @@ void cmMakefileTargetGenerator::WriteTargetRequiresRules()
}
//----------------------------------------------------------------------------
+#ifdef CMAKE_BUILD_WITH_CMAKE
+void cmMakefileTargetGenerator::WriteTargetFortranModuleScanRules()
+{
+
+ std::vector<std::string> depends;
+ std::vector<std::string> no_commands, commands;
+
+ std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
+ this->InfoFileNameFull = dir;
+ this->InfoFileNameFull += "/DependInfo.cmake";
+
+ this->InfoFileNameFull =
+ this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
+
+ // Construct the name of the dependency generation target.
+ std::string depTargetDir =
+ this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
+ depTargetDir += "/fortran_module_scan";
+ std::string depTarget = depTargetDir + ".mark";
+
+ // This target drives dependency generation for all object files.
+ std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string pathTarget = this->LocalGenerator->GetTargetDirectory(*(this->Target));
+ std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
+
+
+
+
+ for(std::vector<cmSourceFile*>::const_iterator it = sources.begin();
+ it != sources.end(); ++it)
+ {
+ std::string srcRelPath = (*it)->GetFullPath();
+ srcRelPath = this->Convert(srcRelPath.c_str(), cmLocalGenerator::FULL);
+ depends.push_back(srcRelPath);
+ }
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTarget.c_str(),
+ depends, no_commands, true);
+ depends.clear();
+
+ {
+ cmOStringStream depCmd;
+ // Generate a call this signature:
+ //
+ // -E cmake_fortran_module_scan <generator>
+ // <home-src-dir> <start-src-dir>
+ // <home-out-dir> <start-out-dir>
+ // <dep-info>
+ depCmd << "$(CMAKE_COMMAND) -E cmake_fortran_module_scan \""
+ << this->GlobalGenerator->GetName() << "\" "
+ << this->Convert(this->Makefile->GetHomeDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->Makefile->GetStartDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->Makefile->GetHomeOutputDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->Makefile->GetStartOutputDirectory(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
+ << " "
+ << this->Convert(this->InfoFileNameFull.c_str(),
+ cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
+
+ std::string command = depCmd.str();
+ commands.push_back(command.c_str());
+ }
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTarget.c_str(),
+ depends, commands, true);
+
+ depends.clear();
+ depends.push_back(depTarget);
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ depTargetDir.c_str(),
+ depends, no_commands, true);
+
+}
+#endif // CMAKE_BUILD_WITH_CMAKE
+
+
+//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetCleanRules()
{
std::vector<std::string> depends;
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index fac9597..76b3056 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -76,6 +76,11 @@ protected:
// write the provide require rules for this target
void WriteTargetRequiresRules();
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // write the fortran scan rules for this target
+ void WriteTargetFortranModuleScanRules();
+#endif
+
// write the clean rules for this target
void WriteTargetCleanRules();
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 1eb087f..4e8c75f 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1433,7 +1433,51 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
}
return 1;
}
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // This command looks almost the same as cmake_depends
+ else if (args[1] == "cmake_fortran_module_scan" && args.size() >= 6)
+ {
+ // Create a cmake object instance to process dependencies.
+ cmake cm;
+ // signature:
+ //
+ // -E cmake_fortran_module_scan <generator>
+ // <home-src-dir> <start-src-dir>
+ // <home-out-dir> <start-out-dir>
+ // <dep-info>
+ std::string gen = args[2];
+ std::string homeDir = args[3];
+ std::string startDir = args[4];
+ std::string homeOutDir = args[5];
+ std::string startOutDir = args[6];
+ std::string depInfo = args[7];
+
+ // Create a local generator configured for the directory in
+ // which dependencies will be scanned.
+ homeDir = cmSystemTools::CollapseFullPath(homeDir.c_str());
+ startDir = cmSystemTools::CollapseFullPath(startDir.c_str());
+ homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir.c_str());
+ startOutDir = cmSystemTools::CollapseFullPath(startOutDir.c_str());
+ cm.SetHomeDirectory(homeDir.c_str());
+ cm.SetStartDirectory(startDir.c_str());
+ cm.SetHomeOutputDirectory(homeOutDir.c_str());
+ cm.SetStartOutputDirectory(startOutDir.c_str());
+ if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
+ {
+ cm.SetGlobalGenerator(ggd);
+ std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
+ lgd->SetGlobalGenerator(ggd);
+
+ lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
+ lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
+ lgd->GetMakefile()->MakeStartDirectoriesCurrent();
+ // Scan for fortran modules.
+ return lgd->FortranModuleScan(depInfo.c_str()) ? 0 : 2;
+ }
+ return 1;
+ }
+#endif
// Internal CMake link script support.
else if (args[1] == "cmake_link_script" && args.size() >= 3)
{
testcases_rev0.tar.gz [^] (2,365 bytes) 2007-12-23 13:59 |