Học cách biên dịch mọi thứ từ nguồn (trên Unix / Linux / OSX)


47

Trong khi tôi cài đặt phần mềm từ các gói (MacPorts / apt-get) bất cứ khi nào có thể, tôi thường thấy mình cần phải biên dịch các gói từ nguồn. ./configure && make && sudo make installthường là đủ, nhưng đôi khi nó không hoạt động - và khi không, tôi thường xuyên bị kẹt. Điều này hầu như luôn luôn liên quan đến các phụ thuộc thư viện khác theo một cách nào đó.

Tôi muốn học như sau:

  • Làm thế nào để tôi tìm ra những đối số để vượt qua ./configure?
  • Các thư viện chia sẻ hoạt động như thế nào trong OS X / Linux - nơi chúng sống trên hệ thống tệp, cách ./configure && maketìm thấy chúng, những gì thực sự xảy ra khi chúng được liên kết với
  • Sự khác biệt thực tế giữa một thư viện chia sẻ và liên kết tĩnh là gì? Tại sao tôi không thể liên kết tĩnh mọi thứ (RAM và dung lượng ổ đĩa ngày nay rẻ) và do đó tránh xung đột phiên bản thư viện kỳ ​​lạ?
  • Làm cách nào để biết thư viện nào tôi đã cài đặt và phiên bản nào?
  • Làm cách nào tôi có thể cài đặt nhiều hơn một phiên bản của thư viện mà không phá vỡ hệ thống bình thường của tôi?
  • Nếu tôi đang cài đặt công cụ từ nguồn trên một hệ thống được quản lý bằng cách sử dụng các gói, thì cách làm sạch nhất là gì?
  • Giả sử tôi quản lý để biên dịch một cái gì đó khó khăn từ nguồn, làm thế nào tôi có thể đóng gói nó để người khác không phải nhảy qua cùng một vòng? Riêng trên OS X ....
  • Các công cụ dòng lệnh tôi cần nắm vững để có được những thứ này là gì? Những thứ như otool, pkg-config, v.v.

Tôi sẵn sàng đầu tư khá nhiều thời gian và công sức vào đây - Tôi không nhất thiết muốn có câu trả lời trực tiếp cho các câu hỏi trên, tôi muốn nhận các đề xuất về sách / hướng dẫn / Câu hỏi thường gặp mà tôi có thể đọc sẽ cung cấp cho tôi kiến thức tôi cần phải hiểu những gì đang thực sự xảy ra và từ đó tự mình tìm ra vấn đề.

Câu trả lời:


40

Tôi xin lỗi vì đã trực tiếp trả lời tất cả mọi thứ, nhưng tôi không biết bất kỳ hướng dẫn, Câu hỏi thường gặp hữu ích nào, v.v ... Về cơ bản, sau 8 năm tạo ra các ứng dụng máy tính để bàn (mà tôi giúp phân phối), sự thất vọng và googling:

1. Làm thế nào để tôi tìm ra những đối số để chuyển đến ./mình?

Thực hành thực sự. Autotools là đủ dễ dàng vì nó phù hợp. Nhưng có rất nhiều thứ ngoài kia bằng cách sử dụng cmake hoặc tập lệnh xây dựng tùy chỉnh. Nói chung, bạn không cần phải vượt qua bất cứ điều gì để cấu hình, nó sẽ tìm hiểu xem hệ thống của bạn có thể xây dựng foo-tool hay không.

Các công cụ cấu hình và GNU đều tìm trong /, / usr và / usr / local cho các phụ thuộc. Nếu bạn cài đặt bất cứ thứ gì khác (điều này làm cho mọi thứ trở nên đau đớn nếu phần phụ thuộc được cài đặt bởi MacPorts hoặc Fink), bạn sẽ phải chuyển một cờ để định cấu hình hoặc sửa đổi môi trường của shell để giúp các công cụ GNU tìm thấy các phụ thuộc này.

2. Các thư viện được chia sẻ hoạt động như thế nào trong OS X / Linux - nơi chúng sống trên hệ thống tập tin, làm thế nào ./cool && make find them, điều gì thực sự xảy ra khi chúng được liên kết với

Trên Linux, chúng cần được cài đặt vào một đường dẫn mà trình liên kết động có thể tìm thấy, điều này được xác định bởi LD_LIBRARY_PATHbiến môi trường và nội dung của /etc/ld.conf. Trên Mac, hầu hết các phần mềm nguồn mở đều giống nhau (trừ khi đó là Dự án Xcode). Ngoại trừ biến env là DYLD_LIBRARY_PATHthay thế.

Có một đường dẫn mặc định mà trình liên kết tìm kiếm các thư viện. Đó là / lib: / usr / lib: / usr / local / lib

Bạn có thể bổ sung điều này bằng cách sử dụng biến CPATH hoặc CFLAGS hoặc bất kỳ số lượng biến môi trường nào khác thực sự (rất phức tạp). Tôi đề nghị CFLAGS như vậy:

xuất CFLAGS = "$ CFLAGS -L / mới / đường dẫn"

Tham số -L thêm vào đường dẫn liên kết.

Công cụ hiện đại sử dụng công cụ pkg-config. Những thứ hiện đại bạn cài đặt cũng cài đặt một tệp .pc mô tả thư viện và vị trí của nó và cách liên kết với nó. Điều này có thể làm cho cuộc sống dễ dàng hơn. Nhưng nó không đi kèm với OS X 10.5 nên bạn cũng sẽ phải cài đặt nó. Ngoài ra rất nhiều deps cơ bản không hỗ trợ nó.

Hành động liên kết chỉ là "giải quyết chức năng này trong thời gian chạy", thực sự đó là một bảng chuỗi lớn.

3. Sự khác biệt thực tế giữa một thư viện được chia sẻ và liên kết tĩnh là gì? Tại sao tôi không thể liên kết tĩnh mọi thứ (RAM và dung lượng ổ đĩa ngày nay rẻ) và do đó tránh xung đột phiên bản thư viện kỳ ​​lạ?

Khi bạn liên kết đến một tệp thư viện tĩnh, mã sẽ trở thành một phần của ứng dụng của bạn. Nó sẽ giống như nếu có một tệp .c khổng lồ cho thư viện đó và bạn đã biên dịch nó vào ứng dụng của mình.

Các thư viện động có cùng mã, nhưng khi ứng dụng được chạy, mã được tải vào ứng dụng khi chạy (giải thích đơn giản).

Bạn có thể liên kết tĩnh với mọi thứ, tuy nhiên, thật đáng buồn là hầu như không có hệ thống xây dựng nào làm điều này dễ dàng. Bạn sẽ phải chỉnh sửa các tệp hệ thống xây dựng theo cách thủ công (ví dụ: Makefile.am hoặc CMakeLists.txt). Tuy nhiên, điều này có lẽ đáng để học hỏi nếu bạn thường xuyên cài đặt những thứ yêu cầu các phiên bản khác nhau của thư viện và bạn gặp khó khăn trong việc cài đặt song song.

Mẹo nhỏ là thay đổi dòng liên kết từ -lfoo thành -l / path / thành / static / foo.a

Bạn có thể có thể tìm và thay thế. Sau đó, kiểm tra công cụ không liên kết đến .so hoặc dylib bằng ldd foo hoặc otool -L foo

Một vấn đề khác là không phải tất cả các thư viện biên dịch thành các thư viện tĩnh. Nhiều người làm. Nhưng sau đó MacPorts hoặc Debian có thể đã quyết định không gửi nó.

4. Làm cách nào tôi có thể biết thư viện nào tôi đã cài đặt và phiên bản nào?

Nếu bạn có tệp pkg-config cho các thư viện đó thì thật dễ dàng:

pkg-config --list-all

Nếu không, bạn thường không thể dễ dàng. Các dylib có thể có một soname (ví dụ: foo.0.1.dylib, soname là 0,1) giống như phiên bản của thư viện. Tuy nhiên điều này là không bắt buộc. Soname là một tính năng tính toán nhị phân, bạn phải tìm phần chính của soname nếu bạn thay đổi định dạng của các hàm trong thư viện. Vì vậy, bạn có thể nhận được ví dụ. phiên bản 14.0.5 soname cho thư viện 2.0. Mặc dù điều này không phổ biến.

Tôi đã thất vọng với loại điều này và đã phát triển một giải pháp cho vấn đề này trên Mac, và tôi sẽ nói về nó tiếp theo.

5. Làm cách nào tôi có thể cài đặt nhiều hơn một phiên bản của thư viện mà không phá vỡ hệ thống bình thường của tôi?

Giải pháp của tôi cho vấn đề này là ở đây: http://github.com/mxcl/homebrew/

Tôi thích cài đặt từ nguồn, và muốn một công cụ làm cho nó dễ dàng, nhưng với một số quản lý gói. Vì vậy, với Homebrew tôi xây dựng, ví dụ. quên mình khỏi nguồn, nhưng đảm bảo cài đặt vào tiền tố đặc biệt:

/usr/local/Cellar/wget/1.1.4

Sau đó, tôi sử dụng công cụ homebrew để liên kết tất cả những thứ đó vào / usr / local, vì vậy tôi vẫn có / usr / local / bin / wget và /usr/local/lib/libwget.dylib

Sau này nếu tôi cần một phiên bản wget khác, tôi có thể cài đặt song song và chỉ cần thay đổi phiên bản được liên kết thành cây / usr / local.

6. Nếu tôi đang cài đặt công cụ từ nguồn trên một hệ thống được quản lý bằng các gói khác, cách làm sạch nhất là gì?

Tôi tin rằng cách Homebrew là sạch nhất, vì vậy hãy sử dụng nó hoặc làm tương đương. Cài đặt vào / usr / local / pkgs / name / version và symlink hoặc liên kết cứng phần còn lại trong.

Sử dụng / usr / địa phương. Mỗi công cụ xây dựng tồn tại tìm kiếm ở đó cho các phụ thuộc và tiêu đề. Cuộc sống của bạn sẽ dễ dàng hơn nhiều .

7. Giả sử tôi quản lý để biên dịch một cái gì đó khó khăn từ nguồn, làm thế nào tôi có thể đóng gói nó để người khác không phải nhảy qua cùng một vòng? Riêng trên OS X ....

Nếu nó không có phụ thuộc, bạn có thể mở thư mục xây dựng và đưa nó cho người khác có thể thực hiện "thực hiện cài đặt". Tuy nhiên, bạn chỉ có thể làm điều này một cách đáng tin cậy cho các phiên bản chính xác của OS X. Trên Linux, nó có thể sẽ hoạt động với Linux tương tự (ví dụ: Ubuntu) với cùng phiên bản Kernel và phiên bản nhỏ libc.

Lý do không dễ để phân phối nhị phân trên Unix là vì khả năng tương thích nhị phân. Người GNU và mọi người khác thường xuyên thay đổi giao diện nhị phân của họ.

Về cơ bản không phân phối nhị phân. Mọi thứ có thể sẽ phá vỡ theo những cách rất kỳ lạ.

Trên Mac, tùy chọn tốt nhất là tạo gói macports. Mọi người đều sử dụng macports. Trên Linux có rất nhiều hệ thống và kết hợp xây dựng khác nhau, tôi không nghĩ có lời khuyên nào tốt hơn là viết một mục blog về cách bạn đã thành công xây dựng công cụ x trong cấu hình lạ.

Nếu bạn tạo một mô tả gói (cho macports hoặc homebrew) thì bất cứ ai cũng có thể cài đặt gói đó và nó cũng giải quyết được các vấn đề phụ thuộc. Tuy nhiên, điều này thường không dễ dàng và cũng không dễ để đưa công thức macports của bạn vào cây macports chính. Ngoài ra, macports không hỗ trợ các loại cài đặt kỳ lạ, họ cung cấp một sự lựa chọn cho tất cả các gói.

Một trong những mục tiêu trong tương lai của tôi với Homebrew là làm cho nó có thể nhấp vào một liên kết trên một trang web (ví dụ: homebrew: // blah và nó sẽ tải xuống tập lệnh Ruby đó, cài đặt deps cho gói đó và sau đó xây dựng ứng dụng. chưa được thực hiện, nhưng không quá khó khăn khi xem xét thiết kế tôi đã chọn.

8. Các công cụ dòng lệnh tôi cần nắm vững để có thể làm tốt công cụ này là gì? Những thứ như otool, pkg-config, v.v.

otool thực sự chỉ hữu ích sau đó. Nó cho bạn biết những gì các liên kết nhị phân được xây dựng để. Khi bạn đang tìm ra sự phụ thuộc của một công cụ bạn phải xây dựng, nó là vô dụng. Điều tương tự cũng đúng với pkg-config vì bạn sẽ cài đặt phần phụ thuộc trước khi bạn có thể sử dụng nó.

Chuỗi công cụ của tôi là, đọc các tệp README và INSTALL và thực hiện cấu hình --help. Xem đầu ra xây dựng để kiểm tra xem nó có lành mạnh không. Phân tích bất kỳ lỗi xây dựng. Có thể trong tương lai, hãy hỏi về serverfault :)


2
Thú vị hơn, Homebrew có vẻ rất giống Portage (người quản lý gói từ Gentoo Linux). Âm thanh như một tác phẩm tốt đẹp.
David Z

12

Đây là một chủ đề lớn vì vậy hãy bắt đầu với các thư viện chia sẻ trên Linux (ELF trên Linux và Mach-O trên OS X), Ulrich Drepper đã giới thiệu tốt về cách viết DSO (đối tượng chia sẻ động) bao gồm một số lịch sử của các thư viện chia sẻ trên Linux có sẵn ở đây bao gồm cả tại sao chúng quan trọng

Ulrich cũng mô tả lý do tại sao liên kết tĩnh được coi là có hại, một trong những điểm quan trọng ở đây là cập nhật bảo mật. Bộ đệm tràn vào một thư viện chung (ví dụ zlib) được liên kết rộng rãi tĩnh có thể gây ra một chi phí rất lớn cho các bản phân phối - điều này xảy ra với zlib 1.1.3 ( tư vấn của Red Hat )

ELF

Trang hướng dẫn liên kết ld.so

man ld.so 

giải thích các đường dẫn và tệp cơ bản liên quan đến liên kết động thời gian chạy. Trên các hệ thống Linux hiện đại, bạn sẽ thấy các đường dẫn bổ sung được thêm thông qua /etc/ld.so.conf.d/ thường được thêm thông qua toàn cầu bao gồm trong /etc/ld.so.conf.

Nếu bạn muốn xem những gì có sẵn một cách linh hoạt thông qua cấu hình ld.so của bạn, bạn có thể chạy

ldconfig -v -N -X

Đọc DSO như thế nào sẽ cung cấp cho bạn một mức độ kiến ​​thức cơ bản tốt để sau đó tiếp tục hiểu cách các nguyên tắc đó áp dụng cho Mach-O trên OS X.

Bậc nam nhi

Trên OS X, định dạng nhị phân là Mach-O. Tài liệu hệ thống cục bộ cho trình liên kết là

man dyld

Các tài liệu Định dạng Mach có sẵn từ Apple

Các công cụ xây dựng UNIX

Phổ biến configure, make, make installquá trình thường được cung cấp bởi GNU autotools trong đó có một cuốn sách trực tuyến mà bìa một số lịch sử của configure / build chia và toolchain GNU. Autoconf sử dụng các bài kiểm tra để xác định tính khả dụng trên hệ thống xây dựng mục tiêu, nó sử dụng ngôn ngữ macro M4 để điều khiển việc này. Automake về cơ bản là một phương thức tạo khuôn mẫu cho Makefiles, mẫu thường được gọi là Makefile.am tạo ra Makefile.in rằng đầu ra của autoconf (tập lệnh cấu hình) chuyển đổi thành Makefile.

Các chào GNU chương trình hoạt động như một ví dụ điển hình cho sự hiểu biết toolchain GNU - và cuốn cẩm nang bao gồm tài liệu autotools.


10

Simon! Tôi hiểu cảm giác của bạn; Tôi cũng vật lộn với phần học Linux này. Dựa trên kinh nghiệm của bản thân, tôi đã viết một bài hướng dẫn về một số mục mà bạn đề cập (chủ yếu là tài liệu tham khảo cho bản thân mình!): Http://easyaspy.blogspot.com/2008/12/buildinginstalling-application-from.html . Tôi nghĩ bạn sẽ đánh giá cao lưu ý của tôi về cách xây dựng / cài đặt các ứng dụng Python đơn giản. :)

Hy vọng rằng điều này sẽ giúp! Và hạnh phúc biên dịch.

Tim Jones


Xây dựng / Cài đặt ứng dụng từ nguồn trong Ubuntu Linux

Mặc dù các kho lưu trữ Ubuntu có rất nhiều ứng dụng tuyệt vời, nhưng lúc này hay lúc khác, bạn nhất định bắt gặp công cụ "phải có" đó không có trong kho (hoặc không có gói Debian) hoặc bạn cần phiên bản mới hơn trong kho. Bạn làm nghề gì? Vâng, bạn phải xây dựng ứng dụng từ nguồn! Đừng lo lắng, nó thực sự không phức tạp như âm thanh. Dưới đây là một số lời khuyên, dựa trên kinh nghiệm của tôi về việc trở thành một người nghiệp dư hạng! (Trong khi tôi đang sử dụng Ubuntu cho ví dụ này, các khái niệm chung nên được áp dụng cho hầu hết mọi bản phân phối Unix / Linux, như Fedora, và thậm chí cả nền tảng Cygwin trên Windows.)

Quá trình cơ bản của việc xây dựng (biên dịch) hầu hết các ứng dụng từ nguồn tuân theo trình tự này: configure -> compile -> install. Các lệnh Unix / Linux điển hình để thực hiện những việc này là: config-> make-> make install. Trong một số trường hợp, bạn thậm chí sẽ tìm thấy các trang web cho thấy rằng tất cả những trang này có thể được kết hợp thành một lệnh duy nhất:

$ config && make && make install

Tất nhiên, lệnh này giả định rằng không có vấn đề trong bất kỳ bước nào trong số này. Đây là nơi niềm vui đến!

Bắt đầu

Nếu bạn chưa biên dịch một ứng dụng từ nguồn trên hệ thống của mình trước đó, có lẽ bạn sẽ cần phải thiết lập nó với một số công cụ phát triển chung, chẳng hạn như bộ gcctrình biên dịch, một số tệp tiêu đề phổ biến (hãy nghĩ rằng đây là mã đã được viết bởi người khác được sử dụng bởi chương trình bạn đang cài đặt) và công cụ make. May mắn thay, trong Ubuntu, có một siêu dữ liệu được gọi là build-essentialsẽ cài đặt cái này. Để cài đặt nó (hoặc chỉ cần đảm bảo rằng bạn đã có nó!), Hãy chạy lệnh này trong terminal:

$ sudo apt-get install build-essential

Bây giờ bạn đã có thiết lập cơ bản, tải xuống các tệp nguồn ứng dụng và lưu chúng vào một thư mục mà bạn có quyền đọc / ghi, chẳng hạn như thư mục "nhà" của bạn. Thông thường, chúng sẽ nằm trong một tệp lưu trữ có phần mở rộng tệp là .tar.gzhoặc .tar.bz2. Điều .tarđơn giản có nghĩa là đó là một "kho lưu trữ băng", đó là một nhóm các tệp bảo tồn cấu trúc thư mục tương đối của chúng. Chữ .gzviết tắt của gzip (GNU zip), là định dạng nén Unix / Linux phổ biến. Tương tự, .bz2viết tắt của bzip2, là định dạng nén mới hơn cung cấp khả năng nén cao hơn (kích thước tệp nén nhỏ hơn) so với gzip.

Sau khi bạn đã tải xuống tệp nguồn, hãy mở một cửa sổ đầu cuối (System Terminal từ menu Ubuntu) và thay đổi thư mục nơi bạn đã lưu tệp của mình. (Tôi sẽ sử dụng ~/downloadtrong ví dụ này. Ở đây, '~' là lối tắt đến thư mục "nhà" của bạn.) Sử dụng lệnh tar để trích xuất các tệp từ tệp lưu trữ đã tải xuống:

Nếu tệp của bạn là kho lưu trữ gzip (ví dụ: kết thúc bằng .tar.gz), hãy sử dụng lệnh:

            $ tar -zxvf filename.tar.gz

Nếu tệp của bạn là tệp lưu trữ bzip2 (ví dụ: kết thúc bằng .tar.bz2), hãy sử dụng lệnh:

            $ tar -jxvf filename.tar.gz

Mẹo: Nếu bạn không muốn phải nhớ tất cả các công tắc dòng lệnh để trích xuất tài liệu lưu trữ, tôi khuyên bạn nên lấy một (hoặc cả hai) các tiện ích này: dtrx (yêu thích của tôi!) Hoặc trang trí (phổ biến hơn). Với một trong hai tiện ích này, bạn chỉ cần nhập tên của tiện ích (dtrx hoặc trang trí) và tên tệp, nó sẽ thực hiện tất cả các phần còn lại. Cả hai cách "biết" này để xử lý hầu hết mọi định dạng lưu trữ mà bạn có khả năng chạy qua và chúng có khả năng xử lý lỗi rất lớn.

Khi xây dựng từ nguồn, có hai loại lỗi phổ biến mà bạn có thể gặp phải:

  1. Lỗi cấu hình xảy ra khi bạn chạy tập lệnh cấu hình (thường được đặt tên là config hoặc configure) để tạo tệp tạo tệp dành riêng cho thiết lập của bạn.
  2. Lỗi trình biên dịch xảy ra khi bạn chạy lệnh make (sau khi tệp makefile được tạo) và trình biên dịch không thể tìm thấy một số mã mà nó cần.

Chúng ta sẽ xem xét từng vấn đề và thảo luận cách giải quyết chúng.

Lỗi cấu hình và cấu hình

Sau khi bạn giải nén tệp lưu trữ mã nguồn, trong thiết bị đầu cuối, bạn nên thay đổi thư mục chứa các tệp được giải nén. Thông thường, tên thư mục này sẽ giống như tên của tệp (không có .tar.gzhoặc .tar.bz2phần mở rộng). Tuy nhiên, đôi khi tên thư mục chỉ là tên của ứng dụng, không có bất kỳ thông tin phiên bản nào.

Trong thư mục nguồn, hãy tìm một READMEtệp và / hoặc một INSTALLtệp (hoặc một cái gì đó có tên tương tự). Các tệp này thường chứa thông tin hữu ích về cách xây dựng / biên dịch ứng dụng và cài đặt ứng dụng, bao gồm thông tin về các phụ thuộc. "Phụ thuộc" chỉ là một tên ưa thích cho các thành phần hoặc thư viện khác được yêu cầu để biên dịch thành công.

Sau khi bạn đã đọc READMEvà / hoặc INSTALLtệp (và, hy vọng xem bất kỳ tài liệu trực tuyến có liên quan nào cho ứng dụng), hãy tìm tệp thực thi (có quyền "x" được đặt trên tệp) có tên confighoặc configure. Đôi khi tệp có thể có phần mở rộng, chẳng hạn như .sh(ví dụ config.sh:). Đây thường là tập lệnh shell chạy một số tiện ích khác để xác nhận rằng bạn có môi trường "lành mạnh" để biên dịch. Nói cách khác, nó sẽ kiểm tra để đảm bảo rằng bạn đã cài đặt mọi thứ mà bạn cần.

Mẹo: Nếu đây là một ứng dụng dựa trên Python, thay vì tệp cấu hình, bạn nên tìm một tệp có tên setup.py. Các ứng dụng Python thường rất đơn giản để cài đặt. Để cài đặt ứng dụng này, với quyền root (ví dụ: đặt sudo trước lệnh sau trong Ubuntu), hãy chạy lệnh này:

    $ python setup.py install

Đó nên là tất cả những gì bạn cần làm. Bạn có thể bỏ qua phần còn lại của hướng dẫn này và trực tiếp sử dụng và thưởng thức ứng dụng của bạn.

Chạy tập lệnh cấu hình trong thiết bị đầu cuối. Thông thường, bạn có thể (và nên!) Chạy tập lệnh cấu hình bằng tài khoản người dùng thông thường của bạn.

$ ./config

Kịch bản sẽ hiển thị một số thông báo để cho bạn biết về những gì nó đang làm. Thông thường, tập lệnh sẽ cung cấp cho bạn một dấu hiệu cho biết nó đã thành công hay thất bại và nếu thất bại, một số thông tin về nguyên nhân của sự thất bại. Nếu bạn không nhận được bất kỳ thông báo lỗi nào, thì bạn thường có thể cho rằng mọi thứ đều ổn.

Nếu bạn không tìm thấy bất kỳ tập lệnh nào trông giống như tập lệnh cấu hình, thì điều đó thường có nghĩa là ứng dụng này rất đơn giản và nó độc lập với nền tảng. Điều này có nghĩa là bạn có thể chỉ cần bỏ qua bước xây dựng / biên dịch bên dưới, vì được cung cấp Makefilesẽ hoạt động trên bất kỳ hệ thống nào.

Một ví dụ

Trong hướng dẫn này, tôi sẽ sử dụng trình đọc RSS dựa trên văn bản có tên Newsbeuter làm ví dụ cho các loại lỗi mà bạn có thể gặp phải khi xây dựng ứng dụng của mình. Đối với Newsbeuter, tên của tập lệnh cấu hình là config.sh. Trên hệ thống của tôi, khi tôi chạy config.sh, xảy ra các lỗi sau:

tester@sitlabcpu22:~/download/newsbeuter-1.3$ ./config.sh
Checking for package sqlite3... not found

You need package sqlite3 in order to compile this program.
Please make sure it is installed.

Khi thực hiện một số nghiên cứu, tôi thấy rằng, trên thực tế, sqlite3ứng dụng đã được cài đặt. Tuy nhiên, vì tôi đang cố gắng xây dựng từ nguồn, đây là một mẹo mà những gì config.shthực sự tìm kiếm là các thư viện phát triển (tiêu đề) sqlite3. Trong Ubuntu, hầu hết các gói đều có gói đối tác phát triển liên quan kết thúc bằng -dev. (Các nền tảng khác, chẳng hạn như Fedora, thường sử dụng hậu tố gói -develcho các gói phát triển.)

Để tìm gói thích hợp cho gói sqlite3phát triển, chúng ta có thể sử dụng apt-cachetiện ích trong Ubuntu (và tương tự, yumtiện ích trong Fedora):

tester@sitlabcpu22:~/download/newsbeuter-1.3$ sudo apt-cache search sqlite

Lệnh này trả về một danh sách khá lớn các kết quả, vì vậy chúng tôi phải thực hiện một chút công việc thám tử để xác định gói nào là phù hợp. Trong trường hợp này, gói thích hợp hóa ra là libsqlite3-dev. Lưu ý rằng đôi khi gói chúng tôi đang tìm kiếm sẽ có libtiền tố, thay vì chỉ có cùng tên gói -dev. Điều này là do đôi khi chúng ta chỉ tìm kiếm một thư viện chia sẻ có thể được sử dụng bởi nhiều ứng dụng khác nhau. Để cài đặt libsqlite3-dev, hãy chạy lệnh cài đặt apt-get điển hình trong thiết bị đầu cuối:

tester@sitlabcpu22:~/download/newsbeuter-1.3$ sudo apt-get install libsqlite3-dev

Bây giờ, chúng tôi phải chạy config.shlại để đảm bảo rằng chúng tôi đã giải quyết vấn đề phụ thuộc này và chúng tôi không có bất kỳ vấn đề phụ thuộc nào nữa. (Mặc dù tôi sẽ không hiển thị ở đây, nhưng trong trường hợp của Newsbeuter, tôi cũng phải cài đặt libcurl4-openssl-devgói.) Ngoài ra, nếu bạn cài đặt gói phát triển (như libsqlite3-dev) và gói ứng dụng liên quan (ví dụ sqlite3:) thì không đã được cài đặt, hầu hết các hệ thống sẽ tự động cài đặt gói ứng dụng liên quan cùng một lúc.

Khi cấu hình chạy thành công, kết quả sẽ là nó sẽ tạo một hoặc nhiều tệp tạo. Các tệp này thường được đặt tên Makefile(hãy nhớ rằng trường hợp tên tệp có vấn đề trong Unix / Linux!). Nếu gói xây dựng bao gồm các thư mục con, chẳng hạn như src, v.v., thì mỗi thư mục con này cũng sẽ chứa một Makefile.

Lỗi xây dựng và biên dịch

Bây giờ, chúng tôi đã sẵn sàng để thực sự biên dịch ứng dụng. Điều này thường được gọi là xây dựng và tên được mượn từ quá trình xây dựng một cái gì đó trong thế giới thực. Các "mảnh" khác nhau của ứng dụng, thường là nhiều tệp mã nguồn, được kết hợp với nhau để tạo thành ứng dụng tổng thể. Tiện ích make quản lý quá trình xây dựng và gọi các ứng dụng khác, chẳng hạn như trình biên dịch và trình liên kết, để thực sự làm việc. Trong hầu hết các trường hợp, bạn chỉ cần chạy make (với tài khoản người dùng thông thường) từ thư mục nơi bạn chạy cấu hình. (Trong một số trường hợp, chẳng hạn như biên dịch các ứng dụng được viết bằng thư viện Qt, bạn sẽ cần chạy một ứng dụng "trình bao bọc" khác như qmake. Một lần nữa, luôn luôn kiểm tra READMEvà / hoặc INSTALLtài liệu để biết chi tiết.)

Như với tập lệnh cấu hình ở trên, khi bạn chạy make (hoặc tiện ích tương tự) trong thiết bị đầu cuối, nó sẽ hiển thị một số thông báo về những gì đang thực thi và bất kỳ cảnh báo và lỗi nào. Bạn thường có thể bỏ qua các cảnh báo, vì chúng chủ yếu dành cho các nhà phát triển ứng dụng và đang nói với họ rằng có một số thực tiễn tiêu chuẩn đang bị vi phạm. Thông thường, những cảnh báo này không ảnh hưởng đến chức năng ứng dụng. Mặt khác, các lỗi biên dịch phải được xử lý. Với Newsbeuter, khi tôi thực hiện, mọi thứ đã ổn trong một thời gian, nhưng sau đó tôi đã gặp một lỗi:

tester@sitlabcpu22:~/download/newsbeuter-1.3$ make
...
c++ -ggdb -I/sw/include -I./include -I./stfl -I./filter -I. -I./xmlrss -Wall -Wextra -DLOCALEDIR=\"/usr/local/share/locale\" -o src/configparser.o -c src/configparser.cpp
c++ -ggdb -I/sw/include -I./include -I./stfl -I./filter -I. -I./xmlrss -Wall -Wextra -DLOCALEDIR=\"/usr/local/share/locale\" -o src/colormanager.o -c src/colormanager.cpp
In file included from ./include/pb_view.h:5,
from src/colormanager.cpp:4:
./include/stflpp.h:5:18: error: stfl.h: No such file or directory
In file included from ./include/pb_view.h:5,
from src/colormanager.cpp:4:
./include/stflpp.h:33: error: ISO C++ forbids declaration of \u2018stfl_form\u2019 with no type
./include/stflpp.h:33: error: expected \u2018;\u2019 before \u2018*\u2019 token
./include/stflpp.h:34: error: ISO C++ forbids declaration of \u2018stfl_ipool\u2019 with no type
./include/stflpp.h:34: error: expected \u2018;\u2019 before \u2018*\u2019 token
make: *** [src/colormanager.o] Error 1

Quá trình thực hiện sẽ dừng lại ngay khi gặp lỗi đầu tiên. Xử lý lỗi trình biên dịch đôi khi có thể là khó khăn kinh doanh. Bạn phải xem xét các lỗi cho một số manh mối về vấn đề. Thông thường, vấn đề là một số tệp tiêu đề, thường có phần mở rộng .hhoặc .hpp, bị thiếu. Trong trường hợp lỗi ở trên, rõ ràng (hoặc nên là!) Rõ ràng rằng vấn đề là stfl.htệp tiêu đề không thể được tìm thấy. Như ví dụ này cho thấy, bạn muốn xem các dòng đầu tiên của thông báo lỗi và tìm cách tìm ra nguyên nhân cơ bản của vấn đề.

Sau khi xem tài liệu Newsbeuter (mà tôi nên làm trước khi bắt đầu, nhưng sau đó phần này của hướng dẫn sẽ không có ý nghĩa lắm!), Tôi thấy rằng nó yêu cầu một thư viện của bên thứ 3 có tên là STFL. Vậy chúng ta phải làm gì trong trường hợp này? Vâng, về cơ bản, chúng tôi lặp lại quy trình chính xác này cho thư viện cần thiết đó: lấy thư viện và thực hiện quy trình configure-build-install cho nó và sau đó, tiếp tục xây dựng ứng dụng mong muốn. Ví dụ, trong trường hợp STFL, tôi đã phải cài đặt libncursesw5-devgói cho nó để xây dựng đúng. (Thông thường, không cần thiết phải làm lại bước cấu hình trên ứng dụng gốc của chúng tôi sau khi cài đặt một ứng dụng bắt buộc khác, nhưng nó cũng không bao giờ bị tổn thương.)

Sau khi cài đặt thành công bộ công cụ STFL, quá trình tạo cho Newsbeuter đã chạy thành công. Quá trình thực hiện thường diễn ra ở nơi nó rời đi (tại điểm xảy ra lỗi). Do đó, bất kỳ tệp nào đã được biên dịch thành công sẽ không được biên dịch lại. Nếu bạn muốn biên dịch lại mọi thứ, bạn có thể chạy make make all để xóa mọi đối tượng đã biên dịch và sau đó chạy make make.

Cài đặt

Sau khi quá trình xây dựng hoàn tất thành công, bạn đã sẵn sàng để cài đặt ứng dụng. Trong hầu hết các trường hợp, để cài đặt ứng dụng vào các khu vực chung của hệ thống tệp (ví dụ: /usr/binhoặc /usr/share/bin, v.v.), bạn sẽ cần chạy cài đặt dưới dạng root. Cài đặt thực sự là bước đơn giản nhất trong toàn bộ quá trình. Để cài đặt, trong thiết bị đầu cuối chạy:

$ make install

Kiểm tra đầu ra của quá trình này cho bất kỳ lỗi. Nếu mọi thứ đã thành công, bạn sẽ có thể chạy tên lệnh trong thiết bị đầu cuối và nó sẽ khởi chạy. (Nối và vào cuối dòng lệnh, nếu đó là ứng dụng GUI hoặc bạn sẽ không thể sử dụng phiên cuối cho đến khi ứng dụng kết thúc chạy.)

Khi bạn xây dựng một ứng dụng từ nguồn, nó thường sẽ không thêm biểu tượng hoặc lối tắt vào các menu GUI trong Ubuntu. Bạn sẽ cần phải thêm nó bằng tay.

Và về cơ bản, đó là quá trình, mặc dù có khả năng lặp lại, để xây dựng và cài đặt một ứng dụng từ nguồn trong Ubuntu. Sau khi bạn thực hiện điều này chỉ một vài lần, nó sẽ trở thành bản chất thứ hai đối với bạn!


Tim, tôi muốn đọc hướng dẫn của bạn, nhưng liên kết bạn đã đăng không hoạt động.
gareth_bowles

6

Chà, ./mình - trợ giúp sẽ cung cấp cho bạn rất nhiều thông tin, đối với các tệp tự động GNU được tạo cấu hình. Hầu hết trong số đó được chuyển đến - với / mà không bật các tính năng (những tính năng này có thể cần thêm một tham số, như "chia sẻ" để nói nơi tìm thư viện).

Những cái quan trọng khác là --prefix (mặc định là / usr / local / hầu hết thời gian) để nói nơi cài đặt (nếu bạn đang xây dựng các gói bạn thường muốn cái này là --prefix = / usr hoặc có thể --prefix = / opt / YourPackage).

Trên Linux, / lib, / usr / lib và / usr / local / lib thường được tìm kiếm gcc của tôi và được bao gồm trong cấu hình mặc định của ldconfig. Trừ khi bạn có một lý do chính đáng, đây là nơi bạn muốn thư viện của mình. /etc/ld.so.conf có thể liệt kê các mục nhập thêm, tuy nhiên.

cấu hình và thực hiện tìm chúng bằng cách chỉ chạy "gcc -l" và xem nếu nó bị lỗi. Bạn có thể thêm "-L" vào tham số CFLAGS của mình để thêm đường dẫn bổ sung vào tìm kiếm.

Bạn có thể cài đặt nhiều phiên bản và phần mềm được liên kết với phiên bản cũ hơn sẽ được liên kết với nó (chạy ldd để tìm ra ràng buộc trên Linux), nhưng các trình biên dịch mới thường nhắm mục tiêu phiên bản mới nhất của thư viện động trên hệ thống của bạn.

Hầu hết các phần mềm giả định libs động, đặc biệt là nếu nó sử dụng libtool, vì vậy bạn có thể thấy các ứng dụng không tầm thường không xây dựng chính xác tĩnh.

ls -l là đặt cược tốt nhất của bạn để tìm các thư viện được cài đặt.

Và đó là nơi tôi hết thông tin; Làm thế nào để chơi tốt với các gói: không biết. Khi có thể, tôi cố gắng và gói mọi thứ vào một gói để tránh vấn đề.


4

"Làm thế nào để tôi tìm ra những đối số để chuyển đến ./mình?"

thường là: ./mình - trợ giúp sẽ cho bạn biết những gì bạn muốn ở đó.

"Làm cách nào tôi có thể biết thư viện nào tôi đã cài đặt và phiên bản nào?"

Điều đó phụ thuộc vào hệ thống. Một cách là chỉ làm một find /|grep libname|lesstệp thư viện nói chung có phiên bản trong tên tệp.

"Làm thế nào tôi có thể cài đặt nhiều hơn một phiên bản của thư viện mà không phá vỡ hệ thống bình thường của tôi?"

Một lần nữa, phụ thuộc vào hệ thống và thư viện. sudo make altinstallsẽ tạo một tên phiên bản cho bạn. Các tập tin thư viện thường phiên bản mặc dù. Hãy ghi nhớ tuy nhiên; vì các phiên bản thường tạo liên kết tượng trưng cho một tên "bình thường hóa" nên điều này có thể phá vỡ mọi thứ.

"Nếu tôi đang cài đặt công cụ từ nguồn trên một hệ thống được quản lý bằng cách sử dụng các gói, thì cách làm sạch nhất là gì?"

Sử dụng các tham số --prefix trong ./mình và đặt chúng ở đâu đó /optlà một cách tốt để làm theo.

Tuyên bố miễn trừ trách nhiệm: Tôi không có nghĩa là một chuyên gia, nhưng tôi đã sử dụng linux trong hơn 5 năm từ dòng cmd (slackware, CentOS, redhat, ubfox, misc other và OS X).


4

Để trả lời một chút câu hỏi của bạn, tôi đã tìm thấy một cách hay vào ngày khác để xem thư viện nào bạn đã cài đặt và các phiên bản (Đây là trên Linux Debian vì vậy cũng sẽ hoạt động với các phiên bản khác).

dpkg --list

Bạn sẽ nhận được một danh sách thực sự dài với một số đầu ra như thế này

ii  libssl0.9.8    0.9.8c-4etch5  SSL shared libraries
ii  libssp0        4.1.1-21       GCC stack smashing protection library
ii  libstdc++5     3.3.6-15       The GNU Standard C++ Library v3
ii  libstdc++5-3.3 3.3.6-15       The GNU Standard C++ Library v3 (development
ii  libstdc++6     4.1.1-21       The GNU Standard C++ Library v3

4

Simon,

1.) ./mình - trợ giúp cung cấp một lượng thông tin tốt. Tôi đề nghị kiểm tra nó ra. Nó thường có các tùy chọn để biên dịch các thư viện liên kết tĩnh / động khi thích hợp.

2.) Libaries sống trong đường dẫn liên kết động. Điều này thường được đặt trong /etc/ld.so.conf. Trình liên kết tìm kiếm các thư viện thích hợp giống như biến môi trường PATH khớp với biến đầu tiên được tìm thấy.

3.) Điều đó thường dẫn đến các vấn đề khi bạn phải biên dịch lại mọi thứ khi phiên bản thư viện thay đổi. Nếu bạn thực hiện một số tìm kiếm, có lẽ bạn sẽ tìm thấy vô số lý do tại sao liên kết tĩnh là một ý tưởng tồi. Tôi đã không làm điều đó trong một thời gian dài, tôi không thể thực sự xây dựng ở đây.

4.) Đây là một chút khó khăn. Bạn cần kiểm tra đường dẫn thư viện của mình để đảm bảo chắc chắn. Các thư viện thường có một liên kết tượng trưng đến phiên bản được cài đặt.

ví dụ: libssh2.so.1 -> libssh2.so.1.0.0

Nói chung, mọi người quản lý các thư viện và chương trình họ cài đặt bằng cách cuộn các gói debian của riêng họ hoặc sử dụng một số kỹ thuật khác. Tôi quản lý phần mềm đã cài đặt bằng stow ( http://www.gnu.org/software/stow/ ) rất đơn giản và cài đặt thư viện bằng các liên kết tượng trưng. Tôi thấy dễ dàng hơn vì tôi không phải xây dựng / cài đặt / kiểm tra gói deb / rpm.

5.) Nhiều phiên bản của thư viện có thể được cài đặt bình thường trong các thư mục thư viện. Các thư viện được liên kết với các tệp thực thi sẽ được liên kết với các phiên bản mà chúng được liên kết với. chạy ldd trên một tệp thực thi sẽ cho bạn biết các thư viện mà tệp thực thi được liên kết đến.

6.) Giống như tôi đã đề cập trước đó, cuộn các gói debian của riêng bạn hoặc sử dụng stow có lẽ là giải pháp sạch nhất.

7.) Tôi thực sự không thể nói cho Mac OSX nhưng đối với Linux, hệ thống đóng gói của bản phân phối là cách tốt nhất.

8.) Có lẽ rất nhiều sự thất vọng sẽ được giải quyết bằng cách sử dụng ldd và tìm ra phiên bản nào đó được liên kết với hoặc thư viện nào được liên kết với một tệp thực thi không thể được tìm thấy. pkg-config sẽ giúp bạn rất nhiều nhưng chỉ dành cho phần mềm sử dụng nó. Nó không phải là một phần của hệ thống xây dựng tự động mặc định mặc dù nó phổ biến ngày nay.


4

Thư viện tĩnh không phải là một ý tưởng hay - nếu bạn cần nâng cấp thư viện (ví dụ để khắc phục vấn đề bảo mật), bạn sẽ cần biên dịch lại mọi thứ với sự phụ thuộc vào thư viện đó.

Tôi không thích ý tưởng "thực hiện cài đặt" có khả năng gây rối cho hệ thống của mình, nhưng như những người khác đã nói, việc cài đặt mọi thứ trong / usr / local thay vì sử dụng --prefix để cài đặt ở nơi khác sẽ ít đau đớn hơn. Vì vậy, tôi đã chọn / usr / local cho người dùng thông thường (không có đặc quyền) của mình. Bằng cách đó, "thực hiện cài đặt" được đảm bảo khá nhiều để không gây rối với các tệp hệ thống quan trọng. (Điều này rõ ràng sẽ không hoạt động trên các hệ thống nhiều người dùng. Mặc dù vậy, nó rất tuyệt cho các máy chủ ảo.)


4

Mặc dù nó không rõ ràng trong danh sách câu hỏi của bạn, bạn đề cập đến trong lời nói đầu của bạn:

./configure && make && sudo make install thường là đủ, nhưng đôi khi nó không hoạt động - và khi không, tôi thường xuyên bị kẹt.

Khi tôi gặp khó khăn trên Debian hoặc Ubuntu, tôi sẽ sử dụng auto-apt để tự động cài đặt các gói có chứa các tệp mà cấu hình không thể tìm thấy.

Xem:

Một công cụ khác mà bạn có thể thấy tiện dụng là CheckInstall, nó bổ sung các ứng dụng được cài đặt make installvào danh sách các gói đã cài đặt của bạn: https : //help.ub Ubuntu.com/community/CheckInstall


3

Đối với hệ điều hành X:

  • Làm thế nào để tôi tìm ra những đối số để chuyển đến ./mình?

./mình - trợ giúp

  • Sự khác biệt thực tế giữa một thư viện chia sẻ và liên kết tĩnh là gì? Tại sao tôi không thể liên kết tĩnh mọi thứ (RAM và dung lượng ổ đĩa ngày nay rẻ) và do đó tránh xung đột phiên bản thư viện kỳ ​​lạ?

Sử dụng các thư viện dùng chung cho phép bạn nâng cấp thư viện mà không cần biên dịch lại mọi thứ sử dụng nó.

  • Các thư viện được chia sẻ hoạt động như thế nào trong OS X / Linux - nơi chúng sống trên hệ thống tập tin, làm thế nào ./cool && tạo ra chúng, những gì thực sự xảy ra khi chúng được liên kết với

Thư viện hệ thống sống trong / usr / lib.

Các thư viện bạn tự biên dịch trực tiếp trong / usr / local / lib (/ usr / local là cờ --prefix mặc định cho ./cool).

Các biến môi trường DUY NHẤT

  • Làm cách nào tôi có thể cài đặt nhiều hơn một phiên bản của thư viện mà không phá vỡ hệ thống bình thường của tôi?

Cài đặt mọi thứ vào / usr / local - với các biến môi trường ở trên, phiên bản trong / usr / local / lib được ưu tiên hơn phiên bản trong / usr / lib trong môi trường của bạn.

  • Nếu tôi đang cài đặt công cụ từ nguồn trên một hệ thống được quản lý bằng cách sử dụng các gói, thì cách làm sạch nhất là gì?

Cài đặt vào / usr / cục bộ. Trong Ubuntu, tôi thử và sử dụng checkinstall trước để tạo gói deb.

  • Giả sử tôi quản lý để biên dịch một cái gì đó khó khăn từ nguồn, làm thế nào tôi có thể đóng gói nó để người khác không phải nhảy qua cùng một vòng? Riêng trên OS X ....

Tài liệu về các bước biên dịch trong một bài đăng trên blog, tôi muốn nói.

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.