Ответ 1
Используйте один файл make и поместите его в conditionals, например
ifeq ($(OS),Windows_NT)
DLLEXT := .dll
else
DLLEXT := .so
endif
DLL := libfoo$(DLLEXT)
lib : $(DLL)
В настоящее время я разрабатываю проект C под Linux и Win32. "Deliverable" - это общая библиотека, и вся разработка выполняется под Linux с помощью цепочки инструментов GNU. Я использую Makefile для компиляции разделяемой библиотеки.
Время от времени мне нужно создать DLL под Win32 из того же src.
Я установил MinGW в поле Win32, чтобы я мог использовать make и получать гораздо меньше жалоб от компилятора (по сравнению с MSVC). Я на этапе, когда код src компилируется на обеих платформах
Но файлы Makefile Linux и Makefile Win32 отличаются. Мне любопытно, как лучше всего справиться с этим - должен ли я:
имеют 2 make файла, например. Makefile для linux и Makefile.WIN32, а затем запустите make -f Makefile.WIN32
в окне Windows
Должен ли я создать другую цель в одном файле Makefile и сделать что-то вроде make WIN32
в окне Windows
Должен ли я использовать и использовать CMake (это сок стоит сжать для такого простого проекта, то есть 1 разделяемая библиотека)
Используйте один файл make и поместите его в conditionals, например
ifeq ($(OS),Windows_NT)
DLLEXT := .dll
else
DLLEXT := .so
endif
DLL := libfoo$(DLLEXT)
lib : $(DLL)
Я использую UNAME := $(shell uname)
в моем Makefile
для обнаружения платформы (Linux или MS-Windows).
Ниже приведен полный пример на основе make
и gcc
для создания общей библиотеки: *.so
или *.dll
в зависимости от платформы.
Пример является основным/простым/глупым, чтобы быть более понятным:-)
Чтобы использовать make
и gcc
в MS-Windows, Cygwin или MinGW может быть установлен.
В этом примере используются пять файлов:
├── app
│ └── Makefile
│ └── main.c
└── lib
└── Makefile
└── hello.h
└── hello.c
Makefiles
app/Makefile
app.exe: main.o
gcc -o [email protected] $^ -L../lib -lhello
# '-o [email protected]' => output file => [email protected] = the target file (app.exe)
# ' $^' => no options => Link all depended files
# => $^ = main.o and other if any
# '-L../lib' => look for libraries in directory ../lib
# '-lhello => use shared library hello (libhello.so or hello.dll)
%.o: %.c
gcc -o [email protected] -c $< -I ../lib
# '-o [email protected]' => output file => [email protected] = the target file (main.o)
# '-c $<' => COMPILE the first depended file (main.cpp)
# '-I ../lib' => look for headers (*.h) in directory ../lib
clean:
rm -f *.o *.so *.dll *.exe
lib/Makefile
UNAME := $(shell uname)
ifeq ($(UNAME), Linux)
TARGET = libhello.so
else
TARGET = hello.dll
endif
$(TARGET): hello.o
gcc -o [email protected] $^ -shared
# '-o [email protected]' => output file => [email protected] = libhello.so or hello.dll
# ' $^' => no options => Link all depended files => $^ = hello.o
# '-shared' => generate shared library
%.o: %.c
gcc -o [email protected] -c $< -fPIC
# '-o [email protected]' => output file => [email protected] = the target file (main.o)
# '-c $<' => compile the first depended file (main.cpp)
# '-fPIC' => Position-Independent Code (required for shared lib)
clean:
rm -f *.o *.so *.dll *.exe
app/main.c
#include "hello.h" //hello()
#include <stdio.h> //puts()
int main()
{
const char* str = hello();
puts(str);
}
lib/hello.h
#ifndef __HELLO_H__
#define __HELLO_H__
const char* hello();
#endif
lib/hello.c
#include "hello.h"
const char* hello()
{
return "hello";
}
Исправьте копию-копию Makefiles
(замените начальные пробелы на табуляцию).
> sed -i 's/^ */\t/' */Makefile
Команда make
на обеих платформах одинакова. Данный вывод предназначен для MS-Windows (ненужные строки удалены).
> cd lib
> make clean
> make
gcc -o hello.o -c hello.c -fPIC
gcc -o hello.dll hello.o -shared
> cd ../app
> make clean
> make
gcc -o main.o -c main.c -I ../lib
gcc -o app.exe main.o -L../lib -lhello
Приложение должно знать, где находится общая библиотека.
В MS-Windows простой/основной/глупый способ заключается в том, чтобы скопировать библиотеку, в которой находится приложение:
> cp -v lib/hello.dll app
`lib/hello.dll' -> `app/hello.dll'
В Linux используйте переменную среды LD_LIBRARY_PATH
:
> export LD_LIBRARY_PATH=lib
Командная строка и вывод выполнения на обеих платформах одинаковы:
> app/app.exe
hello
У меня была аналогичная проблема несколько лет назад, и я обнаружил, что cmake намного проще для перекрестного -платформенная компиляция И будет использовать любой компилятор для этой системы. Синтаксис более ясен и абстрагирует детали, которые в большинстве случаев не нужны (иногда это мешало, но обычно это было вокруг)
В качестве основного совета я предлагаю использовать libtool, autoconf и automake; они делают кросс-компиляцию очень простой и намного легче, чем CMake.
Если вы идете по ручному маршруту, я предлагаю идти с разными целями. Переключение между make файлами имеет тенденцию скрывать в противном случае очевидные ошибки в Makefiles, например. дублированные объекты с разными правилами. Пример: объект foo.o скомпилирован для цели DLL и для целевого объекта .so, но с разными флагами. Если кто-то переключает Make файлы, используется существующий файл .o с неправильными флагами, нарушая сборку. Если вы используете один Makefile, это станет очевидным с помощью конфликтов правил.
Как кто-то, кто использовал как autotools, так и CMake, я бы рекомендовал использовать CMake для перелистывания собственных Make файлов и использования autotools. У CMake так много полезных, простых в использовании преимуществ, даже если это простой проект. Например, CMake создаст установщик NSIS, управляет производственной и отладочной компиляцией и имеет хорошую структуру тестирования. Один удар, который у меня был, заключался в том, что было трудно найти реальные примеры того, как его использовать. Так много программного обеспечения с открытым исходным кодом использует autotools, что реальные примеры для него легко найти. Однако, если вы загружаете источник CMake, в каталоге примеров и тестовом каталоге есть много примеров.
Другими словами, сок стоит сжать.