tell if make is running on windows or linux

17.7k views Asked by At

Is there a way to know in makefiles if GNU make is running on a linux OS or a windows OS?

I've built a bash script that generates a makefile for building my app and it works fine on my Debian machine. I want to try to build it on MinGW/MSYS, but the problem is that I have to build and run some test programs that check errors in source code, and to run it on Windows, I must add the .exe suffix.

2

There are 2 answers

2
Rook On BEST ANSWER

uname command should give you the basic info about the OS. Can you use that, and then make an IF based on the return value?

As not to rewrite everything, here - these two questions may be of some interest to you
1. OS detecting makefile
2. Makefile that distincts between Windows and Unix-like systems

0
oHo On

UPDATE
Please read this similar but better answer:
https://stackoverflow.com/a/14777895/938111


make (and gcc) can be easily installed on MS-Windows using Cygwin or MinGW.

As @ldigas says, make can detect the platform using UNAME:=$(shell uname) (the command uname is also installed by Cygwin or MinGW installer).

Below, I provide a complete example based on make (and gcc) to explain how to build a shared library: *.so or *.dll depending on the platform.

The example is basic/simple to be easily understandable :-)

Let's see the five files:

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

The 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.c)
        # '-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 (hello.o)
        # '-c $<' => compile the first depended file (hello.c)
        # '-fPIC' => Position-Independent Code (required for shared lib)

clean:
        rm -f *.o *.so *.dll *.exe

The source code

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";
}

The build

Fix Makefiles copy (replace leading spaces by tabulation).

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

The make command is the same on both platforms. This is the output on MS-Windows (removed unnecessary lines).

> 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

The run

The application requires to know where is the shared library.

On MS-Windows, the simple/basic/stupid way is to copy the library where the application is:

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

On Linux, use the LD_LIBRARY_PATH environment variable:

> export LD_LIBRARY_PATH=lib

The run command line and output are the same on both platforms:

> app/app.exe
hello