1 /* $Id: proj_src_resolver.cpp 575393 2018-11-28 16:02:09Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Viatcheslav Gorelenkov
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31 #include "proj_src_resolver.hpp"
32 #include "proj_builder_app.hpp"
33 #include "proj_tree_builder.hpp"
34
35 BEGIN_NCBI_SCOPE
36
37 // collect include statements and resolve to abs pathes
s_GetMakefileIncludes(const string & applib_mfilepath,const string & source_base_dir,list<string> * includes)38 static void s_GetMakefileIncludes(const string& applib_mfilepath,
39 const string& source_base_dir,
40 list<string>* includes)
41 {
42 includes->clear();
43
44 CNcbiIfstream ifs(applib_mfilepath.c_str(),
45 IOS_BASE::in | IOS_BASE::binary);
46 if ( !ifs )
47 NCBI_THROW(CProjBulderAppException, eFileOpen, applib_mfilepath);
48
49 string strline;
50 while ( getline(ifs, strline) ) {
51 const string include_token("include ");
52 strline = NStr::TruncateSpaces(strline);
53 if ( NStr::StartsWith(strline, include_token) ) {
54 string include = strline.substr(include_token.length());
55
56 string root;
57 string srcdir_token("$(srcdir)");
58 if (include.find(srcdir_token) == 0) {
59 root = source_base_dir;
60 } else {
61 srcdir_token = "$(top_srcdir)";
62 if (include.find(srcdir_token) == 0) {
63 root = GetApp().GetProjectTreeInfo().m_Root;
64 }
65 else {
66 #if 0
67 srcdir_token = "$(builddir)";
68 if (NStr::StartsWith(include, srcdir_token)) {
69 root = GetApp().GetBuildRoot();
70 if (root.empty()) {
71 root = CDirEntry(GetApp().m_Solution).GetDir();
72 }
73 }
74 #endif
75 }
76 }
77 if (!root.empty()) {
78 include = include.substr(srcdir_token.length());
79 include = CDirEntry::ConcatPath(root, include);
80 include = CDirEntry::NormalizePath(include);
81 }
82 includes->push_back(include);
83 }
84 }
85 }
86
87
88 //-----------------------------------------------------------------------------
CProjSRCResolver(const string & applib_mfilepath,const string & source_base_dir,const list<string> & sources_src)89 CProjSRCResolver::CProjSRCResolver(const string& applib_mfilepath,
90 const string& source_base_dir,
91 const list<string>& sources_src)
92 :m_MakefilePath (applib_mfilepath),
93 m_SourcesBaseDir(source_base_dir),
94 m_SourcesSrc (sources_src)
95 {
96 }
97
98
~CProjSRCResolver(void)99 CProjSRCResolver::~CProjSRCResolver(void)
100 {
101 }
102
s_SourceFileExists(const string & dir,const string & name)103 static bool s_SourceFileExists(const string& dir, const string& name)
104 {
105 string path = CDirEntry::ConcatPath(dir, name);
106
107 if ( CDirEntry(path + ".cpp").Exists() )
108 return true;
109 if ( CDirEntry(path + ".cxx").Exists() )
110 return true;
111 if ( CDirEntry(path + ".cc").Exists() )
112 return true;
113 if ( CDirEntry(path + ".c").Exists() )
114 return true;
115 if ( CDirEntry(path + ".metal").Exists() )
116 return true;
117
118 return false;
119 }
120
ResolveTo(list<string> * sources_dst)121 void CProjSRCResolver::ResolveTo(list<string>* sources_dst)
122 {
123 sources_dst->clear();
124 PrepareResolver();
125
126 list<string> sources_names;
127 ITERATE(list<string>, p, m_SourcesSrc) {
128 const string& src = *p;
129 string src_define;
130 if (SMakeProjectT::IsConfigurableDefine(src)) {
131 src_define = "$(" + SMakeProjectT::StripConfigurableDefine(src) + ")";
132 } else if (CSymResolver::IsDefine(src)) {
133 src_define = FilterDefine(src);
134 } else {
135 sources_names.push_back(src);
136 continue;
137 }
138 list<string> resolved_src_defines;
139 m_Resolver.Resolve(src_define, &resolved_src_defines);
140 if (resolved_src_defines.size() == 1 && resolved_src_defines.front() == src_define) {
141 continue;
142 }
143 copy(resolved_src_defines.begin(),
144 resolved_src_defines.end(),
145 back_inserter(sources_names));
146 }
147
148 ITERATE(list<string>, p, sources_names) {
149 const string& src = *p;
150 bool found = false;
151 if ( s_SourceFileExists(m_SourcesBaseDir, src) ) {
152 sources_dst->push_back(src);
153 found = true;
154 } else {
155 ITERATE(list<string>, n, m_MakefileDirs) {
156 const string& dir = *n;
157 if ( s_SourceFileExists(dir, src) ) {
158 string path =
159 CDirEntry::CreateRelativePath(m_SourcesBaseDir, dir);
160 path = CDirEntry::ConcatPath(path, src);
161 sources_dst->push_back(path);
162 found = true;
163 break;
164 }
165 }
166 }
167 if ( !found )
168 sources_dst->push_back(src);
169 }
170 }
171
172
PrepareResolver(void)173 void CProjSRCResolver::PrepareResolver(void)
174 {
175 if ( !m_Resolver.IsEmpty() )
176 return;
177
178 list<string> include_makefiles;
179 s_GetMakefileIncludes(m_MakefilePath,
180 m_SourcesBaseDir, &include_makefiles);
181
182 ITERATE(list<string>, p, include_makefiles) {
183 m_MakefileDirs.push_back( CDirEntry(*p).GetDir());
184 }
185 CSymResolver::LoadFrom(m_MakefilePath, &m_Resolver);
186 m_Resolver.Append( GetApp().GetSite().GetMacros());
187 }
188
189 END_NCBI_SCOPE
190