“ #define _GNU_SOURCE” หมายถึงอะไร


152

วันนี้ฉันต้องใช้basename()ฟังก์ชั่นและman 3 basename( ที่นี่ ) ให้ข้อความแปลก ๆ แก่ฉัน:

หมายเหตุ

มีbasenameสองเวอร์ชันที่แตกต่างกัน- เวอร์ชันPOSIX ที่อธิบายไว้ข้างต้นและเวอร์ชัน GNUซึ่งเวอร์ชันหนึ่งได้รับหลังจาก

#define _GNU_SOURCE
#include <string.h>

ฉันสงสัยว่าสิ่งที่นี้#define _GNU_SOURCEหมายถึง: มันtaintingที่ผมเขียนโค้ดที่มีใบอนุญาต GNU เกี่ยวข้อง? หรือจะเป็นเพียงแค่ใช้ในการบอกสิ่งที่คอมไพเลอร์เช่น " ดีฉันรู้ว่าชุดของฟังก์ชั่นนี้ไม่ได้เป็น POSIX จึงไม่ได้พกพา แต่ผมอยากจะใช้มันต่อไป "

ถ้าเป็นเช่นนั้นทำไมไม่ให้คนส่วนหัวที่แตกต่างกันแทนที่จะต้องกำหนดแมโครที่คลุมเครือเพื่อรับฟังก์ชั่นหนึ่งหรืออีกอันหนึ่ง?

มีข้อบกพร่องบางอย่างสำหรับฉันด้วย: คอมไพเลอร์รู้ได้อย่างไรว่าการใช้งานฟังก์ชั่นใดเพื่อเชื่อมโยงกับปฏิบัติการ? มันใช้สิ่งนี้#defineด้วยหรือไม่

ใครมีพอยน์เตอร์ให้ฉันบ้าง

คำตอบ:


172

การกำหนด_GNU_SOURCEไม่มีส่วนเกี่ยวข้องกับสิทธิ์ใช้งานและทุกอย่างเกี่ยวกับการเขียน (ไม่ใช่) รหัสพกพา หากคุณกำหนด_GNU_SOURCEคุณจะได้รับ:

  1. เข้าถึงฟังก์ชันส่วนขยาย GNU / Linux ที่ไม่เป็นมาตรฐานจำนวนมาก
  2. การเข้าถึงฟังก์ชั่นดั้งเดิมที่ถูกตัดออกจากมาตรฐาน POSIX (มักจะมีเหตุผลที่ดีเช่นการถูกแทนที่ด้วยทางเลือกที่ดีกว่าหรือถูกผูกติดอยู่กับการใช้งานแบบดั้งเดิม)
  3. การเข้าถึงฟังก์ชั่นในระดับต่ำที่ไม่สามารถจะพกพา แต่บางครั้งคุณจำเป็นสำหรับการดำเนินงานระบบสาธารณูปโภคที่ชอบmount, ifconfigฯลฯ
  4. พฤติกรรมที่ไม่สมบูรณ์สำหรับฟังก์ชั่นที่ระบุ POSIX จำนวนมากซึ่งกลุ่ม GNU ไม่เห็นด้วยกับคณะกรรมการมาตรฐานเกี่ยวกับการทำงานของฟังก์ชั่นและตัดสินใจที่จะทำสิ่งต่าง ๆ ของตนเอง

ตราบใดที่คุณตระหนักถึงสิ่งเหล่านี้ก็ไม่ควรมีปัญหาในการกำหนด_GNU_SOURCEแต่คุณควรหลีกเลี่ยงการกำหนดและกำหนดแทน_POSIX_C_SOURCE=200809Lหรือ_XOPEN_SOURCE=700เมื่อเป็นไปได้เพื่อให้แน่ใจว่าโปรแกรมของคุณพกพาได้

โดยเฉพาะอย่างยิ่งสิ่งต่าง ๆ_GNU_SOURCEที่คุณไม่ควรใช้คือ # 2 และ # 4 ด้านบน


71
แน่นอนทุกคนรู้จริงเหตุผลที่จะกำหนด_GNU_SOURCEอยู่ในลำดับที่จะได้รับและstrfry memfrob
user4815162342

5
ลิงก์นี้ไปยังเอกสาร GNU C Library ให้รายละเอียดเพิ่มเติมบางอย่าง (เช่น#define _GNU_SOURCEแนะนำให้ "สิ่งแรกสุดในไฟล์นำหน้าด้วยความคิดเห็นเท่านั้น")
Alexander Pozdneev

ไม่เกี่ยวข้อง แต่ใช้เพื่อขยายขีด จำกัด ขนาดไฟล์ 2GB บนเป้าหมาย 32 บิต
mckenzm

1
@mckenzm: ฉันคิดว่าคุณกำลังความคิดของไม่ได้_FILE_OFFSET_BITS _GNU_SOURCE
. GitHub หยุดช่วยน้ำแข็ง

ฉันต้องการเป็นโปรแกรมเมอร์ที่ได้รับค่าจ้างสำหรับการย้ายพอร์ตของmemfrob strfry และสิ่งอำนวยความสะดวกที่คล้ายกันกับแพลตฟอร์มและโซ่เครื่องมืออื่น ๆ
Massimo

6

ให้ฉันตอบสองคะแนนเพิ่มเติม:

มีข้อบกพร่องบางอย่างสำหรับฉันด้วย: คอมไพเลอร์รู้ได้อย่างไรว่าการใช้งานฟังก์ชั่นใดเพื่อเชื่อมโยงกับปฏิบัติการ? ใช้ #define นี้ด้วยหรือไม่

วิธีการทั่วไปคือการ#defineระบุตามเงื่อนไขbasenameให้กับชื่อต่าง ๆ ขึ้นอยู่กับว่า_GNU_SOURCEมีการกำหนดไว้หรือไม่ ตัวอย่างเช่น

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

ตอนนี้ไลบรารีต้องการเพียงแสดงพฤติกรรมทั้งสองอย่างภายใต้ชื่อเหล่านั้น

ถ้าเป็นเช่นนั้นทำไมไม่ให้คนส่วนหัวที่แตกต่างกันแทนที่จะต้องกำหนดตัวแปรสภาพแวดล้อมที่คลุมเครือเพื่อรับฟังก์ชั่นหนึ่งหรืออื่น ๆ

บ่อยครั้งที่ส่วนหัวเดียวกันมีเนื้อหาที่แตกต่างกันเล็กน้อยในเวอร์ชัน Unix ที่แตกต่างกันดังนั้นจึงไม่มีเนื้อหาที่เหมาะสมสำหรับพูด<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 จะมีความสำคัญกว่า

จากหน้า man Linux บนมาโครทดสอบคุณลักษณะ :

_GNU_SOURCE

การกำหนดมาโครนี้ (มีค่าใด ๆ ) จะกำหนด _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _LOCGECE เวอร์ชันก่อนหน้านี้ในเวอร์ชัน 2.59 ในเวอร์ชัน 2.59 ในเวอร์ชันก่อนหน้านี้ในเวอร์ชัน 2.59 ในรุ่นก่อนหน้านี้ _XOPEN_SOURCE ที่มีค่า 700 (600 ในรุ่น glibc ก่อน 2.10; 500 ในรุ่น glibc ก่อน 2.2) นอกจากนี้ส่วนขยายเฉพาะ GNU ต่าง ๆ ก็มีให้เห็นเช่นกัน

ตั้งแต่ glibc 2.19 การกำหนด _GNU_SOURCE ก็มีผลในการกำหนด _DEFAULT_SOURCE โดยปริยาย ในรุ่น glibc ก่อน 2.20 การกำหนด _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's include / features.h:

_GNU_SOURCE จากทั้งหมดข้างต้นรวมทั้งส่วนขยาย GNU

ซึ่งหมายความว่ามันช่วยให้ทั้งหมดนี้:

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE, _LARGEFILE64_SOURCE, _FOC_SETURN, _LOPGEFILE64_OURCE

ดังนั้นจึงช่วยให้รวบรวมการตั้งค่าสถานะทั้งหมดสำหรับ gcc


21
ไม่ส่งผลกระทบต่อพฤติกรรมของคอมไพเลอร์เฉพาะต้นแบบและสิ่งที่มองเห็นได้จากส่วนหัว
Spudd86
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.