2009-11-26 29 views
11

Tôi đang viết mã C cho một hệ thống nhúng (nền tảng dsPIC33) và tôi đang xem xét xây dựng thư viện mã có thể sử dụng lại để sử dụng trong nhiều dự án.Các phương pháp hay nhất để sử dụng lại nhúng C?

Thực tiễn tốt nhất để buộc thư viện cho từng dự án là gì?

Rõ ràng thư viện sẽ có một số phụ thuộc phần cứng cụ thể (và do đó dự án cụ thể), vì vậy hợp lý để giả định rằng nó sẽ được biên dịch với từng dự án (thay vì liên kết dưới dạng nhị phân).

Điều tôi đã đưa ra cho đến nay là giữ thư viện ở vị trí trung tâm, nhưng yêu cầu thư viện dự án cụ thểConfig.h bao gồm các định nghĩa hàm, macro, v.v. Điều này yêu cầu thư viện phải bao gồm tiêu đề mã, có nghĩa là thư mục nguồn dự án sẽ cần phải có trong đường dẫn bao gồm (không chỉ thư mục nguồn thư viện). Đó là loại messes lên sự khác biệt giữa #include ""#include <>, phải không?

Đây có phải là cách nó được thực hiện bình thường không?

Trả lời

7

Câu hỏi rất hay và câu trả lời không đơn giản. Một số điều cần xem xét. Dưới đây là một vài ý kiến ​​từ kinh nghiệm của tôi cho đến nay.

tắc chung vs Project-Local Sao chép

Một quyết định quan trọng là liệu sử dụng "chung" mã thư viện được cập nhật tự động từ một vị trí trung tâm (của công ty bạn "thư viện tái sử dụng"), hoặc cho dù để giữ bản sao dự án địa phương.

Điều này được thảo luận chi tiết trong this SO question.

Lợi ích của thư viện trung tâm là công việc được thực hiện một lần có thể mang lại lợi ích cho nhiều dự án. Khó khăn với bản sao dự án cục bộ là mọi sửa lỗi và cải tiến không được đóng góp lại vào thư viện trung tâm và mọi sửa lỗi trong thư viện trung tâm có thể không được đưa vào dự án của bạn. Tuy nhiên, một khó khăn tiềm năng khi sử dụng thư viện trung tâm là nếu mọi người sửa đổi nó theo cách không kiểm soát được để phù hợp với dự án của họ, và vô tình phá vỡ các dự án khác. Tôi đã thấy cá nhân đó, trong mã "phổ biến" đã trở thành đầy đủ #ifdef và thường xuyên phá vỡ các dự án khác.

Để có được giá trị tốt ra khỏi mã chung aka trung tâm thư viện tái sử dụng:

Thư viện:

  • phải có những yêu cầu rõ ràng, API, và kiểm tra đơn vị
  • phải tránh dự án cụ thể mã; cần có mục đích chung là
  • cần có cơ chế để đặt rõ ràng các cài đặt cụ thể cho dự án (điều này có thể được xem là một phần của API một cách hiệu quả)
  • phải có quy trình phát hành chính thức, với số phiên bản và bản sửa lỗi, sự cố phải được theo dõi.

dự án cá nhân:

  • không nên tự động và một cách mù quáng "mới nhất", nhưng sẽ có thể để có được một "phiên bản" đặc biệt với một số phiên bản nhất định. Sau đó, các dự án nên có quyền kiểm soát nếu/khi họ cập nhật lên phiên bản mới hơn. Dự án sẽ có thể theo dõi rõ ràng, "chúng tôi đang sử dụng phiên bản 1.2.3 của thư viện xyz".
  • nên tránh "cấm" mã thư viện nếu có thể. Ví dụ. tránh thêm "tính năng" cụ thể của dự án vào mã thư viện.
  • nên theo dõi bất kỳ sửa đổi cục bộ nào đối với mã thư viện
  • nên coi lỗi là lỗi thư viện, được sửa trong thư viện trung tâm nếu có thể. Công ty cần có các quy trình để sửa chúng trong thư viện trung tâm, kiểm tra thư viện với bộ thử nghiệm đơn vị riêng của nó (có thể cải thiện các bài kiểm tra đơn vị để bắt lỗi trong tương lai). Sau đó phát hành một phiên bản mới của thư viện trung tâm khi cần thiết và triển khai các dự án khác nếu/khi các dự án đó thấy phù hợp.

Nếu một công ty không có quy trình như vậy, thì dự án chỉ cần sao chép cục bộ một đoạn mã (sao chép từ dự án trước) và sau đó chịu trách nhiệm toàn bộ dự án từ đó trở đi. Bạn vẫn nhận được một số lợi ích từ việc tái sử dụng trong tình huống đó, bởi vì bạn không viết lại nó từ đầu.

Dự án Cụ thể cấu hình

Nếu mã cần cấu hình dự án cụ thể, tốt nhất nên được giữ ở càng nhỏ một phần của mã càng tốt - không phân tán thông qua một loạt các tập tin nguồn. Lý tưởng nhất là một tệp tiêu đề duy nhất. Nhưng cũng có thể là một tệp .C (nói, nếu bạn cần xác định một số bảng tra cứu). Thư viện sẽ cung cấp một mẫu, với các tùy chọn được nhận xét tốt.

Để có ví dụ điển hình về cách thực hiện việc này, hãy xem µC/OS-II RTOS (book) của Jean Labrosse, từ Micrium.

1

Nó không làm xáo trộn sự khác biệt, hầu như hoàn toàn do nền tảng định nghĩa. Hành vi được xác định duy nhất là nếu một bao gồm sử dụng "" không tìm thấy tệp, sau đó nó tìm kiếm lại như thể bạn đã nói <>.

Tôi nghĩ bạn đang làm đúng. Cách thông thường để xử lý một tiêu đề nền tảng cụ thể, theo kinh nghiệm của tôi, là bạn cho nó một cái tên bạn tự tin nhất có thể sẽ không bao giờ va chạm với bất kỳ thứ gì khác và #include nó với "". Sau đó, bạn nói với porter nền tảng để làm bất cứ điều gì cụ thể trình biên dịch là cần thiết để đảm bảo rằng nó được tìm thấy. Thông thường chỉ có nghĩa là chỉ định một số đối số trình biên dịch như -I, cho bất cứ nơi nào anh ta muốn giữ lại tệp. Vì vậy, có, một trong các thư mục của dự án của ông. Nhưng nếu thất bại, anh ta luôn có thể sao chép tập tin của mình vào một nơi mà trình biên dịch của anh ta sẽ xem xét. Ông thậm chí có thể sao chép nó vào bản sao địa phương của nguồn thư viện của bạn, nếu trình biên dịch của ông là không hợp lý khó khăn về toàn bộ điều.

Một cách khác là phải có một tập tin trong thư viện, selectplatform.h, nhìn như thế này:

// obviously WIN32 isn't an embedded platform, and GCC is too broad 
// to be supported by a single header file. Replace with whatever platforms 
// it is you do support out of the box. 
#if _WIN32 
    #include "platforms/msvc32.h" 
#elif __GNUC__ 
    #include "platforms/gcc.h" 
#else 
    #error "You must add a new clause to selectplatform.h for your platform" 
#endif 

này tránh sự cần thiết cho cấu hình biên dịch, nhưng có nhược điểm là mỗi cổng nền tảng mới có thay đổi tập tin. Nếu bạn là người duy nhất làm bất kỳ cổng nào chắc chắn không phải là vấn đề. Nếu không, một tập tin được phân chia bởi bên thứ ba. Sau đó, có thể họ thêm tệp mới vào platforms/ trong thư viện của bạn hoặc có thể họ đặt tệp của họ ở nơi khác. Vì vậy, với bên thứ ba, chỉ có có thể là không phải là vấn đề. Họ có thể đóng góp những thay đổi của họ (có thể bao gồm cả tiêu đề nền tảng của họ) ngược dòng nếu họ và cả hai đều muốn.

1

số
Thông thường bạn xác định đường dẫn đến thư mục lib của bạn bao gồm thư mục sử dụng cờ lệnh trong trình biên dịch của bạn (thường là cờ -I).

Này, nếu bạn đang sử dụng trình biên dịch GCC, và các tập tin tiêu đề của thư viện của bạn đang trong

/usr/local/include/mylibheaders 

sau đó bạn phải gọi trình biên dịch với tùy chọn sau đây:

-I/usr/local/include/mylibheader/mycurrentplatform 

nơi mycurrentplatform thư mục khác nhau cho mỗi dự án và chứa thư viện cụ thể của dự ánConfig.h

Vì vậy, bạn có thể sử dụng #include<libraryConfig.h> trong mọi dự án.

1

Đây thực sự là một câu hỏi về quản lý cấu hình so với câu hỏi C. Theo kinh nghiệm của tôi, việc sử dụng một chương trình kiểm soát phiên bản tốt là hữu ích nhất. Tìm một cái cho phép bạn xác định "dự án" bằng cách kéo mã nguồn từ nhiều vị trí khác nhau. Nhận ra rằng định nghĩa chương trình kiểm soát phiên bản của bạn về một "dự án" sau đó sẽ trở thành một yếu tố thiết yếu trong việc xây dựng dự án. Bạn cũng có thể thay đổi mã thư viện của mình cho một chi nhánh dự án và kiểm tra chúng vào hệ thống kiểm soát phiên bản của bạn nhiều lần mà không cần phải kiểm tra các thay đổi đối với vị trí thư viện chính cho đến khi các thay đổi được chứng minh kể từ chúng có thể ảnh hưởng đến nhiều dự án khác nhau.

Mô-đun thư viện của bạn cũng có thể kết thúc bằng tệp xác định các tùy chọn thư viện cho từng dự án cụ thể. Một thực tế tôi đã áp dụng là đặt tên cho các tệp giao diện _PAL.h trong đó _PAL biểu thị tệp Lớp trừu tượng dự án.

Các vấn đề liên quan