4 * Build options generated by the configure script.
6 * Portable Windows Library
8 * Copyright (c) 2003 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
27 * Revision 1.40 2007/08/26 12:25:00 rjongbloed
28 * Changes to allow for 64 bit builds and 64 bit library linking.
30 * Revision 1.39 2007/08/22 07:00:53 rjongbloed
31 * Added new MSWIN_FIND_FILE option to locate files, eg .lib files, within the
32 * features detected directory sub-tree. Different packaging someimes has
33 * lib files in slightly different locations.
35 * Revision 1.38 2007/02/10 07:21:23 csoutheren
36 * Fixed problem with excluding directories
38 * Revision 1.37 2006/07/31 06:53:39 csoutheren
39 * Fixed problem with excluding directories
41 * Revision 1.36 2006/07/23 21:49:17 shorne
42 * Fix for exclude directories not being excluded
44 * Revision 1.35 2006/07/23 05:13:25 rjongbloed
45 * Disabled some code till get a chance to amke it work! Back to doing full disk searches all the time.
47 * Revision 1.34 2006/07/23 04:44:18 rjongbloed
48 * Fixed directory comparison to be more accurate, using Win32 API call to get absolute path.
50 * Revision 1.33 2006/07/22 06:20:55 rjongbloed
51 * Changes to configure program so will process dependencies before directory search so
52 * does not search for features it is not going to use.
53 * Added dependencies so both SSL libs cannot be included or searched for.
55 * Revision 1.32 2006/07/14 15:20:54 csoutheren
56 * Applied 1519950 - configure --extern-dir not working
57 * Thanks to Dinis Rosario
59 * Revision 1.31 2006/07/06 01:10:14 csoutheren
60 * Added parsing of version.h to configure
61 * PWLib version variables now set in ptbuildopts.h
63 * Revision 1.30 2006/07/05 13:38:17 shorne
64 * Fix compile error on MSVC6
66 * Revision 1.29 2006/07/04 00:40:16 csoutheren
67 * Added capability for multiple feature dependencies
69 * Revision 1.28 2006/06/29 02:37:23 csoutheren
70 * Fixed compile problem on VC 2005
72 * Revision 1.27 2006/06/26 01:02:55 csoutheren
73 * Improved configure.exe to ignore case when matching exclude dirs
74 * Allow exclusion of drive root directories
76 * Revision 1.26 2005/11/30 12:47:42 csoutheren
77 * Removed tabs, reformatted some code, and changed tags for Doxygen
79 * Revision 1.25 2005/08/15 09:40:58 rjongbloed
80 * Captalised the word "disabled" so more obvious.
82 * Revision 1.24 2005/08/13 19:13:49 shorne
83 * Fix so when feature not found it is marked as disabled.
85 * Revision 1.23 2004/12/09 02:05:52 csoutheren
86 * Added IF_FEATURE option to allow features dependent on existence/non-existence of
89 * Revision 1.22 2004/12/01 11:59:19 csoutheren
90 * Incremented version number
92 * Revision 1.21 2004/12/01 11:57:03 csoutheren
93 * Fixed problem with not finding MSWIN macros with leading spaces and added ability to enable/disable features using --name as as well as --enable-name
94 * Thank to Guilhem Tardy
96 * Revision 1.20 2004/08/13 01:08:09 csoutheren
97 * Changed to look for configure.ac, then configure.in
99 * Revision 1.19 2004/07/12 02:32:58 csoutheren
100 * Fixed problem when more than two elements in env var
102 * Revision 1.18 2004/04/29 02:02:25 csoutheren
103 * Removed debugging (oops)
105 * Revision 1.17 2004/04/29 02:00:49 csoutheren
106 * Fixed problem with checking for NULL error return from FindFirstFile rather than INVALID_HANDLE_VALUE
108 * Revision 1.16 2004/04/04 01:30:37 csoutheren
109 * Added ability to specify exclude environment variable on configure command line which allows easy switching between MSVC and VS.net 2003
111 * Revision 1.15 2004/03/23 06:32:01 csoutheren
112 * Fixed problems with multiple directories in exclude spec
114 * Revision 1.14 2004/03/16 01:45:17 rjongbloed
115 * Fixed locating lbrary in pre-defined search directories.
116 * Added version number to configure program.
117 * Tidied the --help display.
119 * Revision 1.13 2004/03/13 02:50:56 rjongbloed
120 * Fixed anomalous message where even though a feature was disabled, a "Located "
121 * directiory message is still displayed causing confusion.
122 * Added --disable-<feature> as synonym to existing --no-<feature> to be compatible
124 * Added default value to defines of 1 rather than blank.
126 * Revision 1.12 2004/01/30 02:33:58 csoutheren
129 * Revision 1.11 2004/01/30 01:43:41 csoutheren
130 * Added excludedir options and environment variable
132 * Revision 1.10 2003/11/25 08:21:37 rjongbloed
133 * Fixed display of configured items
135 * Revision 1.9 2003/11/06 09:13:20 rjongbloed
136 * Improved the Windows configure system to allow multiple defines based on file existence. Needed for SDL support of two different distros.
138 * Revision 1.8 2003/10/30 01:17:15 dereksmithies
139 * Add fix from Jose Luis Urien. Many thanks.
141 * Revision 1.7 2003/10/23 21:49:51 dereksmithies
142 * Add very sensible fix to limit extent of search. Thanks Ben Lear.
144 * Revision 1.6 2003/08/04 05:13:17 dereksmithies
145 * Reinforce the disablement if the command lines specifies --no-XXXX to a feature.
147 * Revision 1.5 2003/08/04 05:07:08 dereksmithies
148 * Command line option now disables feature when feature found on disk.
150 * Revision 1.4 2003/05/16 02:03:07 rjongbloed
151 * Fixed being able to manually disable a "feature" when does a full disk search.
153 * Revision 1.3 2003/05/05 08:39:52 robertj
154 * Added ability to explicitly disable a feature, or tell configure exactly
155 * where features library is so it does not need to search for it.
157 * Revision 1.2 2003/04/17 03:32:06 robertj
158 * Improved windows configure program to use lines out of configure.in
160 * Revision 1.1 2003/04/16 08:00:19 robertj
161 * Windoes psuedo autoconf support
165 #pragma warning(disable:4786)
166 #pragma warning(disable:4996)
181 #define VERSION "1.12"
183 static char * VersionTags
[] = { "MAJOR_VERSION", "MINOR_VERSION", "BUILD_NUMBER", "BUILD_TYPE" };
187 bool DirExcluded(const string
& dir
);
189 string
ToLower(const string
& _str
)
193 for(r
= str
.begin(); r
!= str
.end(); ++r
)
194 *r
= (char)tolower(*r
);
198 string
GetFullPathNameString(const string
& path
)
201 DWORD len
= ::GetFullPathName(path
.c_str(), 0, NULL
, NULL
);
203 fullPath
.resize(len
-1);
204 ::GetFullPathName(path
.c_str(), len
, &fullPath
[0], NULL
);
206 return ToLower(fullPath
);
222 Feature() : state(Enabled
) { }
223 Feature(const string
& featureName
, const string
& optionName
, const string
& optionValue
);
225 void Parse(const string
& optionName
, const string
& optionValue
);
226 void Adjust(string
& line
);
227 bool Locate(const char * testDir
);
231 string directorySymbol
;
232 string simpleDefineName
;
233 string simpleDefineValue
;
234 map
<string
, string
> defines
;
235 map
<string
, string
> defineValues
;
237 struct CheckFileInfo
{
238 CheckFileInfo() : found(false), defineName("1") { }
240 bool Locate(const string
& testDir
);
248 list
<CheckFileInfo
> checkFiles
;
250 list
<string
> checkDirectories
;
252 struct FindFileInfo
{
258 list
<FindFileInfo
> findFiles
;
260 list
<string
> ifFeature
;
261 list
<string
> ifNotFeature
;
269 vector
<Feature
> features
;
270 list
<string
> excludeDirList
;
272 ///////////////////////////////////////////////////////////////////////
274 Feature::Feature(const string
& featureNameParam
,
275 const string
& optionName
,
276 const string
& optionValue
)
277 : featureName(featureNameParam
),
280 Parse(optionName
, optionValue
);
284 void Feature::Parse(const string
& optionName
, const string
& optionValue
)
286 if (optionName
== "DISPLAY")
287 displayName
= optionValue
;
289 else if (optionName
== "DEFINE") {
290 string::size_type equal
= optionValue
.find('=');
291 if (equal
== string::npos
)
292 simpleDefineName
= optionValue
;
294 simpleDefineName
.assign(optionValue
, 0, equal
);
295 simpleDefineValue
.assign(optionValue
, equal
+1, INT_MAX
);
299 else if (optionName
== "VERSION") {
300 string::size_type equal
= optionValue
.find('=');
301 if (equal
!= string::npos
)
302 defines
.insert(pair
<string
,string
>(optionValue
.substr(0, equal
), optionValue
.substr(equal
+1)));
305 else if (optionName
== "CHECK_FILE") {
306 string::size_type comma
= optionValue
.find(',');
307 if (comma
== string::npos
)
311 string::size_type pipe
= optionValue
.find('|');
312 if (pipe
< 0 || pipe
> comma
)
313 check
.fileName
.assign(optionValue
, 0, comma
);
315 check
.fileName
.assign(optionValue
, 0, pipe
);
316 check
.fileText
.assign(optionValue
, pipe
+1, comma
-pipe
-1);
319 string::size_type equal
= optionValue
.find('=', comma
);
320 if (equal
== string::npos
)
321 check
.defineName
.assign(optionValue
, comma
+1, INT_MAX
);
323 check
.defineName
.assign(optionValue
, comma
+1, equal
-comma
-1);
324 check
.defineValue
.assign(optionValue
, equal
+1, INT_MAX
);
327 checkFiles
.push_back(check
);
330 else if (optionName
== "DIR_SYMBOL")
331 directorySymbol
= '@' + optionValue
+ '@';
333 else if (optionName
== "CHECK_DIR")
334 checkDirectories
.push_back(GetFullPathNameString(optionValue
));
336 else if (optionName
== "FIND_FILE") {
337 string::size_type comma1
= optionValue
.find(',');
338 if (comma1
== string::npos
)
341 string::size_type comma2
= optionValue
.find(',', comma1
+1);
342 if (comma2
== string::npos
)
346 find
.symbol
.assign(optionValue
, 0, comma1
);
347 find
.basename
.assign(optionValue
, comma1
+1, comma2
-comma1
-1);
348 find
.subdir
.assign(optionValue
, comma2
+1, INT_MAX
);
349 if (find
.subdir
.empty())
351 findFiles
.push_back(find
);
354 else if (optionName
== "IF_FEATURE") {
355 const char * delimiters
= "&";
356 string::size_type lastPos
= optionValue
.find_first_not_of(delimiters
, 0);
357 string::size_type pos
= optionValue
.find_first_of(delimiters
, lastPos
);
358 while (string::npos
!= pos
|| string::npos
!= lastPos
) {
359 string str
= optionValue
.substr(lastPos
, pos
- lastPos
);
361 ifNotFeature
.push_back(str
.substr(1));
363 ifFeature
.push_back(str
);
364 lastPos
= optionValue
.find_first_not_of(delimiters
, pos
);
365 pos
= optionValue
.find_first_of(delimiters
, lastPos
);
371 static bool CompareName(const string
& line
, const string
& name
)
373 string::size_type pos
= line
.find(name
);
374 if (pos
== string::npos
)
377 pos
+= name
.length();
378 return !isalnum(line
[pos
]) && line
[pos
] != '_';
381 void Feature::Adjust(string
& line
)
383 if (state
== Enabled
&& line
.find("#undef") != string::npos
) {
384 if (!simpleDefineName
.empty() && CompareName(line
, simpleDefineName
)) {
385 line
= "#define " + simpleDefineName
+ ' ';
386 if (simpleDefineValue
.empty())
389 line
+= simpleDefineValue
;
392 map
<string
,string
>::iterator r
, s
;
393 for (r
= defines
.begin(); r
!= defines
.end(); ++r
) {
394 if (CompareName(line
, r
->first
)) {
395 s
= defineValues
.find(r
->second
);
396 if (s
!= defineValues
.end())
397 line
= "#define " + r
->first
+ ' ' + s
->second
;
401 for (list
<CheckFileInfo
>::iterator file
= checkFiles
.begin(); file
!= checkFiles
.end(); file
++) {
402 if (file
->found
&& CompareName(line
, file
->defineName
)) {
403 line
= "#define " + file
->defineName
+ ' ' + file
->defineValue
;
408 for (list
<FindFileInfo
>::iterator file
= findFiles
.begin(); file
!= findFiles
.end(); file
++) {
409 if (!file
->fullname
.empty() && CompareName(line
, file
->symbol
)) {
410 line
= "#define " + file
->symbol
+ " \"" + file
->fullname
+ '"';
416 if (directorySymbol
[0] != '\0') {
417 string::size_type pos
= line
.find(directorySymbol
);
418 if (pos
!= string::npos
)
419 line
.replace(pos
, directorySymbol
.length(), directory
);
424 bool FindFileInTree(const string
& directory
, string
& filename
)
427 string wildcard
= directory
;
430 WIN32_FIND_DATA fileinfo
;
431 HANDLE hFindFile
= FindFirstFile(wildcard
.c_str(), &fileinfo
);
432 if (hFindFile
!= INVALID_HANDLE_VALUE
) {
434 if (stricmp(fileinfo
.cFileName
, filename
.c_str()) == 0) {
435 filename
.insert(0, directory
);
440 string subdir
= GetFullPathNameString(directory
+ fileinfo
.cFileName
);
441 if ((fileinfo
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
) != 0 &&
442 fileinfo
.cFileName
[0] != '.' &&
443 stricmp(fileinfo
.cFileName
, "RECYCLER") != 0 &&
444 !DirExcluded(subdir
)) {
447 found
= FindFileInTree(subdir
, filename
);
451 } while (FindNextFile(hFindFile
, &fileinfo
));
453 FindClose(hFindFile
);
460 bool Feature::Locate(const char * testDir
)
462 if (state
!= Enabled
)
465 if (!directory
.empty())
468 if (checkFiles
.empty())
471 string testDirectory
= testDir
;
472 if (testDirectory
[testDirectory
.length()-1] != '\\')
473 testDirectory
+= '\\';
475 list
<CheckFileInfo
>::iterator file
= checkFiles
.begin();
476 if (!file
->Locate(testDirectory
))
479 while (++file
!= checkFiles
.end())
480 file
->Locate(testDirectory
);
483 _fullpath(buf
, testDirectory
.c_str(), _MAX_PATH
);
486 if (DirExcluded(directory
))
489 cout
<< "Located " << displayName
<< " at " << directory
<< endl
;
491 string::size_type pos
;
492 while ((pos
= directory
.find('\\')) != string::npos
)
493 directory
[pos
] = '/';
494 pos
= directory
.length()-1;
495 if (directory
[pos
] == '/')
496 directory
.erase(pos
);
498 for (list
<FindFileInfo
>::iterator file
= findFiles
.begin(); file
!= findFiles
.end(); file
++) {
499 string::size_type elipses
= file
->subdir
.find("...");
500 if (elipses
== string::npos
) {
501 string filename
= directory
+ '/' + file
->subdir
+ '/' + file
->basename
;
502 if (_access(filename
.c_str(), 0) == 0)
503 file
->fullname
= filename
;
506 string subdir
= directory
+ '/';
507 subdir
.append(file
->subdir
, 0, elipses
);
508 string filename
= file
->basename
;
509 if (FindFileInTree(subdir
, filename
)) {
510 while ((pos
= filename
.find('\\')) != string::npos
)
512 file
->fullname
= filename
;
521 bool Feature::CheckFileInfo::Locate(const string
& testDirectory
)
523 string filename
= testDirectory
+ fileName
;
524 ifstream
file(filename
.c_str(), ios::in
);
528 if (fileText
.empty())
531 while (file
.good()) {
534 if (line
.find(fileText
) != string::npos
) {
544 string
ExcludeDir(const string
& _dir
)
546 if (_dir
.length() == 0)
549 string
dir(GetFullPathNameString(_dir
));
551 if (dir
[dir
.length()-1] != '\\')
554 excludeDirList
.push_back(dir
);
560 bool DirExcluded(const string
& _dir
)
562 if (_dir
.length() == 0)
566 if (dir
[dir
.length()-1] != '\\')
569 list
<string
>::const_iterator r
;
571 for (r
= excludeDirList
.begin(); r
!= excludeDirList
.end(); ++r
) {
572 string excludeDir
= *r
;
573 string
dirPrefix(dir
.substr(0, excludeDir
.length()));
574 if (dirPrefix
== excludeDir
)
582 bool TreeWalk(const string
& directory
)
584 bool foundAll
= false;
586 if (DirExcluded(directory
))
589 string wildcard
= directory
;
592 WIN32_FIND_DATA fileinfo
;
593 HANDLE hFindFile
= FindFirstFile(wildcard
.c_str(), &fileinfo
);
594 if (hFindFile
!= INVALID_HANDLE_VALUE
) {
596 string subdir
= GetFullPathNameString(directory
+ fileinfo
.cFileName
);
597 if ((fileinfo
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
) != 0 &&
598 fileinfo
.cFileName
[0] != '.' &&
599 stricmp(fileinfo
.cFileName
, "RECYCLER") != 0 &&
600 !DirExcluded(subdir
)) {
604 vector
<Feature
>::iterator feature
;
605 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
606 if (!feature
->Locate(subdir
.c_str()))
614 } while (FindNextFile(hFindFile
, &fileinfo
));
616 FindClose(hFindFile
);
623 bool ProcessHeader(const string
& headerFilename
)
625 string inFilename
= headerFilename
;
628 ifstream
in(inFilename
.c_str(), ios::in
);
630 cerr
<< "Could not open " << inFilename
<< endl
;
634 ofstream
out(headerFilename
.c_str(), ios::out
);
635 if (!out
.is_open()) {
636 cerr
<< "Could not open " << headerFilename
<< endl
;
644 vector
<Feature
>::iterator feature
;
645 for (feature
= features
.begin(); feature
!= features
.end(); feature
++)
646 feature
->Adjust(line
);
651 return !in
.bad() && !out
.bad();
655 bool FeatureEnabled(const string
& name
)
657 vector
<Feature
>::iterator feature
;
658 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
659 if (feature
->featureName
== name
&& feature
->state
== Feature::Enabled
)
666 bool AllFeaturesAre(bool state
, const list
<string
> & features
, string
& breaker
)
668 for (list
<string
>::const_iterator iter
= features
.begin(); iter
!= features
.end(); ++iter
) {
669 size_t pos
= iter
->find('|');
670 if (pos
== string::npos
) {
671 if (FeatureEnabled(*iter
) != state
) {
678 bool anyOfState
= false;
680 while (str
.length() != 0) {
681 string key
= str
.substr(0, pos
);
682 if (FeatureEnabled(key
) == state
) {
686 if (pos
== string::npos
)
688 str
= str
.substr(pos
+1);
701 int main(int argc
, char* argv
[])
703 // open and scan configure.ac
704 cout
<< "PWLib Configure " VERSION
" - ";
705 ifstream
conf("configure.ac", ios::in
);
706 if (conf
.is_open()) {
707 cout
<< "opened configure.ac" << endl
;
710 conf
.open("configure.in", ios::in
);
711 if (conf
.is_open()) {
712 cout
<< "opened " << "configure.in" << endl
;
714 cerr
<< "could not open configure.ac/configure.in" << endl
;
720 list
<string
> headers
;
721 vector
<Feature
>::iterator feature
;
723 while (conf
.good()) {
726 string::size_type pos
;
727 if ((pos
= line
.find("AC_CONFIG_HEADERS")) != string::npos
) {
728 if ((pos
= line
.find('(', pos
)) != string::npos
) {
729 string::size_type end
= line
.find(')', pos
);
730 if (end
!= string::npos
)
731 headers
.push_back(line
.substr(pos
+1, end
-pos
-1));
734 else if ((pos
= line
.find("dnl MSWIN_")) != string::npos
) {
735 string::size_type space
= line
.find(' ', pos
+10);
736 if (space
!= string::npos
) {
737 string
optionName(line
, pos
+10, space
-pos
-10);
738 while (line
[space
] == ' ')
740 string::size_type comma
= line
.find(',', space
);
741 if (comma
!= string::npos
) {
742 string
optionValue(line
, comma
+1, INT_MAX
);
743 if (!optionValue
.empty()) {
744 string
featureName(line
, space
, comma
-space
);
746 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
747 if (feature
->featureName
== featureName
) {
753 feature
->Parse(optionName
, optionValue
);
755 features
.push_back(Feature(featureName
, optionName
, optionValue
));
762 // scan version.h if there is a feature called version and if version.h exists
763 for (feature
= features
.begin(); feature
!= features
.end(); ++feature
)
764 if (feature
->featureName
== "version")
766 if (feature
!= features
.end()) {
767 ifstream
version("version.h", ios::in
);
768 if (version
.is_open()) {
769 while (version
.good()) {
771 getline(version
, line
);
772 string::size_type pos
;
774 for (i
= 0; i
< (sizeof(VersionTags
)/sizeof(VersionTags
[0])); ++i
) {
775 size_t tagLen
= strlen(VersionTags
[i
]);
776 if ((pos
= line
.find(VersionTags
[i
])) != string::npos
) {
777 string::size_type space
= line
.find(' ', pos
+tagLen
);
778 if (space
!= string::npos
) {
779 while (line
[space
] == ' ')
781 string version
= line
.substr(space
);
782 while (::iswspace(version
[0]))
784 while (version
.length() > 0 && ::iswspace(version
[version
.length()-1]))
785 version
.erase(version
.length()-1);
786 feature
->defineValues
.insert(pair
<string
,string
>(VersionTags
[i
], version
));
791 string
version("\"");
792 map
<string
,string
>::iterator ver
;
793 if ((ver
= feature
->defineValues
.find(VersionTags
[0])) != feature
->defineValues
.end())
794 version
+= ver
->second
;
798 if ((ver
= feature
->defineValues
.find(VersionTags
[1])) != feature
->defineValues
.end())
799 version
+= ver
->second
;
803 if ((ver
= feature
->defineValues
.find(VersionTags
[2])) != feature
->defineValues
.end())
804 version
+= ver
->second
;
808 feature
->defineValues
.insert(pair
<string
,string
>("VERSION", version
));
812 const char EXTERN_DIR
[] = "--extern-dir=";
813 const char EXCLUDE_DIR
[] = "--exclude-dir=";
814 const char EXCLUDE_ENV
[] = "--exclude-env=";
816 bool searchDisk
= true;
817 char *externDir
= NULL
;
818 char *externEnv
= NULL
;
820 for (i
= 1; i
< argc
; i
++) {
821 if (stricmp(argv
[i
], "--no-search") == 0 || stricmp(argv
[i
], "--disable-search") == 0)
823 else if (strnicmp(argv
[i
], EXCLUDE_ENV
, sizeof(EXCLUDE_ENV
) - 1) == 0){
824 externEnv
= argv
[i
] + sizeof(EXCLUDE_ENV
) - 1;
826 else if (strnicmp(argv
[i
], EXTERN_DIR
, sizeof(EXTERN_DIR
) - 1) == 0){
827 externDir
= argv
[i
] + sizeof(EXTERN_DIR
) - 1;
829 else if (strnicmp(argv
[i
], EXCLUDE_DIR
, sizeof(EXCLUDE_DIR
) - 1) == 0) {
830 string
dir(argv
[i
] + sizeof(EXCLUDE_DIR
) - 1);
831 cout
<< "Excluding \"" << ExcludeDir(dir
) << "\" from feature search" << endl
;
833 else if (stricmp(argv
[i
], "-v") == 0 || stricmp(argv
[i
], "--version") == 0) {
834 cout
<< "configure version " VERSION
"\n";
837 else if (stricmp(argv
[i
], "-h") == 0 || stricmp(argv
[i
], "--help") == 0) {
838 cout
<< "configure version " VERSION
"\n"
839 "usage: configure args\n"
840 " --no-search Do not search disk for libraries.\n"
841 " --extern-dir=dir Specify where to search disk for libraries.\n"
842 " --exclude-dir=dir Exclude dir from search path.\n";
843 " --exclude-env=var Exclude dirs decribed by specified env var from search path.\n";
844 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
845 if (feature
->featureName
[0] != '\0') {
846 cout
<< " --disable-" << feature
->featureName
847 << setw(20-feature
->featureName
.length()) << "Disable " << feature
->displayName
<< '\n';
848 if (!feature
->checkFiles
.empty())
849 cout
<< " --" << feature
->featureName
<< "-dir=dir"
850 << setw(30-feature
->featureName
.length()) << "Set directory for " << feature
->displayName
<< '\n';
856 // parse environment variable if it exists
857 std::vector
<std::string
> envConfigureList
;
858 char * envStr
= getenv("PWLIB_CONFIGURE_FEATURES");
859 if (envStr
!= NULL
) {
861 string::size_type offs
= 0;
862 while (offs
< str
.length()) {
863 string::size_type n
= str
.find(',', offs
);
865 if (n
!= string::npos
) {
866 xable
= str
.substr(offs
, n
-offs
);
869 xable
= str
.substr(offs
);
870 offs
+= str
.length();
872 envConfigureList
.push_back(ToLower(xable
));
876 // go through features and disable ones that need disabling either from command line or environment
877 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
878 if (stricmp(argv
[i
], ("--no-" + feature
->featureName
).c_str()) == 0 ||
879 stricmp(argv
[i
], ("--disable-"+ feature
->featureName
).c_str()) == 0) {
880 feature
->state
= Feature::Disabled
;
883 else if (stricmp(argv
[i
], ("--enable-"+ feature
->featureName
).c_str()) == 0) {
884 feature
->state
= Feature::Enabled
;
887 else if (find(envConfigureList
.begin(), envConfigureList
.end(), "enable-"+ feature
->featureName
) != envConfigureList
.end()) {
888 feature
->state
= Feature::Enabled
;
891 else if (find(envConfigureList
.begin(), envConfigureList
.end(), "disable-"+ feature
->featureName
) != envConfigureList
.end() ||
892 find(envConfigureList
.begin(), envConfigureList
.end(), "no-"+ feature
->featureName
) != envConfigureList
.end()) {
893 feature
->state
= Feature::Disabled
;
896 else if (strstr(argv
[i
], ("--" + feature
->featureName
+ "-dir=").c_str()) == argv
[i
] &&
897 !feature
->Locate(argv
[i
] + strlen(("--" + feature
->featureName
+ "-dir=").c_str())))
898 cerr
<< feature
->displayName
<< " not found in "
899 << argv
[i
] + strlen(("--" + feature
->featureName
+"-dir=").c_str()) << endl
;
905 for (i
= 0; i
< 2; i
++) {
909 env
= getenv("PWLIB_CONFIGURE_EXCLUDE_DIRS");
912 if (externEnv
!= NULL
)
913 env
= getenv(externEnv
);
918 string::size_type offs
= 0;
919 while (offs
< str
.length()) {
920 string::size_type n
= str
.find(';', offs
);
922 if (n
!= string::npos
) {
923 dir
= str
.substr(offs
, n
-offs
);
926 dir
= str
.substr(offs
);
927 offs
+= str
.length();
929 cout
<< "Excluding \"" << ExcludeDir(dir
) << "\" from feature search" << endl
;
934 bool foundAll
= true;
935 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
936 #if 0 // Does not work yet
937 if (feature
->state
== Feature::Enabled
&& !AllFeaturesAre(true, feature
->ifFeature
, feature
->breaker
))
938 feature
->state
= Feature::Dependency
;
939 if (feature
->state
== Feature::Enabled
&& !AllFeaturesAre(false, feature
->ifNotFeature
, feature
->breaker
))
940 feature
->state
= Feature::Blocked
;
942 if (feature
->state
== Feature::Enabled
&& !feature
->checkFiles
.empty()) {
943 bool foundOne
= false;
944 list
<string
>::iterator dir
;
945 for (dir
= feature
->checkDirectories
.begin(); dir
!= feature
->checkDirectories
.end(); dir
++) {
946 if (!DirExcluded(*dir
) && feature
->Locate(dir
->c_str())) {
956 if (searchDisk
&& !foundAll
) {
957 // Do search of entire system
960 if (!GetLogicalDriveStrings(sizeof(drives
), drives
))
961 strcpy(drives
, "C:\\");
964 strcpy(drives
, externDir
);
965 drives
[strlen(externDir
)+1] = '\0';
968 const char * drive
= drives
;
969 while (*drive
!= '\0') {
970 if (externDir
|| GetDriveType(drive
) == DRIVE_FIXED
) {
971 cout
<< "Searching " << drive
<< endl
;
975 drive
+= strlen(drive
)+1;
979 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
980 if (feature
->state
== Feature::Enabled
&& !AllFeaturesAre(true, feature
->ifFeature
, feature
->breaker
))
981 feature
->state
= Feature::Dependency
;
982 if (feature
->state
== Feature::Enabled
&& !AllFeaturesAre(false, feature
->ifNotFeature
, feature
->breaker
))
983 feature
->state
= Feature::Blocked
;
984 if (feature
->state
== Feature::Enabled
&& !feature
->checkFiles
.empty() && !feature
->checkFiles
.begin()->found
)
985 feature
->state
= Feature::NotFound
;
988 int longestNameWidth
= 0;
989 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
990 int length
= feature
->displayName
.length();
991 if (length
> longestNameWidth
)
992 longestNameWidth
= length
;
995 cout
<< "\n\nFeatures:\n";
996 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
997 cout
<< setw(longestNameWidth
+3) << feature
->displayName
<< ' ';
998 switch (feature
->state
)
1000 case Feature::Enabled
:
1004 case Feature::Disabled
:
1005 cout
<< "DISABLED by user";
1008 case Feature::Dependency
:
1009 cout
<< "DISABLED due to absence of feature " << feature
->breaker
;
1012 case Feature::Blocked
:
1013 cout
<< "DISABLED due to presence of feature " << feature
->breaker
;
1023 for (list
<string
>::iterator hdr
= headers
.begin(); hdr
!= headers
.end(); hdr
++)
1024 ProcessHeader(*hdr
);
1026 cout
<< "Configuration completed.\n";