Используйте тот же make файл для make (Linux) и nmake (Windows)

У меня есть простой C-Programm (1 исходный файл), который я хочу скомпилировать в Linux и Windows через make resp. NMAKE. Есть ли возможность выполнить это с помощью одного файла makefile?

Я подумал о чем-то вроде

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

К сожалению, nmake, похоже, не понимает ifeq, поэтому я не могу это использовать. У меня есть рабочий файл makefile, но это дает очень уродливые результаты:

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

Это работает в обеих системах. Проблема в том, что результат зависит от поведения по умолчанию соответствующих компиляторов. В Linux я получаю исполняемый файл с именем "a.out", а не "привет". В Windows я получаю "hello.exe", но есть также "hello.obj", который я не хочу иметь.

Кто-нибудь знает об альтернативном пути? Или это то, что я пытаюсь сделать абсолютно невозможным?

Ответ 1

Это, вероятно, не невозможно, но, скорее всего, так сложно, что было бы проще писать два make файла в любом случае.

Оба GNU make (используемые в Linux) и nmake содержат директивы, поэтому некоторые распространенные вещи могут быть помещены в общий make файл, который включен в основной файл makefile.

Ответ 2

Для этого вам следует использовать CMake. С одним исходным файлом это должно быть довольно просто!

EDIT:

Вот как вы могли бы создать простой проект:

cmake_minimum_required(VERSION 2.8)

project(Simple)

include_directories("${PROJECT_BINARY_DIR}")

add_executable(Simple simple.cpp)

Чтобы создать простой проект, вы должны сделать следующее (это предполагает, что файлы вашего источника и CMakeLists.txt находятся в ~/src/simple:

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

Ответ 3

Я хотел использовать тот же make файл, который будет использоваться make и nmake. Поскольку make распознает продолжение строки в строках комментариев, но nmake не делает этого, это означает, что мы можем иметь отдельные инструкции для make и nmake. например:

# \
!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

Просто убедитесь, что определенный код nmake завершен с помощью #\

Ответ 4

Я просто подумал о чем-то совершенно другом.

Если вы придерживаетесь своего чрезвычайно простого Makefile, который, как вы говорите, работает, и просто ставьте "стандартные" переменные CC и CFLAGS в ваших соответствующих средах, скажем

  export CC=gcc

соответственно

  set CC=CL.EXE

и

  export CFLAGS=-o myexecutable

соответственно

  set CFLAGS=/out:myexecutable.exe

он может работать.

Имейте в виду, я не уверен в том, какие именно варианты использовать, вам придется самим понять их. Но AFAIK оба делают варианты распознающими один и тот же набор флагов. Вы даже можете установить их в соответствующих командных строках (но не в make файле, так как NMAKE использует другой синтаксис ifeq...)

Ответ 5

Да, вы можете сделать это с помощью одного Makefile. Лучшим источником для этого материала является книга О'Рейли:

Управление проектами с помощью GNU Make, третье издание Robert Mecklenburg

См. главу 7: Переносимые файлы Makefile.

В сводке, метод должен протестировать переменную среды ComSpec, которая говорит, что присутствует интерпретатор команд Windows:

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

Я переношу это с помощью переносимой оболочки script, которая использует sed для редактирования make файла для Nmake или Gnu-make.

Ответ 6

Я не могу найти способ использовать общий make файл для работы как GNU make, так и MS nmake, главным образом потому, что у них есть несовместимый синтаксис для директив "include" и/или "if". MS nmake требует использования! префикс для директив. например,! if,! include и т.д.

Если разрешено иметь отдельные макросы, его можно обмануть. Здесь я представляю лучший способ, который я нашел до сих пор, чтобы сделать makefile совместимым как с GNU make, так и с MS nmake, соблюдая следующие правила:

  • MS nmake считывает файл TOOLS.ini для макросов по умолчанию.
  • MS suite использует .obj как расширение объектного файла.
  • GNU make считывает файлы, определенные в переменной среды MAKEFILES.
  • GNU suite использует .o как расширение объектного файла.
  • GNU не нужно давать исполняемый файл расширения .exe для цели.

Примечание. Следующие испытания были протестированы с использованием MS Visual Studio 2015 и MINGW32.

Шаг 1: создайте следующий пакетный файл DOS и пусть он запускается всякий раз, когда вызывается приглашение CMD.

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

Шаг 2. Создайте файл TOOLS.ini в рабочем каталоге, как показано ниже: (этот файл не зависит от зависимостей вашего проекта, за исключением библиотек)

[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]

Шаг 3. Создайте TOOLS.gcc в рабочем каталоге, как показано ниже: (этот файл не зависит от зависимостей вашего проекта, за исключением библиотек)

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]

Шаг 4: отредактируйте свой make файл, как показано ниже (обратите внимание на $(X) и $(O)), где указаны только зависимости.

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 *~

Шаг 5: Наслаждайтесь GNU make и MS nmake с тем же make файлом

$ nmake
$ make clean
$ nmake clean
$ make