“#define _GNU_SOURCE”는 무엇을 의미합니까?


152

오늘 나는 basename()함수 를 사용해야했고 man 3 basename( here )는 나에게 이상한 메시지를 주었다.

노트

이 두 가지 다른 버전입니다 기본 이름은 () 더 - POSIX의 버전이 위의 설명과 GNU 버전 한 후 도착,

#define _GNU_SOURCE
#include <string.h>

이것이 #define _GNU_SOURCE의미하는 바가 궁금 합니다. GNU 관련 라이센스로 작성한 코드 가 오염 되어 있습니까? 또는 단순히 컴파일러에게 " 이 기능 세트는 POSIX가 아니므로 이식성이 없으며, 어쨌든 사용하고 싶습니다 "와 같이 간단하게 사용됩니다 .

그렇다면 사람들에게 다른 헤더를 부여하지 말고, 하나의 함수 구현 또는 다른 함수를 얻기 위해 모호한 매크로를 정의 해야하는 대신?

뭔가 나에게도 버그가있다 : 컴파일러는 실행 파일과 연결할 함수 구현을 어떻게 알 수 있습니까? 이것도 사용합니까 #define?

누구든지 나에게 줄 조언이 있습니까?

답변:


172

정의 _GNU_SOURCE는 라이센스와 관련이 없으며 이식 가능하지 않은 코드 작성과 관련이 있습니다. 를 정의 _GNU_SOURCE하면 다음을 얻을 수 있습니다.

  1. 많은 비표준 GNU / Linux 확장 기능에 액세스
  2. POSIX 표준에서 생략 된 기존 기능에 대한 액세스
  3. 가끔 시스템 유틸리티 좋아 구현하기위한 필요하지만, 이식 할 수없는 낮은 수준의 기능에 대한 액세스 mount, ifconfig
  4. GNU 사람들이 표준위원회와 의견이 일치하지 않아 기능이 어떻게 행동하고 스스로 결정해야하는지에 대해 POSIX가 지정한 많은 기능의 동작이 깨졌습니다.

당신이 이런 일을 알고있는 한, 정의하는 문제가되지 않습니다 _GNU_SOURCE,하지만 당신은 그것을 정의 피하고 대신 정의해야 _POSIX_C_SOURCE=200809L또는 _XOPEN_SOURCE=700가능하면 프로그램이 휴대용 것을 확인 할 수 있습니다.

특히, 절대로 사용 _GNU_SOURCE해서는 안되는 것은 위의 # 2와 # 4입니다.


71
물론, 모든 사람들은 정의해야 할 진정한 이유 _GNU_SOURCEstrfry와 를 얻기위한 것임을 알고 memfrob있습니다.
user4815162342

5
GNU C 라이브러리 문서에 대한 이 링크 는 몇 가지 추가 세부 사항을 제공합니다 (예 : #define _GNU_SOURCE"파일에서 첫 번째로 주석 앞에 오도록 권장").
Alexander Pozdneev

관련성이 없지만 32 비트 대상에서 2GB 파일 크기 제한을 확장하는 데 사용됩니다.
mckenzm

1
@mckenzm : 나는 당신이 생각하고 있다고 생각 _FILE_OFFSET_BITS하지 않습니다 _GNU_SOURCE.
R .. GitHub 중지 지원 얼음 얼음

strfry memfrob 및 기타 플랫폼 및 툴 체인과 유사한 편의 시설을 포팅하기위한 유료 프로그래머가 되고 싶습니다 .
Massimo

6

두 가지 추가 사항에 대답하겠습니다.

뭔가 나에게도 버그가있다 : 컴파일러는 실행 파일과 연결할 함수 구현을 어떻게 알 수 있습니까? 이 #define도 사용합니까?

일반적인 접근 방식 은 정의 여부에 따라 다른 이름 으로 조건부 #define식별자 basename를 사용하는 것 _GNU_SOURCE입니다. 예를 들어 :

#ifdef _GNU_SOURCE
# define basename __basename_gnu
#else
# define basename __basename_nongnu
#endif

이제 라이브러리는 해당 이름으로 두 가지 동작을 모두 제공하면됩니다.

그렇다면 사람들에게 다른 헤더를 부여하지 말고, 하나의 함수 구현 또는 다른 함수를 얻기 위해 모호한 환경 변수를 정의 해야하는 대신?

종종 같은 헤더가 다른 유닉스 버전에서 약간 다른 내용을 가지고 있기 때문에 <string.h>많은 표준 ( xkcd )이 있습니다. 좋아하는 매크로를 선택하기위한 전체 매크로 세트가 있으므로 프로그램이 하나의 표준을 기대하면 라이브러리가이를 준수합니다.


6

의 모든 기능에 대한 자세한 내용은 _GNU_SOURCE설명서를 참조하십시오.

GNU 문서에서 :

매크로 : _GNU_SOURCE

이 매크로를 정의하면 ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS 및 GNU 확장과 같은 모든 것이 포함됩니다. POSIX.1이 BSD와 충돌하는 경우 POSIX 정의가 우선합니다.

기능 테스트 매크로 의 Linux 매뉴얼 페이지에서 :

_GNU_SOURCE

이 매크로를 정의하면 (임의의 값으로) _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE 값이 200809L (2.11 이전의 glibc 버전에서 200112L, 2.8에서 glibc 버전 이전의 2,020b 버전 2.1 이전의 glibc 버전에서 2,020b 버전 2.1 이전의 glibc 버전 2, glibc 버전 2.1 이전 버전) 값이 700 인 _XOPEN_SOURCE (2.10 이전의 glibc 버전에서는 600, 2.2 이전의 glibc 버전에서는 500) 또한 다양한 GNU 관련 확장도 노출됩니다.

glibc 2.19부터 _GNU_SOURCE를 정의하면 _DEFAULT_SOURCE를 암시 적으로 정의하는 효과도 있습니다. 2.20 이전의 glibc 버전에서 _GNU_SOURCE를 정의하면 _BSD_SOURCE 및 _SVID_SOURCE를 암시 적으로 정의하는 효과도있었습니다.

참고 : 헤더 파일을 포함 하기 전에 해당 헤더가 기능을 사용할 수 있도록 _GNU_SOURCE정의 해야 합니다. 예를 들면 다음과 같습니다.

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
...

_GNU_SOURCE-D플래그를 사용하여 컴파일마다 활성화 할 수도 있습니다 .

$ gcc -D_GNU_SOURCE file.c

( -D특정한 것은 _GNU_SOURCE아니지만 매크로는 이런 식으로 정의됩니다).


4

Google을 통한 메일 링리스트에서 :

glibc의 include / features.h를보십시오 :

_GNU_SOURCE 위의 모든 사항과 GNU 확장.

이것이 모든 것을 가능하게한다는 것을 의미합니다.

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE, _LARGEFILE64_SOURCE, _FILE_OFFSET_BITS = N, _BSD_SOURCE, _SVID_SOURCE

따라서 gcc에 대해 많은 컴파일 플래그를 사용할 수 있습니다.


21
컴파일러의 동작에는 영향을 미치지 않으며 헤더에서 볼 수있는 프로토 타입과 사물에만 영향을줍니다.
Spudd86
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.