tell if make is running on windows or linux
Asked Answered
S

2

9

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.

Selie answered 24/10, 2011 at 14:5 Comment(4)
It's Time to use Maven. It is platform independent.Contradistinction
To sidestep this particular issue, you could just include the .exe suffix on all platforms; Linux won't mind it if it's there, as long as you remember to include it when running the program.Immaterial
This is a duplicate of https://mcmap.net/q/20159/-os-detecting-makefileDeluge
@Deluge Disagree that this is a duplicate. I searched for this specific question about .exe on different OSes, but Google showed first the question you referenced, which had no direct answer, only a collection of various techniques to identify an OS, not specifically how to optionally add a ".exe" file extension solely for the platforms that use it. The other techniques may allow for a wider range of more generic solutions to similar problems, but it's not the same as a duplicate answering or even asking this specific question.Resect
C
5

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

Couperin answered 24/10, 2011 at 14:11 Comment(2)
thanks, i think this should work. maybe add some code for ignoring versions, so that it can work on different relasesSelie
Makefiles I've invoked from Powershell have failed when I try this, since they can't find uname. For MinGW/MSYS, maybe you could just have your makefile check for the $MSYSTEM environment variable? Though that won't help in Cygwin.Macarthur
G
5

UPDATE
Please read this similar but better answer:
https://mcmap.net/q/20159/-os-detecting-makefile


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
Gopher answered 8/2, 2013 at 17:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.