mkstemp() and fdopen() in Cygwin 1.7.28
在使用GNU GCC 4.8.2在Cygwin(1.7.28-2,64位)下构建一些基于C的代码的过程中,遇到了以下错误:
1 2 3 4 5 6 7 8 | ... SortDetails.cpp: In function a€?FILE* create_tmpfile(const char*, char**)a€?: SortDetails.cpp:127:20: error: a€?mkstempa€? was not declared in this scope fd = mkstemp(tmpl); ^ SortDetails.cpp:133:24: error: a€?fdopena€? was not declared in this scope fp = fdopen(fd,"wb+"); ... |
无法编译的特定代码块是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | FILE * create_tmpfile(char const* path, char** fileName) { FILE* fp; int fd; char* tmpl; if ( path == NULL ) { fileName = NULL; return tmpfile(); } tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam); strcpy(tmpl, path); strcpy(tmpl+strlen(path),"/sb.XXXXXX"); fd = mkstemp(tmpl); /* <----- here... */ if(fd == -1) { fprintf(stderr,"unable to create temp file!\ "); return NULL; } fp = fdopen(fd,"wb+"); /* <----- ...and here */ *fileName = (char*)malloc(strlen(tmpl) + 1); strcpy(*fileName, tmpl); free(tmpl); return fp; } |
(正在强制转换
回归
此代码可在Linux主机上的GNU GCC 4.8.x以及OS X下的Clang / 5.0编译并成功使用。
环境
我正在使用以下版本的Cygwin:
1 2 | $ uname -a CYGWIN_NT-6.1 CygFoo-PC 1.7.28(0.271/5/3) 2014-02-09 21:06 x86_64 Cygwin |
这是我使用的GCC版本:
1 2 3 4 5 6 7 8 | $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-cygwin/4.8.2/lto-wrapper.exe Target: x86_64-pc-cygwin Configured with: /cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.2-2/src/gcc-4.8.2/configure --srcdir=/cygdrive/i/szsz/tmpp/cygwin64/gcc/gcc-4.8.2-2/src/gcc-4.8.2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/libexec --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target=x86_64-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --disable-__cxa_atexit --with-dwarf2 --with-tune=generic --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libgomp --disable-libitm --enable-libquadmath --enable-math-support --enable-libssp --enable-libada --enable-libgcj-sublibs --disable-java-awt --disable-symvers --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib Thread model: posix gcc version 4.8.2 (GCC) |
问题
在GCC 4.8.2中是否为Cygwin支持
如果没有,是否有我可以添加的程序包或我可以相对容易地编译以添加对这些功能的支持的库?
如果没有,我可以使用
可能的解决方法
这是此功能的修改版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | FILE * create_tmpfile(char const* path, char** fileName) { FILE* fp; char* tmpl; if ( path == NULL ) { fileName = NULL; return tmpfile(); } #if defined(__CYGWIN__) && !defined(_WIN32) const char *cygwinPrefix ="/sb."; const char *cygwinTmpDir ="/tmp"; char *cygwinTmplSuffix = (char *)malloc(1 + L_tmpnam); tmpnam(cygwinTmplSuffix); tmpl = (char *)malloc(1 + strlen(path) + strlen(cygwinPrefix) + strlen(cygwinTmplSuffix + strlen(cygwinTmpDir) + 1)); strcpy(tmpl, path); strcpy(tmpl+strlen(path), cygwinPrefix); strcpy(tmpl+strlen(path)+strlen(cygwinPrefix), cygwinTmplSuffix + strlen(cygwinTmpDir) + 1); fp = fopen(tmpl,"wbx+"); /* we add the 'x' extension to apply the O_EXCL flag, to avoid a security hole described in the GNU C library docs */ free(cygwinTmplSuffix); #else tmpl = (char*)malloc(1 + strlen(path) + L_tmpnam); strcpy(tmpl, path); strcpy(tmpl+strlen(path),"/sb.XXXXXX"); int fd = mkstemp(tmpl); if(fd == -1) { fprintf(stderr,"unable to create temp file!\ "); return NULL; } fp = fdopen(fd,"wb+"); #endif *fileName = (char*)malloc(strlen(tmpl) + 1); strcpy(*fileName, tmpl); free(tmpl); return fp; } |
这很丑。如果可以使用POSIX函数,请尽量使用它们。感谢您的任何建议。
在Cygwin上使用
1 2 3 | $ g++ -std=c++11 -E -Dd foo.cpp > foo.log.c++11 $ g++ -ansi -E -Dd foo.cpp > foo.log.ansi $ g++ -E -Dd foo.cpp > foo.log.noFlag |
比较日志很有用。在
在文件
同样,在文件
C头文件
似乎适用于玩具代码示例的解决方案是在编译之前取消定义
1 | $ g++ -std=c++11 -U__STRICT_ANSI__ foo.cpp |
目前尚不清楚它的副作用是什么,但是从谷歌搜索来看,这似乎是一个常见问题,并且是其他需要针对Cygwin的开发人员所应用的常见修复程序。
Cygwin具有一组类似Linux的功能测试宏。但是,在具有C的Linux上,
如前所述,使用任何
最近我在编译git-crypt并遇到相同的问题。上面答案中的解决方案有效,除了必须通过" make"而不是" g"进行部署,如下所示:
1 | make CXXFLAGS="-U__STRICT_ANSI__ -std=c++11" |
我的朋友Vincent制作了一个与Cygwin一起使用的简单版本。 http://code.google.com/p/xpost/source/browse/src/lib/xpost_compat.c#113
它可能无法涵盖所有??情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h> #include <fcntl.h> #include <sys/stat.h> # include <windows.h> # include <io.h> int mkstemp(char *template) { char *temp; temp = _mktemp(template); if (!temp) return -1; return _open(temp, _O_CREAT | _O_TEMPORARY | _O_EXCL | _O_RDWR, _S_IREAD | _S_IWRITE); } |
对于