Используйте один и тот же файл makefile для make (Linux) и nmake (Windows)
у меня есть простая C-программа (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".из", а не "привет". Под окнами я получаю "привет".exe а также Здравствуйте.возражение, которого я не хочу иметь.
кто-нибудь знает альтернативный способ? Или то, что я пытаюсь сделать, абсолютно невозможно?
6 ответов
Это, вероятно, не невозможно, но, скорее всего, так сложно, что было бы проще написать два файла Makefile в любом случае.
как GNU make (используется в Linux), так и nmake имеют директивы include, поэтому некоторые общие вещи могут быть помещены в общий файл makefile, который включен в основной файл makefile.
вы должны смотреть на использование CMake для этого. С одним исходным файлом это должно быть довольно просто!
EDIT:
вот как вы могли бы настроить простой проект:
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
Я хотел использовать тот же файл makefile 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 завершается # \
Я не могу найти способ использовать общий файл makefile для работы как для GNU make, так и для MS nmake, главным образом потому, что у них есть несовместимый синтаксис для директив "include" и/или "if". MS nmake требует использования ! префикс для директив. например !если !включать и т. д...
если разрешено иметь отдельные макросы, однако, его можно обмануть. Здесь я представляю лучший способ, который я нашел до сих пор для совместимости makefile как для GNU make, так и для MS nmake, наблюдая за следующими:
- MS nmake считывает инструменты.ini-файл для макросов по умолчанию.
- MS suite использует .obj как расширение файла объекта.
- GNU make считывает файлы, определенные в переменной среды MAKEFILES.
- использование GNU suite .o как расширение файла объекта.
- 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: Создайте инструменты.файл 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: Создайте инструменты.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: отредактируйте файл makefile, как показано ниже (Примечание $(X) и $(O)), где указаны только dependecies.
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 с тем же makefile
$ nmake
$ make clean
$ nmake clean
$ make
Я просто думал о чем-то совершенно другом.
если вы придерживаетесь своего чрезвычайно простого файла Makefile, который, как вы говорите, работает, и просто помещаете "стандартные" переменные CC и CFLAGS в соответствующие среды, скажем
export CC=gcc
соответственно
set CC=CL.EXE
и
export CFLAGS=-o myexecutable
соответственно
set CFLAGS=/out:myexecutable.exe
это может сработать.
имейте в виду, я не тверд в точных вариантах использования, вам придется их выяснить себе. Но AFAIK оба варианта распознают один и тот же набор флагов. Вы даже можете установить их в соответствующих командных строках (но не в файле makefile, так как NMAKE использует другой синтаксис "ifeq"...)
Да, вы можете сделать это с помощью одного из Makefile. Лучший источник этого материала-книга О'Рейли:--2-->
Управление проектами с GNU Make, третье издание Роберта Мекленбурга
см. Главу 7: переносные файлы Makefile.
В общем, метод состоит в том, чтобы проверить переменную среды ComSpec, которая говорит, если присутствует интерпретатор команд windows:
ifdef COMSPEC
MV ?= move
RM ?= del
else
MV ?= mv -f
RM ?= rm -f
endif
Я обертываю это с помощью портативного скрипта оболочки, который использует sed для отредактируйте файл makefile для Nmake или Gnu-make..