<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Juan Burgos</title>
    <description>The latest articles on Forem by Juan Burgos (@jlburgos).</description>
    <link>https://forem.com/jlburgos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F752322%2F414a0ec1-c224-4aad-bf21-f5729564eda3.png</url>
      <title>Forem: Juan Burgos</title>
      <link>https://forem.com/jlburgos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jlburgos"/>
    <language>en</language>
    <item>
      <title>Micro-Post: Stop using `rm` to delete things!</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Tue, 13 Feb 2024 19:02:46 +0000</pubDate>
      <link>https://forem.com/jlburgos/micro-post-stop-using-rm-to-delete-things-1657</link>
      <guid>https://forem.com/jlburgos/micro-post-stop-using-rm-to-delete-things-1657</guid>
      <description>&lt;p&gt;The &lt;code&gt;rm&lt;/code&gt; shell command is probably the most dangerous command in popular use. You can accidentally delete things you never meant to delete. As such, there are several precautions one should take to avoid any horrific situations.&lt;/p&gt;

&lt;p&gt;The following are some simple things you can set in your shell's configuration files (i.e. &lt;code&gt;.bashrc&lt;/code&gt;, &lt;code&gt;.zshrc&lt;/code&gt;, etc.) that should come in handy!&lt;/p&gt;

&lt;p&gt;(1) Always adding &lt;code&gt;-i&lt;/code&gt; to request confirmation before deletion and &lt;code&gt;-v&lt;/code&gt; to see exactly what you are deleting, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias rm='rm -i -v'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this approach may still fail if you add &lt;code&gt;-f&lt;/code&gt; which forces the deletion operation, so be aware that, though useful, this strategy is not a panacea.&lt;/p&gt;

&lt;p&gt;(2) Avoiding use of &lt;code&gt;rm&lt;/code&gt; completely and switching to a custom soft-delete method as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function softdelete() {
  local -r path=$(realpath -q "${1}")
  [[ -z "${1}" || -z "${path}" ]] &amp;amp;&amp;amp; {
    echo "No valid path was found for argument '${1}'"
    return 1
  }
  local -r backup ="/tmp/$(echo -n "${path}" | tr /' '_')"
  mv -v ${path} ${backup}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this approach is less versatile since you don't have all the command-line options &lt;code&gt;rm&lt;/code&gt; provides. However, the benefits should far outweigh the costs since this method effectively soft-deletes files/folders alike to the &lt;code&gt;/tmp&lt;/code&gt; directory. Though you could always modify this to point to any other directory of your choosing.&lt;/p&gt;

&lt;p&gt;Another benefit of this method is that it preserves the original file path with &lt;code&gt;/&lt;/code&gt;'s replaced with &lt;code&gt;_&lt;/code&gt;'s so you don't have to remember the file's original path. This also helps with filename collisions to some extent.&lt;/p&gt;

&lt;p&gt;Hope others find this useful!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>bash</category>
      <category>learning</category>
    </item>
    <item>
      <title>Micro-Post: End of Year 2024 Message</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Sat, 23 Dec 2023 00:27:22 +0000</pubDate>
      <link>https://forem.com/jlburgos/micro-post-end-of-year-2024-message-24n4</link>
      <guid>https://forem.com/jlburgos/micro-post-end-of-year-2024-message-24n4</guid>
      <description>&lt;p&gt;Well, 2024 was a bit of an insane year. Did a lot of personal learning as part of my developer journey. My hope is that I can continue learning more in the coming year and document my journey better, mainly to help keep me accountable to myself :P&lt;/p&gt;

&lt;p&gt;With the end of the year just around the corner, I wanted to end the year with a cute little C++ program :D&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat main.cpp
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;cstdint&amp;gt;

// I'm going to define my own shorter integral types!
using U8 = uint8_t; // unsigned char
using U64 = uint64_t; // unsigned long long

// This was something new I learned the other week :D
// https://en.cppreference.com/w/cpp/language/user_literal
consteval U8 operator ""_uc(const U64 value) {
  return static_cast&amp;lt;U8&amp;gt;(value);
}

int main() {
  std::cout
    &amp;lt;&amp;lt; 67_uc
    &amp;lt;&amp;lt; 43_uc
    &amp;lt;&amp;lt; 43_uc
    &amp;lt;&amp;lt; " is awesome! See you all next year!"
    &amp;lt;&amp;lt; std::endl;
  return EXIT_SUCCESS;
}

$ g++ main.cpp -o main.exe &amp;amp;&amp;amp; ./main.exe
C++ is awesome! See you all next year!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>2024</category>
      <category>cpp</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Micro-Post: Tracking TMUX pane zoom-in status</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Wed, 20 Sep 2023 20:31:19 +0000</pubDate>
      <link>https://forem.com/jlburgos/micro-post-tracking-tmux-pane-zoom-in-status-1325</link>
      <guid>https://forem.com/jlburgos/micro-post-tracking-tmux-pane-zoom-in-status-1325</guid>
      <description>&lt;p&gt;Something that I used to struggle with is remembering whether or not I'm currently zoomed into a particular pane on any particular TMUX window.&lt;/p&gt;

&lt;p&gt;The following is what I implemented to resolve this problem for myself, and I thought this may be interesting to others.&lt;/p&gt;

&lt;p&gt;In my &lt;code&gt;tmux.conf&lt;/code&gt; file, I added the following zoom binding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# automatically reload zoomed-in status
bind z {
  resize-pane -Z
  if-shell "tmux list-panes -F '#{?window_zoomed_flag,yes,no}' | grep yes" {
    set -g status-left "[#S | ZOOMED-IN ] " ## Print session label in the left side of the status bar
  } {
    set -g status-left "[#S] " ## Print session label in the left side of the status bar
  }
}
...
...
# simple pane rename binding
bind R command-prompt -p "(rename-pane)" -I "#T" { select-pane -T "%%" }
...
...
# setting the pane status bar how I like it
set -g pane-border-style fg=yellow
set -g pane-active-border-style "bg=default fg=yellow"
set -g pane-border-status top
set -g pane-border-format "[ ###P | #T | CMD: `#{pane_current_command}` ]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is that when I'm "zoomed out" I see, the following in my window status bar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[SESSION_NAME] (0: WINDOW_NAME)
──[ #0 | PANE_NAME | CMD: `zsh`]───────────
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I zoom into pane #0, my window status bar shows the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[SESSION_NAME | ZOOMED-IN ] (0: WINDOW_NAME)
──[ #0 | PANE_NAME | CMD: `zsh`]───────────
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zooming out will automatically return the window status bar back to what it originally was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[SESSION_NAME] (0: WINDOW_NAME)
──[ #0 | PANE_NAME | CMD: `zsh`]───────────
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I just so happened to prefer seeing the "ZOOMED-IN" statement at the very top of my TMUX session's status bar since it catches my attention more easily.&lt;/p&gt;

&lt;p&gt;I also threw in here a simple binding for quickly changing pane titles since it's also useful.&lt;/p&gt;

&lt;p&gt;Hope others find this info useful :-)&lt;/p&gt;

</description>
      <category>tmux</category>
      <category>beginners</category>
      <category>shell</category>
      <category>programming</category>
    </item>
    <item>
      <title>Micro-Post: Simple Logging PreProcessor Macro</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Sun, 25 Jun 2023 15:30:39 +0000</pubDate>
      <link>https://forem.com/jlburgos/micro-post-simple-logging-preprocessor-macro-4b07</link>
      <guid>https://forem.com/jlburgos/micro-post-simple-logging-preprocessor-macro-4b07</guid>
      <description>&lt;p&gt;Was chatting with a university student I'm mentoring and she mentioned she's going to take a C Programming course in the Fall semester and was asking for advice.&lt;/p&gt;

&lt;p&gt;Among the various advice I gave her, I included this macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat logger.h
// Preprocessor Macro: https://en.cppreference.com/w/c/preprocessor/replace
#define LOG(msg, ...) { \
  printf("File %s | Line %d :: ", __FILE__, __LINE__); \
  printf((msg), ##__VA_ARGS__); \
}

$ cat -n test-logger.cc
     1  #include &amp;lt;stdio.h&amp;gt;
     2  #include "logger.h"
     3
     4  int main() {
     5    LOG("%s %s!\n", "HELLO", "WORLD");
     6    bool check = true; // Bit dumb but imagine a method call instead
     7    if (check) {
     8      LOG("[ERROR] Some condition has been fulfilled that shouldn't have! Check what happened...\n");
     9    }
    10    return 0;
    11  }

$ cc test-logger.cc -o test-logger &amp;amp;&amp;amp; ./test-logger
File test-logger.cc | Line 5 :: HELLO WORLD!
File test-logger.cc | Line 8 :: [ERROR] Some condition has been fulfilled that shouldn't have! Check what happened...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bit of a contrived example, but it should hopefully illustrate the macro's potential.&lt;/p&gt;

&lt;p&gt;Really wish I knew this macro, and other useful ones, when I was taking my C/C++ intro courses back in the day. Would have been a great tool in my "debug my own code" toolset to replace the famous &lt;code&gt;printf("I HAVE REACHED LINE XYZ IN MY CODE")&lt;/code&gt; style of debugging with hardcoded line numbers :D&lt;/p&gt;

&lt;p&gt;-- Addendum --&lt;br&gt;
If you want to use these macros in a C++ program, you may need to add &lt;code&gt;--std=c++11&lt;/code&gt; or higher along with &lt;code&gt;-Wno-gnu-zero-variadic-macro-arguments&lt;/code&gt; to avoid errors such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: variadic macros are a C99 feature [-Werror,-Wvariadic-macros]
#define LOG_INFO(msg, ...) \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Werror,-Wgnu-zero-variadic-macro-arguments]
  fprintf(stderr, "File %s | Line %d :: (ERROR) ", __FILE__, __LINE__); fprintf(stderr, (msg), ##__VA_ARGS__);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cpp</category>
      <category>beginners</category>
      <category>programming</category>
      <category>coding</category>
    </item>
    <item>
      <title>Easier shell directory navigation</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Wed, 16 Nov 2022 21:43:14 +0000</pubDate>
      <link>https://forem.com/jlburgos/easier-shell-directory-navigation-1e4k</link>
      <guid>https://forem.com/jlburgos/easier-shell-directory-navigation-1e4k</guid>
      <description>&lt;p&gt;This is another small post to highlight a useful little piece of code that solves a rather annoying problem I deal with on a daily basis.&lt;/p&gt;

&lt;p&gt;While the solution is neither unique nor likely the cleanest method, it is one that's simple enough that others can likely find utility in expanding.&lt;/p&gt;

&lt;p&gt;Suppose you're in the following situation in your dev environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ${PROJ_DIR}
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz/network-interface/interface/impl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose further that you'd like to periodically jump between several different directories. It's really annoying doing &lt;code&gt;cd ../../../&lt;/code&gt; and so on, though you do have tools like &lt;code&gt;cd ${OLDPWD}&lt;/code&gt; or &lt;code&gt;cd -&lt;/code&gt; and such via BASH/ZSH. But this can still be tedious.&lt;/p&gt;

&lt;p&gt;In comes the following shell method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdback() {
  local -r dirname=${1}
  [[ -z ${dirname} ]] &amp;amp;&amp;amp; {
    echo "Missing required parameter: Parent Directory Name\n"
    return 1
  }
  ## Note: https://stackoverflow.com/questions/22537804/retrieve-a-word-after-a-regular-expression-in-shell-script
  ##       ZSH uses ${match} for array while bash has ${BASH_REMATCH}.
  ## Note: https://stackoverflow.com/questions/1335815/how-to-slice-an-array-in-bash
  ##       Made use of nested ${..} bash constructs to rebuild directory path.
  ## Note: Had to do the bash version a bit differently due to "substitution error" with nested ${..} construct.
  ##       Also, array indexing was different between zsh and bash for some reason...
  local -r pattern="^(.+)\/(${dirname})\/(.*)$"
  [[ ${PWD} =~ ${pattern} ]] &amp;amp;&amp;amp; {
    [[ -n $ZSH_VERSION ]] &amp;amp;&amp;amp; cd "${${match[@]:0:2}/ //}" || cd "$(echo ${BASH_REMATCH[@]:1:2} | tr ' ' '/')"
  } || {
    echo "Parent Directory '${dirname}' could not be found\n"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea behind this method is that we can use the power of regex to jump up the directory tree to a directory with a name that matches the first argument to the &lt;code&gt;cdback&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ${PROJ_DIR}
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz/network-interface/interface/impl
$ cdback mybiz
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz
cd ${OLDPWD}
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz/network-interface/interface/impl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This even works by repetition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ${PROJ_DIR}
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz/network-interface/interface/impl
$ cdback network
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz/network-interface
$ cdback network
$ pwd
~/dev/shared/network-interface/dev/shared/network
$ cdback network
$ pwd
~/dev/shared/network-interface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to avoid repetition for similarly named directories, you can include parent/child directories like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ${PROJ_DIR}
$ pwd
~/dev/shared/network-interface/dev/shared/network/src/main/java/com/mybiz/network-interface/interface/impl
$ cdback shared/network-interface
$ pwd
~/dev/shared/network-interface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's more elegant ways to set this up and to support directories with spaces (but who does that really), but I found this setup immediately useful. Especially for heavily nested project directory structures.&lt;/p&gt;

&lt;p&gt;Any comments/criticism are welcome! Hopefully folks find this useful.&lt;/p&gt;

</description>
      <category>welcome</category>
    </item>
    <item>
      <title>MicroPost: Install "ueberzug" on MacOS</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Sun, 17 Jul 2022 20:09:27 +0000</pubDate>
      <link>https://forem.com/jlburgos/micropost-install-ueberzug-on-macos-3371</link>
      <guid>https://forem.com/jlburgos/micropost-install-ueberzug-on-macos-3371</guid>
      <description>&lt;p&gt;Today I discovered the &lt;a href="https://github.com/d0c-s4vage/lookatme"&gt;https://github.com/d0c-s4vage/lookatme&lt;/a&gt; repository and thought the project was really cool! Sure there's some security implications with the "terminal" extension (among other things), but if you know what you're doing, the tool is really interesting :-)&lt;/p&gt;

&lt;p&gt;Trying to install it however, was a bit of a pain. I only really cared about the &lt;code&gt;image_ueberzug&lt;/code&gt; extension, so that's the main one I wanted to install, however, installing it wouldn't work!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip install lookatme.contrib.image_ueberzug
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Collecting ueberzug
  Using cached ueberzug-18.1.9.tar.gz (36 kB)
  Preparing metadata (setup.py): started
  Preparing metadata (setup.py): finished with status 'done'
Requirement already satisfied: python-xlib in /usr/local/lib/python3.9/site-packages (from ueberzug) (0.31)
Requirement already satisfied: pillow in /usr/local/lib/python3.9/site-packages (from ueberzug) (9.2.0)
Requirement already satisfied: docopt in /usr/local/lib/python3.9/site-packages (from ueberzug) (0.6.2)
Requirement already satisfied: attrs&amp;gt;=18.2.0 in /usr/local/lib/python3.9/site-packages (from ueberzug) (21.4.0)
Requirement already satisfied: six&amp;gt;=1.10.0 in /usr/local/lib/python3.9/site-packages (from python-xlib-&amp;gt;ueberzug) (1.16.0)
Building wheels for collected packages: ueberzug
  Building wheel for ueberzug (setup.py): started
  Building wheel for ueberzug (setup.py): finished with status 'error'
  error: subprocess-exited-with-error

  × python setup.py bdist_wheel did not run successfully.
  │ exit code: 1
  ╰─&amp;gt; [51 lines of output]
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-12-x86_64-cpython-39
      creating build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/scaling.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/tmux_util.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/files.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/xutil.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/loading.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/thread.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/version.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/library.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/terminal.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/ui.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/batch.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/conversion.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/__init__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/pattern.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/query_windows.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/action.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/parser.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/geometry.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/layer.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/process.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/__main__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      creating build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib
      copying ueberzug/lib/__init__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib
      creating build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib/v0
      copying ueberzug/lib/v0/__init__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib/v0
      running egg_info
      writing ueberzug.egg-info/PKG-INFO
      writing dependency_links to ueberzug.egg-info/dependency_links.txt
      writing entry points to ueberzug.egg-info/entry_points.txt
      writing requirements to ueberzug.egg-info/requires.txt
      writing top-level names to ueberzug.egg-info/top_level.txt
      reading manifest file 'ueberzug.egg-info/SOURCES.txt'
      reading manifest template 'MANIFEST.in'
      writing manifest file 'ueberzug.egg-info/SOURCES.txt'
      copying ueberzug/lib/lib.sh -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib
      running build_ext
      building 'Xshm' extension
      creating build/temp.macosx-12-x86_64-cpython-39
      creating build/temp.macosx-12-x86_64-cpython-39/Xshm
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk -I/usr/local/opt/node@10/include -I/usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/include/python3.9 -c Xshm/Xshm.c -o build/temp.macosx-12-x86_64-cpython-39/Xshm/Xshm.o
      Xshm/Xshm.c:5:10: fatal error: 'X11/Xlib.h' file not found
      #include &amp;lt;X11/Xlib.h&amp;gt;
               ^~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for ueberzug
  Running setup.py clean for ueberzug
Failed to build ueberzug
Installing collected packages: ueberzug
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
  Running setup.py install for ueberzug: started
  Running setup.py install for ueberzug: finished with status 'error'
  error: subprocess-exited-with-error

  × Running setup.py install for ueberzug did not run successfully.
  │ exit code: 1
  ╰─&amp;gt; [53 lines of output]
      running install
      /usr/local/lib/python3.9/site-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
        warnings.warn(
      running build
      running build_py
      creating build
      creating build/lib.macosx-12-x86_64-cpython-39
      creating build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/scaling.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/tmux_util.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/files.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/xutil.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/loading.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/thread.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/version.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/library.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/terminal.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/ui.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/batch.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/conversion.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/__init__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/pattern.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/query_windows.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/action.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/parser.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/geometry.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/layer.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/process.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      copying ueberzug/__main__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug
      creating build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib
      copying ueberzug/lib/__init__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib
      creating build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib/v0
      copying ueberzug/lib/v0/__init__.py -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib/v0
      running egg_info
      writing ueberzug.egg-info/PKG-INFO
      writing dependency_links to ueberzug.egg-info/dependency_links.txt
      writing entry points to ueberzug.egg-info/entry_points.txt
      writing requirements to ueberzug.egg-info/requires.txt
      writing top-level names to ueberzug.egg-info/top_level.txt
      reading manifest file 'ueberzug.egg-info/SOURCES.txt'
      reading manifest template 'MANIFEST.in'
      writing manifest file 'ueberzug.egg-info/SOURCES.txt'
      copying ueberzug/lib/lib.sh -&amp;gt; build/lib.macosx-12-x86_64-cpython-39/ueberzug/lib
      running build_ext
      building 'Xshm' extension
      creating build/temp.macosx-12-x86_64-cpython-39
      creating build/temp.macosx-12-x86_64-cpython-39/Xshm
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk -I/usr/local/opt/node@10/include -I/usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/include/python3.9 -c Xshm/Xshm.c -o build/temp.macosx-12-x86_64-cpython-39/Xshm/Xshm.o
      Xshm/Xshm.c:5:10: fatal error: 'X11/Xlib.h' file not found
      #include &amp;lt;X11/Xlib.h&amp;gt;
               ^~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure

× Encountered error while trying to install package.
╰─&amp;gt; ueberzug

note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a pretty large error message! But the important part is towards the bottom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      Xshm/Xshm.c:5:10: fatal error: 'X11/Xlib.h' file not found
      #include &amp;lt;X11/Xlib.h&amp;gt;
               ^~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did a lot of Googling and eventually found that you can pass build parameters to the &lt;code&gt;pip&lt;/code&gt; command... cool! You learn something new everyday!&lt;/p&gt;

&lt;p&gt;Long story short, I had to pass two additional parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;-I/usr/local/include&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-L/usr/X11/lib&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This gave me the following &lt;code&gt;pip install&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install \
  --global-option=build_ext \
  --global-option="-I/usr/local/include" \
  --global-option="-L/opt/X11/lib"  \
  lookatme.contrib.image_ueberzug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this wasn't enough! Upon trying to run the &lt;code&gt;ueberzug&lt;/code&gt; executable, I got a "command not found" error!!&lt;/p&gt;

&lt;p&gt;Yet another long story short... had to run this to set it up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ln -s $(find /usr/local/Cellar -name ueberzug) /usr/local/bin/ueberzug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To summarize my adventure... here's a short script that'll do the above in a single run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat install.lookatme-contrib.sh
#!/bin/zsh

pip install \
  --global-option=build_ext \
  --global-option="-I/usr/local/include" \
  --global-option="-L/opt/X11/lib"  \
  lookatme.contrib.image_ueberzug

[[ -x "$(command -v ueberzug)" ]] || {
  echo "Locating 'ueberzug' executable to set up soft-link ..."
  ln -s $(find /usr/local/Cellar -name ueberzug) /usr/local/bin/ueberzug
}

echo "\nDone"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;^^^ For the above script, the &lt;code&gt;[[ -x "$(command -v &amp;lt;cmd&amp;gt;)" ]]&lt;/code&gt; part checks to see if the shell can find the specified command.&lt;/p&gt;

&lt;p&gt;Found how to do that here: &lt;a href="https://stackoverflow.com/questions/592620/how-can-i-check-if-a-program-exists-from-a-bash-script"&gt;https://stackoverflow.com/questions/592620/how-can-i-check-if-a-program-exists-from-a-bash-script&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Praise StackOverFlow!! :P&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Making my Makefile find things for me</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Sun, 06 Mar 2022 02:34:33 +0000</pubDate>
      <link>https://forem.com/jlburgos/what-i-learned-today-about-makefiles-30ff</link>
      <guid>https://forem.com/jlburgos/what-i-learned-today-about-makefiles-30ff</guid>
      <description>&lt;p&gt;Welp, this is my first actual post on &lt;a href="//dev.to"&gt;dev.to&lt;/a&gt;, and what better way to document my slow descent to madness then to dedicate my first post to some "fun" and "cool" stuff I learned while trying to set up a &lt;code&gt;Makefile&lt;/code&gt; for a SDL2 game project I'm using as a learning exercise :-)&lt;/p&gt;

&lt;p&gt;I'll make this short maybe further expand on stuff in a later post. Also, my apologies of the discussions seems a little hurried and unorganized. This is my first post and I'm writing this later into the evening. Hopefully as time goes on, I'll improve in my writing ability!&lt;/p&gt;

&lt;p&gt;Ran into a problem of my own making when pulling the SDL2 MINGW libraries &lt;a href="https://github.com/libsdl-org/SDL/releases"&gt;SDL2 Dev&lt;/a&gt;, &lt;a href="https://github.com/libsdl-org/SDL_image/releases"&gt;SDL Image&lt;/a&gt;, and so on.  So... I decided, in my infinite wisdom, that I didn't want to go through each of the MINGW tarballs to find all the includes, libs, and DLLs. Yes, DLLs. Not only did I want to make sure that my future game code can be compiled on Linux, but that I can actually do some coding on my Windows machine. &lt;/p&gt;

&lt;p&gt;And I wanted my Makefile to do that all for me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PLATFORM_VERSION = x86_64
EXTERNAL_SDL2_DEP=../MINGW-SDL2
ifeq ($(OS), Windows_NT)
    ifeq ("$(wildcard $(EXTERNAL_SDL2_DEP))","")
$(error "Failed to locate expected '$(EXTERNAL_SDL2_DEP)' directory containing SDL2 dependencies!")
    else
INCLUDES := $(shell powershell 'Get-ChildItem "include" -Directory -Path "$(EXTERNAL_SDL2_DEP)" -Recurse | Where {$$_.FullName -match "$(PLATFORM_VERSION)"} | Resolve-Path -Relative')
INCLUDES := $(subst \,/,$(addprefix -I, $(addsuffix /SDL2, $(INCLUDES))))
LIBRARIES := $(shell powershell 'Get-ChildItem "lib" -Directory -Path "$(EXTERNAL_SDL2_DEP)" -Recurse | Where {$$_.FullName -match "$(PLATFORM_VERSION)"} | Resolve-Path -Relative')
LIBRARIES := $(subst \,/,$(addprefix -L, $(LIBRARIES)))
SDL_FLAGS+=$(INCLUDES) $(LIBRARIES)
    endif
else
SDL_FLAGS+=$(shell sdl2-config --cflags)
endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above we can see that I'm specifying &lt;code&gt;x86_64&lt;/code&gt; as my platform of choice... sorry no 32-bit architectures for me. I tossed all the SDL2 release folders I downloaded from Github to my the &lt;code&gt;MINGW-SDL2&lt;/code&gt; folder that sits parallel to my game project directory.&lt;/p&gt;

&lt;p&gt;I then check to see if the OS I'm sporting is Windows, and if so, I proceed to run some &lt;a href="https://docs.microsoft.com/en-us/powershell/"&gt;Powershell&lt;/a&gt; commands to automatically locate the includes and libs. Using the &lt;code&gt;addprefix&lt;/code&gt; and &lt;code&gt;addsuffix&lt;/code&gt; Makefile functions, I construct the &lt;code&gt;-I&amp;lt;path/to/inc&amp;gt;&lt;/code&gt; and &lt;code&gt;-L&amp;lt;path/to/lib&amp;gt;&lt;/code&gt; parameters that the &lt;code&gt;gcc&lt;/code&gt; compiler will require later on.&lt;/p&gt;

&lt;p&gt;Minor note 1: &lt;em&gt;Usually when looking through Google and StackOverflow results on how to do certain things in Makefiles, you'll see folks point out the use of &lt;code&gt;$(shell &amp;lt;...&amp;gt;)&lt;/code&gt; calls which invoke Bash/Zsh commands. Since I'm in Windows, I want to invoke Powershell commands that do similar things to their Linux counterparts and make sure those commands work when either running in the Powershell shell itself or via some other shell like the MINGW Git Bash shell.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Minor note 2: &lt;em&gt;The use of &lt;code&gt;$$&lt;/code&gt; in the &lt;code&gt;Where {$$_.DirectoryName -match "$(PLATFORM_VERSION)"}&lt;/code&gt; Powershell call is important. The &lt;code&gt;$&lt;/code&gt; is already used in a Makefile for referring to variables and executing function calls. In order to use the &lt;code&gt;$&lt;/code&gt; for the Powershell call, you need to "escape" it with another &lt;code&gt;$&lt;/code&gt;, hence the &lt;code&gt;$$&lt;/code&gt;. You can find this in the &lt;a href="https://www.gnu.org/software/make/manual/make.html"&gt;Makefile manual online&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To breakdown the Powershell calls a bit... &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem"&gt;Get-ChildItem&lt;/a&gt; call is sort of like the Bash &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; commands smashed into a single super command.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Where {...}&lt;/code&gt; call (similar to &lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object"&gt;Where-Object&lt;/a&gt;) is a simple filter on the &lt;code&gt;PLATFORM_VERSION&lt;/code&gt; string &lt;code&gt;x86_64&lt;/code&gt; so we ignore any &lt;code&gt;i686&lt;/code&gt; directories.&lt;/li&gt;
&lt;li&gt;Finally the &lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/resolve-path"&gt;Resolve-Path&lt;/a&gt; call returns a simple list of directory paths related to the Makefile's location as a newline separate list. When stored in the &lt;code&gt;INCLUDES&lt;/code&gt; variable, this result is constructed into a list of relative directory paths.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at the two lines setting up the &lt;code&gt;$(INCLUDES)&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INCLUDES := $(shell powershell 'Get-ChildItem "include" -Directory -Path "$(EXTERNAL_SDL2_DEP)" -Recurse | Where {$$_.FullName -match "$(PLATFORM_VERSION)"} | Resolve-Path -Relative')
INCLUDES := $(subst \,/,$(addprefix -I, $(addsuffix /SDL2, $(INCLUDES))))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding additional logging calls &lt;code&gt;$(info INCLUDES: $(INCLUDES))&lt;/code&gt; after each line, you can see this process more clearly.&lt;/p&gt;

&lt;p&gt;Here is the result of the first line which located all the &lt;code&gt;include&lt;/code&gt; directories for the &lt;code&gt;x86_64&lt;/code&gt; platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INCLUDES: ..\MINGW-SDL2\SDL2-devel-2.0.20-mingw\SDL2-
2.0.20\x86_64-w64-mingw32\include ..\MINGW-SDL2\SDL2_image-devel-
2.0.5-mingw\SDL2_image-2.0.5\x86_64-w64-mingw32\include ..\MINGW-
SDL2\SDL2_ttf-devel-2.0.18-mingw\SDL2_ttf-2.0.18\x86_64-w64-
mingw32\include
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the result of the second line which prepends and appends &lt;code&gt;-I&lt;/code&gt; and &lt;code&gt;\SDL2&lt;/code&gt; respectively to each entry and converts all &lt;code&gt;\&lt;/code&gt; to &lt;code&gt;/&lt;/code&gt; in the above list to provide the correct linker arguments for the &lt;code&gt;gcc&lt;/code&gt; compiler call later on in the Makefile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INCLUDES: -I../MINGW-SDL2/SDL2-devel-2.0.20-mingw/SDL2-
2.0.20/x86_64-w64-mingw32/include/SDL2 -I../MINGW-SDL2/SDL2_image-
devel-2.0.5-mingw/SDL2_image-2.0.5/x86_64-w64-mingw32/include/SDL2 
-I../MINGW-SDL2/SDL2_ttf-devel-2.0.18-mingw/SDL2_ttf-
2.0.18/x86_64-w64-mingw32/include/SDL2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Minor note 1: &lt;em&gt;Setting up the compile flags for Linux is so easy with &lt;code&gt;sdl2-config --cflags&lt;/code&gt; ... but doing things in Windows is always more complicated and "fun" for those insane enough to try I suppose :P&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Minor note 2: &lt;em&gt;The use of the "walrus operator :=" above is kind of important when setting the &lt;code&gt;INCLUDES&lt;/code&gt; variable. Basically evaluates the right-hand and stores the results in the variable. Without it, you'd essentially store the &lt;code&gt;$(shell powershell ...)&lt;/code&gt; call in the variable and get a Make error due to the &lt;code&gt;INCLUDES&lt;/code&gt; variable being present in its own redefinition. You can find more on this in the &lt;a href="https://www.gnu.org/software/make/manual/make.html"&gt;Makefile manual online&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As for DLLs, I do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## DLL files and output location where they will be copied
ifeq ($(OS), Windows_NT)
DLLS_SRC  := $(shell powershell 'Get-ChildItem "*.dll" -Path "$(EXTERNAL_SDL2_DEP)" -Recurse | Where {$$_.DirectoryName -match "$(PLATFORM_VERSION)"} | Resolve-Path -Relative')
DLLS_O    := $(addprefix $(BIN_DIR)/, $(notdir $(DLLS_SRC)))
endif
...
...
## Copy all the DLLs for Windows build
$(DLLS_O):
ifeq ($(OS), Windows_NT)
    $(foreach dll,$(DLLS_SRC),$(shell powershell 'Copy-Item -Path "$(dll)" -Destination "$(BIN_DIR)"'))
endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Minor note: &lt;em&gt;So it's a bit hacky. I set the &lt;code&gt;$(DLLS_O)&lt;/code&gt; list to be all the DLL file names prepended with the game's bin directory path. I use this for the target. Since the Powershell &lt;code&gt;Copy-Item&lt;/code&gt; command requires a comma-separated list of files when you want to copy multiple files around and the &lt;code&gt;$(DLLS_SRC)&lt;/code&gt; list is space-separated, I opted to use the Makefile &lt;a href="https://www.gnu.org/software/make/manual/html_node/Foreach-Function.html"&gt;foreach(..)&lt;/a&gt; function to copy each DLL file separately.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Honestly, there's probably a more "elegant" way to do what I did here. But as you can see, I've used a similar Powershell command to automatically locate all the DLLs and store their relative paths in a list. Later the &lt;code&gt;$(DLLS_O)&lt;/code&gt; target runs a &lt;code&gt;foreach&lt;/code&gt; command that copies all these DLLs to my game project's bin directory.&lt;/p&gt;

&lt;p&gt;Pretty insane ehh? I could have simply copied all the header (.h) files to the appropriate directory along with the library (.a and .la) files and DLL files. But noooo... I had to be simultaneously lazy and insane. But at least I learned something cool doing all this :D&lt;/p&gt;

&lt;p&gt;Anyways, this about does it for this diary entry. For now I refuse to use tools like CMake to automatically generate the Makefile since I want to learn how Makefiles work and really get into the nitty-gritty with how things can be set up. &lt;/p&gt;

&lt;p&gt;There's still more interesting stuff I'm learning from manually tinkering with my project's Makefile.&lt;/p&gt;

&lt;p&gt;See you all next time!&lt;/p&gt;

</description>
      <category>makefile</category>
      <category>sdl2</category>
      <category>windows</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hello World</title>
      <dc:creator>Juan Burgos</dc:creator>
      <pubDate>Fri, 26 Nov 2021 23:44:29 +0000</pubDate>
      <link>https://forem.com/jlburgos/hello-world-178n</link>
      <guid>https://forem.com/jlburgos/hello-world-178n</guid>
      <description>&lt;p&gt;Testing... testing... hopefully this is working :-)&lt;/p&gt;

&lt;p&gt;Looking forward to posting things as I move forward!&lt;/p&gt;

</description>
      <category>firstpost</category>
    </item>
  </channel>
</rss>
