Tôi có nên thêm nguồn thư viện thay vì liên kết với chúng không?


14

Tôi còn khá mới đối với C ++, vì vậy tôi không chắc mình nên xử lý tốt nhất các phụ thuộc nhỏ như thế nào (ví dụ: ngôn ngữ kịch bản lệnh hoặc Trình phân tích cú pháp JSON / YAML / XML).

Tôi có nên tạo các dự án riêng biệt và liên kết chúng dưới dạng thư viện tĩnh hay có nhược điểm nào khi chỉ đưa các tệp .h / .cpp vào dự án chính của mình không?

Cái sau có vẻ dễ hơn nhiều vì tôi đã dành vài giờ để xử lý các thư viện không tương thích (cài đặt trình biên dịch khác nhau khi xây dựng thư viện), nhưng tôi không muốn bắt đầu học C ++ sai cách.

Nếu muốn giữ chúng thành các thư viện riêng biệt, làm thế nào tốt nhất tôi có thể giữ các cờ biên dịch đồng bộ hóa để các tệp .lib / .a liên kết thành công với ứng dụng của tôi?

(Tôi hiện đang làm việc với MSVC 2015, nhưng mục tiêu là biên dịch trên Mac OS X và iOS bằng XCode / clang, do đó tôi phải xử lý ít nhất 3 loại thư viện khác nhau (Win x86, Mac x64, ARM) )


5
Nhìn vào ABIss và họ sẽ nhìn vào bạn
Basilevs

1
Hãy nhớ rằng một số thư viện dự định sẽ được sử dụng theo cách này. Mẫu sử dụng ưa thích của thư viện SQLite là thả tệp nguồn và tiêu đề được hợp nhất vào cây nguồn của ứng dụng C hoặc C ++ để biên dịch thành tệp thực thi.
Mark Benningfield

Câu trả lời:


6

TLDR;

Nên bạn thêm nguồn? X
nên thêm nguồn? TIỀN GỬI

Đây là lý do tại sao ...

Trước đây, thời gian biên dịch là một vấn đề thậm chí các dự án nhỏ hơn đã có. Tổng hợp các nguồn của bạn và không bao giờ lo lắng về kết quả của trình biên dịch bộ nhớ đệm chắc chắn đã hấp dẫn một số người. Đó là một điểm cho các thư viện không liên quan đến bạn.

Một điều quan trọng khác là phiên bản. Bạn có thực sự cần phiên bản riêng từng thư viện? Chạy thử nghiệm với từng người? Phân phối nó giữa nhiều thành viên trong nhóm? Thư viện là tuyệt vời nếu bạn làm, và thuận tiện để di chuyển, nhưng một lần nữa, dường như bạn cũng không quan tâm đến điều này.

Điểm cuối cùng ở đây là, đó là một chi phí bổ sung và việc thả các tệp nguồn dễ dàng hơn trong trường hợp của bạn, điều này mang lại một điểm rất mạnh để giảm các nguồn thay vì sử dụng các thư viện. Như bạn đã nhận thấy, một khi bạn thực hiện một thay đổi cài đặt trình biên dịch, bạn phải theo đuổi tất cả các phụ thuộc khác.

Tôi biết tất cả điều này từ kinh nghiệm:

Đối với các dự án Swift, tôi chắc chắn sử dụng các khung (thư viện) và liên kết với chúng, vì nó dễ dàng cấu hình bằng Xcode. Tôi cũng thực sự cần phiên bản, kiểm tra và tách rời ở đó, vì vậy đó là lý do.

Đối với các dự án Mono (C #), đối với Unity, tôi bắt đầu với cách tiếp cận mạnh mẽ là chia nhỏ dự án thành các thư viện, biên soạn và thử nghiệm từng dự án, điều này thật tuyệt ... nhưng một khi tôi bỏ thư viện vào Unity, mọi vấn đề đã xảy ra , từ phiên bản hack của Mono Unity sử dụng, chỉ đơn giản là hành vi đôi khi khác nhau mà mã thể hiện khi thay đổi nền tảng. Không có một IDE duy nhất ở đây để quản lý tất cả các thư viện là một nỗi đau thực sự, vì vậy việc đưa tất cả nguồn vào Unity là một chiến thắng lớn cho năng suất.

Cuối cùng, phù hợp nhất với bạn, một dự án trò chơi C ++ mà tôi đã làm việc. Một công cụ trò chơi, máy khách thời gian thực mạng, máy khách HTTP mạng, AI và một cửa hàng kiên trì đã được viết cho trò chơi này, chỉ ở phía máy khách. Tôi đã chọn gì? CLion + Thư viện. Mặc dù tôi đang sử dụng các thư viện, tôi không cảm thấy như vậy. Tất cả các nguồn đều nằm trong dự án CLion IDE và bằng cách soạn CMakeLists, tôi có thể kích hoạt tất cả các bản dựng và liên kết chúng trong một nét.

Để kết luận , tôi sẽ nói sử dụng các thư viện là một giải pháp chứng minh trong tương lai, nhưng cũng là một tối ưu hóa sớm nếu không cần thiết. Theo như tôi có thể xác định được từ tình huống của bạn, việc chuyển từ MSVC sang Xcode sẽ là một nỗi đau nếu bạn sẽ có nhiều mục tiêu xây dựng. Vì vậy, chỉ cần thả nó vào và duy trì càng nhiều cách ly càng tốt cho khi thời gian khi bạn có thể cần phải sử dụng thư viện.

PS: Tôi đang có một tình huống khó xử tương tự những ngày này với docker. Có nên sáng tác? Tôi có nên chạy địa phương? .. vv Ngoài ra Elixir, vì nó cho phép bạn xây dựng Ứng dụng trong cùng một ứng dụng .. Tôi có nên làm điều đó không? Hoặc tách ứng dụng thành cái gọi là dịch vụ vi mô? ... vv Không có viên đạn bạc, luôn tự đo mình, như YMMV.


2

Liên kết với các thư viện C ++ đòi hỏi rất nhiều rắc rối và nó đòi hỏi nhiều kiến ​​thức và nỗ lực để thực hiện chính xác. Nó có thể đáng sợ đối với người học C ++.


Thông thường, các tác giả / người duy trì một thư viện C ++ cụ thể sẽ ghi nhớ điều này và sẽ đề xuất cách này hay cách khác.

Nói cách khác, nếu các tác giả / người bảo trì dự định thư viện sẽ được bao gồm bởi các tiêu đề (chỉ * .h và .hpp), hoặc bao gồm bởi nguồn ( .h *, hoặc .c ), thì nó sẽ nói rất rõ trong readme hoặc tài liệu.


Các thư viện được thiết kế và duy trì là đa nền tảng (và tương thích với nhiều nhà cung cấp và môi trường trình biên dịch C ++) thường sẽ có hệ thống makefile hoặc hệ thống cấu hình xây dựng (như CMake). Các hệ thống này được sử dụng để tạo các shims tiêu đề giúp làm giảm sự khác biệt của nền tảng và để tạo các tập lệnh sẽ gọi trình biên dịch và trình liên kết trên các tệp nguồn bằng cách sử dụng các tùy chọn dòng lệnh thích hợp và theo đúng trình tự. Tùy thuộc vào nền tảng và cấu hình, các hệ thống xây dựng này có thể bao gồm hoặc loại trừ các tiêu đề hoặc tệp nguồn nhất định hoặc chúng có thể xác định hoặc xác định các ký hiệu tiền xử lý nhất định.


Đi ngược lại khuyến nghị của các tác giả / nhà bảo trì là có thể, nhưng điều đó luôn đòi hỏi một nỗ lực chuyển rộng. Lượng công việc cần thiết cho nỗ lực chuyển đó có thể tương đương với chuyển sang môi trường C ++ khác.


Do Visual C ++ sử dụng hệ thống xây dựng riêng dựa trên tệp mô tả dự án (dựa trên một phần XML), nên nó không giống với hệ thống xây dựng dựa trên kịch bản được sử dụng trong Linux. Cách tiếp cận được CMake sử dụng là để CMake thực hiện các cài đặt cấu hình và sau đó phát ra toàn bộ cấu trúc dự án Visual C ++, với các tùy chọn cấu hình được đưa vào các tệp * .vcxproj.

Nếu sự cố phát sinh trong quá trình liên kết C ++ với Visual C ++, cài đặt bản dựng trong tệp * .vcxproj có thể được sửa đổi bằng GUI Visual Studio (sử dụng hộp thoại trang thuộc tính dự án của nó). Điều này giả định rằng bạn hiểu thấu đáo ý nghĩa và hậu quả của hàng tá cài đặt biên dịch và liên kết C ++ quan trọng.

Bây giờ đến phần ngu ngốc nhất khi sử dụng Visual C ++: nếu bạn đang sử dụng hàng tá thư viện bên thứ ba khác nhau, việc thay đổi cài đặt bản dựng cho tất cả chúng có nghĩa là đi vào từng tệp * .vcxproj và lặp lại cùng một thay đổi trên GUI cho hàng tá lần Một rắc rối, nhưng nó có thể được thực hiện, nếu bạn biết làm thế nào cho đúng.

Hầu hết những người học Visual C ++ đều học các cài đặt này một cách khó khăn, bằng cách quan sát các trình biên dịch và trình liên kết của Visual C ++, được xác định bởi mã lỗi của họ. Ví dụ, người ta có thể tra cứu LNK2005, với ý nghĩa hời hợt là "Biểu tượng biểu tượng được xác định nhiều lần", nhưng với sự hiểu rằng định nghĩa trùng lặp không phát sinh từ một lỗi lập trình bất cẩn, thay vào đó có thể xảy ra do một số lỗi xung đột hoặc ứng dụng sai của các tùy chọn biên dịch và liên kết.


Để cung cấp một câu trả lời cụ thể và hữu ích hơn cho tình huống của bạn, người ta sẽ cần biết tên của các thư viện bạn định sử dụng, cũng như các lỗi liên kết hoặc các khó khăn khác mà bạn gặp phải. Bạn có thể tìm thấy câu trả lời hiện có cho những câu hỏi đó trong bảng thảo luận của thư viện tương ứng. Những câu hỏi này có xu hướng được gắn thẻ với "các vấn đề liên kết", "cửa sổ" và "trực quan C ++".

Một hướng dẫn từ người mới bắt đầu đến chuyên gia về vấn đề này là có thể, nhưng nó sẽ dành riêng cho dự án. Các ưu tiên khác nhau được lựa chọn bởi các dự án khác nhau sẽ yêu cầu viết lại hoàn toàn hướng dẫn.


Nếu bạn sử dụng CMake để phát ra .vcxproj, thay vì sửa đổi .vcxproj, bạn có thể sửa đổi cấu hình CMake
Caleth

1

Tôi sẽ nói có, miễn là nó dễ dàng hơn. Có khá nhiều lợi ích:

  1. Nó sẽ dẫn đến mã nhanh hơn và tốt hơn, đặc biệt nếu bạn bật Tối ưu hóa thời gian liên kết.

  2. IDE của bạn sẽ thích nó hơn, ví dụ, nó sẽ (hy vọng) cho phép bạn chuyển sang triển khai (.cpp) mã thư viện, thay vì chỉ giao diện (.h), cực kỳ hữu ích khi làm việc với mã tài liệu kém (nghĩa là hầu hết mã).

  3. Nó thường cho phép bạn thêm phụ thuộc dưới dạng một mô hình con git, đây là một cách hơi hack nhưng thực sự khá tốt để có các phụ thuộc (dù sao đối với C ++, không có nhiều hệ thống xây dựng lành mạnh). Nó làm cho nó thực sự dễ dàng để cập nhật thư viện và thử nghiệm các phiên bản khác nhau.

  4. Bạn không phải lo lắng về việc phụ thuộc được biên dịch với MSVC ++ 2013, trong khi bạn đang sử dụng 2017 chẳng hạn. Hoặc chia sẻ với MSVCRT tĩnh.

  5. Bạn có thể dễ dàng xây dựng trong chế độ gỡ lỗi và bước vào thư viện.

Lý do duy nhất tôi nghĩ bạn sẽ không muốn làm điều này là nếu thư viện lớn và có hệ thống xây dựng phức tạp mà bạn không muốn sao chép trong máy của mình, ví dụ Boost hoặc LLVM. Nhưng đối với các thư viện đơn giản không có nhược điểm thực sự.

Ví dụ, tôi sử dụng libusb trong một vài dự án và tôi cần hỗ trợ Windows. libusb sử dụng autotools, một trò đùa của hệ thống xây dựng và dù sao cũng không thực sự hoạt động trên Windows. Họ cung cấp các tệp nhị phân được biên dịch sẵn nhưng chúng được xây dựng với MSVC ++ 2013 và sẽ không hoạt động với năm 2017. Giải pháp đơn giản nhất cho đến nay chỉ là thêm tất cả các tệp .c và .h có liên quan vào dự án của tôi.


2
1) thật sao? Một thư viện tĩnh chỉ là một tập hợp các tệp đối tượng, giống như nếu bạn vừa biên dịch chúng.
Baldrickk

Bạn có thể tạo một kho lưu trữ các .otệp đã được biên dịch -fltonhưng chúng không thực sự là một thư viện tĩnh - đối với Clang chúng là các tệp bitcode LLVM. Và rõ ràng nó sẽ không hoạt động nếu bạn sử dụng các thư viện tĩnh mà người khác cung cấp.
Timmmm

ok, hãy nâng cấp cuộc thảo luận này - Tôi mong được học hỏi thêm một số điều :)
Baldrickk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.