Rotineiramente, trabalho em vários computadores e sistemas operacionais diferentes, que são Mac OS X, Linux ou Solaris. Para o projeto em que estou trabalhando, retiro meu código de um repositório git remoto.
Eu gosto de poder trabalhar em meus projetos, independentemente do terminal em que estou. Até agora, encontrei maneiras de contornar as alterações no sistema operacional alterando o makefile toda vez que troco de computador. No entanto, isso é tedioso e causa um monte de dores de cabeça.
Como posso modificar meu makefile para detectar qual SO estou usando e modificar a sintaxe de acordo?
Aqui está o makefile:
cc = gcc -g
CC = g++ -g
yacc=$(YACC)
lex=$(FLEX)
all: assembler
assembler: y.tab.o lex.yy.o
$(CC) -o assembler y.tab.o lex.yy.o -ll -l y
assembler.o: assembler.c
$(cc) -o assembler.o assembler.c
y.tab.o: assem.y
$(yacc) -d assem.y
$(CC) -c y.tab.c
lex.yy.o: assem.l
$(lex) assem.l
$(cc) -c lex.yy.c
clean:
rm -f lex.yy.c y.tab.c y.tab.h assembler *.o *.tmp *.debug *.acts
fonte
PROCESSOR_ARCHITECTURE
envvar parece estar virtualizado, dependendo se o processo é de 32 ou 64 bits. Portanto, se vocêmake
tem 32 bits e está tentando criar um aplicativo de 64 bits, ele falhará. Usá-lo em combinação comPROCESSOR_ARCHITEW6432
funcionou para mim (ver esta , e que )make
equipe adicionasse algumas variáveis mágicas com os e arch, provavelmente com muitos problemas.OS
está definido em sistemas não Windows. Faça guloseimas desabilitadas da mesma forma que vazias, o que causará um salto nouname
bloco baseado em. Você só precisa adicionar uma verificação do FreeBSD lá./bin/sh: -c: line 0: syntax error near unexpected token
, Windows_NT '/ bin / sh: -c: linha 0:ifeq (,Windows_NT)' make: *** [os] Error 2
O comando uname ( http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/uname.1.html ) sem parâmetros deve informar o nome do sistema operacional. Eu usaria isso, então faria condicionais com base no valor de retorno.
Exemplo
fonte
Detecte o sistema operacional usando dois truques simples:
OS
uname
comandoOu uma maneira mais segura, se não estiver no Windows e
uname
indisponível:Ken Jackson propõe uma alternativa interessante se você deseja distinguir Cygwin / MinGW / MSYS / Windows. Veja a resposta dele assim:
Depois, você pode selecionar o material relevante, dependendo de
detected_OS
:Notas:
O comando
uname
é o mesmo queuname -s
opção-s
(--kernel-name
) é o padrão. Veja por queuname -s
é melhor queuname -o
.O uso de
OS
(em vez deuname
) simplifica o algoritmo de identificação. Você ainda pode usar apenasuname
, mas precisa lidar com osif/else
blocos para verificar todas as variações do MinGW, Cygwin etc.A variável de ambiente
OS
é sempre definida como"Windows_NT"
em diferentes versões do Windows (consulte%OS%
variável de ambiente na Wikipedia ).Uma alternativa de
OS
é a variável de ambienteMSVC
(verifica a presença do MS Visual Studio , veja o exemplo usando o Visual C ++ ).Abaixo, forneço um exemplo completo usando
make
egcc
para criar uma biblioteca compartilhada:*.so
ou*.dll
dependendo da plataforma. O exemplo é o mais simples possível para ser mais compreensível.Para instalar
make
egcc
no Windows, consulte Cygwin ou MinGW .Meu exemplo é baseado em cinco arquivos
Lembrete:
Makefile
é recuado usando tabulação . Cuidado ao copiar e colar abaixo dos arquivos de amostra.Os dois
Makefile
arquivos1
lib/Makefile
2)
app/Makefile
Para saber mais, leia a documentação de Variáveis automáticas , conforme indicado pelo cfi .
O código fonte
-
lib/hello.h
-
lib/hello.c
-
app/main.c
A compilação
Corrija a copiar-colar de
Makefile
(substitua os espaços à esquerda por uma tabulação).O
make
comando é o mesmo nas duas plataformas. A saída fornecida é em sistemas operacionais semelhantes ao Unix:A corrida
O aplicativo requer saber onde está a biblioteca compartilhada.
No Windows, uma solução simples é copiar a biblioteca onde o aplicativo está:
Em sistemas operacionais semelhantes ao Unix, você pode usar a
LD_LIBRARY_PATH
variável de ambiente:Execute o comando no Windows:
Execute o comando em sistemas operacionais semelhantes ao Unix:
fonte
uname
não é Linux. Dou apenas um exemplo que você pode não precisar, mas isso pode ajudar alguém a pesquisar (na Web) uma maneira de implementar umMakefile
para ambas as plataformas ;-) O que devo mudar na minha resposta? Cheerslib/Makefile
exemplo,target
é usado para.so
vs.dll
. Um exemplo paralelo para oapp/makefile
seria útil para a comparaçãoempty string
vs.exe
para o nome do arquivo do aplicativo. Por exemplo, eu não costumo verapp.exe
em sistemas operacionais semelhantes ao Unix. ;-)Eu estava experimentando recentemente para responder a essa pergunta que estava me perguntando. Aqui estão as minhas conclusões:
Como no Windows, você não pode ter certeza de que o
uname
comando está disponível, você pode usá-logcc -dumpmachine
. Isso exibirá o destino do compilador.Também pode haver um problema ao usar
uname
se você deseja fazer alguma compilação cruzada.Aqui está uma lista de exemplo de saída possível de
gcc -dumpmachine
:Você pode verificar o resultado no makefile assim:
Funcionou bem para mim, mas não tenho certeza de que seja uma maneira confiável de obter o tipo de sistema. Pelo menos, é confiável sobre o MinGW e é tudo o que preciso, pois não requer o
uname
comando ou o pacote MSYS no Windows.Para resumir,
uname
fornece o sistema no qual você está compilando egcc -dumpmachine
o sistema para o qual você está compilando.fonte
uname
vem deMinGW
qualquer maneira? No entanto, a nota extra sobre compilação cruzada é ótima.$(shell $(CC) -dumpmachine)
. No OS X Sierra, o comando -dumpmachine funciona no Clang.x86_64-apple-darwin16.6.0
e que obras o tempo que você chamá-logcc
,cc
ouclang
, mas nãocl
O makefile do git contém vários exemplos de como gerenciar sem o autoconf / automake, mas ainda funciona em várias plataformas unixy.
fonte
if (!usesAutotools(git)) aversionTo(autotools) = justified;
vou esclarecer também que são apenas as ferramentas às quais sou avesso. Tenho certeza de que o pessoal da Autotools é uma pessoa legal.Atualização: Agora considero esta resposta obsoleta. Postei uma nova solução perfeita mais abaixo.
Se o seu makefile pode estar em execução no Windows não Cygwin,
uname
pode não estar disponível. Isso é estranho, mas essa é uma solução potencial. Você deve verificar primeiro o Cygwin para descartá-lo, porque ele também possui o WINDOWS em suaPATH
variável de ambiente.fonte
uname
partir de um terminal cmd normal, isso me dará MINGW. O que quero dizer é que ainda tenhouname
sem usar o Cygwin. Eu também tenho o git bash, mas ainda não tentei uname (agora estou no Linux). Você pode me dizer como esses dois podem ser incorporados ao seu código?uname
não for possível, entenderíamos que estamos no Windows?Esse é o trabalho que o automake / autoconf do GNU foi projetado para resolver. Você pode querer investigá-los.
Como alternativa, você pode definir variáveis de ambiente em suas diferentes plataformas e tornar o Makefile condicional em relação a elas.
fonte
make
a fazer o que quero. Agora, também quero entrar no automake / autoconf? - NÃO. O que pode ser feito no makefile, certamente deve ser feito no makefile, mesmo que apenas para que eu não tenha vários pontos de parada toda vez que eu desejar alterar a compilação e o link.Finalmente encontrei a solução perfeita que resolve esse problema para mim.
A variável UNAME está configurada para Linux, Cygwin, MSYS, Windows, FreeBSD, NetBSD (ou presumivelmente Solaris, Darwin, OpenBSD, AIX, HP-UX) ou Desconhecido. Em seguida, ele pode ser comparado em todo o restante do Makefile para separar quaisquer variáveis e comandos sensíveis ao SO.
A chave é que o Windows usa ponto e vírgula para separar os caminhos na variável PATH, enquanto todos os outros usam dois pontos. (É possível criar um diretório Linux com um ';' no nome e adicioná-lo ao PATH, o que quebraria isso, mas quem faria isso?) Esse parece ser o método menos arriscado para detectar o Windows nativo porque ele não precisa de uma chamada de shell. Os Cygwin e Msys uso PATH dois pontos assim uname é chamado por eles.
Observe que a variável de ambiente do sistema operacional pode ser usada para detectar o Windows, mas não para distinguir entre o Cygwin e o Windows nativo. Testar o eco de aspas funciona, mas requer uma chamada de shell.
Infelizmente, Cygwin adiciona algumas informações de versão à saída de uname , então adicionei as chamadas 'patsubst' para alterá-las para apenas 'Cygwin'. Além disso, uname para MSYS na verdade tem três saídas possíveis começando com MSYS ou MINGW, mas eu também uso o patsubst para transformar tudo em apenas 'MSYS'.
Se é importante distinguir entre sistemas Windows nativos com e sem o uname.exe no caminho, essa linha pode ser usada em vez da atribuição simples:
É claro que em todos os casos é necessário o GNU make , ou outro make que suporte as funções usadas.
fonte
Encontrei esse problema hoje e precisava dele no Solaris, então aqui está uma maneira padrão do POSIX de fazer (algo muito próximo disso) isso.
fonte
Aqui está uma solução simples que verifica se você está em um ambiente Windows ou posix (Linux / Unix / Cygwin / Mac):
Ele aproveita o fato de que o eco existe nos ambientes do tipo posix e do Windows, e que no Windows o shell não filtra as aspas.
fonte
$PATH
pode se referir a outroecho
(Minas faz ...)-mwindows
sinalizador ou escolher entre a.dll
ou.so
, isso falhará.Observe que os Makefiles são extremamente sensíveis ao espaçamento. Aqui está um exemplo de um Makefile que executa um comando extra no OS X e que funciona no OS X e Linux. No geral, porém, autoconf / automake é o caminho a percorrer para qualquer coisa que não seja trivial.
fonte
Outra maneira de fazer isso é usando um script "configure". Se você já está usando um com seu makefile, pode usar uma combinação de uname e sed para fazer com que as coisas funcionem. Primeiro, no seu script, faça:
Então, para colocar isso no seu Makefile, comece com Makefile.in, que deve ter algo como
iniciar.
Use o seguinte comando sed no seu script de configuração após o
UNAME=uname
bit.Agora seu makefile deveria ter
UNAME
definido como desejado. Se as instruções / elif / else são tudo o que resta!fonte
Eu tive um caso em que tive que detectar a diferença entre duas versões do Fedora, para ajustar as opções de linha de comando do inkscape:
- no Fedora 31, o inkscape padrão é 1.0beta que usa
--export-file
- no Fedora <31, o inkscape padrão é 0,92 que usa
--export-pdf
Meu Makefile contém o seguinte
Isso funciona porque
/etc/os-release
contém uma linhapara que o comando shell no Makefile retorne a string
VERSION_ID=<value>
, o comando eval atua sobre isso para definir a variável MakefileVERSION_ID
. Obviamente, isso pode ser ajustado para outros sistemas operacionais, dependendo de como os metadados são armazenados. Note que no Fedora não existe uma variável de ambiente padrão que dê a versão do sistema operacional, caso contrário eu teria usado isso!fonte