Detecção de compilação do Windows e *nix
-
20-09-2019 - |
Pergunta
Um projeto deve ser compilado para Windows, Linux e um alvo incorporado.O aplicativo apresenta diferenças de comportamento ao ser executado em hosts ou destinos incorporados.Para resumir meus requisitos, aqui está a tabela:
Target Compiler Behavior
Windows MSVC, gcc A
Host Linux gcc A
Embedded Linux cross pltf gcc B
Desejo criar um Makefile que reconheça o compilador e as diferenças ambientais automaticamente (sem necessidade de passar parâmetros/definições manualmente).É possível resolver esse problema usando apenas a compilação condicional no nível do arquivo de origem C?
Eu não uso o automake até agora.
Solução
o AutoTools foram feitos para resolver esse problema. Um Makefile por si só não pode fazer isso.
Quanto à compilação condicional, existem várias macros disponíveis que esses compiladores definem (por exemplo _MSC_VER
Para MSVC ++, _WIN32
para janelas e e __linux__
para Linux). Além disso, o GCC fornece afirmações para lidar com diferentes alvos da CPU.
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)
Isso deve ser suficiente para seus propósitos.
Outras dicas
Minha resposta é: provavelmente. Depende das diferenças entre seus ambientes.
Eu geraria uma lista das macros precedidas pelo pré-processador no GCC para cada um de seus ambientes. Tudo que você precisa fazer é criar um arquivo vazio, digamos foo.h
, e execute o seguinte comando: gcc -E -dM foo.h
para cada ambiente. Eu redirecionaria a saída para um arquivo diferente para cada ambiente.
Em seguida, compare as macros predefinidas e procure uma que se encaixe na conta. Em sua pergunta, você indicou que o ambiente incorporado tem um comportamento diferente das plataformas Windows e Host Linux. Supondo que você esteja usando uma arquitetura de chip diferente para o ambiente incorporado, deve haver uma macro definida que indique a arquitetura. Por exemplo, na minha caixa Linux de 64 bits, __x86_64__
é definido.
Depois de ter essas informações, use essa macro como seu valor condicional:
#ifdef MACRO_INDICATING_EMBEDDED
// Behavior B
#else
// Behavior A
#endif
O GCC definirá
__linux__
Ao compilar no Linux. MSVC define algo semelhante - eu esqueço qual, mas tenho certeza que os documentos lhe dirão
Mas realmente você precisa aprender a usar a configuração. É para isso que é. É uma dor para aprender, mas altamente útil (Autorake, Autoconf etc)
Você poderia tentar uma combinação de macros predefinidas para sistemas operacionais e arquiteturas;talvez também interessante: IDs do compilador.
Se não quiser usar um sistema de compilação mais sofisticado, você pode analisar os argumentos da linha de comando dentro do seu makefile.Um exemplo simples seria a adição de .exe
para nomes de executáveis no Windows.Para isso tenho um código como este dentro do makefile
ifeq ($(target),win32)
foo_binary := $(foo_binary).exe
endif
e invocar make através de um make.bat
arquivo contendo
@make.exe target=win32 %*