使用make进行跨平台编译

bph*_*bph 20 c cross-platform makefile

我目前正在Linux和Win32下开发一个C项目.'deliverrable'是一个共享库,所有开发都是在Linux下使用GNU工具链完成的.我正在使用Makefile来编译共享库.

我不得不从同一个src在Win32下构建一个.dll.

我在Win32的盒子,这样我可以使用make并获得安装MinGW的从编译器的投诉减少(相比于MSVC).我正处于src代码在两个平台上编译的阶段

但是Linux Makefile和Win32 Makefile是不同的.我很好奇如何最好地处理这个 - 我应该:

  1. 有2个makefile,例如Makefile for linux和Makefile.WIN32,然后make -f Makefile.WIN32在Windows框上运行

  2. 我应该在单个Makefile中创建一个不同的目标,并make WIN32在Windows框中执行类似的操作

  3. 我应该放弃制作并使用CMake(对于这样一个简单的项目来说,果汁值得挤压,即1个共享库)

Chr*_*oph 21

使用单个make文件并将特定于平台的内容放在条件中,例如

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

DLL := libfoo$(DLLEXT)

lib : $(DLL)
Run Code Online (Sandbox Code Playgroud)


oli*_*bre 12

我用UNAME := $(shell uname)Makefile来检测平台(Linux或MS-Windows).

我在下面提供了一个基于makegcc构建共享库的完整示例:*.so或者*.dll取决于平台.

这个例子是基本的/简单的/愚蠢的更容易理解:-)

要在MS-Windows上使用make,可以安装CygwinMinGW.gcc

该示例使用五个文件:

 ??? app
 ?   ??? Makefile
 ?   ??? main.c
 ??? lib
     ??? Makefile
     ??? hello.h
     ??? hello.c
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

源代码

app/main.c

#include "hello.h" //hello()
#include <stdio.h> //puts()

int main()
{
    const char* str = hello();
    puts(str);
}
Run Code Online (Sandbox Code Playgroud)

lib/hello.h

#ifndef __HELLO_H__
#define __HELLO_H__

const char* hello();

#endif
Run Code Online (Sandbox Code Playgroud)

lib/hello.c

#include "hello.h"

const char* hello()
{
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

构建

修复Makefiles(通过制表替换前导空格)的复制粘贴.

> sed  -i  's/^  */\t/'  */Makefile
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

运行

应用程序需要知道共享库的位置.

在MS-Windows上,简单/基本/愚蠢的方法是复制应用程序所在的库:

> cp -v lib/hello.dll app
`lib/hello.dll' -> `app/hello.dll'
Run Code Online (Sandbox Code Playgroud)

在Linux上,使用LD_LIBRARY_PATH环境变量:

> export LD_LIBRARY_PATH=lib
Run Code Online (Sandbox Code Playgroud)

两个平台上的运行命令行和输出相同:

> app/app.exe
hello
Run Code Online (Sandbox Code Playgroud)


小智 7

作为同时使用 autotools 和 CMake 的人,我建议使用 CMake,而不是滚动您自己的 Makefile 和使用 autotools。CMake 有这么多有用的、易于使用的好处,即使它是一个简单的项目。例如,CMake 将创建一个 NSIS 安装程序,管理生产与调试编译,并有一个很好的测试框架。我遇到的唯一问题是很难找到如何使用它的真实示例。如此多的开源软件使用自动工具,以至于在现实世界中很容易找到它的示例。但是,如果您下载 CMake 源代码,Example 目录和 Test 目录中有很多示例。

换句话说,果汁值得挤压。

  • 链接到上述来源? (2认同)

Tay*_*ick 5

几年前我遇到了类似的问题,发现cmake对于跨平台编译要容易得多,并且 会使用该系统本机的任何编译器。语法更清晰,抽象了大部分不必要的细节(有时会妨碍,但通常有办法绕过它)

  • 我不会说 CMake 对于跨平台编译很有用。它对 _multi-platform_ 很有用,因为一组 CMake 文件可以在 CMake 支持的所有平台上使用。它并不容易在一个平台上创建某种 make 文件,然后可以在没有 CMake 的情况下在其他平台上使用。它也不理解在不同平台上为一个平台编译的交叉编译器。 (2认同)