One project should be compiled for Windows, Linux and an embedded target. The application has behavior differences when running on host or embedded targets. To summarize my requirements, here is the table:
Target Compiler Behavior
Windows MSVC, gcc A
Host Linux gcc A
Embedded Linux cross pltf gcc B
I wish to create a Makefile that would recognize the compiler and environmental differences automatically (without need to pass parameters/defines manually). Is it possible to resolve such problem by just using conditional compilation at C source file level?
I don'开发者_高级运维t use automake so far.The autotools were made to solve this problem. A Makefile by itself can't do this.
As for conditional compilation, there are several macros available that these compilers define (e.g. _MSC_VER
for MSVC++, _WIN32
for Windows and and __linux__
for Linux). Also, gcc provides assertions for handling different CPU targets.
Target Compiler Conditional
Windows MSVC++ #ifdef _MSC_VER
Windows gcc #if defined(_WIN32) && defined(__GNUC__)
Linux gcc #if defined(__linux__) && defined(__GNUC__)
Platform (x86) gcc #if #cpu(i386)
Platform (arm) gcc #if #cpu(arm)
That should be sufficient for your purposes.
My answer is: probably. It depends on the differences between your environments.
I would generate a list of the macros pre-defined by the preprocessor in gcc for each of your environments. All you need to do is create an empty file, say foo.h
, and run the following command: gcc -E -dM foo.h
for each environment. I'd redirect the output to a different file for each environment.
Then, compare the predefined macros and look for one that fits the bill. In your question, you indicated that the embedded environment has different behavior from the Windows and Host Linux platforms. Assuming you're using a different chip architecture for the embedded environment, there should be a macro defined that indicates the architecture. For example, on my 64-bit linux box, __x86_64__
is defined.
Once you have that info, use that macro as your conditional value:
#ifdef MACRO_INDICATING_EMBEDDED
// Behavior B
#else
// Behavior A
#endif
gcc will define
__linux__
when compiling on linux. MSVC defines something similar - I forget which but I am sure the docs will tell you
but really you need to learn how to use configure. Thats what its for. Its a pain to learn but highly useful (automake, autoconf etc)
You could try a combination of predefined macros for operating systems and architectures; perhaps also interesting: compiler ids.
If you don't want to use a more sophisticated build system, you can parse command line arguments within your makefile. A simple example would be the addition of .exe
to executable names on windows. For this I have code like this within the makefile
ifeq ($(target),win32)
foo_binary := $(foo_binary).exe
endif
and invoke make via a make.bat
file containing
@make.exe target=win32 %*
精彩评论