<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pt-BR"><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" hreflang="pt-BR" /><updated>2026-04-12T18:13:15+00:00</updated><id>/feed.xml</id><title type="html">rafaellcoellho.com</title><subtitle>Blog sobre programação e desenvolvimento de software</subtitle><author><name>Rafael Coelho</name></author><entry xml:lang="pt"><title type="html">Usando argparse, tox e setuptools para fazer aplicativo de cli em python</title><link href="/2022/10/16/argparse-tox-setuptools-para-fazer-aplicativo-de-cli-em-python.html" rel="alternate" type="text/html" title="Usando argparse, tox e setuptools para fazer aplicativo de cli em python" /><published>2022-10-16T14:45:00+00:00</published><updated>2022-10-16T14:45:00+00:00</updated><id>/2022/10/16/argparse-tox-setuptools-para-fazer-aplicativo-de-cli-em-python</id><content type="html" xml:base="/2022/10/16/argparse-tox-setuptools-para-fazer-aplicativo-de-cli-em-python.html">&lt;p&gt;Vou escrever um aplicativo “hello world” para aprender como escrever, testar e
deployar um aplicativo de linha de comando.&lt;/p&gt;

&lt;h3 id=&quot;criando-aplicação&quot;&gt;Criando aplicação&lt;/h3&gt;

&lt;p&gt;O python já vem com uma biblioteca para facilitar a criação de aplicações de linha
de comando chamada argparse. Vou começar criando o modulo principal:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;└── cli
    ├── main.py
    └── __init__.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O arquivo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.py&lt;/code&gt; vai conter todo o código:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;greet&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f&quot;hello &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vou testar se o módulo está funcionando usando a linha de comando:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python -m cli.main rafael
hello rafael
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sucesso! Mas caso a minha aplicação comece a ficar mais complexa não vou querer
testar manualmente todas as possibilidades. Vou criar um teste para garantir que
essa lógica esteja sempre correta.&lt;/p&gt;

&lt;h3 id=&quot;escrevendo-testes&quot;&gt;Escrevendo testes&lt;/h3&gt;

&lt;p&gt;Criando o mudulo de testes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── cli
│   ├── __init__.py
│   ├── main.py
└── tests
    ├── __init__.py
    └── test_cli.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Utilizei a própria função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; para passar os argumentos e o pytest também
ajuda a checar o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; utilizando o argumento &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capsys&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cli.main&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_hello_world_cli&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capsys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capsys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readouterr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello test&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Usando pytest:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pytest
============================= test session starts ==============================
platform linux -- Python 3.10.4, pytest-7.1.3, pluggy-1.0.0
[...]
collected 1 item                                                               

tests/test_cli.py .                                                      [100%]

============================== 1 passed in 0.01s ===============================
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mas ter que rodar o pytest instalado globalmente não é tão bom assim. Prefiro utilizar
a ferramenta tox, que vai automatizar esses testes serem executados em vários ambientes
diferentes. Mas antes disso é preciso empacotar a nossa aplicação utilizando o
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setuptoopls&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;empacotando-usando-setuptools&quot;&gt;Empacotando usando setuptools&lt;/h3&gt;

&lt;p&gt;O &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setuptools&lt;/code&gt; precisa de alguns arquivos de configuração para empacotar
o aplicativo, são eles: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.py&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.cfg&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt;. Após criar eles
na raiz do projeto, é preciso preencher o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.py&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt; com valores
padrão:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;setuptools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[build-system]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;build-backend&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;setuptools.build_meta&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[&quot;setuptools&quot;, &quot;wheel&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora vou criar o arquivo principal, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.cfg&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[metadata]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;greet&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0.0.1&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[options]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;packages&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cli&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[options.entry_points]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;console_scripts&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;greet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cli.main:main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora basta usar o comando build:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python -m build
* Creating virtualenv isolated environment...
* Installing packages in isolated environment... (setuptools, wheel)
* Getting dependencies for sdist...
[...]
Successfully built greet-0.0.1.tar.gz and greet-0.0.1-py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Temos o nosso pacote na pasta &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dist/&lt;/code&gt;. Para instalar basta usar pip:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pip install dist/greet-0.0.1-py3-none-any.whl 
Processing ./dist/greet-0.0.1-py3-none-any.whl
Installing collected packages: greet
Successfully installed greet-0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora a aplicação foi instalada, basta usar:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ greet rafael
hello rafael
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finalmente posso usar o tox para rodar os testes.&lt;/p&gt;

&lt;h3 id=&quot;rodando-testes-com-tox&quot;&gt;Rodando testes com tox&lt;/h3&gt;

&lt;p&gt;Adicionando o arquivo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tox.ini&lt;/code&gt; na raiz do projeto com uma configuração bem básica:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[tox]
envlist = py310

[testenv]
deps = pytest
commands =
    pytest {posargs:tests}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Para rodar os testes em todos os ambientes disponíveis na sua máquina:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ tox --skip-missing-interpreters
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Caso eu queira rodar um teste especifico em um ambiente específico:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ tox -e py310 -- tests/test_cli.py::test_hello_world_cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;black-mypy-e-pre-commit&quot;&gt;Black, mypy e pre-commit&lt;/h3&gt;

&lt;p&gt;Também vou adicionar algumas ferramentas para ajudar no desenvolvimento. Mais
um arquivo de configuração na raiz do projeto chamado &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pre-commit-config.yaml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/pre-commit-hooks&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v3.2.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;trailing-whitespace&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;end-of-file-fixer&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;check-yaml&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/psf/black&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;22.10.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;black&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/mirrors-mypy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v0.982&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mypy&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;additional_dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;types-all&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A ideia é usar o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pre-commit&lt;/code&gt; para sempre utilizar o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mypy&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; antes de
cada commit. Para iniciar no projeto basta:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Caso queira executar sem fazer commit basta usar:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pre-commit run --all-files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h3&gt;

&lt;p&gt;Esse foi o esqueleto básico de uma aplicação de linha de comando usando python.
O código-fonte mostrado nesse post se encontra no
&lt;a href=&quot;https://github.com/rafaellcoellho/exemplo-cli-python&quot;&gt;meu github&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;referências&quot;&gt;Referências&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/argparse.html&quot;&gt;tutorial do argparse&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html&quot;&gt;testar stdout usando pytest&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tox.wiki/en/latest/&quot;&gt;documentação do tox&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pybit.es/articles/how-to-package-and-deploy-cli-apps/&quot;&gt;tutorial explicando como empacotar aplicativos python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pypa-build.readthedocs.io/en/stable/&quot;&gt;página da documentação do build&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pre-commit.com/&quot;&gt;documentação do pre-commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="python" /><category term="cli" /><category term="argparse" /><category term="tox" /><category term="setuptools" /><category term="pre-commit" /><summary type="html">Vou escrever um aplicativo “hello world” para aprender como escrever, testar e deployar um aplicativo de linha de comando.</summary></entry><entry xml:lang="en"><title type="html">Using argparse, tox and setuptools to build a Python CLI app</title><link href="/en/2022/10/16/argparse-tox-setuptools-python-cli-app/" rel="alternate" type="text/html" title="Using argparse, tox and setuptools to build a Python CLI app" /><published>2022-10-16T14:45:00+00:00</published><updated>2022-10-16T14:45:00+00:00</updated><id>/en/2022/10/16/argparse-tox-setuptools-python-cli-app</id><content type="html" xml:base="/en/2022/10/16/argparse-tox-setuptools-python-cli-app/">&lt;p&gt;I’ll write a “hello world” application to learn how to write, test and
deploy a command-line application.&lt;/p&gt;

&lt;h3 id=&quot;creating-the-application&quot;&gt;Creating the application&lt;/h3&gt;

&lt;p&gt;Python ships with a library to make building command-line applications easier
called argparse. I’ll start by creating the main module:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;└── cli
    ├── main.py
    └── __init__.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.py&lt;/code&gt; file will contain all the code:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;greet&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f&quot;hello &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ll test if the module is working using the command line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python -m cli.main rafael
hello rafael
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Success! But if my application starts getting more complex I won’t want to
test all possibilities manually. I’ll create a test to ensure this
logic is always correct.&lt;/p&gt;

&lt;h3 id=&quot;writing-tests&quot;&gt;Writing tests&lt;/h3&gt;

&lt;p&gt;Creating the test module:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── cli
│   ├── __init__.py
│   ├── main.py
└── tests
    ├── __init__.py
    └── test_cli.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function itself to pass arguments, and pytest also
helps check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capsys&lt;/code&gt; argument:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cli.main&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_hello_world_cli&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capsys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capsys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readouterr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello test&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using pytest:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pytest
============================= test session starts ==============================
platform linux -- Python 3.10.4, pytest-7.1.3, pluggy-1.0.0
[...]
collected 1 item                                                               

tests/test_cli.py .                                                      [100%]

============================== 1 passed in 0.01s ===============================
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But having to run a globally installed pytest isn’t ideal. I prefer using
the tox tool, which will automate running these tests in multiple different environments.
But first we need to package our application using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setuptools&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;packaging-with-setuptools&quot;&gt;Packaging with setuptools&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setuptools&lt;/code&gt; needs some configuration files to package
the application: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.py&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.cfg&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt;. After creating them
at the root of the project, fill in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.py&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt; with default values:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;setuptools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[build-system]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;build-backend&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;setuptools.build_meta&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[&quot;setuptools&quot;, &quot;wheel&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I’ll create the main file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.cfg&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[metadata]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;greet&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0.0.1&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[options]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;packages&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cli&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[options.entry_points]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;console_scripts&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;greet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cli.main:main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now just use the build command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python -m build
* Creating virtualenv isolated environment...
* Installing packages in isolated environment... (setuptools, wheel)
* Getting dependencies for sdist...
[...]
Successfully built greet-0.0.1.tar.gz and greet-0.0.1-py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We have our package in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dist/&lt;/code&gt; folder. To install it just use pip:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pip install dist/greet-0.0.1-py3-none-any.whl 
Processing ./dist/greet-0.0.1-py3-none-any.whl
Installing collected packages: greet
Successfully installed greet-0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now the application is installed, just use it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ greet rafael
hello rafael
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I can finally use tox to run the tests.&lt;/p&gt;

&lt;h3 id=&quot;running-tests-with-tox&quot;&gt;Running tests with tox&lt;/h3&gt;

&lt;p&gt;Adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tox.ini&lt;/code&gt; file at the root of the project with a very basic configuration:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[tox]
envlist = py310

[testenv]
deps = pytest
commands =
    pytest {posargs:tests}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To run tests in all available environments on your machine:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ tox --skip-missing-interpreters
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If I want to run a specific test in a specific environment:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ tox -e py310 -- tests/test_cli.py::test_hello_world_cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;black-mypy-and-pre-commit&quot;&gt;Black, mypy and pre-commit&lt;/h3&gt;

&lt;p&gt;I’ll also add some tools to help with development. One more
configuration file at the root of the project called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pre-commit-config.yaml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/pre-commit-hooks&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v3.2.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;trailing-whitespace&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;end-of-file-fixer&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;check-yaml&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/psf/black&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;22.10.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;black&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/mirrors-mypy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v0.982&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mypy&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;additional_dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;types-all&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The idea is to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pre-commit&lt;/code&gt; to always run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mypy&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;black&lt;/code&gt; before
each commit. To set it up in the project:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To run it without making a commit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ pre-commit run --all-files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This was the basic skeleton of a command-line application using Python.
The source code shown in this post can be found on
&lt;a href=&quot;https://github.com/rafaellcoellho/exemplo-cli-python&quot;&gt;my github&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/argparse.html&quot;&gt;argparse tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html&quot;&gt;test stdout using pytest&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tox.wiki/en/latest/&quot;&gt;tox documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pybit.es/articles/how-to-package-and-deploy-cli-apps/&quot;&gt;tutorial explaining how to package Python applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pypa-build.readthedocs.io/en/stable/&quot;&gt;build documentation page&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pre-commit.com/&quot;&gt;pre-commit documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="python" /><category term="cli" /><category term="argparse" /><category term="tox" /><category term="setuptools" /><category term="pre-commit" /><summary type="html">I’ll write a “hello world” application to learn how to write, test and deploy a command-line application.</summary></entry><entry xml:lang="en"><title type="html">Makefile as a Command Runner</title><link href="/en/2022/02/26/makefile-as-command-runner/" rel="alternate" type="text/html" title="Makefile as a Command Runner" /><published>2022-02-26T23:34:29+00:00</published><updated>2022-02-26T23:34:29+00:00</updated><id>/en/2022/02/26/makefile-as-command-runner</id><content type="html" xml:base="/en/2022/02/26/makefile-as-command-runner/">&lt;p&gt;Make is a “build automation tool” according to &lt;a href=&quot;https://en.wikipedia.org/wiki/Make_(software)&quot;&gt;wikipedia&lt;/a&gt;.
But it can be useful even when there’s nothing to compile.&lt;/p&gt;

&lt;p&gt;It’s possible to use make as a command runner. The advantage of using make
for this is that it’s commonly found in Linux distributions. It’s also
easy to read, write and maintain a makefile for this purpose.&lt;/p&gt;

&lt;p&gt;An example of this can be found in the &lt;a href=&quot;https://github.com/samuelcolvin/pydantic&quot;&gt;pydantic&lt;/a&gt; project.
I’ll use the &lt;a href=&quot;https://github.com/samuelcolvin/pydantic/blob/v1.9.0/Makefile&quot;&gt;makefile from version 1.9.0 of the lib&lt;/a&gt; as an example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.DEFAULT_GOAL := all
isort = isort pydantic tests
black = black -S -l 120 --target-version py38 pydantic tests

[...]

.PHONY: lint
lint:
	flake8 pydantic/ tests/
	$(isort) --check-only --df
	$(black) --check --diff

[...]

.PHONY: mypy
mypy:
	mypy pydantic

[...]

.PHONY: test
test:
	pytest --cov=pydantic

.PHONY: testcov
testcov: test
	@echo &quot;building coverage html&quot;
	@coverage html

[...]

.PHONY: all
all: lint mypy testcov

[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;how-make-executes-a-rule&quot;&gt;How make executes a rule&lt;/h2&gt;

&lt;p&gt;Assuming I’m in the root folder of the pydantic project and I run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make looks for the first rule in the file to start executing. This is
called the &lt;strong&gt;default goal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In pydantic’s makefile, it uses the special variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.DEFAULT_GOAL&lt;/code&gt;
to point to which rule make should execute first. Even though
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lint&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mypy&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testcov&lt;/code&gt; rules are written before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt; rule,
they will be executed afterwards.&lt;/p&gt;

&lt;h2 id=&quot;how-to-run-a-specific-rule&quot;&gt;How to run a specific rule&lt;/h2&gt;

&lt;p&gt;If I only want to run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testcov&lt;/code&gt; rule:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make testcov
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case make will only run the &lt;strong&gt;testcov&lt;/strong&gt; rule and its dependency
target &lt;strong&gt;test&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;phony-targets&quot;&gt;.PHONY targets&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.PHONY&lt;/code&gt; syntax is used to signal that the target is not
a filename. This avoids a possible conflict with the name of a real
file and optimizes performance. The syntax:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.PHONY action_name
action_name: dependencies
  commands
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;print-command-output&quot;&gt;Print command output&lt;/h2&gt;

&lt;p&gt;The default behavior of make is that &lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Echoing&quot;&gt;every command executed is sent to standard output&lt;/a&gt;.
One way to prevent this is to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--silent&lt;/code&gt; flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make --silent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want it to only print without executing the commands, there is the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--just-print&lt;/code&gt; flag:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make --just-print
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;help-command&quot;&gt;Help command&lt;/h2&gt;

&lt;p&gt;Moving away from the pydantic makefile example and into other tips.&lt;/p&gt;

&lt;p&gt;Browsing the web there are several examples of ways to automatically add a help
command to a makefile. One of the most interesting I found was
&lt;a href=&quot;https://gist.github.com/klmr/575726c7e05d8780505a&quot;&gt;this one&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.PHONY: help
help:
	@echo &quot;$$(tput bold)Commands:$$(tput sgr0)&quot;
	@echo
	@sed -n -e &quot;/^## / { \
		h; \
		s/.*//; \
		:doc&quot; \
		-e &quot;H; \
		n; \
		s/^## //; \
		t doc&quot; \
		-e &quot;s/:.*//; \
		G; \
		s/\\n## /---/; \
		s/\\n/ /g; \
		p; \
	}&quot; ${MAKEFILE_LIST} \
	| LC_ALL='C' sort --ignore-case \
	| awk -F '---' \
		-v ncol=$$(tput cols) \
		-v indent=19 \
		-v col_on=&quot;$$(tput setaf 6)&quot; \
		-v col_off=&quot;$$(tput sgr0)&quot; \
	'{ \
		printf &quot;%s%*s%s &quot;, col_on, -indent, $$1, col_off; \
		n = split($$2, words, &quot; &quot;); \
		line_length = ncol - indent; \
		for (i = 1; i &amp;lt;= n; i++) { \
			line_length -= length(words[i]) + 1; \
			if (line_length &amp;lt;= 0) { \
				line_length = ncol - indent - length(words[i]) - 1; \
				printf &quot;\n%*s &quot;, -indent, &quot; &quot;; \
			} \
			printf &quot;%s &quot;, words[i]; \
		} \
		printf &quot;\n&quot;; \
	}' \
	| more $(shell test $(shell uname) == Darwin &amp;amp;&amp;amp; echo '--no-init --raw-control-chars')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can then populate the help command like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.PHONY: hello-world
## Prints hello world message to the terminal
hello-world:
	@echo &quot;hello world&quot;


.PHONY: wont-appear-in-help
# This one won't appear in help
wont-appear-in-help:
	@echo &quot;Not shown in help&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make help
Commands:

hello-world         Prints hello world message to the terminal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;splitting-commands-into-different-files&quot;&gt;Splitting commands into different files&lt;/h2&gt;

&lt;p&gt;Make has an option to specify which file the command will read:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make -f FileName.mk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By convention I used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mk&lt;/code&gt; extension for other makefile files in the same project.&lt;/p&gt;

&lt;p&gt;In this &lt;a href=&quot;https://github.com/rafaellcoellho/template-c-gameboy&quot;&gt;example project&lt;/a&gt; I decided to separate the command runner from the
makefile that compiles source files. Considering the folder structure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── src
│   └── main.c
├── Makefile
└── MakeGb.mk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the main makefile, I created the command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gb:
	@ make -f MakeGb.mk all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make gb&lt;/code&gt;, make only compiles the source files.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/&quot;&gt;make tool docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/samuelcolvin/pydantic&quot;&gt;pydantic&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#How-Make-Works&quot;&gt;how make processes a makefile&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Echoing&quot;&gt;every command executed is sent to standard output&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="make" /><category term="makefile" /><category term="automation" /><summary type="html">Make is a “build automation tool” according to wikipedia. But it can be useful even when there’s nothing to compile.</summary></entry><entry xml:lang="pt"><title type="html">Makefile como executor de comandos</title><link href="/2022/02/26/makefile-como-executor-de-comandos.html" rel="alternate" type="text/html" title="Makefile como executor de comandos" /><published>2022-02-26T23:34:29+00:00</published><updated>2022-02-26T23:34:29+00:00</updated><id>/2022/02/26/makefile-como-executor-de-comandos</id><content type="html" xml:base="/2022/02/26/makefile-como-executor-de-comandos.html">&lt;p&gt;O make é uma “ferramenta de automação de compilação” segundo a &lt;a href=&quot;https://en.wikipedia.org/wiki/Make_(software)&quot;&gt;wikipedia&lt;/a&gt;. 
Mas ela pode ser útil mesmo quando não é preciso compilar nada.&lt;/p&gt;

&lt;p&gt;É possível usar o make como um executor de comandos. A vantagem de usar o make 
para fazer isso é por ser comumente encontrada em distribuições Linux. Além de 
fácil de ler, escrever e manter um makefile para esse objetivo.&lt;/p&gt;

&lt;p&gt;Um exemplo de utilização pode ser encontrado no projeto &lt;a href=&quot;https://github.com/samuelcolvin/pydantic&quot;&gt;pydantic&lt;/a&gt;. 
Vou usar como exemplo o &lt;a href=&quot;https://github.com/samuelcolvin/pydantic/blob/v1.9.0/Makefile&quot;&gt;makefile na versão 1.9.0 da lib&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.DEFAULT_GOAL := all
isort = isort pydantic tests
black = black -S -l 120 --target-version py38 pydantic tests

[...]

.PHONY: lint
lint:
	flake8 pydantic/ tests/
	$(isort) --check-only --df
	$(black) --check --diff

[...]

.PHONY: mypy
mypy:
	mypy pydantic

[...]

.PHONY: test
test:
	pytest --cov=pydantic

.PHONY: testcov
testcov: test
	@echo &quot;building coverage html&quot;
	@coverage html

[...]

.PHONY: all
all: lint mypy testcov

[...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;como-o-make-executa-uma-regra&quot;&gt;Como o make executa uma regra&lt;/h2&gt;

&lt;p&gt;Considerando que estou na pasta raiz do projeto do pydantic e executo o comando:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O make procura a primeira regra no arquivo para começar a executar. Isso é 
chamado &lt;strong&gt;default goal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No makefile do pydantic, ele usa a variável especial chamada &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.DEFAULT_GOAL&lt;/code&gt; 
para apontar para qual regra o make deve executar primeiro. Apesar das
regras de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lint&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mypy&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testcov&lt;/code&gt; estarem escritas antes da regra &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt; 
elas serão executadas depois.&lt;/p&gt;

&lt;h2 id=&quot;como-executar-uma-regra-específica&quot;&gt;Como executar uma regra específica&lt;/h2&gt;

&lt;p&gt;Caso eu queira executar só a regra de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testcov&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make testcov
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nesse caso o make vai executar apenas a regra &lt;strong&gt;testcov&lt;/strong&gt; e seu target
com dependência &lt;strong&gt;test&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;targets-phony&quot;&gt;Targets .PHONY&lt;/h2&gt;

&lt;p&gt;A sintaxe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.PHONY&lt;/code&gt; é utilizada para sinalizar que o target não 
é um nome de arquivo. Isso evita um possível conflito com o nome de um 
arquivo real e otimiza desempenho. A sintaxe:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.PHONY nome_da_acao
nome_da_acao: dependecias
  comandos
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;imprimir-comando-da-saída&quot;&gt;Imprimir comando da saída&lt;/h2&gt;

&lt;p&gt;O comportamento comum do make é que &lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Echoing&quot;&gt;todo comando executado é enviado para saída padrão&lt;/a&gt;. 
Uma maneira de evitar isso é usar a flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt; ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--silent&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make --silent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Caso queira que apenas exiba e não execute os comandos, existem a flag 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt; ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--just-print&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make --just-print
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;comando-help&quot;&gt;Comando help&lt;/h2&gt;

&lt;p&gt;Já saindo do exemplo do makefile do pydantic e entrando em outras dicas.&lt;/p&gt;

&lt;p&gt;Fuçando na web existem vários exemplos de maneiras de adicionar um comando de 
help automaticamente num makefile. Um dos mais interessantes que encontrei foi 
&lt;a href=&quot;https://gist.github.com/klmr/575726c7e05d8780505a&quot;&gt;esse&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.PHONY: help
help:
	@echo &quot;$$(tput bold)Comandos:$$(tput sgr0)&quot;
	@echo
	@sed -n -e &quot;/^## / { \
		h; \
		s/.*//; \
		:doc&quot; \
		-e &quot;H; \
		n; \
		s/^## //; \
		t doc&quot; \
		-e &quot;s/:.*//; \
		G; \
		s/\\n## /---/; \
		s/\\n/ /g; \
		p; \
	}&quot; ${MAKEFILE_LIST} \
	| LC_ALL='C' sort --ignore-case \
	| awk -F '---' \
		-v ncol=$$(tput cols) \
		-v indent=19 \
		-v col_on=&quot;$$(tput setaf 6)&quot; \
		-v col_off=&quot;$$(tput sgr0)&quot; \
	'{ \
		printf &quot;%s%*s%s &quot;, col_on, -indent, $$1, col_off; \
		n = split($$2, words, &quot; &quot;); \
		line_length = ncol - indent; \
		for (i = 1; i &amp;lt;= n; i++) { \
			line_length -= length(words[i]) + 1; \
			if (line_length &amp;lt;= 0) { \
				line_length = ncol - indent - length(words[i]) - 1; \
				printf &quot;\n%*s &quot;, -indent, &quot; &quot;; \
			} \
			printf &quot;%s &quot;, words[i]; \
		} \
		printf &quot;\n&quot;; \
	}' \
	| more $(shell test $(shell uname) == Darwin &amp;amp;&amp;amp; echo '--no-init --raw-control-chars')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assim podemos popular o comando de help da seguinte maneira:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.PHONY: oi-mundo
## Mostra mensagem de oi mundo no terminal
oi-mundo:
	@echo &quot;oi mundo&quot;


.PHONY: nao-aparecer-no-help
# Essa não vai aparecer no help
nao-aparecer-no-help:
	@echo &quot;Não mostra no help&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Temos então o resultado:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make help
Comandos:

oi-mundo            Mostra mensagem de oi mundo no terminal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dividindo-comandos-em-arquivos-diferentes&quot;&gt;Dividindo comandos em arquivos diferentes&lt;/h2&gt;

&lt;p&gt;O make tem uma opção onde é possível passar qual arquivo vai ser lido pelo comando:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make -f NomeDoArquivo.mk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por convenção usei a extensão &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mk&lt;/code&gt; para outros arquivos de makefile no mesmo projeto.&lt;/p&gt;

&lt;p&gt;Nesse &lt;a href=&quot;https://github.com/rafaellcoellho/template-c-gameboy&quot;&gt;projeto de exemplo&lt;/a&gt; resolvi separar o executor de comandos do makefile 
que compila os arquivos de código-fonte. Considerando a estrutura de pastas:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── src
│   └── main.c
├── Makefile
└── MakeGb.mk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No makefile principal, criei o comando:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gb:
	@ make -f MakeGb.mk all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Então ao dar um &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make gb&lt;/code&gt;, o make apenas compila os arquivos código-fonte.&lt;/p&gt;

&lt;h2 id=&quot;referências&quot;&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/&quot;&gt;docs da ferramenta make&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/samuelcolvin/pydantic&quot;&gt;pydantic&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#How-Make-Works&quot;&gt;como make processa um makefile&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Echoing&quot;&gt;todo comando executado é enviado para saída padrão&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="make" /><category term="makefile" /><category term="automação" /><summary type="html">O make é uma “ferramenta de automação de compilação” segundo a wikipedia. Mas ela pode ser útil mesmo quando não é preciso compilar nada.</summary></entry><entry xml:lang="pt"><title type="html">Aprendendo o básico de makefile</title><link href="/2022/02/24/aprendendo-o-basico-de-makefile.html" rel="alternate" type="text/html" title="Aprendendo o básico de makefile" /><published>2022-02-24T22:05:44+00:00</published><updated>2022-02-24T22:05:44+00:00</updated><id>/2022/02/24/aprendendo-o-basico-de-makefile</id><content type="html" xml:base="/2022/02/24/aprendendo-o-basico-de-makefile.html">&lt;p&gt;Ao decorrer dos anos eu já precisei usar/escrever makefiles várias vezes. 
Mas eu nunca entendi bem a sintaxe e nunca parei para estudar.
Decidi escrever esse post para aprender melhor.&lt;/p&gt;

&lt;p&gt;Nada melhor para aprender do que encontrar uma motivação em um projeto pessoal.
Inspirado pelo Modern Vintage Gamer nesse 
&lt;a href=&quot;https://www.youtube.com/watch?v=FzPTK91EJY8&quot;&gt;vídeo&lt;/a&gt; resolvi escrever um 
makefile simples para compilar jogos de GameBoy escritos em C usando o GBDK-2020.&lt;/p&gt;

&lt;p&gt;Criei um &lt;a href=&quot;https://github.com/rafaellcoellho/template-c-gameboy&quot;&gt;repositório&lt;/a&gt; 
com um projeto exemplo para usar como modelo para outros projetos.&lt;/p&gt;

&lt;h2 id=&quot;variáveis&quot;&gt;Variáveis&lt;/h2&gt;

&lt;p&gt;Nas primeiras linhas do makefile é definido as variáveis necessárias 
para configurar as regras de compilação e evitar reescrever a mesma 
coisa várias vezes.&lt;/p&gt;

&lt;p&gt;A sintaxe de uma variável é a seguinte:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;NOME_DA_VARIAVEL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; valor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O nome das variáveis é case sensitive, mas por convenção são sempre nomeadas 
em caixa alta. O valor é uma string. Para utilizar o valor das variáveis é só usar 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(NOME_DA_VARIAVEL)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Comecei criando algumas variáveis de configuração. Os nomes são auto-explicativos:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;NOME_DO_JOGO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;foo
&lt;span class=&quot;nv&quot;&gt;ARQUIVO_GB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build/&lt;span class=&quot;nv&quot;&gt;$(NOME_DO_JOGO)&lt;/span&gt;.gb

&lt;span class=&quot;nv&quot;&gt;DIRETORIO_SOURCES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;src
&lt;span class=&quot;nv&quot;&gt;DIRETORIO_OBJ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build
&lt;span class=&quot;err&quot;&gt;[...]&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;COMPILADOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gbdk/bin/lcc

&lt;span class=&quot;nv&quot;&gt;FLAGS_DO_COMPILADOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;funções-builtin&quot;&gt;Funções builtin&lt;/h2&gt;

&lt;p&gt;Em seguida é preciso definir variáveis que leiam quais arquivos 
existe no projeto. Para isso utilizarei funções &lt;em&gt;builtin&lt;/em&gt; dos makefiles. 
A primeira é o &lt;strong&gt;wildcard&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;ARQUIVOS_C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;wildcard&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_SOURCES)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.c&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Como &lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Wildcard-Function&quot;&gt;demonstrado na documentação&lt;/a&gt; 
a sintaxe é &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(wildcard pattern…)&lt;/code&gt;. Essa função vai expandir para um valor 
com nomes dos arquivos que coincidem com o &lt;strong&gt;pattern&lt;/strong&gt;, separado por espaço.&lt;/p&gt;

&lt;p&gt;Considerando que a estrutura de pastas seja:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── build
├── src
│   ├── main.c
│   ├── oi_mundo.c
│   └── oi_mundo.h
└── Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A variável vai conter o valor:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;ARQUIVOS_C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; src/main.c src/oi_mundo.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A segunda função &lt;em&gt;buildin&lt;/em&gt; que utilizei foi a 
&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#index-patsubst-1&quot;&gt;&lt;strong&gt;patsubst&lt;/strong&gt;&lt;/a&gt;. 
A sintaxe é:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;$(patsubst&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;pattern,replacement,text)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa função encontra palavras separadas por espaço em &lt;strong&gt;text&lt;/strong&gt; que coincidem 
com o &lt;strong&gt;pattern&lt;/strong&gt; e substitui pelo formato do &lt;strong&gt;replacement&lt;/strong&gt;. Meio confuso 
mas é possível entender melhor com o exemplo a seguir:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;ARQUIVOS_OBJ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;patsubst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_SOURCES)&lt;/span&gt;/%.c, &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_OBJ)&lt;/span&gt;/%.o, &lt;span class=&quot;nv&quot;&gt;$(ARQUIVOS_C)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O objetivo é transformar todos os arquivos de código-fonte (.c) em arquivos 
objeto (.o). Então no &lt;strong&gt;pattern&lt;/strong&gt; passamos &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(DIRETORIO_SOURCES)/%.c&lt;/code&gt; para 
coincidir com todos os arquivos no &lt;strong&gt;text&lt;/strong&gt;, o conteúdo da variável 
&lt;em&gt;ARQUIVOS_C&lt;/em&gt; que criei anteriormente. O &lt;strong&gt;replacemnt&lt;/strong&gt; é o formato que os 
arquivos .o devem ter na pasta build. O resultado seria:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;ARQUIVOS_OBJ&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; build/main.o build/oi_mundo.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;regras&quot;&gt;Regras&lt;/h2&gt;

&lt;p&gt;Agora vou começar a escrever as &lt;strong&gt;regras de compilação&lt;/strong&gt;. Como indicado no 
&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Rule-Example&quot;&gt;manual&lt;/a&gt; 
cada regra segue a sintaxe:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;targets &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prerequisites&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;recipe&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;targets&lt;/strong&gt;: normalmente é o nome do arquivo resultado dessa regra. 
Mas também pode ser uma ação;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: arquivos de entrada ou outro &lt;strong&gt;target&lt;/strong&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;recipe&lt;/strong&gt;: comando para ser interpretados pelo shell. Por padrão o 
make usa o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin/sh&lt;/code&gt; ao executar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A primeira regra que escrevi é essa:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;criar_diretorio_build $(ARQUIVO_GB)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O primeiro pré-requisito é &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;criar_diretorio_build&lt;/code&gt; e logo em seguida temos o 
arquivo do jogo. O foco aqui é entender que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt; é a regra principal do 
makefile e ela comunica que primeiro é preciso criar a pasta para armazenar 
os artefatos para em seguida criar o arquivo do jogo.&lt;/p&gt;

&lt;p&gt;Para criar o &lt;em&gt;ARQUIVO_GB&lt;/em&gt;, o makefile precisa saber como 
gerar esse arquivo. Então escrevi a segunda regra:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;$(ARQUIVO_GB)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(ARQUIVOS_OBJ)&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(FLAGS_DO_COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(ARQUIVO_GB)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(ARQUIVOS_OBJ)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa regra pode ser lida assim: para gerar o &lt;em&gt;ARQUIVO_GB&lt;/em&gt;, passo como 
entrada &lt;em&gt;ARQUIVOS_OBJ&lt;/em&gt; e executa o comando 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(COMPILADOR) $(FLAGS_DO_COMPILADOR) -o $(ARQUIVO_GB) $(ARQUIVOS_OBJ)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para facilitar o entendimento, a regra anterior seria o equivalente a escrever isso:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;foo.gb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build/main.o build/oi_mundo.o&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;build/foo.gb&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;build/main.o&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;build/oi_mundo.o&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;variáveis-automáticas-em-regras&quot;&gt;Variáveis automáticas em regras&lt;/h2&gt;

&lt;p&gt;Antes de continuar para a escrever a próxima regra, preciso 
primeiro apresentar duas 
&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Automatic-Variables&quot;&gt;&lt;strong&gt;variáveis automáticas&lt;/strong&gt;&lt;/a&gt;: 
&lt;strong&gt;$@&lt;/strong&gt; e &lt;strong&gt;$&amp;lt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No exemplo a seguir&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;objeto.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;requisito.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;$(COMPILADOR)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$(FLAGS_DO_COMPILADOR)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;$@&lt;/strong&gt;: O valor do target (objeto.o);&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;$&amp;lt;&lt;/strong&gt;: O valor do pré-requisito (requisito.c).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;regras-implícitas&quot;&gt;Regras Implícitas&lt;/h2&gt;

&lt;p&gt;Partindo da ideia de que eu fosse executar os comandos de compilação manualmente, 
ficaria assim:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gbdk/bin/lcc &lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; build/main.o src/main.c
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gbdk/bin/lcc &lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; build/oi_mundo.o src/oi_mundo.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Então o objetivo aqui é criar uma regra para gerar um comando para cada 
arquivo objeto sendo construído.&lt;/p&gt;

&lt;p&gt;Para ser mais didático, vou partir dessas regras mais simples:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;build/main.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src/main.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;build/oi_mundo.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src/oi_mundo.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;O problema dessa abordagem é que ao adicionar um novo arquivo terei que 
escrever mais uma regra. Para evitar isso posso usar a sintaxe do makefile 
para compilar qualquer quantidade arbitrária de arquivos. Com a vantagem 
do make não executar regras novamente se os pré-requisitos não mudaram 
desde a última vez, deixando esse processo muito mais eficiente.&lt;/p&gt;

&lt;p&gt;Mas como fazer isso? Através do conceito de 
&lt;a href=&quot;https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html&quot;&gt;&lt;strong&gt;regras implícitas&lt;/strong&gt;&lt;/a&gt;. 
Um bom tutorial de como isso funciona está &lt;a href=&quot;https://rebelsky.cs.grinnell.edu/musings/cnix-make-implicit-rules&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basicamente posso substituir pelos patterns e variáveis automáticas:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;build/%.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src/%.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa regra esta definindo que para cada arquivo na pasta build que coincide 
com o pattern de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%.o&lt;/code&gt;, vamos ter como pré-requisito outro arquivo na 
pasta src que coincide com o pattern &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%.c&lt;/code&gt; e vamos executar o comando 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gbdk/bin/lcc -Wa-l -Wl-m -Wf--debug -Wl-y -Wl-w -DUSE_SFR_FOR_REG -c -o  $@ $&amp;lt;&lt;/code&gt; 
substituindo o target (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$@&lt;/code&gt;) e pré-requisito (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&amp;lt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Por fim substituindo pelas variáveis já criadas no início:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;$(DIRETORIO_OBJ)/%.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(DIRETORIO_SOURCES)/%.c&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(FLAGS_DO_COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;regra-como-executor-de-comandos&quot;&gt;Regra como executor de comandos&lt;/h2&gt;

&lt;p&gt;Mas ainda faltam algumas regras extras:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;criar_diretorio_build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; build

&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_OBJ)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por padrão o makefile &lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Echoing&quot;&gt;imprime na saída&lt;/a&gt; 
todo comando executado em uma regra, mas usei o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; no começo do 
comando para evitar isso.&lt;/p&gt;

&lt;p&gt;A regra &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;criar_diretorio_build&lt;/code&gt; é auto-explicativa. Já a regra &lt;strong&gt;clean&lt;/strong&gt; 
é uma regra bastante comum em makefiles, que por convenção apaga e limpa o ambiente.
Nessa situação isso significa apagar todos os arquivos na pasta de build.&lt;/p&gt;

&lt;h2 id=&quot;makefile-completo&quot;&gt;Makefile completo&lt;/h2&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;NOME_DO_JOGO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;foo
&lt;span class=&quot;nv&quot;&gt;ARQUIVO_GB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build/&lt;span class=&quot;nv&quot;&gt;$(NOME_DO_JOGO)&lt;/span&gt;.gb

&lt;span class=&quot;nv&quot;&gt;DIRETORIO_SOURCES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;src
&lt;span class=&quot;nv&quot;&gt;DIRETORIO_OBJ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build

&lt;span class=&quot;nv&quot;&gt;ARQUIVOS_C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;wildcard&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_SOURCES)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.c&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ARQUIVOS_OBJ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;patsubst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_SOURCES)&lt;/span&gt;/%.c, &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_OBJ)&lt;/span&gt;/%.o, &lt;span class=&quot;nv&quot;&gt;$(ARQUIVOS_C)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;COMPILADOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gbdk/bin/lcc

&lt;span class=&quot;nv&quot;&gt;FLAGS_DO_COMPILADOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;criar_diretorio_build $(ARQUIVO_GB)&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(ARQUIVO_GB)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(ARQUIVOS_OBJ)&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(FLAGS_DO_COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(ARQUIVO_GB)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(ARQUIVOS_OBJ)&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(DIRETORIO_OBJ)/%.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(DIRETORIO_SOURCES)/%.c&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(FLAGS_DO_COMPILADOR)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&amp;lt;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;criar_diretorio_build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; build

&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(DIRETORIO_OBJ)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;referências&quot;&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/&quot;&gt;docs da ferramenta make&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://rebelsky.cs.grinnell.edu/musings/cnix-make-implicit-rules&quot;&gt;tutorial de como funciona regra implícita no make&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="make" /><category term="makefile" /><category term="c" /><category term="build" /><summary type="html">Ao decorrer dos anos eu já precisei usar/escrever makefiles várias vezes. Mas eu nunca entendi bem a sintaxe e nunca parei para estudar. Decidi escrever esse post para aprender melhor.</summary></entry><entry xml:lang="en"><title type="html">Learning Makefile Basics</title><link href="/en/2022/02/24/learning-makefile-basics/" rel="alternate" type="text/html" title="Learning Makefile Basics" /><published>2022-02-24T22:05:44+00:00</published><updated>2022-02-24T22:05:44+00:00</updated><id>/en/2022/02/24/learning-makefile-basics</id><content type="html" xml:base="/en/2022/02/24/learning-makefile-basics/">&lt;p&gt;Over the years I’ve had to use/write makefiles many times.
But I never really understood the syntax and never stopped to study it.
I decided to write this post to learn it better.&lt;/p&gt;

&lt;p&gt;Nothing beats learning when you find motivation in a personal project.
Inspired by Modern Vintage Gamer in this
&lt;a href=&quot;https://www.youtube.com/watch?v=FzPTK91EJY8&quot;&gt;video&lt;/a&gt; I decided to write a
simple makefile to compile GameBoy games written in C using GBDK-2020.&lt;/p&gt;

&lt;p&gt;I created a &lt;a href=&quot;https://github.com/rafaellcoellho/template-c-gameboy&quot;&gt;repository&lt;/a&gt;
with an example project to use as a template for other projects.&lt;/p&gt;

&lt;h2 id=&quot;variables&quot;&gt;Variables&lt;/h2&gt;

&lt;p&gt;The first lines of the makefile define the variables needed
to configure the compilation rules and avoid rewriting the same
thing multiple times.&lt;/p&gt;

&lt;p&gt;The syntax of a variable is as follows:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;VARIABLE_NAME&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; value
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Variable names are case sensitive, but by convention they are always named
in uppercase. The value is a string. To use the value of variables just use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(VARIABLE_NAME)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I started by creating some configuration variables. The names are self-explanatory:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;GAME_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;foo
&lt;span class=&quot;nv&quot;&gt;GB_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build/&lt;span class=&quot;nv&quot;&gt;$(GAME_NAME)&lt;/span&gt;.gb

&lt;span class=&quot;nv&quot;&gt;SOURCES_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;src
&lt;span class=&quot;nv&quot;&gt;OBJ_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build
&lt;span class=&quot;err&quot;&gt;[...]&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;COMPILER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gbdk/bin/lcc

&lt;span class=&quot;nv&quot;&gt;COMPILER_FLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;builtin-functions&quot;&gt;Builtin functions&lt;/h2&gt;

&lt;p&gt;Next we need to define variables that read which files
exist in the project. For that I’ll use make’s &lt;em&gt;builtin&lt;/em&gt; functions.
The first is &lt;strong&gt;wildcard&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;C_FILES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;wildcard&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(SOURCES_DIR)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.c&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As &lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Wildcard-Function&quot;&gt;shown in the documentation&lt;/a&gt;
the syntax is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(wildcard pattern…)&lt;/code&gt;. This function will expand to a value
with the names of files matching the &lt;strong&gt;pattern&lt;/strong&gt;, separated by spaces.&lt;/p&gt;

&lt;p&gt;Assuming the folder structure is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├── build
├── src
│   ├── main.c
│   ├── hello_world.c
│   └── hello_world.h
└── Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The variable will contain:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;C_FILES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; src/main.c src/hello_world.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second &lt;em&gt;builtin&lt;/em&gt; function I used was
&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#index-patsubst-1&quot;&gt;&lt;strong&gt;patsubst&lt;/strong&gt;&lt;/a&gt;.
The syntax is:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;$(patsubst&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;pattern,replacement,text)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This function finds space-separated words in &lt;strong&gt;text&lt;/strong&gt; that match
the &lt;strong&gt;pattern&lt;/strong&gt; and replaces them with the &lt;strong&gt;replacement&lt;/strong&gt; format. A bit confusing
but it’s easier to understand with the following example:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;OBJ_FILES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;patsubst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(SOURCES_DIR)&lt;/span&gt;/%.c, &lt;span class=&quot;nv&quot;&gt;$(OBJ_DIR)&lt;/span&gt;/%.o, &lt;span class=&quot;nv&quot;&gt;$(C_FILES)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The goal is to transform all source files (.c) into object files (.o).
So in &lt;strong&gt;pattern&lt;/strong&gt; we pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(SOURCES_DIR)/%.c&lt;/code&gt; to match
all files in &lt;strong&gt;text&lt;/strong&gt;, the content of the &lt;em&gt;C_FILES&lt;/em&gt; variable I created earlier.
The &lt;strong&gt;replacement&lt;/strong&gt; is the format the .o files should have in the build folder. The result would be:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;OBJ_FILES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; build/main.o build/hello_world.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rules&quot;&gt;Rules&lt;/h2&gt;

&lt;p&gt;Now I’ll start writing the &lt;strong&gt;compilation rules&lt;/strong&gt;. As indicated in the
&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Rule-Example&quot;&gt;manual&lt;/a&gt;
each rule follows the syntax:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;targets &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prerequisites&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;recipe&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;targets&lt;/strong&gt;: usually the name of the file produced by this rule.
But it can also be an action;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: input files or another &lt;strong&gt;target&lt;/strong&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;recipe&lt;/strong&gt;: commands to be interpreted by the shell. By default
make uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin/sh&lt;/code&gt; when executing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first rule I wrote is this:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_build_dir $(GB_FILE)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first prerequisite is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_build_dir&lt;/code&gt; followed by the game file.
The key point here is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all&lt;/code&gt; is the main rule of the
makefile and it communicates that we first need to create the folder to store
the build artifacts and then create the game file.&lt;/p&gt;

&lt;p&gt;To create the &lt;em&gt;GB_FILE&lt;/em&gt;, the makefile needs to know how
to generate that file. So I wrote the second rule:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;$(GB_FILE)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(OBJ_FILES)&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILER)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(COMPILER_FLAGS)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(GB_FILE)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(OBJ_FILES)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This rule can be read as: to generate the &lt;em&gt;GB_FILE&lt;/em&gt;, pass &lt;em&gt;OBJ_FILES&lt;/em&gt; as
input and run the command
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(COMPILER) $(COMPILER_FLAGS) -o $(GB_FILE) $(OBJ_FILES)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make it easier to understand, the above rule would be equivalent to writing:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;foo.gb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build/main.o build/hello_world.o&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;build/foo.gb&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;build/main.o&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;build/hello_world.o&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;automatic-variables-in-rules&quot;&gt;Automatic variables in rules&lt;/h2&gt;

&lt;p&gt;Before moving on to write the next rule, I first need to
introduce two
&lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Automatic-Variables&quot;&gt;&lt;strong&gt;automatic variables&lt;/strong&gt;&lt;/a&gt;:
&lt;strong&gt;$@&lt;/strong&gt; and &lt;strong&gt;$&amp;lt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the following example:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;object.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prerequisite.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;$(COMPILER)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$(COMPILER_FLAGS)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;$@&lt;/strong&gt;: The value of the target (object.o);&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;$&amp;lt;&lt;/strong&gt;: The value of the prerequisite (prerequisite.c).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;implicit-rules&quot;&gt;Implicit rules&lt;/h2&gt;

&lt;p&gt;Starting from the idea that I would run the compilation commands manually,
it would look like this:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gbdk/bin/lcc &lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; build/main.o src/main.c
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gbdk/bin/lcc &lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; build/hello_world.o src/hello_world.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So the goal here is to create a rule that generates a command for each
object file being built.&lt;/p&gt;

&lt;p&gt;To be more didactic, let me start from these simpler rules:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;build/main.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src/main.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;build/hello_world.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src/hello_world.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem with this approach is that when adding a new file I’ll have to
write another rule. To avoid this I can use makefile syntax to compile
any arbitrary number of files — with the bonus that make won’t re-run rules
if the prerequisites haven’t changed since the last time, making the process much more efficient.&lt;/p&gt;

&lt;p&gt;But how? Through the concept of
&lt;a href=&quot;https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html&quot;&gt;&lt;strong&gt;implicit rules&lt;/strong&gt;&lt;/a&gt;.
A good tutorial on how this works is &lt;a href=&quot;https://rebelsky.cs.grinnell.edu/musings/cnix-make-implicit-rules&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I can basically substitute with patterns and automatic variables:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;build/%.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;src/%.c&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;gbdk/bin/lcc&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-o&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This rule defines that for each file in the build folder matching
the pattern &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%.o&lt;/code&gt;, we’ll have another file in the
src folder matching the pattern &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%.c&lt;/code&gt; as a prerequisite, and we’ll run
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gbdk/bin/lcc -Wa-l -Wl-m -Wf--debug -Wl-y -Wl-w -DUSE_SFR_FOR_REG -c -o  $@ $&amp;lt;&lt;/code&gt;
substituting the target (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$@&lt;/code&gt;) and prerequisite (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&amp;lt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Finally, substituting with the variables already created at the beginning:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;$(OBJ_DIR)/%.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(SOURCES_DIR)/%.c&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILER)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(COMPILER_FLAGS)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;rule-as-a-command-executor&quot;&gt;Rule as a command executor&lt;/h2&gt;

&lt;p&gt;There are still a few extra rules missing:&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;create_build_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; build

&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(OBJ_DIR)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default makefile &lt;a href=&quot;https://www.gnu.org/software/make/manual/make.html#Echoing&quot;&gt;prints to output&lt;/a&gt;
every command executed in a rule, but I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; at the beginning of the
command to prevent that.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_build_dir&lt;/code&gt; rule is self-explanatory. The &lt;strong&gt;clean&lt;/strong&gt; rule
is a very common one in makefiles — by convention it deletes and cleans the environment.
In this case that means deleting all files in the build folder.&lt;/p&gt;

&lt;h2 id=&quot;complete-makefile&quot;&gt;Complete makefile&lt;/h2&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;GAME_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;foo
&lt;span class=&quot;nv&quot;&gt;GB_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build/&lt;span class=&quot;nv&quot;&gt;$(GAME_NAME)&lt;/span&gt;.gb

&lt;span class=&quot;nv&quot;&gt;SOURCES_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;src
&lt;span class=&quot;nv&quot;&gt;OBJ_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;build

&lt;span class=&quot;nv&quot;&gt;C_FILES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;wildcard&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(SOURCES_DIR)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.c&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;OBJ_FILES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;patsubst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(SOURCES_DIR)&lt;/span&gt;/%.c, &lt;span class=&quot;nv&quot;&gt;$(OBJ_DIR)&lt;/span&gt;/%.o, &lt;span class=&quot;nv&quot;&gt;$(C_FILES)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;COMPILER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gbdk/bin/lcc

&lt;span class=&quot;nv&quot;&gt;COMPILER_FLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Wa-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-m&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wf--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wl-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DUSE_SFR_FOR_REG&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_build_dir $(GB_FILE)&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(GB_FILE)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(OBJ_FILES)&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILER)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(COMPILER_FLAGS)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(GB_FILE)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(OBJ_FILES)&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(OBJ_DIR)/%.o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(SOURCES_DIR)/%.c&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;$(COMPILER)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(COMPILER_FLAGS)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$&amp;lt;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;create_build_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; build

&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$(OBJ_DIR)&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/make/manual/&quot;&gt;make tool docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://rebelsky.cs.grinnell.edu/musings/cnix-make-implicit-rules&quot;&gt;tutorial on how implicit rules work in make&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="make" /><category term="makefile" /><category term="c" /><category term="build" /><summary type="html">Over the years I’ve had to use/write makefiles many times. But I never really understood the syntax and never stopped to study it. I decided to write this post to learn it better.</summary></entry><entry xml:lang="en"><title type="html">Basic OpenGL Setup with C++ on Linux</title><link href="/en/2020/10/27/basic-opengl-setup-on-linux/" rel="alternate" type="text/html" title="Basic OpenGL Setup with C++ on Linux" /><published>2020-10-28T01:59:00+00:00</published><updated>2020-10-28T01:59:00+00:00</updated><id>/en/2020/10/27/basic-opengl-setup-on-linux</id><content type="html" xml:base="/en/2020/10/27/basic-opengl-setup-on-linux/">&lt;p&gt;Before we start we need to check if we have the OpenGL drivers installed on our machine.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ glxinfo | grep OpenGL
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics (Whiskey Lake 3x8 GT2) 
OpenGL core profile version string: 4.5 (Core Profile) Mesa 19.1.8
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 19.1.8
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 19.1.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the command output is empty, you’ll need to look up how to install &lt;a href=&quot;https://www.mesa3d.org/&quot;&gt;Mesa 3D&lt;/a&gt; on your Linux system. But if everything is fine with the drivers, we can move on to the essential libraries:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.glfw.org/&quot;&gt;GLFW&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://glew.sourceforge.net/&quot;&gt;GLEW&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install them on Fedora:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo dnf install glfw-devel glew-devel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s start putting it all together and write some code. Let’s create a folder for our first project and create the first source file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mkdir hello-world-opengl &amp;amp;&amp;amp; cd hello-world-opengl &amp;amp;&amp;amp; touch main.cpp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using the example of how to create a window provided by the GLFW documentation:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;iostream&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;GL/glew.h&amp;gt;
#include &amp;lt;GLFW/glfw3.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;GLFWwindow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glfwCreateWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glfwTerminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwMakeContextCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glewInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GLEW_OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Error!&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glGetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GL_VERSION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwWindowShouldClose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glClear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GL_COLOR_BUFFER_BIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;glBegin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GL_TRIANGLES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glVertex2f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glVertex2f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glVertex2f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;glfwSwapBuffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glfwPollEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwTerminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now what? What do we do with this? We need to compile our code together with the libraries to generate the binary and run it. Let’s use &lt;a href=&quot;https://cmake.org/&quot;&gt;CMake&lt;/a&gt; to make the process easier. We need to write the CMakeLists.txt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.15)
project(hello_world_opengl)

set(CMAKE_CXX_STANDARD 14)

add_executable(hello_world_opengl main.cpp)
target_link_libraries(hello_world_opengl -lGL -lGLEW -lglfw)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now just generate the makefile, compile and run the program:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mkdir build &amp;amp;&amp;amp; cd build
$ cmake ..
-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- Check for working C compiler: /usr/lib64/ccache/cc
[...]
$ make
Scanning dependencies of target hello_world_opengl
[ 50%] Building CXX object CMakeFiles/hello_world_opengl.dir/main.cpp.o
[100%] Linking CXX executable hello_world_opengl
[100%] Built target hello_world_opengl
$ ./hello_world_opengl
3.0 Mesa 19.1.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/imagens/posts/2020-10-27-setup-basico-opengl-no-linux/01.png&quot; alt=&quot;result&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you don’t change anything in CMakeLists.txt, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make -C ./build &amp;amp;&amp;amp; ./build/hello_world_opengl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now it’s time to start playing with OpenGL :D.&lt;/p&gt;

&lt;h3 id=&quot;references&quot;&gt;References:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=H2E3yO0J7TM&amp;amp;list=PLlrATfBNZ98foTJPJ_Ev03o2oq3-GGOS2&amp;amp;index=3&quot;&gt;video about modern OpenGL from The Cherno channel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=h8ij7zzIxIc&quot;&gt;video on how to set up the environment in CLion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.glfw.org/documentation.html&quot;&gt;GLFW getting started tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="opengl" /><category term="c++" /><category term="linux" /><category term="cmake" /><summary type="html">Before we start we need to check if we have the OpenGL drivers installed on our machine.</summary></entry><entry xml:lang="pt"><title type="html">Setup básico para OpenGL com C++ no Linux</title><link href="/2020/10/28/setup-basico-opengl-no-linux.html" rel="alternate" type="text/html" title="Setup básico para OpenGL com C++ no Linux" /><published>2020-10-28T01:59:00+00:00</published><updated>2020-10-28T01:59:00+00:00</updated><id>/2020/10/28/setup-basico-opengl-no-linux</id><content type="html" xml:base="/2020/10/28/setup-basico-opengl-no-linux.html">&lt;p&gt;Antes de começar precisamos descobrir se temos os drivers para OpenGL instalados na nossa máquina.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ glxinfo | grep OpenGL
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics (Whiskey Lake 3x8 GT2) 
OpenGL core profile version string: 4.5 (Core Profile) Mesa 19.1.8
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 19.1.8
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 19.1.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Caso a saída do comando esteja vazia é preciso procurar como instalar o &lt;a href=&quot;https://www.mesa3d.org/&quot;&gt;Mesa 3D&lt;/a&gt; no seu sistema linux. Mas se tudo estiver nos conformes com os drivers, podemos partir para as bibliotecas essenciais:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.glfw.org/&quot;&gt;GLFW&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://glew.sourceforge.net/&quot;&gt;GLEW&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para instalar os pacotes dela no fedora seria algo como:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo dnf install glfw-devel glew-devel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora vamos começar a juntar tudo isso e escrever algum código. Vamos criar a pasta para nosso primeiro projeto e criar o primeiro arquivo de código fonte:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mkdir hello-world-opengl &amp;amp;&amp;amp; cd hello-world-opengl &amp;amp;&amp;amp; touch main.cpp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Usando o exemplo de como criar uma janela fornecido pela documentação do GLFW temos:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;iostream&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;GL/glew.h&amp;gt;
#include &amp;lt;GLFW/glfw3.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;GLFWwindow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glfwCreateWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glfwTerminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwMakeContextCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glewInit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GLEW_OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Erro!&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glGetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GL_VERSION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glfwWindowShouldClose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glClear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GL_COLOR_BUFFER_BIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;glBegin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GL_TRIANGLES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glVertex2f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glVertex2f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glVertex2f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;glfwSwapBuffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;glfwPollEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;glfwTerminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;E agora? Fazemos o que com isso? Temos que compilar o nosso código junto com as bibliotecas para gerar o binário e executar o código. Vamos usar o &lt;a href=&quot;https://cmake.org/&quot;&gt;CMake&lt;/a&gt; para facilitar o processo. Temos que escrever o CMakeLists.txt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.15)
project(hello_world_opengl)

set(CMAKE_CXX_STANDARD 14)

add_executable(hello_world_opengl main.cpp)
target_link_libraries(hello_world_opengl -lGL -lGLEW -lglfw)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora só gerar o makefile, compilar e rodar o programa:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mkdir build &amp;amp;&amp;amp; cd build
$ cmake ..
-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- Check for working C compiler: /usr/lib64/ccache/cc
[...]
$ make
Scanning dependencies of target hello_world_opengl
[ 50%] Building CXX object CMakeFiles/hello_world_opengl.dir/main.cpp.o
[100%] Linking CXX executable hello_world_opengl
[100%] Built target hello_world_opengl
$ ./hello_world_opengl
3.0 Mesa 19.1.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Resultado:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/imagens/posts/2020-10-27-setup-basico-opengl-no-linux/01.png&quot; alt=&quot;resultado&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Se não mudar nada no CMakeLists.txt é só dar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make -C ./build &amp;amp;&amp;amp; ./build/hello_world_opengl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora é só começar a brincar com OpenGL :D.&lt;/p&gt;

&lt;h3 id=&quot;referências&quot;&gt;Referências:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=H2E3yO0J7TM&amp;amp;list=PLlrATfBNZ98foTJPJ_Ev03o2oq3-GGOS2&amp;amp;index=3&quot;&gt;vídeo sobre OpenGL moderno do canal The Cherno&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=h8ij7zzIxIc&quot;&gt;vídeo sobre como fazer setup do ambiente no CLion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.glfw.org/documentation.html&quot;&gt;tutorial inicial do GLFW&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="opengl" /><category term="c++" /><category term="linux" /><category term="cmake" /><summary type="html">Antes de começar precisamos descobrir se temos os drivers para OpenGL instalados na nossa máquina.</summary></entry><entry xml:lang="pt"><title type="html">Grafo em C usando lista de adjacências</title><link href="/2019/03/02/grafo-em-c.html" rel="alternate" type="text/html" title="Grafo em C usando lista de adjacências" /><published>2019-03-02T22:19:30+00:00</published><updated>2019-03-02T22:19:30+00:00</updated><id>/2019/03/02/grafo-em-c</id><content type="html" xml:base="/2019/03/02/grafo-em-c.html">&lt;p&gt;Como falei no post anterior, meu objetivo ao implementar uma lista ligada era para na sequência implementar algoritmos relacionados a grafos. Mas antes disso eu preciso implementar o grafo em si.&lt;/p&gt;

&lt;p&gt;A implementação não é indicada para ser utilizada em coisas sérias, é apenas uma prova de conceito. Eu não me importei em verificar se ponteiros são nulos ou se tentaram inserir uma aresta num vértice inexistente.&lt;/p&gt;

&lt;p&gt;Uma boa fonte para entender grafos está &lt;a href=&quot;https://www.tutorialspoint.com/graph_theory/index.htm&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No post anterior eu acabei por esquecer de implementar uma operação de lista ligada que seria útil na implementação do grafo, então vou começar por ela.&lt;/p&gt;

&lt;h2 id=&quot;como-saber-que-itens-uma-lista-ligada-tem&quot;&gt;Como saber que itens uma lista ligada tem?&lt;/h2&gt;

&lt;p&gt;Acontece que eu preciso percorrer os itens da linked list para o algoritmo que eu quero implementar. A maneira mais simples de fazer isso (não a mais eficiente e elegante) é percorrer toda a lista e retornar um array com os itens.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LinkedList_Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;estruturas&quot;&gt;Estruturas&lt;/h2&gt;

&lt;p&gt;Um grafo é um conjunto de vértices conectados por arestas. Existem várias maneiras de representar isso numa estrutura de dados, é possível mencionar &lt;em&gt;Lista de Adjacências&lt;/em&gt;, &lt;em&gt;Lista de incidência&lt;/em&gt;, &lt;em&gt;Matriz de Adjacências&lt;/em&gt; e &lt;em&gt;Matriz de Incidência&lt;/em&gt;. A primeira é muito interessante pois é possível fazer várias operações comuns (obter grau de um vértice etc) em grafos de maneira satisfatória, sendo a mais adequada das quatro para ser uma implementação generalista de um grafo.&lt;/p&gt;

&lt;p&gt;Uma lista de adjacências é um array de vértices, e cada posição do array contém um ponteiro para uma lista ligada contendo as adjacências do vértice em si. É mais fácil trabalhar com exemplos:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/imagens/posts/2019-03-02-grafo-em-c/01.png&quot; alt=&quot;grafo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A lista de adjacência seria a seguinte:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;V[1]    2-&amp;gt;4-&amp;gt;              // O vertice 1 se liga ao vertice 2 e 4
V[2]    1-&amp;gt;3-&amp;gt;4-&amp;gt;5-&amp;gt;        // O vertice 2 se liga ao 1, 3, 4 e 5
V[3]    2-&amp;gt;5-&amp;gt;              // etc...
V[4]    1-&amp;gt;2-&amp;gt;5-&amp;gt;
V[5]    2-&amp;gt;3-&amp;gt;4-&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa seria a estrutura em C:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_edges&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;e-como-alocar-dinamicamente-um-array-de-ponteiros&quot;&gt;E como alocar dinamicamente um array de ponteiros?&lt;/h2&gt;

&lt;p&gt;Nessa hora que o bicho pega. A lógica é simples mas pode ser difícil de lembrar se você não programa em C frequentemente. Quem já teve que alocar dinamicamente uma matriz sabe como fazer.&lt;/p&gt;

&lt;p&gt;A implementação nada mais é que um ponteiro para um ponteiro. Primeiro você aloca como um array normal, usando um:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A matriz tem que acomodar um ponteiro para uma lista ligada, e tem que ter o tamanho do número de vértices do grafo.&lt;/p&gt;

&lt;p&gt;Depois disso você precisa percorrer cada posição do array e colocar uma lista ligada vazia em cada posição. O detalhe é que caso uma dessas alocações falhe, você tem que ir “voltando” dando free no que você já alocou. Como eu já implementei a alocação da lista ligada, ficou assim:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LinkedList_Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;LinkedList_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No fim, adicionando umas verificação de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; e retornando a “matriz”:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;allocate_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LinkedList_Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;LinkedList_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;criando-e-destruindo&quot;&gt;Criando e destruindo&lt;/h2&gt;

&lt;p&gt;Depois que nos livramos desse fardo que é a alocação da matriz de vértices, criar e destruir um grafo é mais do mesmo:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Graph_Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_edges&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allocate_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Graph_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;LinkedList_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Agora é possível instanciar um grafo e utilizar como um “objeto”.&lt;/p&gt;

&lt;h2 id=&quot;inserindo-arestas&quot;&gt;Inserindo arestas&lt;/h2&gt;

&lt;p&gt;Uma operação tão boba. Escolhendo os dois vértices para ligar, u e v por exemplo. Vou na lista ligada de u adicionando v, e vice-versa.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Graph_InsertEdge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;   
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;LinkedList_Prepend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LinkedList_Prepend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note que se eu chamar a função passando source e destiny inexistentes, o programa dá um &lt;em&gt;segmentation fault&lt;/em&gt; violento. Mas só quem vai usar sou eu, então tá tudo de boas.&lt;/p&gt;

&lt;h2 id=&quot;considerações-finais&quot;&gt;Considerações finais&lt;/h2&gt;

&lt;p&gt;O próximo passo é implementar algum algoritmo. Vou usar &lt;a href=&quot;https://github.com/rafaellcoellho/graph&quot;&gt;esse&lt;/a&gt; repositório para deixar o código disponível, e ir adicionando algoritmos conforme for postando.&lt;/p&gt;

&lt;p&gt;No post passado eu falei que estava usando o &lt;a href=&quot;https://github.com/ThrowTheSwitch/Ceedling&quot;&gt;Ceedling&lt;/a&gt;. Acontece que build systems &lt;strong&gt;&lt;em&gt;são um inferno&lt;/em&gt;&lt;/strong&gt;. O ceedling funcionou bem para aquele projeto e é um ótimo software, mas como é do nicho do &lt;em&gt;firmware&lt;/em&gt; e não muito popular acaba tendo carência de quantidade de informação na internet.&lt;/p&gt;

&lt;p&gt;Resolvi fazer minha ultima tentativa: &lt;a href=&quot;https://mesonbuild.com/&quot;&gt;meson&lt;/a&gt;. É relativamente popular, tem uma documentação orientada a exemplos e casos comuns, alguns tutoriais no medium…&lt;/p&gt;

&lt;p&gt;Para testar migrei o projeto anterior para ele. Esse projeto também faz uso do mesmo. Quem sabe eu faço um post no futuro sobre casos de uso.&lt;/p&gt;

&lt;h2 id=&quot;referências&quot;&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.tutorialspoint.com/graph_theory/index.htm&quot;&gt;tutorialspoint.com/graph_theory/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="c" /><category term="algoritmos" /><category term="grafos" /><category term="estrutura-de-dados" /><summary type="html">Como falei no post anterior, meu objetivo ao implementar uma lista ligada era para na sequência implementar algoritmos relacionados a grafos. Mas antes disso eu preciso implementar o grafo em si.</summary></entry><entry xml:lang="en"><title type="html">Graph in C Using Adjacency Lists</title><link href="/en/2019/03/02/graph-in-c-using-adjacency-lists/" rel="alternate" type="text/html" title="Graph in C Using Adjacency Lists" /><published>2019-03-02T22:19:30+00:00</published><updated>2019-03-02T22:19:30+00:00</updated><id>/en/2019/03/02/graph-in-c-using-adjacency-lists</id><content type="html" xml:base="/en/2019/03/02/graph-in-c-using-adjacency-lists/">&lt;p&gt;As I mentioned in the previous post, my goal when implementing a linked list was to then implement graph-related algorithms. But before that I need to implement the graph itself.&lt;/p&gt;

&lt;p&gt;This implementation is not meant to be used in serious projects — it’s just a proof of concept. I didn’t bother checking for null pointers or whether someone tried to insert an edge on a non-existent vertex.&lt;/p&gt;

&lt;p&gt;A good resource for understanding graphs is &lt;a href=&quot;https://www.tutorialspoint.com/graph_theory/index.htm&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the previous post I forgot to implement a linked list operation that would be useful in the graph implementation, so I’ll start with that.&lt;/p&gt;

&lt;h2 id=&quot;how-do-you-know-what-items-a-linked-list-has&quot;&gt;How do you know what items a linked list has?&lt;/h2&gt;

&lt;p&gt;It turns out I need to iterate over the items of the linked list for the algorithm I want to implement. The simplest way to do this (not the most efficient or elegant) is to traverse the entire list and return an array with the items.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LinkedList_Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_aux&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;structures&quot;&gt;Structures&lt;/h2&gt;

&lt;p&gt;A graph is a set of vertices connected by edges. There are several ways to represent this in a data structure — &lt;em&gt;Adjacency List&lt;/em&gt;, &lt;em&gt;Incidence List&lt;/em&gt;, &lt;em&gt;Adjacency Matrix&lt;/em&gt; and &lt;em&gt;Incidence Matrix&lt;/em&gt; are some worth mentioning. The first is very interesting because it allows many common graph operations (getting the degree of a vertex, etc.) to be performed satisfactorily, making it the most suitable of the four for a general-purpose graph implementation.&lt;/p&gt;

&lt;p&gt;An adjacency list is an array of vertices, and each position in the array contains a pointer to a linked list holding that vertex’s adjacencies. It’s easier to understand with an example:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/imagens/posts/2019-03-02-grafo-em-c/01.png&quot; alt=&quot;graph&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The adjacency list would be as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;V[1]    2-&amp;gt;4-&amp;gt;              // Vertex 1 connects to vertices 2 and 4
V[2]    1-&amp;gt;3-&amp;gt;4-&amp;gt;5-&amp;gt;        // Vertex 2 connects to 1, 3, 4 and 5
V[3]    2-&amp;gt;5-&amp;gt;              // etc...
V[4]    1-&amp;gt;2-&amp;gt;5-&amp;gt;
V[5]    2-&amp;gt;3-&amp;gt;4-&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This would be the structure in C:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_edges&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;how-do-you-dynamically-allocate-an-array-of-pointers&quot;&gt;How do you dynamically allocate an array of pointers?&lt;/h2&gt;

&lt;p&gt;This is where things get tricky. The logic is simple but can be hard to remember if you don’t program in C frequently. Anyone who has had to dynamically allocate a matrix knows how to do it.&lt;/p&gt;

&lt;p&gt;The implementation is nothing more than a pointer to a pointer. First you allocate it like a regular array:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The matrix has to accommodate a pointer to a linked list, and it has to be the size of the number of vertices in the graph.&lt;/p&gt;

&lt;p&gt;After that you need to go through each position of the array and place an empty linked list at each position. The detail is that if any of these allocations fails, you have to “roll back” by freeing what you already allocated. Since I already implemented the linked list allocation, it looked like this:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LinkedList_Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;LinkedList_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; check and returning the “matrix”:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;allocate_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LinkedList_Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;LinkedList_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;creating-and-destroying&quot;&gt;Creating and destroying&lt;/h2&gt;

&lt;p&gt;Once we’ve dealt with the burden of allocating the vertex matrix, creating and destroying a graph is more of the same:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Graph_Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_edges&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allocate_matrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Graph_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;LinkedList_Destroy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s now possible to instantiate a graph and use it like an “object”.&lt;/p&gt;

&lt;h2 id=&quot;inserting-edges&quot;&gt;Inserting edges&lt;/h2&gt;

&lt;p&gt;Such a trivial operation. Pick the two vertices to connect, u and v for example. Go to u’s linked list and add v, then do the same for v.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Graph_InsertEdge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;   
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;llist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array_vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;LinkedList_Prepend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destiny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LinkedList_Prepend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that if I call the function passing non-existent source and destiny, the program throws a violent &lt;em&gt;segmentation fault&lt;/em&gt;. But I’m the only one using it, so it’s all good.&lt;/p&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;The next step is to implement some algorithm. I’ll use &lt;a href=&quot;https://github.com/rafaellcoellho/graph&quot;&gt;this&lt;/a&gt; repository to keep the code available and add algorithms as I post about them.&lt;/p&gt;

&lt;p&gt;In the previous post I mentioned I was using &lt;a href=&quot;https://github.com/ThrowTheSwitch/Ceedling&quot;&gt;Ceedling&lt;/a&gt;. It turns out that build systems &lt;strong&gt;&lt;em&gt;are a nightmare&lt;/em&gt;&lt;/strong&gt;. Ceedling worked well for that project and is great software, but since it’s a firmware niche tool and not very popular, it lacks information on the internet.&lt;/p&gt;

&lt;p&gt;I decided to make one last attempt: &lt;a href=&quot;https://mesonbuild.com/&quot;&gt;meson&lt;/a&gt;. It’s relatively popular, has example- and use-case-driven documentation, and a few tutorials on Medium…&lt;/p&gt;

&lt;p&gt;To test it I migrated the previous project to it. This project uses it as well. Maybe I’ll write a post about use cases in the future.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.tutorialspoint.com/graph_theory/index.htm&quot;&gt;tutorialspoint.com/graph_theory/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Rafael Coelho</name></author><category term="c" /><category term="algorithms" /><category term="graphs" /><category term="data-structures" /><summary type="html">As I mentioned in the previous post, my goal when implementing a linked list was to then implement graph-related algorithms. But before that I need to implement the graph itself.</summary></entry></feed>