Reputation: 303
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.
Upvotes: 9
Views: 18705
Reputation: 54541
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
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
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";
}
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 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
Upvotes: 5
Reputation: 62528
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
Upvotes: 5