Использование make для кроссплатформенной компиляции - PullRequest
19 голосов
/ 20 марта 2012

В настоящее время я занимаюсь разработкой проекта C под Linux и Win32. «Результат» - это общая библиотека, и вся разработка выполняется под Linux с помощью цепочки инструментов GNU. Я использую Makefile для компиляции общей библиотеки.

Время от времени мне приходится собирать .dll под Win32 из того же src.

Я установил MinGW на коробку Win32, чтобы я мог использовать make и получить намного меньше жалоб от компилятора (по сравнению с MSVC). Я на этапе, когда код src компилируется на обеих платформах

Но Makefile для Linux и Make32 для Win32 различны. Мне интересно, как лучше всего справиться с этим - я должен:

  1. имеет 2 make-файла, например, Makefile для Linux и Makefile.WIN32, а затем запустите make -f Makefile.WIN32 в окне Windows

  2. Должен ли я создать другую цель в одном файле Makefile и сделать что-то вроде make WIN32 в окне Windows

  3. Должен ли я сделать и использовать CMake (стоит ли сок для такого простого проекта, т. Е. 1 общая библиотека)

Ответы [ 5 ]

20 голосов
/ 21 марта 2012

Используйте один файл make и поместите спецификацию платформы в условных выражениях , например,

ifeq ($(OS),Windows_NT)
    DLLEXT := .dll
else
    DLLEXT := .so
endif

DLL := libfoo$(DLLEXT)

lib : $(DLL)
12 голосов
/ 08 февраля 2013

Я использую 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 $@ $^ -L../lib -lhello
        # '-o $@'    => output file => $@ = 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 $@ -c $< -I ../lib
        # '-o $@'     => output file => $@ = 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 $@  $^  -shared
        # '-o $@'    => output file => $@ = libhello.so or hello.dll
        # '   $^'    => no options => Link all depended files => $^ = hello.o
        # '-shared'  => generate shared library

%.o: %.c
        gcc  -o $@  -c $<  -fPIC
        # '-o $@' => output file => $@ = 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
4 голосов
/ 21 марта 2012

Как человек, который использовал как автоинструменты, так и CMake, я бы порекомендовал использовать CMake вместо того, чтобы перекатывать свои собственные Makefiles и использовать автоинструменты. CMake имеет так много полезных, простых в использовании преимуществ, даже если это простой проект. Например, CMake создаст установщик NSIS, будет управлять производством и отладочной компиляцией и имеет хорошую среду тестирования. Единственный удар, который у меня был, заключался в том, что было довольно трудно найти реальные примеры того, как его использовать. Так много программного обеспечения с открытым исходным кодом использует автоинструменты, что реальные примеры для него легко найти. Однако, если вы загрузите исходный код CMake, в каталоге примеров и каталоге тестов будет много примеров.

Другими словами, Сок стоит выжать.

4 голосов
/ 20 марта 2012

У меня была похожая проблема несколько лет назад, и я обнаружил, что cmake намного проще для кросс-платформенной компиляции и будет использовать любой компилятор, свойственный этой системе. Синтаксис более понятен и абстрагирует детали, которые по большей части не нужны (иногда это мешало, но обычно это обходилось)

3 голосов
/ 20 марта 2012

В качестве основного совета я предлагаю использовать libtool, autoconf и automake;они делают кросс-компиляцию очень простой и намного проще, чем CMake.

Если вы идете по маршруту ручной работы, я бы предложил пойти с разными целями.Переключение между make-файлами имеет тенденцию скрывать очевидные ошибки в Make-файлах, например, дублированные объекты с другими правилами.Пример: объект foo.o скомпилирован для цели DLL и для цели .so, но с разными флагами.Если кто-то переключает Make-файлы, используется существующий файл .o с неправильными флагами, что нарушает сборку.Если вы используете один Makefile, это станет очевидным из-за конфликтов правил.

...