2011-11-25 27 views
11

Tôi có một C-Programm đơn giản (1 tệp nguồn) mà tôi muốn biên dịch trên Linux và trên Windows thông qua make resp. nmake. Có một khả năng để thực hiện điều này với một makefile duy nhất?Sử dụng cùng một makefile để tạo (Linux) và nmake (Windows)

Tôi nghĩ về một cái gì đó giống như

ifeq($(MAKE), nmake) 
    // nmake code here 
else 
    // make code here 
endif 

Thật không may nmake không dường như hiểu ifeq, vì vậy tôi không thể sử dụng. Tôi có một makefile làm việc nhưng điều đó tạo ra kết quả rất xấu xí:

hello: hello.c 
    $(CC) hello.c 

Điều đó hoạt động trên cả hai hệ thống. Vấn đề là kết quả phụ thuộc vào các hành vi mặc định của các trình biên dịch tương ứng. Trong Linux, tôi nhận được một tập tin thực thi có tên 'a.out' thay vì 'hello'. Dưới Windows tôi nhận được 'hello.exe' nhưng cũng có 'hello.obj' mà tôi không muốn có.

Có ai biết cách khác không? Hoặc là những gì tôi đang cố gắng hoàn toàn không thể?

+1

Bạn có thể xây dựng hoặc nhận GNU thực hiện trên hệ thống Windows của bạn. –

+7

Đối với các dự án nền tảng chéo, tôi có thể giới thiệu cmake (http://www.cmake.org). –

+0

Tôi đã đọc về cmake. Nhưng tôi cần điều đó cho một bài tập ở trường đại học nơi mà chúng ta phải sử dụng nmake. – j0ker

Trả lời

9

Nó có lẽ không phải là không thể, nhưng rất có thể khó khăn như vậy sẽ dễ dàng hơn để viết hai makefiles anyway.

Cả hai GNU tạo (được sử dụng trong Linux) và nmake đều bao gồm các chỉ thị, vì vậy một số thông thường có thể được đặt trong một tệp thông thường được bao gồm bởi tệp makefile chính.

+0

Tôi không thể tìm thấy một 'nmake' 'bao gồm chỉ thị' ở bất kỳ đâu trong [msdn] (http://msdn.microsoft.com/en-us/library/dd9y37ha.aspx)? –

+2

@JosephQuinsey http://msdn.microsoft.com/en-us/library/7y32zxwh.aspx –

1

Tôi chỉ nghĩ về một điều hoàn toàn khác.

Nếu bạn dính vào Makefile cực kỳ đơn giản của bạn, trong đó, bạn nói, hoạt động, và chỉ cần đặt các biến 'tiêu chuẩn' CC và CFLAGS trong môi trường tương ứng của bạn, nói

export CC=gcc 

tương ứng

set CC=CL.EXE 

export CFLAGS=-o myexecutable 

tương ứng

set CFLAGS=/out:myexecutable.exe 

nó có thể hoạt động.

Hãy lưu ý, tôi không chắc chắn về các tùy chọn chính xác để sử dụng, bạn sẽ phải tự mình tìm ra chúng. Nhưng AFAIK cả hai biến thể nhận ra cùng một bộ cờ. Bạn thậm chí có thể đặt chúng trên các dòng lệnh tương ứng (nhưng không phải trong makefile, vì NMAKE sử dụng cú pháp 'ifeq' khác nhau ...)

+1

nó có thể là một ý tưởng tốt để viết một kịch bản shell đơn giản và tập tin thực thi mà thiết lập môi trường và gọi ... – Christoph

6

Bạn nên xem xét sử dụng CMake cho việc này. Với một tệp nguồn, nó sẽ khá dễ dàng!

EDIT:

Đây là cách bạn có thể thiết lập một dự án đơn giản:

cmake_minimum_required(VERSION 2.8) 

project(Simple) 

include_directories("${PROJECT_BINARY_DIR}") 

add_executable(Simple simple.cpp) 

Để xây dựng dự án đơn giản, bạn sẽ làm như sau (điều này giả định nguồn và CMakeLists của bạn.tệp txt nằm trong ~/src/simple:

[email protected]~/src/simple$ mkdir build 
[email protected]~/src/simple$ cd build 
[email protected]~/src/simple$ cmake .. 
[email protected]~/src/simple$ make 
+1

- 1 Trong nhận xét cho câu hỏi OP nói rằng anh ta cần sử dụng NMAKE. –

+2

@JohanBezem Khi tôi đăng câu trả lời này, nhận xét đó không có sẵn. Tuy nhiên, tôi nghĩ câu trả lời này là cách chính xác để giải quyết vấn đề khi không bị ràng buộc về nhân tạo của bài tập về nhà ... – mevatron

+1

CMake có thể tạo ra nmake, vì vậy nó không phải là _that_ được tìm nạp để sử dụng CMake. Đó là ít nhất đáng xem xét. – ideasman42

1

Có, bạn có thể thực hiện việc này bằng một Makefile duy nhất. Các nguồn tốt nhất cho vật liệu này là Sách O'Reilly:

Managing Projects with GNU Make, Third Edition By Robert Mecklenburg

xem Chương 7: Thiết bị Makefiles.

Trong Tóm tắt thông tin, kỹ thuật này là để kiểm tra các biến môi trường ComSpec mà nói nếu người phiên dịch cửa sổ lệnh hiện diện:

ifdef COMSPEC 
MV ?= move 
RM ?= del 
else 
MV ?= mv -f 
RM ?= rm -f 
endif 

tôi quấn này với một kịch bản shell xách tay trong đó sử dụng sed để chỉnh sửa các makefile cho nmake hoặc Gnu-make ..

+0

hm, afaict cú pháp '? =' Không hợp lệ với 'nmake'. tôi nghĩ rằng ví dụ của bạn chỉ phát hiện xem liệu 'GNU make' có đang chạy trên W32 hay không (thay vì là một polyglot nmake/GNUmake)) –

+0

@ umläute - Nó nói rằng tôi sử dụng tập lệnh sed để tùy chỉnh cú pháp .... –

+0

đủ công bằng; Vì vậy, kể từ khi kịch bản shell di động là ma thuật thực sự trả lời câu hỏi, nó có thể là tốt để chia sẻ đó là tốt :-) –

4

Tôi muốn sử dụng cùng một makefile bao gồm để được sử dụng bởi make và nmake. Kể từ khi thực hiện nhận ra dòng tiếp tục trên dòng bình luận nhưng nmake không, điều này có nghĩa rằng chúng ta có thể có hướng dẫn riêng biệt cho thực hiện và nmake. ví dụ:

# \ 
!ifndef 0 # \ 
# nmake code here \ 
MV=move # \ 
RM=del # \ 
CP=copy # \ 
!else 
# make code here 
MV=mv -f 
RM=rm -f 
CP=cp -f 
# \ 
!endif 

Chỉ cần có để đảm bảo rằng nmake mã cụ thể được chấm dứt bởi # \

+0

Tác phẩm này, mặc dù nmake không cho phép nhận xét trên các lệnh. Bạn chỉ có thể sử dụng kỹ thuật này cho các lệnh macro và * dòng đơn *. Bạn có thể nối nhiều lệnh bằng cách sử dụng ';' để giữ chúng bằng một dòng duy nhất. –

1

Tôi không thể tìm thấy một cách để sử dụng một makefile phổ biến để làm việc cho cả hai GNU thực hiện và MS nmake, chủ yếu là vì chúng có cú pháp không tương thích với các chỉ thị "bao gồm" và/hoặc "nếu". MS nmake yêu cầu phải sử dụng! tiền tố cho chỉ thị. ví dụ,! if,! include, etc ...

Nếu nó được phép có các macro riêng biệt, tuy nhiên, nó có thể bị lừa xung quanh. Ở đây tôi trình bày cách tốt nhất tôi đã tìm thấy cho đến nay để làm cho makefile tương thích cho cả GNU và MS nmake bằng cách quan sát những điều sau:

  1. MS nmake đọc TOOLS.ini tệp cho macro mặc định.
  2. MS suite sử dụng .obj làm phần mở rộng tệp đối tượng.
  3. GNU tạo tệp đọc được xác định trong biến môi trường MAKEFILES.
  4. Sử dụng bộ phần mềm GNU làm phần mở rộng tệp đối tượng.
  5. GNU không cần cung cấp phần mở rộng thực thi .exe cho mục tiêu.

Lưu ý: Phần sau đã được kiểm tra bằng MS Visual Studio 2015 và MINGW32.

Bước 1: tạo tệp lô DOS sau và cho phép nó chạy bất cứ khi nào lời nhắc CMD được gọi.

set MAKEFILES=TOOLS.gcc 
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" 

Bước 2: Tạo một file TOOLS.ini dưới thư mục làm việc của bạn như sau: (file này không phụ thuộc vào phụ thuộc dự án của bạn ngoại trừ các thư viện có thể)

[NMAKE] 
LDLIBS = 
CDEBUG = /Zi 
LDEBUG = /debug:full 
WDFLAGS = /wd4996 /wd4774 /wd4018 /wd4710 /wd4820 
CFLAGS = /nologo $(CDEBUG) /EHsc /Wall $(WDFLAGS) 
LDFLAGS = /nologo $(LDEBUG) 
RM  = del /F /Q 
LINK = "$(VCINSTALLDIR)bin\link" $(LDFLAGS) 
CP = copy 
CC = cl 
CPP = $(CC) /P 
X = .exe 
O = .obj 

.obj.exe: 
    $(LINK) $** $(LOADLIBES) $(LDLIBS) /Out:[email protected] 

Bước 3: Tạo một CÔNG CỤ .gcc dưới thư mục làm việc của bạn như sau: (file này không phụ thuộc vào phụ thuộc dự án của bạn ngoại trừ các thư viện có thể)

LD_LIBS = 
LDLIBS = 
CDEBUG = -g 
LDEBUG = -g 
CFLAGS = $(CDEBUG) 
LDFLAGS = $(LDEBUG) 
RM  = rm -f 
LINK = gcc $(LDFLAGS) 
CP  = cp 
CC  = gcc 
CPP  = $(CC) -E 
X  = 
O  = .o 

%: %.o 
    $(LINK) $^ $(LOADLIBES) $(LDLIBS) -o [email protected] 

Bước 4: chỉnh sửa makefile của bạn như sau (lưu ý $ (X) và $ (O)) trong đó chỉ phụ thuộc được xác định.

SHELL = /usr/bin/sh 
app: app1$(X) app2$(X) 
app1$(X): app1$(O) 
app2$(X): app2$(O) 

clean: 
    $(RM) *.exe *.o *.obj *.ilk *.pdb *.tmp *.i *~ 

Bước 5: Thưởng thức GNU thực hiện và MS nmake với cùng makefile

$ nmake 
$ make clean 
$ nmake clean 
$ make 
Các vấn đề liên quan