|
Boost : |
From: Beman Dawes (bdawes_at_[hidden])
Date: 2004-08-22 13:41:35
At 11:28 AM 8/17/2004, Carlo Wood wrote:
>At several places in the code we find something like:
>
>// BOOST_POSIX or BOOST_WINDOWS specify which API to use.
># if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
># if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) ||
>defined(__CYGWIN__)
># define BOOST_WINDOWS
># else
># define BOOST_POSIX
># endif
># endif
>
>(As in for example boost/libs/filesystem/src/path_posix_windows.cpp)
>
>This sets BOOST_WINDOWS explicitely, as default, for cygwin - which
>is a POSIX operating system with a single root.
That's not really the full story. Programs compiled with the Cygwin tools
(gcc compiler, libraries, etc.) are useful (and commonly used) in two
different environments:
* Plain Windows (such as from the Windows command line).
* Cygwin's Linux/POSIX emulator (such as from the bash command line).
Both uses have to be supported by the filesystem library.
Originally only the emulator usage was supported; we quickly heard from
users that this wasn't acceptable.
>
>This breaks a lot of code - if not all - of boost::filesystem.
>For example, the following code:
>
>#include <iostream>
>#include <boost/filesystem/path.hpp>
>#include <boost/filesystem/operations.hpp>
>
>int main()
>{
> boost::filesystem::path p = "/usr";
> if (!boost::filesystem::exists(p))
> std::cerr << p.string() << " doesn't exist according to
>boost::filesystem" << std::endl;
>}
>
>indeed causes boost::filesystem::exists to return 'false' on cygwin
>while "/usr" definitely exists.
>
>The reason for that is obvious and looks like a clear bug:
>The code of boost::filesystem::exists is as follows:
>
> BOOST_FILESYSTEM_DECL bool exists( const path & ph )
> {
># ifdef BOOST_POSIX
> struct stat path_stat;
> if(::stat( ph.string().c_str(), &path_stat ) != 0)
> {
> if((errno == ENOENT) || (errno == ENOTDIR))
> return false; // stat failed because the path does not exist
> // for any other error we assume the file does exist and fall
>through,
> // this may not be the best policy though... (JM 20040330)
> }
> return true;
># else
> if(::GetFileAttributesA( ph.string().c_str() ) == 0xFFFFFFFF)
> {
> UINT err = ::GetLastError();
> if((err == ERROR_FILE_NOT_FOUND) || (err ==
ERROR_PATH_NOT_FOUND)
>|| (err == ERROR_INVALID_NAME))
> return false; // GetFileAttributes failed because the path
does
>not exist
> // for any other error we assume the file does exist and fall
>through,
> // this may not be the best policy though... (JM 20040330)
> return true;
> }
> return true;
># endif
> }
>
>
>Therefore, with BOOST_POSIX undefined, "/usr" is passed directly to
>::GetFileAttributesA()
>and that can obviously not work.
>
>My question is therefore: shouldn't BOOST_POSIX be forced to be defined
on
>cygwin?
Yes, if you want the Cygwin emulator behavior, No, if you want the Windows
behavior. There isn't any way for the compiler to know which the user
prefers.
To make that clearer, a "Note for Cygwin users" was added to the docs
several months ago. See below.
--Beman
Note for Cygwin users
The library's implementation code automatically detects the current
platform, and compiles the POSIX or Windows implementation code
accordingly. Automatic platform detection during object library compilation
can be overridden by defining BOOST_POSIX or BOOST_WINDOWS macros. With the
exception of the Cygwin environment, there is usually no reason to define
one of the macros, as the software development kits supplied with most
compilers only support a single platform.
The Cygwin package of tools supports traditional Windows usage, but also
provides an emulation layer and other tools which can be used to make
Windows act as Linux (and thus POSIX), and provide the Linux look-and-feel.
GCC is usually the compiler of choice in this environment, as it can be
installed via the Cygwin install process. Other compilers can also use the
Cygwin emulation of POSIX, at least in theory.
Those wishing to use the Cygwin POSIX emulation layer should define the
BOOST_POSIX macro when compiling the Boost Filesystem Library's
object-library. The macro does not need to be defined (and will have no
effect if defined) for Boost Filesystem Library user programs.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk