Используйте один и тот же make-файл для make (Linux) и nmake (Windows) - PullRequest
16 голосов
/ 25 ноября 2011

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

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

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

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

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

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

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

Ответы [ 6 ]

10 голосов
/ 25 ноября 2011

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

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

8 голосов
/ 25 ноября 2011

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

РЕДАКТИРОВАТЬ:

Вот как вы можете настроить простой проект:

cmake_minimum_required(VERSION 2.8)

project(Simple)

include_directories("${PROJECT_BINARY_DIR}")

add_executable(Simple simple.cpp)

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

foo@bar~/src/simple$ mkdir build
foo@bar~/src/simple$ cd build
foo@bar~/src/simple$ cmake ..
foo@bar~/src/simple$ make
7 голосов
/ 18 июня 2015

Я хотел использовать один и тот же make-файл include для использования 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 голосов
/ 14 ноября 2017

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

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

  1. MS nmake читает файл TOOLS.ini для макросов по умолчанию.
  2. Пакет MS использует .obj в качестве расширения файла объекта.
  3. GNU make читает файлы, определенные в переменной среды MAKEFILES.
  4. Пакет GNU использует .o как расширение файла объекта.
  5. GNU make не обязана давать исполняемое расширение .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:$@

Шаг 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 $@

Шаг 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
1 голос
/ 24 декабря 2014

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

Управление проектами с помощью GNU Make, третье издание Роберт Мекленбург

См. Главу 7: Переносимые файлы сборки.

В заключение, метод заключается в тестировании переменной среды ComSpec, которая сообщает, присутствует ли интерпретатор команд Windows:

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

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

1 голос
/ 25 ноября 2011

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

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

  export CC=gcc

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

  set CC=CL.EXE

и

  export CFLAGS=-o myexecutable

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

  set CFLAGS=/out:myexecutable.exe

это может просто сработать.

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

...