2017-01-10 26 views
5

Tôi được giao nhiệm vụ di chuyển một mã dựa trên C++ cổ, từ môi trường Unix sang Linux. Dự án được tạo thành từ nhiều Makefiles, cho các "mô-đun" khác nhau của thư viện. Tôi đã giải quyết được một số vấn đề, tuy nhiên hiện tại có vấn đề với chỉ thị bao gồm.Makefile Bao gồm chỉ thị khi di chuyển từ Unix sang Linux

Rõ ràng, cách Makefiles được xây dựng, là có riêng biệt bao gồm chỉ thị, cho các tệp khác nhau và hoạt động trong nhiều năm trong máy chủ Unix.

Ví dụ:

include ../../../../util/genmake.def 

processControl.slOBJS = processControl.o 
outputControlOBJS = outputControl.o 
inputControlOBJS = inputControl.o 
cleanList = *.o *.C *.out processControl.sl outputControl inputControl 

all: processControl.sl outputControl inputControl 

processControl.sl: $(processControl.slOBJS) 
     include ../../../../util/genmake.slinc 

outputControl: $(outputControlOBJS) 
     include ../../../../util/genmake.exeinc 

inputControl: $(inputControlOBJS) 
     include ../../../../util/genmake.exeinc 

include ../../../../util/genmake.inc 

Bạn có thể thấy ở đây, bao gồm tab, chỉ đề cập đến các chỉ tiêu quy định! Chúng là một phần của công thức cho mục tiêu đó.

Tuy nhiên, cấu trúc này là không làm việc trong Linux, tôi nhận được lỗi này:

include ../../../../util/genmake.slinc 
make: include: Command not found 
make: *** [processControl.sl] Error 127 

Rõ ràng là tôi không thể chỉ loại bỏ các tab, vì bao gồm nên chỉ dành cho mục tiêu đó ...

Vì vậy, tôi đã cố gắng để thay thế nó bằng lệnh shell 'nguồn' nguồn tập tin bao gồm như:

 source ../../../../util/genmake.slinc 

doesnt làm việc này rõ ràng, và tôi cũng đã cố gắng để mang lại trong bao gồm c ode trực tiếp vào tệp include (bình luận ra lệnh include) - điều này xử lý các lỗi liên quan đến Makefile, nhưng đây không phải là giải pháp tốt, vì sẽ rất khó di chuyển và duy trì nó, phải lặp lại cùng một mã trên dự án vào tất cả các mô-đun, và sau đó tất nhiên mọi thay đổi nhỏ bé tôi sẽ phải phản ánh trên tất cả các tệp.

Chuyên gia Make có thể tư vấn cho bạn về vấn đề này không? Ngoài ra, thường có bất kỳ lời khuyên nào về cách tốt nhất để tiếp cận tác vụ di chuyển này, sẽ được hoan nghênh :)

Cảm ơn!

Edit- Thông tin thêm: Nội dung genmake.slinc:


####################################################################### 
## This include will inherit the target and dependent files in 
## a make file that inlcudes it. 
## The inclusion of this file should look like: 
## 
## {target}: {dependent file list} 
## include genmake.slinc 
## 
####################################################################### 
     @echo "----------------------------------------------------------------" 
     @echo " (G) Creating shared library [email protected] from $($(MaKeObJs:x=$(@)OBJS))"; 
     @echo "----------------------------------------------------------------" 
     @echo "$(CPP) -b -o [email protected] $($(MaKeObJs:x=$(@)OBJS))" 
     @$(CPP) -b -o [email protected] $($(MaKeObJs:x=$(@)OBJS)) 
     @echo " Moving shared library to $(SHLIBINSTALL) as lib$(@)" 
     @$(MV) [email protected] $(SHLIBINSTALL)/lib$(@) 
     @echo "----------------------------------------------------------------" 

Đó là những tab trước @.

Bây giờ nội dung của genmake.exeinc:


####################################################################### 
## This include will inherit the target and dependent files in 
## a make file that inlcudes it. 
## The inclusion of this file should look like: 
## 
## {target}: {dependent file list} 
## include /opt/app/fba/util/genmake.exeinc 
## 
####################################################################### 
     @cp $(SHLIBINSTALL)/* $(TEMP_SHLIB_DIR)/. 
     @echo "----------------------------------------------------------------" 
     @echo " (G) Linking $($(MaKeObJs:x=$(@)OBJS)) to make [email protected] " 
     @echo "  LDOPTS set to: $(LDOPTS)" 
#  @echo " $(PURIFY) $(LD) " 
     @echo " SHLIB Temp Path: $(TEMP_SHLIB_DIR) 
     @echo "  FBA libraries: $(FBALIB)" 
     @echo "  Application libraries: $(APPLIBS)" 
     $(PURIFY) $(LD) -o [email protected] $($(MaKeObJs:x=$(@)OBJS)) \ 
       $(CXXOPTS) \ 
       $(LDFLAGS) \ 
       $(FBALIB) \ 
       $(PROLDLIBS) \ 
       `cat /usr/local/opt/oracle/product/t1c3d771/lib/ldflags` \ 
       `cat /usr/local/opt/oracle/product/t1c3d771/lib/sysliblist` \ 
       $(APPLIBS) 
     @echo " Moving executable to $(EXEINSTALL) " 
     @$(MV) [email protected] $(EXEINSTALL) 
     @echo "----------------------------------------------------------------" 

Nếu tôi đi đến các Makefile, và loại bỏ các tab hàng đầu trên bao gồm, tôi nhận được lỗi này: ../ .. /../../util/genmake.slinc:10: lệnh *** bắt đầu trước mục tiêu đầu tiên. Dừng lại.

+0

@DOUG Nếu tab bị xóa, phần bao gồm không còn là một phần của công thức. –

+0

Từ GNU Tạo: "Không gian được cho phép và bỏ qua ở đầu dòng, nhưng ký tự đầu tiên không được là tab (hoặc giá trị của .RECIPEPREFIX) —nếu dòng bắt đầu bằng tab, nó sẽ được coi là Khoảng trắng là bắt buộc giữa bao gồm và tên tệp và giữa các tên tệp, khoảng trắng thừa được bỏ qua ở đó và ở cuối chỉ thị. tên chứa bất kỳ tham chiếu biến hoặc hàm nào, chúng được mở rộng. Xem Cách sử dụng các biến. "Có lẽ Make đã thay đổi? –

+0

Nếu thực sự thay đổi từ UNIX sang Linux, làm thế nào để bạn đề xuất rằng tôi giải quyết vấn đề này của nhiều khác nhau bao gồm cho mỗi mục tiêu trong một tập tin thực hiện? Cũng sẽ rất hay khi biết chính xác những gì tạo ra phiên bản hành vi này đã được thay đổi, vì nó giống như một bước lùi từ một tính năng nâng cao hơn. – Carmageddon

Trả lời

0

Chỉ cần thêm mục tiêu vào bao gồm như là một biến: Ví dụ, genmake.exeinc sẽ trở thành:

$(targetControl): $(depControlOBJS) 
    @cp $(SHLIBINSTALL)/* $(TEMP_SHLIB_DIR)/. 
    @echo "----------------------------------------------------------------" 
    @echo " (G) Linking $($(MaKeObJs:x=$(@)OBJS)) to make [email protected] " 
    @echo "  LDOPTS set to: $(LDOPTS)" 
# @echo " $(PURIFY) $(LD) " 
    @echo " SHLIB Temp Path: $(TEMP_SHLIB_DIR) 
    @echo "  FBA libraries: $(FBALIB)" 
    @echo "  Application libraries: $(APPLIBS)" 
    $(PURIFY) $(LD) -o [email protected] $($(MaKeObJs:x=$(@)OBJS)) \ 
      $(CXXOPTS) \ 
      $(LDFLAGS) \ 
      $(FBALIB) \ 
      $(PROLDLIBS) \ 
      `cat /usr/local/opt/oracle/product/t1c3d771/lib/ldflags` \ 
      `cat /usr/local/opt/oracle/product/t1c3d771/lib/sysliblist` \ 
      $(APPLIBS) 
    @echo " Moving executable to $(EXEINSTALL) " 
    @$(MV) [email protected] $(EXEINSTALL) 
    @echo "----------------------------------------------------------------" 

Và sau đó sửa đổi các bộ phận liên quan của makefile của bạn như sau:

#outputControl: $(outputControlOBJS) 
targetControl=outputControl 
depControlOBJS=$(outputControlOBJS) 
include ../../../../util/genmake.exeinc 

#inputControl: $(inputControlOBJS) 
targetControl=inputControl 
depControlOBJS=$(inputControlOBJS) 
include ../../../../util/genmake.exeinc 
+0

Giải pháp tuyệt vời! cảm ơn bạn! Mặc dù các giải pháp awk khác là thông minh, nó không thanh lịch, sau khi tất cả ... – Carmageddon

1

Ý tưởng của tôi về việc cho phép gnumake làm tất cả xử lý được chứng minh là sai.Sự khác biệt có liên quan giữa HP-UX 11i Phiên bản 1 và xây dựng Linux mới nhất như sau:

  • TAB trước include đã âm thầm bỏ qua; bây giờ nó được hiểu là tiền tố công thức, và gnu làm cho cố gắng tìm bao gồm thực thi trên máy của bạn.

  • include trong gnu làm âm thầm bổ sung thêm một dòng trống để đầu ra sáp nhập resets các công thức trên ranh giới của mỗi bao gồm tập tin (như MadScientist một cách chính xác chỉ ra), do đó bao gồm tập tin không thể bao gồm các báo cáo công thức chỉ có.

Nếu các tập tin bao gồm không sử dụng các thủ thuật tương tự đệ quy (và trong ví dụ của bạn họ dường như là hành động đơn giản, không có thêm bao gồm báo cáo), bạn có thể sử dụng awk để chuẩn bị sáp nhập Makefile trên bay như thế này:

awk '{ if (NF == 2 && $1 == "include") { while ((getline line < $2) > 0) print line ; close($2) } else print }' Makefile | make -f - 

Đoạn mã trên sẽ xử lý các tệp như trên hệ thống của bạn, không cần chỉnh sửa.

+0

Tôi nghĩ rằng tôi hiểu bây giờ, nó chạy ở dòng lệnh. Nó cung cấp cho các lỗi sau đây: make:/dev/stdin: Không có thiết bị hoặc địa chỉ như vậy thực hiện: *** Không có mục tiêu. Dừng lại. – Carmageddon

+0

Tôi đã thử nghiệm bằng cách điều khiển bằng tay theo cách thủ công vào temp tạo ra tệp và sau đó sử dụng make -f để kiểm tra - nó hoạt động! (rơi vào các lỗi khác, nhưng đó là bên cạnh điểm) - cảm ơn! Chỉ cần giải quyết lỗi stdin ... – Carmageddon

+0

Ngoài ra, tôi muốn tìm hiểu cách bạn gỡ lỗi để đạt được kết luận này: "bao gồm trong gnu tự động thêm dòng trống vào đầu ra đã hợp nhất" – Carmageddon

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