(事先已久的答案道歉,但我不希望冒險留下太多的細節了。)
你應該使用AH_VERBATIM
創建模板有條件定義_GNU_SOURCE
和AC_DEFINE
定義它的值,而如果您只想爲Glibc完成此操作,則會禁用其他系統的擴展功能。否則,你最好使用默認的系統擴展。請參閱以下代碼的前幾行,以獲得我想要的AH_VERBATIM
的示例。
您可以省去AC_CHECK_ *調用的if/else部分,並使用shell代碼來測試$ac_cv_func_fopencookie
和$ac_cv_member_cookie_io_functions_t_read
是否都是。如果它們都是,請將_GNU_SOURCE
定義爲1.請注意,這可能會影響編譯器的其他測試,因此除非您有充分理由不這樣做,否則您應該在執行此檢查並定義_GNU_SOURCE
之前運行其他任何其他測試編譯測試(例如AC_CHECK_FUNC
)。
請注意,在這種情況下,如果您絕對拒絕使用系統擴展,那麼編寫自己的測試可能會更好。除非我使用AC_USE_SYSTEM_EXTENSIONS
或先前定義的_GNU_SOURCE
,否則cookie_io_functions_t
是未定義的類型。檢查這種類型還需要_GNU_SOURCE
,自然一旦定義,你顯然無法取消定義它。
這是我如何做的一個例子。它說明爲什麼你應該使用AC_USE_SYSTEM_EXTENSIONS
,因爲它只能處理_GNU_SOURCE
:
AC_DEFUN([ck_FUNC_FOPENCOOKIE],
[AH_VERBATIM(
[_GNU_SOURCE],
[/* Enable GNU extensions for fopencookie functionality to work
where required. */
#ifndef _GNU_SOURCE
#undef _GNU_SOURCE
#endif])
AC_CACHE_CHECK(
[whether fopencookie works without _GNU_SOURCE being defined],
[ck_cv_libc_fopencookie],
[AC_LINK_IFELSE(
[AC_LANG_SOURCE(
[#undef _GNU_SOURCE
#include <stdio.h>
cookie_read_function_t *ck_read = (cookie_read_function_t *)foo_read;
cookie_write_function_t *ck_write = (cookie_write_function_t *)ck_read;
cookie_seek_function_t *ck_seek = (cookie_seek_function_t *)ck_read;
cookie_close_function_t *ck_close = (cookie_close_function_t *)fclose;
size_t foo_read(void *cookie, char *buf, size_t size)
{
cookie = buf;
buf = cookie;
return (ssize_t)size;
}
int main(void)
{
cookie_io_functions_t x;
x.read = ck_read;
x.write = ck_write;
x.seek = ck_seek;
x.close = ck_close;
fopencookie(NULL, NULL, x);
return 0;
}
])], [ck_cv_libc_fopencookie=yes], [ck_cv_libc_fopencookie=no])])
if test "x${ck_cv_libc_fopencookie}" = xno ; then
AC_CACHE_CHECK(
[whether fopencookie works at all],
[ck_cv_libc_fopencookie_gnu],
[AC_LINK_IFELSE(
[AC_LANG_SOURCE(
[#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <stdio.h>
cookie_read_function_t *ck_read = (cookie_read_function_t *)foo_read;
cookie_write_function_t *ck_write = (cookie_write_function_t *)ck_read;
cookie_seek_function_t *ck_seek = (cookie_seek_function_t *)ck_read;
cookie_close_function_t *ck_close = (cookie_close_function_t *)fclose;
size_t foo_read(void *cookie, char *buf, size_t size)
{
cookie = buf;
buf = cookie;
return (ssize_t)size;
}
int main(void)
{
cookie_io_functions_t x;
x.read = ck_read;
x.write = ck_write;
x.seek = ck_seek;
x.close = ck_close;
fopencookie(NULL, NULL, x);
return 0;
}
])], [ck_cv_libc_fopencookie_gnu=yes], [ck_cv_libc_fopencookie_gnu=no])])
if test "x${ck_cv_libc_fopencookie_gnu}" = xyes ; then
AC_DEFINE([_GNU_SOURCE], [1])
ck_cv_libc_fopencookie=yes
fi # test with _GNU_SOURCE succeeded
fi # test without _GNU_SOURCE failed
if test "x${ck_cv_libc_fopencookie}" = xyes ; then
AC_DEFINE(
[HAVE_FOPENCOOKIE], [1],
[Define to 1 if fopencookie and related functionality is fully working.])
fi])
我把它包在一個名爲ck_FUNC_FOPENCOOKIE
宏,所以你可以把它放在你打電話之前得到通過m4_include
包括一個獨立的m4文件中宏。這將防止你的配置腳本變得非常混亂,並且很容易添加和測試(以及刪除)。
上面的代碼的行爲摘要:
- 沒有編譯/聯fopencookie的功能或類型不是預期:
- ck_cv_libc_fopencookie =沒有
- ck_cv_libc_fopencookie_gnu =無
- _GNU_SOURCE(AC_DEFINE)= undefined
- HAVE_FOPENCOOKIE = undefined
部
- fopencookie的作品,_GNU_SOURCE不需要:
- ck_cv_libc_fopencookie =是
- ck_cv_libc_fopencookie_gnu =未設置
- _GNU_SOURCE(AC_DEFINE)=未定義
- HAVE_FOPENCOOKIE = 1
- fopencookie作品,_GNU_SOURCE要求:
- ck_cv_libc_fopencookie =是
- ck_cv_libc_fopencookie_gnu =是
- _GNU_SOURCE(AC_DEFINE)= 1個
- HAVE_FOPENCOOKIE = 1
正如你所看到的,是不是更給它_GNU_SOURCE
定義或缺乏。但是,不需要_GNU_SOURCE
的情況用於跨平臺兼容性。
基本上_GNU_SOURCE
僅在需要時啓用(Glibc),並且如果fopencookie
材料可用,您仍然可以獲得定義HAVE_FOPENCOOKIE
。我使用了一個非常通用的測試,但您可以輕鬆編輯代碼以使其更適合。
但是,AC_CHECK_FUNC
宏和上面的代碼之間的主要區別在於,我使用鏈接測試來確保C庫包含fopencookie
函數的符號。如果沒有,那麼即使在位於不同庫中的另一個系統上有這樣的功能,它也將被視爲不可用。由於我對項目的目標一無所知,因此我只能評論以下事實:您需要保存LIBS
變量,根據目標將其設置爲包含特定庫,然後調用AC_LINK_IFELSE
宏並恢復兩個測試完成後的值爲LIBS
。在調用上述宏之前,甚至可以在主代碼中完成此操作。
我想最簡單的方法是「檢查你的蛋糕和吃它」是否會使用調用AC_PREPROC_IFELSE
來確定是否檢測到glibc,並檢查Glibc獨有的宏是否會被檢查以確定它是否被定義。如果是,則進行檢查以確保當前版本包含您需要的功能和成員。如果檢查成功,你會自動定義_GNU_SOURCE
,一切都會很好。但是,您犧牲了跨平臺兼容性,這是GNU Autotools的一個重點,並且可以在不依賴Glibc的情況下進行相同的檢查。對於我沒有研究過的所有知識,uClibc可能具有相同的內容,儘管不是Glibc,也沒有任何Glibc特定的預處理器符號。
我想給這個答案不止一個upvote,因爲它包含了很多關於Autoconf的有用信息,但是我覺得我從Autoconf郵件列表中得到的答案(我發佈在一個單獨的答案中,看哪個)應該被認爲是權威的答案。 – Dolda2000
這就是說,但是,我不認爲有''fopencookie'可用時沒有定義'_GNU_SOURCE'的情況。 – Dolda2000