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.20 2004/08/13 01:08:09 csoutheren
28 * Changed to look for configure.ac, then configure.in
30 * Revision 1.19 2004/07/12 02:32:58 csoutheren
31 * Fixed problem when more than two elements in env var
33 * Revision 1.18 2004/04/29 02:02:25 csoutheren
34 * Removed debugging (oops)
36 * Revision 1.17 2004/04/29 02:00:49 csoutheren
37 * Fixed problem with checking for NULL error return from FindFirstFile rather than INVALID_HANDLE_VALUE
39 * Revision 1.16 2004/04/04 01:30:37 csoutheren
40 * Added ability to specify exclude environment variable on configure command line which allows easy switching between MSVC and VS.net 2003
42 * Revision 1.15 2004/03/23 06:32:01 csoutheren
43 * Fixed problems with multiple directories in exclude spec
45 * Revision 1.14 2004/03/16 01:45:17 rjongbloed
46 * Fixed locating lbrary in pre-defined search directories.
47 * Added version number to configure program.
48 * Tidied the --help display.
50 * Revision 1.13 2004/03/13 02:50:56 rjongbloed
51 * Fixed anomalous message where even though a feature was disabled, a "Located "
52 * directiory message is still displayed causing confusion.
53 * Added --disable-<feature> as synonym to existing --no-<feature> to be compatible
55 * Added default value to defines of 1 rather than blank.
57 * Revision 1.12 2004/01/30 02:33:58 csoutheren
60 * Revision 1.11 2004/01/30 01:43:41 csoutheren
61 * Added excludedir options and environment variable
63 * Revision 1.10 2003/11/25 08:21:37 rjongbloed
64 * Fixed display of configured items
66 * Revision 1.9 2003/11/06 09:13:20 rjongbloed
67 * Improved the Windows configure system to allow multiple defines based on file existence. Needed for SDL support of two different distros.
69 * Revision 1.8 2003/10/30 01:17:15 dereksmithies
70 * Add fix from Jose Luis Urien. Many thanks.
72 * Revision 1.7 2003/10/23 21:49:51 dereksmithies
73 * Add very sensible fix to limit extent of search. Thanks Ben Lear.
75 * Revision 1.6 2003/08/04 05:13:17 dereksmithies
76 * Reinforce the disablement if the command lines specifies --no-XXXX to a feature.
78 * Revision 1.5 2003/08/04 05:07:08 dereksmithies
79 * Command line option now disables feature when feature found on disk.
81 * Revision 1.4 2003/05/16 02:03:07 rjongbloed
82 * Fixed being able to manually disable a "feature" when does a full disk search.
84 * Revision 1.3 2003/05/05 08:39:52 robertj
85 * Added ability to explicitly disable a feature, or tell configure exactly
86 * where features library is so it does not need to search for it.
88 * Revision 1.2 2003/04/17 03:32:06 robertj
89 * Improved windows configure program to use lines out of configure.in
91 * Revision 1.1 2003/04/16 08:00:19 robertj
92 * Windoes psuedo autoconf support
96 #pragma warning(disable:4786)
108 #define VERSION "1.3.3"
117 Feature() : enabled(true) { }
118 Feature(const string
& featureName
, const string
& optionName
, const string
& optionValue
);
120 void Parse(const string
& optionName
, const string
& optionValue
);
121 void Adjust(string
& line
);
122 bool Locate(const char * testDir
);
126 string directorySymbol
;
127 string simpleDefineName
;
128 string simpleDefineValue
;
130 struct CheckFileInfo
{
131 CheckFileInfo() : found(false), defineName("1") { }
133 bool Locate(const string
& testDir
);
141 list
<CheckFileInfo
> checkFiles
;
142 list
<string
> checkDirectories
;
149 list
<Feature
> features
;
150 list
<string
> excludeDirList
;
152 ///////////////////////////////////////////////////////////////////////
154 Feature::Feature(const string
& featureNameParam
,
155 const string
& optionName
,
156 const string
& optionValue
)
157 : featureName(featureNameParam
),
160 Parse(optionName
, optionValue
);
164 void Feature::Parse(const string
& optionName
, const string
& optionValue
)
166 if (optionName
== "DISPLAY")
167 displayName
= optionValue
;
168 else if (optionName
== "DEFINE") {
169 int equal
= optionValue
.find('=');
170 if (equal
== string::npos
)
171 simpleDefineName
= optionValue
;
173 simpleDefineName
.assign(optionValue
, 0, equal
);
174 simpleDefineValue
.assign(optionValue
, equal
+1, INT_MAX
);
177 else if (optionName
== "CHECK_FILE") {
178 int comma
= optionValue
.find(',');
179 if (comma
== string::npos
)
183 int pipe
= optionValue
.find('|');
184 if (pipe
< 0 || pipe
> comma
)
185 check
.fileName
.assign(optionValue
, 0, comma
);
187 check
.fileName
.assign(optionValue
, 0, pipe
);
188 check
.fileText
.assign(optionValue
, pipe
+1, comma
-pipe
-1);
191 int equal
= optionValue
.find('=', comma
);
192 if (equal
== string::npos
)
193 check
.defineName
.assign(optionValue
, comma
+1, INT_MAX
);
195 check
.defineName
.assign(optionValue
, comma
+1, equal
-comma
-1);
196 check
.defineValue
.assign(optionValue
, equal
+1, INT_MAX
);
199 checkFiles
.push_back(check
);
201 else if (optionName
== "DIR_SYMBOL")
202 directorySymbol
= '@' + optionValue
+ '@';
203 else if (optionName
== "CHECK_DIR")
204 checkDirectories
.push_back(optionValue
);
208 static bool CompareName(const string
& line
, const string
& name
)
210 int pos
= line
.find(name
);
211 if (pos
== string::npos
)
214 pos
+= name
.length();
215 return !isalnum(line
[pos
]) && line
[pos
] != '_';
218 void Feature::Adjust(string
& line
)
220 if (enabled
&& line
.find("#undef") != string::npos
) {
221 if (!simpleDefineName
.empty() && CompareName(line
, simpleDefineName
)) {
222 line
= "#define " + simpleDefineName
+ ' ';
223 if (simpleDefineValue
.empty())
226 line
+= simpleDefineValue
;
229 for (list
<CheckFileInfo
>::iterator file
= checkFiles
.begin(); file
!= checkFiles
.end(); file
++) {
230 if (file
->found
&& CompareName(line
, file
->defineName
)) {
231 line
= "#define " + file
->defineName
+ ' ' + file
->defineValue
;
237 if (directorySymbol
[0] != '\0') {
238 int pos
= line
.find(directorySymbol
);
239 if (pos
!= string::npos
)
240 line
.replace(pos
, directorySymbol
.length(), directory
);
245 bool Feature::Locate(const char * testDir
)
250 if (!directory
.empty())
253 if (checkFiles
.empty())
256 string testDirectory
= testDir
;
257 if (testDirectory
[testDirectory
.length()-1] != '\\')
258 testDirectory
+= '\\';
260 list
<CheckFileInfo
>::iterator file
= checkFiles
.begin();
261 if (!file
->Locate(testDirectory
))
264 while (++file
!= checkFiles
.end())
265 file
->Locate(testDirectory
);
268 _fullpath(buf
, testDirectory
.c_str(), _MAX_PATH
);
271 cout
<< "Located " << displayName
<< " at " << directory
<< endl
;
274 while ((pos
= directory
.find('\\')) != string::npos
)
275 directory
[pos
] = '/';
276 pos
= directory
.length()-1;
277 if (directory
[pos
] == '/')
278 directory
.erase(pos
);
284 bool Feature::CheckFileInfo::Locate(const string
& testDirectory
)
286 string filename
= testDirectory
+ fileName
;
287 ifstream
file(filename
.c_str(), ios::in
);
291 if (fileText
.empty())
294 while (file
.good()) {
297 if (line
.find(fileText
) != string::npos
) {
308 bool TreeWalk(const string
& directory
)
310 bool foundAll
= false;
312 string wildcard
= directory
;
315 WIN32_FIND_DATA fileinfo
;
316 HANDLE hFindFile
= FindFirstFile(wildcard
.c_str(), &fileinfo
);
317 if (hFindFile
!= INVALID_HANDLE_VALUE
) {
319 string subdir
= directory
;
320 subdir
+= fileinfo
.cFileName
;
321 list
<string
>::const_iterator r
= find(excludeDirList
.begin(), excludeDirList
.end(), subdir
);
322 if (r
== excludeDirList
.end()) {
323 if ((fileinfo
.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY
) != 0 &&
324 fileinfo
.cFileName
[0] != '.' &&
325 stricmp(fileinfo
.cFileName
, "RECYCLER") != 0) {
329 list
<Feature
>::iterator feature
;
330 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
331 if (!feature
->Locate(subdir
.c_str()))
340 } while (FindNextFile(hFindFile
, &fileinfo
));
342 FindClose(hFindFile
);
349 bool ProcessHeader(const string
& headerFilename
)
351 string inFilename
= headerFilename
;
354 ifstream
in(inFilename
.c_str(), ios::in
);
356 cerr
<< "Could not open " << inFilename
<< endl
;
360 ofstream
out(headerFilename
.c_str(), ios::out
);
361 if (!out
.is_open()) {
362 cerr
<< "Could not open " << headerFilename
<< endl
;
370 list
<Feature
>::iterator feature
;
371 for (feature
= features
.begin(); feature
!= features
.end(); feature
++)
372 feature
->Adjust(line
);
377 return !in
.bad() && !out
.bad();
381 int main(int argc
, char* argv
[])
383 ifstream
conf("configure.ac", ios::in
);
384 if (conf
.is_open()) {
385 cout
<< "Opened " << "configure.ac" << endl
;
388 conf
.open("configure.in", ios::in
);
389 if (conf
.is_open()) {
390 cout
<< "Opened " << "configure.in" << endl
;
392 cerr
<< "Could not open configure.ac/configure.in" << endl
;
397 list
<string
> headers
;
398 list
<Feature
>::iterator feature
;
400 while (conf
.good()) {
404 if ((pos
= line
.find("AC_CONFIG_HEADERS")) != string::npos
) {
405 pos
= line
.find('(', pos
);
406 if (pos
!= string::npos
) {
407 int end
= line
.find(')', pos
);
408 if (pos
!= string::npos
)
409 headers
.push_back(line
.substr(pos
+1, end
-pos
-1));
412 else if (line
.find("dnl MSWIN_") == 0) {
413 int space
= line
.find(' ', 10);
414 if (space
!= string::npos
) {
415 string
optionName(line
, 10, space
-10);
416 while (line
[space
] == ' ')
418 int comma
= line
.find(',', space
);
419 if (comma
!= string::npos
) {
420 string
optionValue(line
, comma
+1, INT_MAX
);
421 if (!optionValue
.empty()) {
422 string
featureName(line
, space
, comma
-space
);
424 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
425 if (feature
->featureName
== featureName
) {
431 feature
->Parse(optionName
, optionValue
);
433 features
.push_back(Feature(featureName
, optionName
, optionValue
));
440 const char EXTERN_DIR
[] = "--extern-dir=";
441 const char EXCLUDE_DIR
[] = "--exclude-dir=";
442 const char EXCLUDE_ENV
[] = "--exclude-env=";
444 bool searchDisk
= true;
445 char *externDir
= NULL
;
446 char *externEnv
= NULL
;
447 for (int i
= 1; i
< argc
; i
++) {
448 if (stricmp(argv
[i
], "--no-search") == 0 || stricmp(argv
[i
], "--disable-search") == 0)
450 else if (strnicmp(argv
[i
], EXCLUDE_ENV
, sizeof(EXCLUDE_ENV
) - 1) == 0){
451 externEnv
= argv
[i
] + sizeof(EXCLUDE_ENV
) - 1;
453 else if (strnicmp(argv
[i
], EXTERN_DIR
, sizeof(EXTERN_DIR
) - 1) == 0){
454 externDir
= argv
[i
] + sizeof(EXTERN_DIR
) - 1;
456 else if (strnicmp(argv
[i
], EXCLUDE_DIR
, sizeof(EXCLUDE_DIR
) - 1) == 0) {
457 string
dir(argv
[i
] + sizeof(EXCLUDE_DIR
) - 1);
458 excludeDirList
.push_back(dir
);
459 cout
<< "Excluding " << dir
<< " from feature search" << endl
;
461 else if (stricmp(argv
[i
], "-v") == 0 || stricmp(argv
[i
], "--version") == 0) {
462 cout
<< "configure version " VERSION
"\n";
465 else if (stricmp(argv
[i
], "-h") == 0 || stricmp(argv
[i
], "--help") == 0) {
466 cout
<< "configure version " VERSION
"\n"
467 "usage: configure args\n"
468 " --no-search Do not search disk for libraries.\n"
469 " --extern-dir=dir Specify where to search disk for libraries.\n"
470 " --exclude-dir=dir Exclude dir from search path.\n";
471 " --exclude-env=var Exclude dirs decribed by specified env var from search path.\n";
472 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
473 if (feature
->featureName
[0] != '\0') {
474 cout
<< " --disable-" << feature
->featureName
475 << setw(20-feature
->featureName
.length()) << "Disable " << feature
->displayName
<< '\n';
476 if (!feature
->checkFiles
.empty())
477 cout
<< " --" << feature
->featureName
<< "-dir=dir"
478 << setw(30-feature
->featureName
.length()) << "Set directory for " << feature
->displayName
<< '\n';
484 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
485 if (stricmp(argv
[i
], ("--no-" +feature
->featureName
).c_str()) == 0 ||
486 stricmp(argv
[i
], ("--disable-"+feature
->featureName
).c_str()) == 0)
487 feature
->enabled
= false;
488 else if (strstr(argv
[i
], ("--" + feature
->featureName
+"-dir=").c_str()) == argv
[i
])
489 if (!feature
->Locate(argv
[i
] + strlen(("--" + feature
->featureName
+ "-dir=").c_str())))
490 cerr
<< feature
->displayName
<< " not found in "
491 << argv
[i
] + strlen(("--" + feature
->featureName
+"-dir=").c_str()) << endl
;
496 for (i
= 0; i
< 2; i
++) {
500 env
= getenv("PWLIB_CONFIGURE_EXCLUDE_DIRS");
503 if (externEnv
!= NULL
)
504 env
= getenv(externEnv
);
509 string::size_type offs
= 0;
510 while (offs
< str
.length()) {
511 string::size_type n
= str
.find(';', offs
);
513 if (n
!= string::npos
) {
514 dir
= str
.substr(offs
, n
-offs
);
517 dir
= str
.substr(offs
);
518 offs
+= str
.length();
520 excludeDirList
.push_back(dir
);
521 cout
<< "Excluding " << dir
<< " from feature search" << endl
;
526 bool foundAll
= true;
527 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
528 if (feature
->enabled
&& !feature
->checkFiles
.empty()) {
529 bool foundOne
= false;
530 list
<string
>::iterator dir
;
531 for (dir
= feature
->checkDirectories
.begin(); dir
!= feature
->checkDirectories
.end(); dir
++) {
532 if (feature
->Locate(dir
->c_str())) {
542 if (searchDisk
&& !foundAll
) {
543 // Do search of entire system
546 if (!GetLogicalDriveStrings(sizeof(drives
), drives
))
547 strcpy(drives
, "C:\\");
550 strcpy(drives
, externDir
);
553 const char * drive
= drives
;
554 while (*drive
!= '\0') {
555 if (GetDriveType(drive
) == DRIVE_FIXED
) {
556 cout
<< "Searching " << drive
<< endl
;
560 drive
+= strlen(drive
)+1;
564 for (feature
= features
.begin(); feature
!= features
.end(); feature
++) {
565 cout
<< " " << feature
->displayName
<< ' ';
566 if (feature
->checkFiles
.empty() && !feature
->simpleDefineValue
.empty())
567 cout
<< "set to " << feature
->simpleDefineValue
;
568 else if (feature
->enabled
&& (feature
->checkFiles
.empty() || feature
->checkFiles
.begin()->found
))
576 for (list
<string
>::iterator hdr
= headers
.begin(); hdr
!= headers
.end(); hdr
++)
579 cout
<< "Configuration completed.\n";