Using make for cross platform compilation

前端 未结 6 1745
野趣味
野趣味 2021-02-05 05:03

I am currently developing a C project under Linux and Win32. The \'deliverable\' is a shared library, and all the development is done under Linux with the GNU tool chain. I am u

6条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-05 05:36

    I use UNAME := $(shell uname) within my Makefile to detect the platform (Linux or MS-Windows).

    I provide below a complete example based on make and gcc to build a shared library: *.so or *.dll depending on the platform.

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

    To use make and gcc on MS-Windows, Cygwin or MinGW can be installed.

    The example uses 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.cpp)
            # '-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 (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
    

    The source code

    app/main.c

    #include "hello.h" //hello()
    #include  //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 the copy-paste of Makefiles (replace leading spaces by tabulation).

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

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

    > 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
    

提交回复
热议问题