ฉันควรเพิ่มแหล่งที่มาของห้องสมุดแทนที่จะเชื่อมโยงไปยังพวกเขาหรือไม่


14

ฉันค่อนข้างใหม่กับ C ++ ดังนั้นฉันไม่แน่ใจว่าฉันควรจัดการกับการอ้างอิงขนาดเล็กได้ดีที่สุดอย่างไร (เช่นภาษาสคริปต์หรือ JSON / YAML / XML Parser)

ฉันควรสร้างโครงการแยกต่างหากและเชื่อมโยงเป็นห้องสมุดแบบคงที่หรือมีข้อเสียเพียงวางไฟล์. h / .cpp ลงในโครงการหลักของฉัน

หลังดูง่ายกว่ามากเพราะฉันใช้เวลาหลายชั่วโมงในการจัดการกับไลบรารีที่เข้ากันไม่ได้ (การตั้งค่าคอมไพเลอร์ที่แตกต่างกันเมื่อสร้างห้องสมุด) แต่ฉันไม่ต้องการเริ่มต้นเรียนรู้ C ++ ในทางที่ผิด

หากการเก็บไว้เป็นไลบรารี่แยกกันฉันจะเก็บแฟล็กการรวบรวมให้ตรงกันได้อย่างไรเพื่อให้ไฟล์. lib / .a เชื่อมโยงกับแอปพลิเคชันของฉันสำเร็จ

(ตอนนี้ฉันทำงานกับ MSVC 2015 แต่เป้าหมายคือการคอมไพล์บน Mac OS X และ iOS โดยใช้ XCode / clang ดังนั้นฉันต้องจัดการกับไลบรารีที่แตกต่างกันอย่างน้อย 3 ประเภท (Win x86, Mac x64, ARM) )


5
มองเข้าไปใน ABIss แล้วพวกเขาจะมองคุณ
Basilevs

1
โปรดจำไว้ว่าห้องสมุดบางแห่งตั้งใจจะใช้วิธีนี้ SQLiteห้องสมุดรูปแบบการใช้งานที่ต้องการคือจะลดลงแหล่งที่ควบเข้ากันและไฟล์ส่วนหัวเข้าไปในแหล่งต้นไม้ของโปรแกรม C หรือ C ++ ที่จะเรียบเรียงปฏิบัติการ
Mark

คำตอบ:


6

TLDR;

คุณควรเพิ่มแหล่งที่มาหรือไม่ ใช่X
ควรเพิ่มแหล่งที่มาหรือไม่? ขึ้นอยู่กับ

มาที่นี่ทำไม ...

ย้อนกลับไปในวันที่เวลารวบรวมเป็นปัญหาแม้แต่โครงการขนาดเล็กมี รวบรวมแหล่งที่มาของคุณและไม่ต้องกังวลเกี่ยวกับผลการรวบรวมแคชได้ดึงดูดบางอย่างแน่นอน นั่นเป็นจุดหนึ่งสำหรับห้องสมุดที่ไม่เกี่ยวข้องกับคุณ

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

จุดสุดท้ายที่นี่คือมันเป็นโอเวอร์เฮดที่เพิ่มขึ้นและการปล่อยไฟล์ต้นฉบับนั้นง่ายกว่าในกรณีของคุณซึ่งให้จุดแข็งมากในการวางในแหล่งข้อมูลแทนที่จะใช้ไลบรารี ดังที่คุณได้สังเกตเห็นเมื่อคุณทำการเปลี่ยนแปลงการตั้งค่าคอมไพเลอร์เดียวคุณจะต้องติดตามการพึ่งพาทั้งหมดเป็นอย่างอื่น

ฉันรู้ทั้งหมดนี้จากประสบการณ์:

สำหรับโครงการ Swift ฉันใช้เฟรมเวิร์ก (ไลบรารี) และเชื่อมโยงกับพวกเขาอย่างแน่นอนเนื่องจากมันง่ายต่อการกำหนดค่าโดยใช้ Xcode ฉันยังต้องการเวอร์ชันการทดสอบและ decoupling ที่นั่นด้วยเหตุนี้

สำหรับโครงการ Mono (C #) สำหรับ Unity ฉันเริ่มต้นด้วยวิธีการแบ่งโครงการเข้าสู่ไลบรารีรวบรวมและทดสอบแต่ละรายการซึ่งยอดเยี่ยมมาก ... แต่เมื่อฉันทิ้งไลบรารี่เป็น Unity ปัญหาทุกประเภทก็เกิดขึ้น จากรุ่นที่ถูกแฮ็กของ Mono Unity ใช้เพื่อแสดงพฤติกรรมที่แตกต่างในบางครั้งที่รหัสแสดงเมื่อเปลี่ยนแพลตฟอร์ม การไม่มี IDE เดียวที่นี่เพื่อจัดการห้องสมุดทั้งหมดเป็นความเจ็บปวดที่แท้จริงดังนั้นการวางแหล่งที่มาทั้งหมดใน Unity จึงเป็นชัยชนะที่ยิ่งใหญ่สำหรับผลผลิต

สุดท้ายเกี่ยวข้องกับคุณมากที่สุดโครงการเกม C ++ ที่ฉันทำงาน เอ็นจิ้นเกม, ไคลเอนต์เรียลไทม์เครือข่าย, ไคลเอนต์เครือข่าย HTTP, AI และร้านค้าที่มีอยู่ถูกเขียนขึ้นสำหรับเกมนี้เพียงแค่ฝั่งไคลเอ็นต์ ฉันเลือกทำอะไร ห้องสมุด CLion + แม้ว่าฉันจะใช้ห้องสมุดมันก็ไม่ได้รู้สึกเหมือนฉัน แหล่งที่มาทั้งหมดอยู่ในโครงการ CLion IDE และโดยการเขียน CMakeLists ฉันสามารถกระตุ้นการสร้างทั้งหมดและเชื่อมโยงพวกเขาในจังหวะเดียว

โดยสรุปฉันจะบอกว่าการใช้ห้องสมุดเป็นวิธีการแก้ปัญหาในอนาคต แต่ยังเป็นการเพิ่มประสิทธิภาพก่อนวัยอันควรหากไม่จำเป็น เท่าที่ฉันสามารถตรวจสอบได้จากสถานการณ์ของคุณการเปลี่ยนจาก MSVC เป็น Xcode จะเป็นความเจ็บปวดถ้าคุณจะมีเป้าหมายการสร้างที่หลากหลาย ดังนั้นเพียงแค่วางลงในและรักษาความเหงามากที่สุดเท่าที่จะเป็นไปได้เมื่อเวลาที่คุณอาจต้องใช้ห้องสมุด

PS: ฉันมีปัญหาที่คล้ายกันวันนี้กับนักเทียบท่า ฉันควรจะเขียน? ฉันควรวิ่งในพื้นที่หรือไม่ .. เป็นต้นนอกจากนี้ Elixir ยังช่วยให้คุณสร้างแอปพลิเคชันภายในแอปพลิเคชันเดียวกัน .. ฉันควรทำอย่างไร หรือแยกแอปออกเป็นบริการไมโครที่เรียกว่า ... ฯลฯ ไม่มีกระสุนเงินวัดตัวเองเสมอเหมือน YMMV


2

การเชื่อมโยงกับไลบรารี C ++ ต้องการความยุ่งยากมากและต้องใช้ความรู้และความพยายามอย่างมากในการทำอย่างถูกต้อง อาจเป็นการข่มขู่ผู้เรียน C ++


บ่อยครั้งที่ผู้เขียน / ผู้ดูแลของไลบรารี C ++ ที่เฉพาะเจาะจงจะมีสิ่งนี้อยู่ในใจและจะแนะนำวิธีหนึ่งหรืออื่น ๆ

กล่าวอีกนัยหนึ่งหากผู้เขียน / ผู้ดูแลตั้งใจที่จะรวมห้องสมุดโดยส่วนหัว (* .h และ. hpp เท่านั้น) หรือรวมโดยแหล่งที่มา ( .h * หรือ. c ) ก็จะได้กล่าวอย่างชัดเจนใน readme หรือเอกสาร


ไลบรารีที่ได้รับการออกแบบและดูแลให้เป็นข้ามแพลตฟอร์ม (และเข้ากันได้กับผู้ขายคอมไพเลอร์และสภาพแวดล้อมหลาย C ++) มักจะมีระบบ makefile หรือระบบกำหนดค่าการสร้าง (เช่น CMake) ระบบเหล่านี้ใช้เพื่อสร้างส่วนหัว shims ที่ปรับความแตกต่างของแพลตฟอร์มให้เรียบและเพื่อสร้างสคริปต์ที่จะเรียกใช้คอมไพเลอร์และลิงเกอร์บนไฟล์ต้นฉบับโดยใช้ตัวเลือกบรรทัดคำสั่งที่เหมาะสมและในลำดับที่ถูกต้อง ขึ้นอยู่กับแพลตฟอร์มและการกำหนดค่าระบบบิลด์เหล่านี้อาจรวมหรือแยกส่วนหัวหรือไฟล์ต้นฉบับบางอย่างหรืออาจกำหนดหรือยกเลิกการกำหนดสัญลักษณ์พรีโปรเซสเซอร์


การขัดกับข้อเสนอแนะของผู้เขียน / ผู้ดูแลรักษานั้นเป็นไปได้ แต่ก็ต้องใช้ความพยายามในการย้ายพอร์ตอย่างกว้างขวางเสมอ จำนวนของงานที่จำเป็นสำหรับความพยายามในการพอร์ตนั้นสามารถเทียบเคียงได้กับการพอร์ตกับสภาพแวดล้อม C ++ ที่แตกต่างกัน


เนื่องจาก Visual C ++ ใช้ระบบการสร้างของตัวเองโดยยึดตามไฟล์คำอธิบายโครงการ (บางส่วนใช้ XML) จึงค่อนข้างแตกต่างจากระบบการสร้างสคริปต์ที่ใช้ภายใต้ Linux วิธีการที่ CMake ใช้สำหรับ CMake เพื่อทำการตั้งค่าการกำหนดค่าจากนั้นปล่อยโครงสร้างโครงการ Visual C ++ ทั้งหมดด้วยตัวเลือกการกำหนดค่าที่ถูกอบเข้าในไฟล์ * .vcxproj

หากปัญหาเกิดขึ้นระหว่างการเชื่อมโยง C ++ กับ Visual C ++ การตั้งค่าการสร้างในไฟล์ * .vcxproj สามารถแก้ไขได้โดยใช้ Visual Studio GUI (โดยใช้กล่องโต้ตอบหน้าคุณสมบัติโครงการ) สิ่งนี้จะถือว่าคุณเข้าใจความหมายและผลของการรวบรวมและตั้งค่าการเชื่อมโยง C ++ ที่สำคัญจำนวนโหล

ตอนนี้ส่วนที่โง่ที่สุดของการใช้ Visual C ++: หากคุณกำลังใช้ไลบรารีบุคคลที่สามที่แตกต่างกันนับสิบการเปลี่ยนการตั้งค่าการสร้างสำหรับพวกเขาทั้งหมดหมายถึงการเข้าไปในแต่ละไฟล์ * .vcxproj และทำซ้ำการเปลี่ยนแปลงเดียวกันบน GUI สำหรับโหล ครั้ง ยุ่งยาก แต่ก็สามารถทำได้ถ้าคุณรู้วิธีการทำอย่างถูกต้อง

ผู้เรียน Visual C ++ ส่วนใหญ่เรียนรู้การตั้งค่าเหล่านี้อย่างหนักโดยสังเกตข้อผิดพลาดของคอมไพเลอร์ Visual C ++ และ linker ที่ระบุด้วยรหัสข้อผิดพลาด ตัวอย่างเช่นหนึ่งอาจค้นหา LNK2005 ด้วยความหมายตื้น ๆ ของ "สัญลักษณ์สัญลักษณ์ถูกกำหนดมากกว่าหนึ่งครั้ง" แต่ด้วยความเข้าใจว่าคำจำกัดความที่ซ้ำกันนั้นไม่ได้เกิดขึ้นจากความผิดพลาดในการเขียนโปรแกรมที่ประมาทแทนที่จะเกิดขึ้นเพราะ ความขัดแย้งหรือการใช้งานผิดพลาดของตัวเลือกการรวบรวมและการเชื่อมโยง


เพื่อให้คำตอบที่เฉพาะเจาะจงและมีประโยชน์กับสถานการณ์ของคุณมากขึ้นคุณจะต้องทราบชื่อของห้องสมุดที่คุณตั้งใจจะใช้รวมถึงข้อผิดพลาดในการเชื่อมโยงหรือปัญหาอื่น ๆ ที่คุณพบ คุณอาจพบคำตอบสำหรับคำถามเหล่านั้นในกระดานสนทนาของห้องสมุดนั้น ๆ คำถามเหล่านี้มักถูกแท็กด้วย "ปัญหาการเชื่อมโยง", "windows" และ "visual C ++"

คำแนะนำเบื้องต้นสำหรับผู้เชี่ยวชาญเกี่ยวกับปัญหานี้เป็นไปได้ แต่เป็นไปได้เฉพาะโครงการ การตั้งค่าที่แตกต่างกันที่เลือกโดยโครงการที่แตกต่างกันจะต้องเขียนใหม่ทั้งหมดของคู่มือ


หากคุณใช้ CMake เพื่อปล่อย. vcxproj แทนที่จะแก้ไข. vcxproj คุณสามารถปรับเปลี่ยนการกำหนดค่า CMake
384

1

ฉันจะบอกว่าใช่ตราบใดที่ง่ายขึ้น มีประโยชน์ค่อนข้างมาก:

  1. มันจะส่งผลให้รหัสเร็วขึ้นและดีขึ้นโดยเฉพาะถ้าคุณเปิดใช้การเพิ่มประสิทธิภาพเวลาเชื่อมโยง

  2. IDE ของคุณจะชอบมากกว่านี้เช่นจะช่วยให้คุณสามารถข้ามไปยังการนำไปใช้ (.cpp) ของรหัสห้องสมุดแทนที่จะเป็นเพียงส่วนต่อประสาน (.h) ซึ่งมีประโยชน์อย่างมากเมื่อทำงานกับรหัสที่มีเอกสารไม่ดี (เช่น รหัสส่วนใหญ่)

  3. มันมักจะช่วยให้คุณสามารถเพิ่มการพึ่งพาเป็น submodule git ซึ่งเป็นแฮ็คเล็กน้อย แต่จริงๆแล้วเป็นวิธีที่ดีที่จะมีการพึ่งพา (สำหรับ C ++ ต่อไปซึ่งไม่มีระบบสร้างสติ) ทำให้การอัปเดตไลบรารีและทดสอบเวอร์ชันต่างๆเป็นเรื่องง่าย

  4. คุณไม่ต้องกังวลกับการพึ่งพาการรวบรวม MSVC ++ 2013 ในขณะที่คุณกำลังใช้ 2017 หรือใช้ร่วมกันแบบคงที่กับ MSVCRT

  5. คุณสามารถสร้างในโหมดแก้ไขข้อบกพร่องและเข้าสู่ไลบรารีได้อย่างง่ายดาย

เหตุผลเดียวที่ฉันคิดว่าคุณไม่ต้องการทำเช่นนี้คือถ้าห้องสมุดมีขนาดใหญ่และมีระบบการสร้างที่ซับซ้อนที่คุณไม่ต้องการทำซ้ำในของคุณเช่น Boost หรือ LLVM แต่สำหรับห้องสมุดธรรมดาไม่มีข้อเสียจริงๆ

ตัวอย่างเช่นฉันใช้ libusb ในบางโครงการและฉันต้องสนับสนุน Windows libusb ใช้ autotools ซึ่งเป็นเรื่องตลกของระบบบิลด์และไม่สามารถใช้กับ Windows ได้ พวกเขาไม่ให้ไบนารี precompiled แต่พวกเขาจะสร้างขึ้นด้วย MSVC ++ 2013 และจะไม่ทำงานกับ 2017 ทางออกที่ง่ายที่สุดโดยไกลเป็นเพียงการเพิ่มทุก .c ที่เกี่ยวข้องและ .h ไฟล์ไปยังโครงการของฉัน


2
1) จริงเหรอ? ไลบรารีแบบสแตติกเป็นเพียงชุดของวัตถุไฟล์เช่นเดียวกับถ้าคุณเพิ่งรวบรวมพวกเขา
Baldrickk

คุณสามารถสร้างไฟล์เก็บถาวรของ.oไฟล์ที่ถูกคอมไพล์ด้วย-fltoแต่ไฟล์เหล่านั้นไม่ใช่ไลบรารีแบบสแตติก - สำหรับ Clang เป็นไฟล์บิตโค้ด LLVM และแน่นอนว่ามันจะไม่ทำงานถ้าคุณใช้สแตติกไลบรารีที่มีคนอื่นจัดไว้ให้
Timmmm

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