NCBI C++ ToolKit
msvc_prj_files_collector.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

00001 /* $Id: msvc_prj_files_collector.cpp 60971 2013-12-17 18:02:47Z gouriano $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Author:  Viatcheslav Gorelenkov
00027  *
00028  */
00029 
00030 #include <ncbi_pch.hpp>
00031 #include "stl_msvc_usage.hpp"
00032 #include "msvc_prj_files_collector.hpp"
00033 #include "msvc_prj_utils.hpp"
00034 #include "configurable_file.hpp"
00035 #include "ptb_err_codes.hpp"
00036 #include "proj_tree_builder.hpp"
00037 
00038 
00039 BEGIN_NCBI_SCOPE
00040 
00041 
00042 static void s_CollectRelPathes(const string&        path_from,
00043                                const list<string>&  abs_dirs,
00044                                list<string>*        rel_pathes);
00045 
00046 // sort files by base file name, ignoring path and extension
00047 bool s_FileName_less(const string& x, const string& y)
00048 {
00049     string base_x, base_y;
00050     CDirEntry::SplitPath(x, NULL, &base_x);
00051     CDirEntry::SplitPath(y, NULL, &base_y);
00052     return NStr::CompareNocase(base_x, base_y) < 0;
00053 }
00054 
00055 //-----------------------------------------------------------------------------
00056 
00057 CMsvcPrjFilesCollector::CMsvcPrjFilesCollector
00058                                 (const CMsvcPrjProjectContext& project_context,
00059                                  const list<SConfigInfo>&      project_configs,
00060                                  const CProjItem&              project)
00061     : m_Context(&project_context),
00062       m_Configs(&project_configs),
00063       m_Project(&project)
00064 {
00065     CollectSources();
00066     CollectHeaders();
00067     CollectInlines();
00068     CollectResources();
00069     CollectExtra();
00070 }
00071 
00072 
00073 CMsvcPrjFilesCollector::~CMsvcPrjFilesCollector(void)
00074 {
00075 }
00076 
00077 
00078 const list<string>& CMsvcPrjFilesCollector::SourceFiles(void) const
00079 {
00080     return m_SourceFiles;
00081 }
00082 
00083 
00084 const list<string>& CMsvcPrjFilesCollector::HeaderFiles(void) const
00085 {
00086     return m_HeaderFiles;
00087 }
00088 
00089 
00090 const list<string>& CMsvcPrjFilesCollector::InlineFiles(void) const
00091 {
00092     return m_InlineFiles;
00093 }
00094 
00095 
00096 // source files helpers -------------------------------------------------------
00097 
00098 const list<string>& CMsvcPrjFilesCollector::ResourceFiles(void) const
00099 {
00100     return m_ResourceFiles;
00101 }
00102 
00103 const map<string, list<string> > CMsvcPrjFilesCollector::GetExtraFiles(void) const
00104 {
00105     return m_ExtraFiles;
00106 }
00107 
00108 struct PSourcesExclude
00109 {
00110     PSourcesExclude(const string& prj_id, const list<string>& excluded_sources)
00111         : m_Prj(prj_id)
00112     {
00113         copy(excluded_sources.begin(), excluded_sources.end(), 
00114              inserter(m_ExcludedSources, m_ExcludedSources.end()) );
00115     }
00116 
00117     bool operator() (const string& src) const
00118     {
00119         string src_base;
00120         CDirEntry::SplitPath(src, NULL, &src_base);
00121         if (m_ExcludedSources.find(src_base) != m_ExcludedSources.end()) {
00122             PTB_WARNING_EX(src, ePTB_FileExcluded,
00123                            "Project " << m_Prj << ": source file excluded");
00124             return true;
00125         }
00126         return false;
00127     }
00128 
00129 private:
00130     string m_Prj;
00131     set<string> m_ExcludedSources;
00132 };
00133 
00134 static bool s_IsInsideDatatoolSourceDir(const string& src_path_abs)
00135 {
00136     string dir_name;
00137     CDirEntry::SplitPath(src_path_abs, &dir_name);
00138 
00139     //This files must be inside datatool src dir
00140     CDir dir(dir_name);
00141     if ( dir.GetEntries("*.module").empty() ) 
00142         return false;
00143     if ( dir.GetEntries("*.asn").empty() &&
00144          dir.GetEntries("*.dtd").empty() &&
00145          dir.GetEntries("*.xsd").empty() ) 
00146         return false;
00147 
00148     return true;
00149 }
00150 
00151 
00152 void 
00153 CMsvcPrjFilesCollector::CollectSources(void)
00154 {
00155     m_SourceFiles.clear();
00156 
00157     list<string> sources;
00158     ITERATE(list<string>, p, m_Project->m_Sources) {
00159 
00160         const string& src_rel = *p;
00161         string src_path = 
00162             CDirEntry::ConcatPath(m_Project->m_SourcesBaseDir, src_rel);
00163         src_path = CDirEntry::NormalizePath(src_path);
00164 
00165         sources.push_back(src_path);
00166     }
00167 
00168     list<string> included_sources;
00169     m_Context->GetMsvcProjectMakefile().GetAdditionalSourceFiles //TODO
00170                                             (SConfigInfo(),&included_sources);
00171 
00172     ITERATE(list<string>, p, included_sources) {
00173         string fullpath = CDirEntry::NormalizePath(
00174             CDirEntry::ConcatPath(m_Project->m_SourcesBaseDir, *p));
00175         string ext = SourceFileExt(fullpath);
00176         if (ext.empty() &&
00177             CDirEntry::IsAbsolutePath(fullpath) &&
00178             !GetApp().GetExtSrcRoot().empty()) {
00179             string tpath = CDirEntry::CreateRelativePath( GetApp().m_Root, fullpath);
00180             tpath = CDirEntry::ConcatPath(GetApp().GetExtSrcRoot(), tpath);
00181             ext = SourceFileExt(tpath);
00182             if (!ext.empty()) {
00183                 fullpath = tpath;
00184             }
00185         }
00186         sources.push_back(fullpath);
00187     }
00188 
00189     list<string> excluded_sources;
00190     m_Context->GetMsvcProjectMakefile().GetExcludedSourceFiles //TODO
00191                                             (SConfigInfo(), &excluded_sources);
00192     if (!excluded_sources.empty()) {
00193         PSourcesExclude pred(m_Project->m_ID, excluded_sources);
00194         EraseIf(sources, pred);
00195     }
00196 
00197     ITERATE(list<string>, p, sources) {
00198 
00199         const string& abs_path = *p; // whithout ext.
00200 
00201         string ext = SourceFileExt(abs_path);
00202         if ( NStr::EndsWith(ext, ".in") ) {
00203             // Special case: skip configurable file generation
00204             // if configurations was not specified
00205             if ( m_Configs->empty() ) {
00206                 m_SourceFiles.push_back(
00207                     CDirEntry::CreateRelativePath(m_Context->ProjectDir(),
00208                                                   abs_path));
00209             } else {
00210                 // configurable source file
00211                 string orig_ext = NStr::Replace(ext, ".in", "");
00212                 string dst_path;
00213                 CDirEntry::SplitPath(abs_path, NULL, &dst_path, NULL);
00214                 dst_path = CDirEntry::MakePath(m_Context->ProjectDir(), dst_path);
00215                 GetApp().SetConfFileData(abs_path + ext, dst_path);
00216 
00217                 // Create configurable file for each enabled configuration
00218                 ITERATE(list<SConfigInfo>, p , *m_Configs) {
00219                     const SConfigInfo& cfg_info = *p;
00220                     string file_dst_path;
00221                     file_dst_path = dst_path + "." +
00222                                     ConfigurableFileSuffix(cfg_info.GetConfigFullName())+
00223                                     orig_ext;
00224 #if 0
00225                     CreateConfigurableFile(abs_path + ext, file_dst_path,
00226                                            cfg_info.GetConfigFullName());
00227 #else
00228 // we postpone creation until later
00229 // here we only create placeholders
00230                     if (!CFile(file_dst_path).Exists()) {
00231                         CNcbiOfstream os(file_dst_path.c_str(),
00232                                          IOS_BASE::out | IOS_BASE::binary | IOS_BASE::trunc);
00233                     }
00234 #endif
00235                 }
00236                 dst_path += ".@config@" + orig_ext;
00237                 m_SourceFiles.push_back(
00238                     CDirEntry::CreateRelativePath(m_Context->ProjectDir(),
00239                                                   dst_path));
00240                 }
00241         }
00242         else if ( !ext.empty() ) {
00243             // add ext to file
00244             string source_file_abs_path = abs_path + ext;
00245             string t;
00246             try {
00247                 t = CDirEntry::CreateRelativePath(
00248                     m_Context->ProjectDir(), source_file_abs_path);
00249             } catch (CFileException&) {
00250                 t = source_file_abs_path;
00251             }
00252             m_SourceFiles.push_back(t);
00253         } 
00254         else if ( IsProducedByDatatool(abs_path, *m_Project) ||
00255                   s_IsInsideDatatoolSourceDir(abs_path) ) {
00256             // .cpp file extension
00257             m_SourceFiles.push_back(
00258                 CDirEntry::CreateRelativePath(m_Context->ProjectDir(), 
00259                                               abs_path + ".cpp"));
00260         } else {
00261             if (m_Project->m_MakeType >= eMakeType_Excluded ||
00262                 SMakeProjectT::IsConfigurableDefine(CDirEntry(abs_path).GetBase()) ||
00263                 m_Project->HasDataspecDependency()) {
00264                 PTB_WARNING_EX(abs_path, ePTB_FileNotFound,
00265                             "Source file not found");
00266             } else {
00267                 PTB_ERROR_EX(abs_path, ePTB_FileNotFound,
00268                            "Source file not found");
00269             }
00270         }
00271     }
00272     m_SourceFiles.sort(s_FileName_less);
00273     m_SourceFiles.unique();
00274 }
00275 
00276 
00277 // header files helpers -------------------------------------------------------
00278 void 
00279 CMsvcPrjFilesCollector::CollectHeaders(void)
00280 {
00281     m_HeaderFiles.clear();
00282     s_CollectRelPathes(m_Context->ProjectDir(), m_Context->IncludeDirsAbs(),
00283                        &m_HeaderFiles);
00284     m_HeaderFiles.sort(s_FileName_less);
00285     m_HeaderFiles.unique();
00286 }
00287 
00288 
00289 // inline files helpers -------------------------------------------------------
00290 
00291 void 
00292 CMsvcPrjFilesCollector::CollectInlines(void)
00293 {
00294     m_InlineFiles.clear();
00295     s_CollectRelPathes(m_Context->ProjectDir(), m_Context->InlineDirsAbs(),
00296                        &m_InlineFiles);
00297     m_InlineFiles.sort(s_FileName_less);
00298     m_InlineFiles.unique();
00299 }
00300 
00301 
00302 // resource files helpers -------------------------------------------------------
00303 
00304 void 
00305 CMsvcPrjFilesCollector::CollectResources(void)
00306 {
00307     m_ResourceFiles.clear();
00308 
00309     // resources from msvc makefile - first priority
00310     list<string> included_sources;
00311     m_Context->GetMsvcProjectMakefile().GetResourceFiles
00312                                             (SConfigInfo(),&included_sources);
00313     list<string> sources;
00314     ITERATE(list<string>, p, included_sources) {
00315         sources.push_back(CDirEntry::NormalizePath
00316                                         (CDirEntry::ConcatPath
00317                                               (m_Project->m_SourcesBaseDir, *p)));
00318     }
00319 
00320     ITERATE(list<string>, p, sources) {
00321 
00322         const string& abs_path = *p; // with ext.
00323         m_ResourceFiles.push_back(
00324             CDirEntry::CreateRelativePath(m_Context->ProjectDir(), 
00325                                           abs_path));
00326     }
00327     if ( m_ResourceFiles.empty() ) {
00328         // if there is no makefile resources - use defaults
00329         string default_rc;
00330         if (m_Project->m_ProjType == CProjKey::eApp) {
00331             default_rc = GetApp().GetSite().GetAppDefaultResource();
00332         }
00333         if ( !default_rc.empty() ) {
00334             string abs_path = GetApp().GetProjectTreeInfo().m_Compilers;
00335             abs_path = 
00336                 CDirEntry::ConcatPath(abs_path, 
00337                                     GetApp().GetRegSettings().m_CompilersSubdir);
00338             abs_path = CDirEntry::ConcatPath(abs_path, default_rc);
00339             abs_path = CDirEntry::NormalizePath(abs_path);
00340             m_ResourceFiles.push_back(
00341                 CDirEntry::CreateRelativePath(m_Context->ProjectDir(), 
00342                                             abs_path));
00343         }
00344     }
00345     m_ResourceFiles.sort(s_FileName_less);
00346     m_ResourceFiles.unique();
00347 }
00348 
00349 void 
00350 CMsvcPrjFilesCollector::CollectExtra(void)
00351 {
00352     m_ExtraFiles.clear();
00353 
00354     const map<string, list<string> >& extra = m_Project->m_ExtraFiles;
00355     for (map<string, list<string> >::const_iterator g = extra.begin(); g != extra.end(); ++g) {
00356         const list<string>& lst(g->second);
00357         ITERATE( list<string>, f, lst) {
00358             m_ExtraFiles[g->first].push_back(
00359                 CDirEntry::CreateRelativePath(m_Context->ProjectDir(), 
00360                     CDirEntry::NormalizePath(CDirEntry::ConcatPath(m_Project->m_SourcesBaseDir, *f))));
00361         }
00362     }
00363     
00364     map<string, list<string> > files;
00365     m_Context->GetMsvcProjectMakefile().GetExtraFiles(&files);
00366     for (map<string, list<string> >::const_iterator g = files.begin(); g != files.end(); ++g) {
00367         const list<string>& lst(g->second);
00368         ITERATE( list<string>, f, lst) {
00369             m_ExtraFiles[g->first].push_back(
00370                 CDirEntry::CreateRelativePath(m_Context->ProjectDir(), 
00371                     CDirEntry::NormalizePath(CDirEntry::ConcatPath(m_Project->m_SourcesBaseDir, *f))));
00372         }
00373     }
00374 }
00375 
00376 
00377 
00378 //-----------------------------------------------------------------------------
00379 // Collect all files from specified dirs having specified exts
00380 static void s_CollectRelPathes(const string&        path_from,
00381                                const list<string>&  abs_dirs,
00382                                list<string>*        rel_pathes)
00383 {
00384     rel_pathes->clear();
00385 
00386     set<string> toremove;
00387     list<string> pathes;
00388     ITERATE(list<string>, n, abs_dirs) {
00389         string value(*n), pdir, base, ext;
00390         if (value.empty()) {
00391             continue;
00392         }
00393         
00394         SIZE_TYPE negation_pos = value.find('!');
00395         bool remove = negation_pos != NPOS;
00396         if (remove) {
00397             value = NStr::Replace(value, "!", kEmptyStr);
00398             if (value.empty() ||
00399                 value[value.length()-1] == CDirEntry::GetPathSeparator()) {
00400                 continue;
00401             }
00402         }
00403         CDirEntry::SplitPath(value, &pdir, &base, &ext);
00404         CDir dir(pdir);
00405         if ( !dir.Exists() )
00406             continue;
00407         CDir::TEntries contents = dir.GetEntries(base + ext);
00408         ITERATE(CDir::TEntries, i, contents) {
00409             if ( (*i)->IsFile() ) {
00410                 string path  = (*i)->GetPath();
00411                 if ( NStr::EndsWith(path, ext, NStr::eNocase) ) {
00412                     if (remove) {
00413                         toremove.insert(path);
00414                     } else {
00415                         pathes.push_back(path);
00416                     }
00417                 }
00418             }
00419         }
00420     }
00421     ITERATE(set<string>, r, toremove) {
00422         pathes.remove(*r);
00423     }
00424 
00425     ITERATE(list<string>, p, pathes)
00426         rel_pathes->push_back(CDirEntry::CreateRelativePath(path_from, *p));
00427 }
00428 
00429 
00430 END_NCBI_SCOPE
Modified on Mon May 04 11:09:42 2015 by modify_doxy.py rev. 426318