OS検出メイクファイル


249

私は、Mac OS X、Linux、Solarisなど、いくつかの異なるコンピューターといくつかの異なるオペレーティングシステムで日常的に作業しています。私が取り組んでいるプロジェクトでは、リモートのgitリポジトリからコードを取得します。

ターミナルに関係なく、プロジェクトに取り組みたいと思っています。これまでのところ、コンピュータを切り替えるたびにメイクファイルを変更することで、OSの変更を回避する方法を見つけました。しかし、これは退屈で、頭痛の種を引き起こします。

makefileを変更して、使用しているOSを検出し、それに応じて構文を変更する方法を教えてください。

ここにmakefileがあります:

cc = gcc -g
CC = g++ -g
yacc=$(YACC)
lex=$(FLEX)

all: assembler

assembler: y.tab.o lex.yy.o
        $(CC) -o assembler y.tab.o lex.yy.o -ll -l y

assembler.o: assembler.c
        $(cc) -o assembler.o assembler.c

y.tab.o: assem.y
        $(yacc) -d assem.y
        $(CC) -c y.tab.c

lex.yy.o: assem.l
        $(lex) assem.l
        $(cc) -c lex.yy.c

clean:
        rm -f lex.yy.c y.tab.c y.tab.h assembler *.o *.tmp *.debug *.acts

回答:


282

ここにはすでに多くの良い答えがありますが、私は両方のより完全な例を共有したいと思います:

  • unameWindowsに存在するとは想定していません
  • プロセッサも検出します

ここで定義されているCCFLAGSは、必ずしも推奨または理想的ではありません。それらは、私がOS / CPU自動検出を追加していたプロジェクトがたまたま使用していたものです。

ifeq ($(OS),Windows_NT)
    CCFLAGS += -D WIN32
    ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
        CCFLAGS += -D AMD64
    else
        ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
            CCFLAGS += -D AMD64
        endif
        ifeq ($(PROCESSOR_ARCHITECTURE),x86)
            CCFLAGS += -D IA32
        endif
    endif
else
    UNAME_S := $(shell uname -s)
    ifeq ($(UNAME_S),Linux)
        CCFLAGS += -D LINUX
    endif
    ifeq ($(UNAME_S),Darwin)
        CCFLAGS += -D OSX
    endif
    UNAME_P := $(shell uname -p)
    ifeq ($(UNAME_P),x86_64)
        CCFLAGS += -D AMD64
    endif
    ifneq ($(filter %86,$(UNAME_P)),)
        CCFLAGS += -D IA32
    endif
    ifneq ($(filter arm%,$(UNAME_P)),)
        CCFLAGS += -D ARM
    endif
endif

8
残念ながらPROCESSOR_ARCHITECTURE、プロセスが32ビットか64ビットかによって、envvarは仮想化されているようです。したがって、make32ビットで64ビットのアプリケーションを構築しようとすると、失敗します。と組み合わせて使用​​するPROCESSOR_ARCHITEW6432ます(私のために働いたこれを、とすることを
トーマス・

4
makeチームがosとarchを使用していくつかの魔法の変数を追加した場合、多分トラブルが多すぎるでしょう。
Alex

6
@JanusTroelsen:OSWindows以外のシステムでが設定されているかどうかは問題になりません。makeはunsetを空と同じように扱います。これにより、unameベースのブロックにジャンプします。そこにFreeBSDチェックを追加するだけです。
Trevor Robinson、

3
これはosxでも壊れます。/bin/sh: -c: line 0: syntax error near unexpected token 、Windows_NT '/ bin / sh:-c:行0:ifeq (,Windows_NT)' make: *** [os] Error 2
k107

1
@kristiこれは、makefileディレクティブのコンテキストではなく、シェルコマンドとして実行したようです。
phord

119

unameコマンド(http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html)をパラメーターなしで実行すると、オペレーティングシステム名がわかります。私はそれを使用し、戻り値に基づいて条件を作成します。

UNAME := $(shell uname)

ifeq ($(UNAME), Linux)
# do something Linux-y
endif
ifeq ($(UNAME), Solaris)
# do something Solaris-y
endif

明確に言うと、その行はMakefileにあります。CygwinとOSXのMakefileでその構造を試したところ、期待通りに動作しました。試してみる:コマンドラインでunameと入力します。そのOSの価値がわかります。OSXはおそらく「ダーウィン」でしょう。
dbrown0708

GnuWin32プロジェクトは、una​​meとGnuの両方をネイティブのWindowsアプリケーションとして利用できるようにし、この手法をコマンドプロンプトのMingWとWindowsのCygwinに移植できるようにします。
RBerteig 2009

makefileの中にあるSolarisマシンでは失敗します。unameコマンドは、そのシステムで使用できます。
samoz 2009

4
これをMaketarget内に置く場合、インデントしてはいけないことに注意してください。
ニランド

4
「:=」構文は、GNU Makeに固有のものではありませんか?
Ankur Sethi

40

2つの簡単なトリックを使用してオペレーティングシステムを検出します。

  • まず、環境変数 OS
  • 次に、unameコマンド
ifeq ($(OS),Windows_NT)     # is Windows_NT on XP, 2000, 7, Vista, 10...
    detected_OS := Windows
else
    detected_OS := $(shell uname)  # same as "uname -s"
endif

または、Windowsではunameなく、利用できない場合のより安全な方法:

ifeq ($(OS),Windows_NT) 
    detected_OS := Windows
else
    detected_OS := $(shell sh -c 'uname 2>/dev/null || echo Unknown')
endif

Cygwin / MinGW / MSYS / Windowsを区別したい場合は、ケンジャクソンが興味深い代替案を提案します。そのような彼の答えを見てください:

ifeq '$(findstring ;,$(PATH))' ';'
    detected_OS := Windows
else
    detected_OS := $(shell uname 2>/dev/null || echo Unknown)
    detected_OS := $(patsubst CYGWIN%,Cygwin,$(detected_OS))
    detected_OS := $(patsubst MSYS%,MSYS,$(detected_OS))
    detected_OS := $(patsubst MINGW%,MSYS,$(detected_OS))
endif

次に、以下に応じて関連するものを選択できますdetected_OS

ifeq ($(detected_OS),Windows)
    CFLAGS += -D WIN32
endif
ifeq ($(detected_OS),Darwin)        # Mac OS X
    CFLAGS += -D OSX
endif
ifeq ($(detected_OS),Linux)
    CFLAGS   +=   -D LINUX
endif
ifeq ($(detected_OS),GNU)           # Debian GNU Hurd
    CFLAGS   +=   -D GNU_HURD
endif
ifeq ($(detected_OS),GNU/kFreeBSD)  # Debian kFreeBSD
    CFLAGS   +=   -D GNU_kFreeBSD
endif
ifeq ($(detected_OS),FreeBSD)
    CFLAGS   +=   -D FreeBSD
endif
ifeq ($(detected_OS),NetBSD)
    CFLAGS   +=   -D NetBSD
endif
ifeq ($(detected_OS),DragonFly)
    CFLAGS   +=   -D DragonFly
endif
ifeq ($(detected_OS),Haiku)
    CFLAGS   +=   -D Haiku
endif

ノート:

  • コマンドunameuname -s、オプション-s--kernel-name)がデフォルトであるため、同じです。がに勝る理由をuname -suname -oご覧ください。

  • OS代わりにを使用するとuname、識別アルゴリズムが簡素化されます。それでも単独unameで使用できますが、if/elseすべてのMinGW、Cygwinなどのバリエーションをチェックするには、ブロックを処理する必要があります。

  • 環境変数 OSは常に"Windows_NT"、異なるWindowsバージョンで設定されます(%OS%Wikipediaの環境変数を参照))。

  • の代替OSは環境変数ですMSVCMS Visual Studioの存在をチェックします。VisualC ++を使用した例を参照してください)。


以下に、私が使用する完全な例を示します makegcc共有ライブラリを構築するために:*.soまたは*.dllます。、プラットフォームによって異なります。この例は、理解しやすいようにできるだけ単純です。

インストールmakeしてgccWindowsに CygwinまたはMinGWを参照してください。

私の例は5つのファイルに基づいています

 ├── lib
    └── Makefile
    └── hello.h
    └── hello.c
 └── app
     └── Makefile
     └── main.c

注意: Makefileを使用してインデントします。以下のサンプルファイルをコピーして貼り付ける場合の注意。

2つのMakefileファイル

1。 lib/Makefile

ifeq ($(OS),Windows_NT)
    uname_S := Windows
else
    uname_S := $(shell uname -s)
endif

ifeq ($(uname_S), Windows)
    target = hello.dll
endif
ifeq ($(uname_S), Linux)
    target = libhello.so
endif
#ifeq ($(uname_S), .....) #See https://stackoverflow.com/a/27776822/938111
#    target = .....
#endif

%.o: %.c
    gcc  -c $<  -fPIC  -o $@
    # -c $<  => $< is first file after ':' => Compile hello.c
    # -fPIC  => Position-Independent Code (required for shared lib)
    # -o $@  => $@ is the target => Output file (-o) is hello.o

$(target): hello.o
    gcc  $^  -shared  -o $@
    # $^      => $^ expand to all prerequisites (after ':') => hello.o
    # -shared => Generate shared library
    # -o $@   => Output file (-o) is $@ (libhello.so or hello.dll)

2。 app/Makefile

ifeq ($(OS),Windows_NT)
    uname_S := Windows
else
    uname_S := $(shell uname -s)
endif

ifeq ($(uname_S), Windows)
    target = app.exe
endif
ifeq ($(uname_S), Linux)
    target = app
endif
#ifeq ($(uname_S), .....) #See https://stackoverflow.com/a/27776822/938111
#    target = .....
#endif

%.o: %.c
    gcc  -c $< -I ../lib  -o $@
    # -c $<     => compile (-c) $< (first file after :) = main.c
    # -I ../lib => search headers (*.h) in directory ../lib
    # -o $@     => output file (-o) is $@ (target) = main.o

$(target): main.o
    gcc  $^  -L../lib  -lhello  -o $@
    # $^       => $^ (all files after the :) = main.o (here only one file)
    # -L../lib => look for libraries in directory ../lib
    # -lhello  => use shared library hello (libhello.so or hello.dll)
    # -o $@    => output file (-o) is $@ (target) = "app.exe" or "app"

詳細については、自動変数のドキュメントを参照してください。 cfiでご覧ください

ソースコード

- lib/hello.h

#ifndef HELLO_H_
#define HELLO_H_

const char* hello();

#endif

- lib/hello.c

#include "hello.h"

const char* hello()
{
    return "hello";
}

- app/main.c

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

int main()
{
    const char* str = hello();
    puts(str);
}

ビルド

のコピーと貼り付けを修正しますMakefile(先頭のスペースを1つの表に置き換えます)。

> sed  's/^  */\t/'  -i  */Makefile

makeコマンドは、両方のプラットフォームで同じです。与えられた出力はUnixライクなOS上にあります:

> make -C lib
make: Entering directory '/tmp/lib'
gcc  -c hello.c  -fPIC  -o hello.o
# -c hello.c  => hello.c is first file after ':' => Compile hello.c
# -fPIC       => Position-Independent Code (required for shared lib)
# -o hello.o  => hello.o is the target => Output file (-o) is hello.o
gcc  hello.o  -shared  -o libhello.so
# hello.o        => hello.o is the first after ':' => Link hello.o
# -shared        => Generate shared library
# -o libhello.so => Output file (-o) is libhello.so (libhello.so or hello.dll)
make: Leaving directory '/tmp/lib'

> make -C app
make: Entering directory '/tmp/app'
gcc  -c main.c -I ../lib  -o main.o
# -c main.c => compile (-c) main.c (first file after :) = main.cpp
# -I ../lib => search headers (*.h) in directory ../lib
# -o main.o => output file (-o) is main.o (target) = main.o
gcc  main.o  -L../lib  -lhello  -o app
# main.o   => main.o (all files after the :) = main.o (here only one file)
# -L../lib => look for libraries in directory ../lib
# -lhello  => use shared library hello (libhello.so or hello.dll)
# -o app   => output file (-o) is app.exe (target) = "app.exe" or "app"
make: Leaving directory '/tmp/app'

実行

アプリケーションは、共有ライブラリの場所を知る必要があります。

Windowsでは、簡単な解決策は、アプリケーションがある場所にライブラリをコピーすることです:

> cp -v lib/hello.dll app
`lib/hello.dll' -> `app/hello.dll'

UnixライクなOSでは、LD_LIBRARY_PATH環境変数を使用できます。

> export LD_LIBRARY_PATH=lib

Windowsでコマンドを実行します。

> app/app.exe
hello

UnixライクなOSでコマンドを実行します。

> app/app
hello

努力に感謝しますが、主な質問はオペレーティングシステムを検出することでした。あなたの例はLinuxのみを検出し、そうでなければ完全にWindowsを想定しています。
Shahbaz 2013

こんにちは@Shahbaz。私の答えは他の答えと異なるアプローチを与えません。さらに、私のスクリプトは、unameLinuxでない場合、プラットフォームがWindowsであると想定しています。私はあなたが必要としないかもしれない例を挙げますが、これはMakefile両方のプラットフォームにを実装する方法を(ウェブ上で)検索している誰かを助けるかもしれません;-)私の答えで何を変更すべきですか?乾杯
olibre

他のオペレーティングシステムを正しく識別する方法も考えてみてください。目標は、あまり複雑ではない方法を見つけることですが、さらに重要なことは、防弾です。つまり、何があっても間違いはありません。
Shahbaz 2013

1
@olibre詳細な例をお寄せいただき、ありがとうございます。lib/Makefile例えば、targetのために使用される.so.dll。の並列例は、アプリのファイル名のvs 比較にapp/makefile役立ちます。たとえば、UnixライクなOSでは通常は表示されません。;-)empty string.exeapp.exe

1
LSF?LFS?打ち間違え?
フランクリンユー

19

私は最近、この質問に答えるために自分自身に問いかけていました。これが私の結論です:

Windowsでは、unameコマンドが使用できるかどうか確信が持てないので、gcc -dumpmachine。コンパイラのターゲットが表示されます。

unameいくつかのクロスコンパイルを行いたい場合、使用時に問題が発生する場合もあります。

以下は、可能な出力のリストの例ですgcc -dumpmachine

  • mingw32
  • i686-pc-cygwin
  • x86_64-redhat-linux

次のようにmakefileで結果を確認できます。

SYS := $(shell gcc -dumpmachine)
ifneq (, $(findstring linux, $(SYS)))
 # Do Linux things
else ifneq(, $(findstring mingw, $(SYS)))
 # Do MinGW things
else ifneq(, $(findstring cygwin, $(SYS)))
 # Do Cygwin things
else
 # Do things for others
endif

それは私にとってはうまくいきましたが、それがシステムタイプを取得する信頼できる方法であるかどうかはわかりません。少なくとも、MinGWについては信頼できます。WindowsにunameコマンドやMSYSパッケージを用意する必要がないため、これで十分です。

要約すると、unameあなたのシステム与えあなたがコンパイルしているこれを、そしてgcc -dumpmachineあなたのシステム与えためにあなたがコンパイルされているが。


これは良い点です。とにかくuname付属しMinGWていませんか?それにもかかわらず、クロスコンパイルに関する追加の注記は素晴らしいです。
Shahbaz

2
@Shahbaz MinGWセットアップはMSYS(unameを含む)をインストールできますが、オプションです。MinGW gccツールのみでシステムを見つけることはまだ可能です
phsym

1
これは、OS XやFreeBSDのように、Clangがデフォルトのコンパイラである場合には機能しません。
MarcusJ 2016年

@SebastianGodelet @MarcusJ簡単な修正です$(shell $(CC) -dumpmachine)。OS X Sierra以降、-dumpmachineコマンドはClangで機能します。
Vortico 2017年

OS X 10.12.5 では、それがx86_64-apple-darwin16.6.0gccccclangcl
、、

17

gitのメイクファイルは、多数のautoconf / automakeをせずに管理する方法の例、まだunixyプラットフォームの多くにはまだ仕事が含まれています。


13
GitがAutofoolsを使用していないことを知っていると、どういうわけか私は彼らへの嫌悪感を正当化するようになります...
Dan Molding

11
「オートフール」?それは意図的なタイプミスでしたか?:)
JesperE

6
そうだった。しかし、考え直してみると、「Autostools」の方が好きだと思います。:D
ダンモール

ところで、「彼ら」とは誰のことですか?GitまたはAutotoolsの人?:D
JesperE

8
英語はとても不正確な言語です。これはどうですか:if (!usesAutotools(git)) aversionTo(autotools) = justified;私はそれが私が嫌うツールだけであることも明確にします。Autotoolsの人たちはきっと素晴らしい人たちだと思います。
ダン成形

11

更新:私は今、この答えは時代遅れだと考えています。さらに完璧な新しいソリューションを投稿しました。

MakefileがCygwin以外のWindowsで実行されてunameいる可能性がある場合は、使用できない可能性があります。それは厄介ですが、これは潜在的な解決策です。PATH環境変数にもWINDOWSがあるため、最初にCygwinをチェックして除外する必要があります。

ifneq (,$(findstring /cygdrive/,$(PATH)))
    UNAME := Cygwin
else
ifneq (,$(findstring WINDOWS,$(PATH)))
    UNAME := Windows
else
    UNAME := $(shell uname -s)
endif
endif

これはこれでいいです!1つだけ教えてください。私はCygwinを使用していませんが、MinGWがPATHのビンパスでインストールされています。uname通常のcmd端末から発行すると、MINGWが表示されます。つまり、私はまだunameCygwinを使用せずに持っています。私はgit bashも持っていますが、unameを試したことはありません(現在はLinuxです)。これら2つをコードに組み込む方法を教えてください。
Shahbaz

unameが利用可能であることが確かな場合は、それが最善の解決策です。しかし、私の環境では、誰もがWindowsを使用しており、cygwinまたはmingwのいずれかがインストールされている人はほとんどいないため、unameと同じくらい標準的なものでも機能するという保証はありません。現在、コマンドシェルでmake.exeを実行している上記のコードに問題があります。Windowsは非常にイライラするプラットフォームです。
ケンジャクソン

つまり、PATHにWINDOWSが存在するかどうかをテストする前に、cygwinを処理していないことを確認します。MinGWを処理していないことを確認するにはどうすればよいですか。たとえば、Makefileでコマンドを実行できるかどうかをテストするunameことは可能ですか?実行できない場合は、Windowsであることがわかりますか?
Shahbaz

このMingw / cygwin / shell-or-cmd / Linuxのクリーンな解決策を見つけるのにも苦労しています。結局のところ、プリメイクやcmakeのようなものが最良のアイデアのように思えます。
Isaac Nequittepas 2013

これはもはや最良の解決策ではありません。私が投稿した新しいソリューションは、「;」を探すことでネイティブWindowsを区別します。シェル変数なしでPATH変数内。
ケンジャクソン

7

それがGNUのautomake / autoconfの仕事ですが解決するように設計されて。あなたはそれらを調査したいと思うかもしれません。

別の方法として、さまざまなプラットフォームで環境変数を設定し、それらに対してMakefileを条件付きにすることができます。


11
automake / autoconfを使用しないことを強くお勧めします。それらは使用するのが面倒で、ファイルやビルド時間に多くのオーバーヘッドを追加します。それらは通常、複雑さを追加するだけで、通常はほとんど効果がありません(システム間の移植性はありません)。
Johannes Overmann 2013年

1
自分のmakeやりたいことを学ぶために数日間過ごしました。automake / autoconfにも参加したいですか?- 番号。何ができるだけなので、私はいくつかの立ち寄りポイント私がコンパイル&リンクを改正したいすべての時間を持っていないという場合は、確かに、メイクファイルで行う必要があり、メイクファイルで行われます。
エンジニア

makefileはいくつのプラットフォームをサポートしていますか?automakeとautoconfは、多くのプラットフォームへの移植性が必要な場合に独自のものになります。
ダグラスリーダー2015

2
役に立たない依存関係を必要としないので、ビルド対象のOSを見つけるためだけにビルドシステム全体を変更します。
MarcusJ 2016年

7

私はこの問題を解決する完璧な解決策を見つけました。

ifeq '$(findstring ;,$(PATH))' ';'
    UNAME := Windows
else
    UNAME := $(shell uname 2>/dev/null || echo Unknown)
    UNAME := $(patsubst CYGWIN%,Cygwin,$(UNAME))
    UNAME := $(patsubst MSYS%,MSYS,$(UNAME))
    UNAME := $(patsubst MINGW%,MSYS,$(UNAME))
endif

UNAME変数は、Linux、Cygwin、MSYS、Windows、FreeBSD、NetBSD(またはおそらくSolaris、Darwin、OpenBSD、AIX、HP-UX)、または不明に設定されています。その後、Makefileの残りの部分で比較して、OSに依存する変数とコマンドを分離できます。

重要なのは、Windowsではセミコロンを使用してPATH変数のパスを区切るのに対し、他のすべての人はコロンを使用するということです。(名前に「;」を使用してLinuxディレクトリを作成し、それをPATHに追加することは可能ですが、これは壊れますが、だれがそのようなことをするのでしょうか?)これは、ネイティブWindowsを検出する最も危険な方法ではないようです。シェル呼び出しは必要ありません。CygwinとMSYSのPATHはコロンを使用しているのでuname、それらに対してが呼び出されます。

OS環境変数を使用してWindowsを検出できますが、CygwinとネイティブWindowsを区別することはできません。引用符のエコーのテストは機能しますが、シェルの呼び出しが必要です。

残念ながら、Cygwinはunameの出力にいくつかのバージョン情報を追加するため、「patsubst」呼び出しを追加して、それを「Cygwin」に変更しました。また、MSYSのunameには、実際にはMSYSまたはMINGWで始まる3つの可能な出力がありますが、patsubstも使用して、すべてを単に「MSYS」に変換します。

パスにuname.exeがある場合とない場合のネイティブWindowsシステムを区別することが重要な場合は、単純な割り当ての代わりに次の行を使用できます。

UNAME := $(shell uname 2>NUL || echo Windows)

すべてのケースで、もちろんGNUのmakeが必要な、または別されるメイク使用される関数をサポートする。


6

今日この問題に遭遇し、Solarisでそれが必要になったので、これを(非常に近いものに)行うPOSIX標準の方法を次に示します。

#Detect OS
UNAME = `uname`

# Build based on OS name
DetectOS:
    -@make $(UNAME)


# OS is Linux, use GCC
Linux: program.c
    @SHELL_VARIABLE="-D_LINUX_STUFF_HERE_"
    rm -f program
    gcc $(SHELL_VARIABLE) -o program program.c

# OS is Solaris, use c99
SunOS: program.c
    @SHELL_VARIABLE="-D_SOLARIS_STUFF_HERE_"
    rm -f program
    c99 $(SHELL_VARIABLE) -o program program.c

1
OSXでエラーを取得:「Makefile:22:***セパレーターがありません。停止してください。」この行:「-@ make $(UNAME_S)」。
Czarek Tomczak

OSXは準拠していない可能性があるため、これらを順番に試してください。(1)行の最初の文字としてTABを使用していることを確認します(2)makeの前にある「-@」を削除します(2a)2が機能した場合は、1つの文字を試し、次にもう1つの文字を試します(3) UNAME_Sが定義されています。-@ make $(UNAME_S)の代わりにecho $(UNAME_S)を試してください
Huckle

6

Windowsまたはposixのような(Linux / Unix / Cygwin / Mac)環境にいるかどうかを確認する簡単なソリューションを次に示します。

ifeq ($(shell echo "check_quotes"),"check_quotes")
   WINDOWS := yes
else
   WINDOWS := no
endif

これは、エコーがposixのような環境とWindows環境の両方に存在し、Windowsではシェルが引用符をフィルタリングしないという事実を利用しています。


1
$PATH別のものを参照する可能性があるため、非常に危険echoです(鉱山は...)
yyny

@YoYoYonnYパスが別のエコーを参照するのはなぜですか?非常にありそうもない状況のようです。
Samuel

1
そうではなく、gitがそれを実行し、mingwがそれを実行し、cygwinがそれを実行します...そして、個人的にC:\ Windows \ System32をパスの最下部に配置します。
yyny

1
この「ソリューション」はすべての環境で「機能」しますが、私の指摘は、これは間違いなくウィンドウを安全に検出しないということです。-mwindowsフラグを設定する.dll.so、またはから選択した場合、これは失敗します。
yyny

1
@YoYoYonnY明確にしていただきありがとうございます。私の状況では、自分が使用しているOSではなく、Cygwin、Windows、またはLinux環境にいる場合にのみ気遣ったので、これは私に役立ちました。あなたのニーズのような音は私のものとは異なります。
サミュエル

3

Makefileは間隔に非常に敏感であることに注意してください。以下は、OS Xで追加のコマンドを実行し、OS XとLinuxで動作するMakefileの例です。ただし、全体として、autoconf / automakeは、何でも簡単にできる方法です。

UNAME:= $(shell uname -s)
CPP = g ++
CPPFLAGS = -pthread -ansi -Wall -Werror -pedantic -O0 -g3 -I / nexopia / include
LDFLAGS = -pthread -L / nexopia / lib -lboost_system

HEADERS = data_structures.h http_client.h load.h lock.h search.h server.h thread.h utility.h
OBJECTS = http_client.o load.o lock.o search.o server.o thread.o utility.o vor.o

すべて:vor

掃除:
    rm -f $(OBJECTS)vor

vor:$(OBJECTS)
    $(CPP)$(LDFLAGS)-o vor $(OBJECTS)
ifeq($(UNAME)、ダーウィン)
    #Boostライブラリの場所を設定する
    install_name_tool -change libboost_system.dylib /nexopia/lib/libboost_system.dylib vor
endif

%.o:%.cpp $(HEADERS)Makefile
    $(CPP)$(CPPFLAGS)-c $

2

これを行う別の方法は、「構成」スクリプトを使用することです。makefileですでに使用している場合は、una​​meとsedの組み合わせを使用して問題を解決できます。まず、スクリプトで次のようにします。

UNAME=uname

次に、これをMakefileに入れるために、Makefile.inから始めます。

UNAME=@@UNAME@@

初期化。

次のsedコマンドをconfigureスクリプトでUNAME=uname少し使ってください。

sed -e "s|@@UNAME@@|$UNAME|" < Makefile.in > Makefile

これで、メイクファイルが必要にUNAME応じて定義されているはずです。if / elif / elseステートメントがすべて残っています!


最初の等価物はこれではありませんか?UNAME = $(uname)
ケンジャクソン

0


インクスケープのコマンドラインオプションを微調整するために、2つのバージョンのFedoraの違いを検出しなければならない場合がありました。-Fedora 31では、デフォルトのインクスケープは1.0betaを使用しています-Fedora --export-file
<31では、デフォルトのインクスケープ使用する0.92--export-pdf

私のメイクファイルには以下が含まれています

# set VERSION_ID from /etc/os-release

$(eval $(shell grep VERSION_ID /etc/os-release))

# select the inkscape export syntax

ifeq ($(VERSION_ID),31)
EXPORT = export-file
else
EXPORT = export-pdf
endif

# rule to convert inkscape SVG (drawing) to PDF

%.pdf : %.svg
    inkscape --export-area-drawing $< --$(EXPORT)=$@

/etc/os-release行が含まれているため、これは機能します

VERSION_ID=<value>

そのため、Makefileのシェルコマンドは文字列を返しVERSION_ID=<value>、evalコマンドはこれに基づいてMakefile変数を設定しますVERSION_ID。これは明らかに、メタデータの格納方法に応じて、他のOSに合わせて調整できます。Fedoraには、OSバージョンを与えるデフォルトの環境変数がないことに注意してください。そうでなければ、私はそれを使用したでしょう!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.