<?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>DEV Community: Tenry</title>
    <description>The latest articles on DEV Community by Tenry (@tenry).</description>
    <link>https://dev.to/tenry</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%2F534365%2F5a3771cd-ff33-4c7f-b160-58af58bce58a.png</url>
      <title>DEV Community: Tenry</title>
      <link>https://dev.to/tenry</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tenry"/>
    <language>en</language>
    <item>
      <title>C++ development with Docker + VSCode</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Sun, 02 Nov 2025 16:55:09 +0000</pubDate>
      <link>https://dev.to/tenry/c-development-with-docker-vscode-5fh9</link>
      <guid>https://dev.to/tenry/c-development-with-docker-vscode-5fh9</guid>
      <description>&lt;p&gt;I recently experimented with C++ development inside Docker containers on my Linux machine. Here's why I use Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolated environments&lt;/strong&gt; with self-contained C++ compilers and libraries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible builds&lt;/strong&gt; that can be easily replicated on fresh systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy cleanup&lt;/strong&gt; of project-related files when they're no longer needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker images
&lt;/h2&gt;

&lt;p&gt;Since I develop C++ projects for various target systems, I created multiple Docker images, each dedicated to a specific target:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cppdev&lt;/strong&gt;: Essential build tools and programs (gcc, cmake, git, etc.) for native Linux compilation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mingwdev&lt;/strong&gt;: Essential build tools for cross-compiling to Windows using mingw-w64&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;devkitpro&lt;/strong&gt;: Complete devkitPro installation for homebrew development on consoles like the Nintendo DS or Nintendo Switch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n64dev&lt;/strong&gt;: Development environment for the Nintendo 64 using &lt;a href="https://github.com/DragonMinded/libdragon" rel="noopener noreferrer"&gt;libdragon&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most images, I differentiate between two tags: "essential" (containing only the compiler and essential programs) and "latest" (which includes commonly used packages like SDL2 pre-installed).&lt;/p&gt;

&lt;p&gt;This is my &lt;code&gt;Dockerfile&lt;/code&gt; for &lt;code&gt;cppdev:essential&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker build -t cppdev:essential .&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  build-essential &lt;span class="se"&gt;\
&lt;/span&gt;  ca-certificates &lt;span class="se"&gt;\
&lt;/span&gt;  cmake &lt;span class="se"&gt;\
&lt;/span&gt;  curl &lt;span class="se"&gt;\
&lt;/span&gt;  git &lt;span class="se"&gt;\
&lt;/span&gt;  nano &lt;span class="se"&gt;\
&lt;/span&gt;  vim &lt;span class="se"&gt;\
&lt;/span&gt;  wget &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is my &lt;code&gt;Dockerfile&lt;/code&gt; for &lt;code&gt;cppdev:latest&lt;/code&gt;, based on the image above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker build -t cppdev:latest .&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; cppdev:essential&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  libfmt-dev &lt;span class="se"&gt;\
&lt;/span&gt;  libglm-dev &lt;span class="se"&gt;\
&lt;/span&gt;  libsdl2-dev &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I follow a similar approach for all other target systems. Some Dockerfiles are more complex when they require downloading, compiling, and installing dependencies from source. Here's my setup for MinGW-W64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker build -t mingwdev:essential .&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  build-essential &lt;span class="se"&gt;\
&lt;/span&gt;  ca-certificates &lt;span class="se"&gt;\
&lt;/span&gt;  cmake &lt;span class="se"&gt;\
&lt;/span&gt;  curl &lt;span class="se"&gt;\
&lt;/span&gt;  git &lt;span class="se"&gt;\
&lt;/span&gt;  mingw-w64 &lt;span class="se"&gt;\
&lt;/span&gt;  nano &lt;span class="se"&gt;\
&lt;/span&gt;  vim &lt;span class="se"&gt;\
&lt;/span&gt;  wget &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker build -t mingwdev:latest .&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; mingwdev:essential&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/src &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git clone https://github.com/libsdl-org/SDL.git &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;SDL &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout release-2.32.10 &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; /usr/build &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /usr/build &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmake &lt;span class="nt"&gt;-DCMAKE_INSTALL_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/x86_64-w64-mingw32 &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/src/SDL/build-scripts/cmake-toolchain-mingw64-x86_64.cmake /usr/src/SDL &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--parallel&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmake &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; / &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /usr/src/SDL /usr/build

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/local/share/cmake/toolchains

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; MinGW.cmake /usr/local/share/cmake/toolchains/MinGW.cmake&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/src &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git clone https://github.com/g-truc/glm.git &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;glm &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout 1.0.2 &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; /usr/build &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /usr/build &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmake &lt;span class="nt"&gt;-DCMAKE_INSTALL_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/x86_64-w64-mingw32 &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/share/cmake/toolchains/MinGW.cmake &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="nt"&gt;-DCMAKE_BUILD_TESTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;OFF &lt;span class="nt"&gt;-DBUILD_SHARED_LIBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;OFF /usr/src/glm &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--parallel&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmake &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; / &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /usr/src/glm /usr/build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is my &lt;code&gt;MinGW.cmake&lt;/code&gt; toolchain file I put next to the &lt;code&gt;Dockerfile&lt;/code&gt; for the &lt;code&gt;mingwdev:latest&lt;/code&gt; image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cmake"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_SYSTEM_NAME Windows&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_SYSTEM_PROCESSOR x86_64&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_SYSROOT &lt;span class="s2"&gt;"/usr/x86_64-w64-mingw32"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_FIND_ROOT_PATH &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_INSTALL_PREFIX &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CMAKE_SYSROOT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_C_COMPILER NAMES x86_64-w64-mingw32-gcc REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_CXX_COMPILER NAMES x86_64-w64-mingw32-g++ REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_RC_COMPILER NAMES x86_64-w64-mingw32-windres windres REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To configure, build, and install an existing CMake-based project via the CLI, I typically follow these steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;path/to/project
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,src&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;,dsts&lt;span class="o"&gt;=&lt;/span&gt;/usr/src &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/src mingwdev:latest

&lt;span class="c"&gt;# inside docker&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; /usr/build
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;
cmake &lt;span class="nt"&gt;-DCMAKE_TOOLCHAIN_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/share/cmake/toolchains/MinGW.cmake /usr/src
cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--parallel&lt;/span&gt;
cmake &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also want to mount a local folder to the build directory inside Docker, or copy the relevant build artifacts to your host system using another method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visual Studio Code + dev containers
&lt;/h2&gt;

&lt;p&gt;Visual Studio Code has an extension that enables &lt;a href="https://code.visualstudio.com/docs/devcontainers/containers" rel="noopener noreferrer"&gt;developing inside a container&lt;/a&gt;. In my projects, I typically configure multiple dev containers for different targets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# .devcontainer/mingwdev-container/Dockerfile&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; mingwdev:latest&lt;/span&gt;

&lt;span class="c"&gt;# RUN ... if you want to install certain programs or libraries that are only relevant for this specific project&lt;/span&gt;

&lt;span class="c"&gt;# The base image happens to provide a user "ubuntu" with UID 1000,&lt;/span&gt;
&lt;span class="c"&gt;# this happens to be the UID of my local user.&lt;/span&gt;
&lt;span class="c"&gt;# Do this, if you want to avoid all new files to be owned by root.&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; ubuntu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.devcontainer/mingwdev-container/devcontainer.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MinGW-W64"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dockerfile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dockerfile"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"bbenoist.Doxygen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"GitHub.copilot-chat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"GitHub.copilot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ms-vscode.cmake-tools"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ms-vscode.cpptools"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"slevesque.shader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"sumneko.lua"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"xaver.clang-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ZixuanWang.linkerscript"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that many VS Code extensions must be installed inside the container—this is what the &lt;code&gt;customizations&lt;/code&gt; section handles. Adjust it according to your needs.&lt;/p&gt;

&lt;p&gt;Once the dev containers are configured, you can reopen your project in a container (&lt;code&gt;F1&lt;/code&gt; or &lt;code&gt;Ctrl+Shift+P&lt;/code&gt; &amp;gt; &lt;strong&gt;Dev Containers: Reopen in Container&lt;/strong&gt;). The first time you reopen the project in a container, it may take a moment to prepare the image.&lt;/p&gt;

&lt;h2&gt;
  
  
  VSCode C/C++ configuration
&lt;/h2&gt;

&lt;p&gt;One final consideration, especially when targeting multiple platforms: VS Code needs to know about your various configurations (include paths, defines, etc.) for IntelliSense to work properly. To set this up, create a &lt;code&gt;.vscode/c_cpp_properties.json&lt;/code&gt; file and add all relevant configurations. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Windows (MinGW-W64)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"includePath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"defines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"compilerPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/x86_64-w64-mingw32-gcc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cStandard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"c11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cppStandard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"c++17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"intelliSenseMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"windows-gcc-x64"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With multiple configurations, you can switch the active configuration in the bottom-right corner of VS Code when you have a C/C++ file open.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>docker</category>
      <category>vscode</category>
    </item>
    <item>
      <title>My first experience with Arch Linux</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Sun, 08 Jun 2025 20:37:55 +0000</pubDate>
      <link>https://dev.to/tenry/my-first-experience-with-arch-linux-3jh3</link>
      <guid>https://dev.to/tenry/my-first-experience-with-arch-linux-3jh3</guid>
      <description>&lt;p&gt;Up until recently I have almost only been using Linux Mint as my main computer's operating system. However I was always interested in Arch Linux: full freedom out of the box, up-to-date software from the official repositories. Now it was finally time to upgrade my computer and I took the chance to install Arch Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test in VirtualBox
&lt;/h2&gt;

&lt;p&gt;Before I started installing it on my computer and getting stucked, I first gave a list of instructions a try in VirtualBox. I installed the base packages and a desktop environment (KDE Plasma) and it was surprisingly easy for me to get everything running. The next step was go apply this to my actual computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to install
&lt;/h2&gt;

&lt;p&gt;After my success attempt within VirtualBox, I created a bootable USB stick with the Arch Linux ISO and booted from it. I created a backup of all my valuable data &lt;em&gt;and&lt;/em&gt; replaced the hard drive in my computer, so there was nothing important that could accidentally be deleted.&lt;/p&gt;

&lt;p&gt;After selecting my USB stick from the boot menu to boot from, I entered the Arch console, where I could start typing commands.&lt;/p&gt;

&lt;p&gt;The first thing, I did, is checking internet connection. My computer is connected via a LAN cable - the same as simulated in VirtualBox before - so pinging any domain using the &lt;code&gt;ping&lt;/code&gt; command should work. It did not.&lt;/p&gt;

&lt;p&gt;I did some research and eventually figured out that "only" DNS resolving was not working. Doing &lt;code&gt;ping 1.1.1.1&lt;/code&gt; or any other specific IP address worked out of the box. I was suggested to check &lt;code&gt;/etc/resolv.conf&lt;/code&gt; for an entry for &lt;code&gt;nameserver&lt;/code&gt;. There was actually one, pointing to something in the &lt;code&gt;127.x.x.x&lt;/code&gt; space. I replaced it via &lt;code&gt;nano&lt;/code&gt; with two other &lt;code&gt;nameserver&lt;/code&gt; lines pointing to &lt;code&gt;1.1.1.1&lt;/code&gt; and &lt;code&gt;8.8.8.8&lt;/code&gt;, tried &lt;code&gt;ping &amp;lt;some-domain&amp;gt;&lt;/code&gt; again and now it was working. Phew! Let's make sure NTP for time sync is enabled via &lt;code&gt;timedatectl set-ntp true&lt;/code&gt; and continue with the actual installation process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disk partitioning
&lt;/h2&gt;

&lt;p&gt;In my case, I have two disks installed in my computer. One HDD, one much smaller but faster SSD. They are identified as &lt;code&gt;/dev/sda&lt;/code&gt; and &lt;code&gt;/dev/sdb&lt;/code&gt; respectively. I used &lt;code&gt;cgdisk /dev/sda&lt;/code&gt; and &lt;code&gt;cgdisk /dev/sdb&lt;/code&gt; to partition these. "Partition" basically means to subdivide each drive into smaller so-called partitions so each of them can later be formatted using a specific filesystem and use. For example, one dedicated partition is required for the boot data, I want a dedicated one on the fast SSD for the actual system and two other ones on the slower but larger HDD for my home and personal files.&lt;/p&gt;

&lt;p&gt;I formatted my disks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 GB (SSD) using FAT32 (type &lt;code&gt;EF00&lt;/code&gt;) for &lt;code&gt;/boot&lt;/code&gt; (&lt;code&gt;/dev/sdb1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;16 GB (SSD) for &lt;a href="https://en.wikipedia.org/wiki/Memory_paging#Unix_and_Unix-like_systems" rel="noopener noreferrer"&gt;Swap&lt;/a&gt; (type &lt;code&gt;8200&lt;/code&gt;) (&lt;code&gt;/dev/sdb2&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;remaining SSD space for system &lt;code&gt;/&lt;/code&gt; using ext4 (type &lt;code&gt;8300&lt;/code&gt;) (&lt;code&gt;/dev/sdb3&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Some amount of HDD using ext4 (type &lt;code&gt;8300&lt;/code&gt;) for &lt;code&gt;/home&lt;/code&gt; (&lt;code&gt;/dev/sda1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Remaining amount of HDD using ext4 (type &lt;code&gt;8300&lt;/code&gt;) for &lt;code&gt;/files&lt;/code&gt; (here I put almost &lt;a href="https://dev.to/tenry/my-folder-hierarchy-3mlg"&gt;all of my personal, user-independent files&lt;/a&gt;) (&lt;code&gt;/dev/sda2&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After confirming and writing all the partitions, it's time to actual format and mount the partitions.&lt;/p&gt;

&lt;p&gt;I used &lt;code&gt;mkfs.fat -F32 /dev/sda1&lt;/code&gt; for the boot / EFI partition (it is required to be FAT32). &lt;code&gt;mkswap /dev/sdb2&lt;/code&gt; for the swap. And &lt;code&gt;mkfs.ext4 /dev/sda1&lt;/code&gt; etc. to format the remaining partitions for using the ext4 filesystem, which is the most common filesystem for Linux system (alongside with the newer btrfs).&lt;/p&gt;

&lt;p&gt;After formatting all the disks, it's time to mount them so I can actually access their contents and install data on them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mount /dev/sdb3 /mnt
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/&lt;span class="o"&gt;{&lt;/span&gt;boot,home&lt;span class="o"&gt;}&lt;/span&gt;
mount /dev/sdb1 /mnt/boot
mount /dev/sda1 /mnt/home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For your understanding: everything, that is found in &lt;code&gt;/mnt&lt;/code&gt; during the installation progress, will later be the actual root &lt;code&gt;/&lt;/code&gt; on the final system (and temporarily during installation when we use &lt;code&gt;arch-chroot&lt;/code&gt; in a few minutes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and configuration
&lt;/h2&gt;

&lt;p&gt;Right now, &lt;code&gt;/mnt&lt;/code&gt; is basically empty. There are no programs, no configuration, no anything. The following command installs the Arch Linux base system there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-K&lt;/span&gt; /mnt base base-devel linux linux-firmware linux-headers nano networkmanager amd-ucode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note since I have an AMD processor, it's reommended to have &lt;code&gt;amd-ucode&lt;/code&gt; for bug and security fixes for my AMD processor. For Intel processors, there would be &lt;code&gt;intel-ucode&lt;/code&gt;. On my previous computer (Linux Mint), both of them were installed, but I don't believe you need both of them if you only have either processor.&lt;/p&gt;

&lt;p&gt;Next I did some basic straight-forward configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;genfstab &lt;span class="nt"&gt;-U&lt;/span&gt; /mnt &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /mnt/etc/fstab
arch-chroot /mnt

&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-sf&lt;/span&gt; /usr/share/zoneinfo/Europe/Berlin /etc/localtime
hwclock &lt;span class="nt"&gt;--systohc&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"en_US.UTF-8 UTF-8"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/locale.gen
locale-gen
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"LANG=en_US.UTF-8"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/locale.conf

&lt;span class="c"&gt;# You can choose any name for your computer you like.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"arch-linux"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/hostname

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/hosts &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
127.0.0.1 arch-linux
::1       arch-linux
127.0.1.1 arch-linux.localdomain arch-linux
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I do have some specific setup using various groups and additional "users" (when accessing files via the network), but I will mostly skip these as for this article. Essentially, I used the &lt;code&gt;groupadd&lt;/code&gt; to create certain groups with specific IDs (since I hade the same IDs on my backup that I'll restore later). The most essential commands to execute for user setup are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 1000 &lt;span class="nt"&gt;-G&lt;/span&gt; wheel &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash tenry
passwd tenry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And typed my personal password I wanted to use for my account. The membership of the &lt;code&gt;wheel&lt;/code&gt; group is used to allow my command to &lt;code&gt;sudo&lt;/code&gt; any commands. To make this possible, I had to run &lt;code&gt;EDITOR=nano visudo&lt;/code&gt; next and uncomment the line near the bottom mentioning &lt;code&gt;%wheel ALL=(ALL:ALL) ALL&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootloader
&lt;/h2&gt;

&lt;p&gt;Next I installed a bootloader, so when the computer starts, that it would find my Arch Linux installation and boots it. I used systemd-boot, for no specific reason. I also know GRUB and there are other options available too.&lt;/p&gt;

&lt;p&gt;For installing systemd-boot, I ran the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bootctl &lt;span class="nb"&gt;install

cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /boot/loader/loader.conf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
default arch
timeout 3
editor 0
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /boot/loader/entries/arch.conf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
title   Arch Linux
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options root=PARTUUID=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;blkid &lt;span class="nt"&gt;-s&lt;/span&gt; PARTUUID &lt;span class="nt"&gt;-o&lt;/span&gt; value /dev/sdb3&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="sh"&gt; rw
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay special attention to the part mentioning &lt;code&gt;/dev/sdb3&lt;/code&gt;. This is where my root partition is located. If it was on a different partition, this has to be adjusted accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extras
&lt;/h2&gt;

&lt;p&gt;Now the base system should be ready. But before finishing up and booting into my system, there were certrain extra things I wanted to install (it could also be done afterwards). The system may be fully ready for some people to use from here, if you do not intend to have any GUI, for example, if you are only using this computer as a server. In my case however I wanted a full GUI right when booting into the computer.&lt;/p&gt;

&lt;p&gt;First, the network manager should be enabled using &lt;code&gt;systemctl enable NetworkManager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, since I have an Nvidia graphics card in my computer (GeForce GTX 1060, to be specific), I wanted the (proprietary) nvidia drivers to be installed. I did so using &lt;code&gt;pacman -S nvidia nvidia-utils nvidia-settings&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then I installed certain packages. For the desktop environment, there are many options, available, such as Cinnamon (which I'm used to from Linux Mint), KDE Plasma and more. After my first glance at KDE Plasma in VirtualBox, I wanted to give this a chance and installed it using &lt;code&gt;pacman -S plasma&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When starting the computer, you would usually be in a terminal, where you log into an account and you would then have to manually start the desktop environment (Plasma in my case). I prefer however to have a nice looking login screen. For that, I installed lightdm using &lt;code&gt;pacman -S lightdm lightdm-gtk-greeter plasma&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To tell the computer to start Plasma on user login, I had to put a line into my user account's &lt;code&gt;.xinitrc&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"exec startplasma-wayland"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /home/tenry/.xinitrc
&lt;span class="nb"&gt;chown &lt;/span&gt;tenry:tenry /home/tenry/.xinitrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plasma supports the legacy X11 window system (the same I had on Linux Mint) and the modern, to some degree experimental Wayland. By "experimental", I mean that many programs &lt;em&gt;might&lt;/em&gt; still have issues with Wayland. If anything, that is important for me, would not work well with Wayland, I can simply use &lt;code&gt;startplasma-x11&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;EDIT: Actually, the &lt;code&gt;.xinitrc&lt;/code&gt; file does not affect which desktop to start upon login (via a display manager like lightdm). This is only when you use the &lt;code&gt;startx&lt;/code&gt; command from the command line. In the case of lightdm, there is a little config icon in the top right where I can choose the desktop environment before logging in.&lt;/p&gt;

&lt;p&gt;I also installed additional packages using &lt;code&gt;pacman -S &amp;lt;package1&amp;gt; &amp;lt;package2&amp;gt; ...&lt;/code&gt; for my personal needs, some of these are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;terminator&lt;/code&gt; for the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;firefox&lt;/code&gt; for the browser&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;thunderbird&lt;/code&gt; for e-mails&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dolphin&lt;/code&gt; for file browsing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;audacious&lt;/code&gt; as the audio player&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few essential programs are still missing, such as a simple image viewer. I will install those later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final cleanup and booting issues
&lt;/h2&gt;

&lt;p&gt;Now everything should be ready, so I used the following commands to exit the installation process and reboot the computer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="c"&gt;# exiting from arch-chroot&lt;/span&gt;
umount &lt;span class="nt"&gt;-R&lt;/span&gt; /mnt
reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the BIOS boot settings, I ensured the order so my SSD, which had the EFI installed, was on the first place, and booted into Arch Linux from that.&lt;/p&gt;

&lt;p&gt;I saw some text on the screen, starting to initialize some things, but it hang up very quickly. Luckily, the text on the screen gave me the hint &lt;em&gt;where&lt;/em&gt; something is wrong. Essentially it told me something about not being able to find something with &lt;code&gt;PARTUUID=$(blkid -s PARTUUID ...&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I restarted my computer and booted from the USB stick again, so I can investigate the installation configuration. Something appeared to be off in &lt;code&gt;/loder/entries/arch.conf&lt;/code&gt; on my boot partition. I did have a typo there which I fixed, but I was still not able to boot. It appeared that for some reason my installation would not be able to run &lt;code&gt;$(blkid -s ...)&lt;/code&gt;, even though the same was working on my VirtualBox test before. Even after typing the &lt;code&gt;blkid&lt;/code&gt; command manually, it gave me an actual uuid. I decided to replace replace the inline command with the actual, hardcoded UUID. This is also where I learned there is a &lt;code&gt;UUID&lt;/code&gt; and a &lt;code&gt;PARTUUID&lt;/code&gt;, and depending on which ID from the &lt;code&gt;blkid&lt;/code&gt; command I'm using, it must be either &lt;code&gt;UUID=...&lt;/code&gt; or &lt;code&gt;PARTUUID=...&lt;/code&gt; in the &lt;code&gt;arch.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Finally I was able to boot successfully into Arch! But... there was no login screen. Not a graphical one. There was only the terminal asking me for credentials. Looks like &lt;code&gt;lightdm&lt;/code&gt; was not starting. Quickly I realized I forgot to execute one more command which I was supposed to execute right after installing &lt;code&gt;lightdm&lt;/code&gt;: &lt;code&gt;systemctl enable lightdm&lt;/code&gt;. So, in the terminal, I logged into my account, ran this command manually and restarted.&lt;/p&gt;

&lt;p&gt;EDIT: It appears that the Plasma installation comes with the "SDDM" login screen, but it was not enabled automatically in my case. If you want to switch from lightdm to SDDM, simply do &lt;code&gt;systemctl disable lightdm &amp;amp;&amp;amp; systemctl enable sddm&lt;/code&gt; as sudo.&lt;/p&gt;

&lt;p&gt;Now I actually had a graphical login screen! Not very beautiful, as the background is fully black, for example, but I'm happy so far! Now, after typing in my credentials to log in, it would actually also start the Plasma desktop interface and basically everything I needed was working! I had internet, I had music, and the nvidia drivers appeared to be working too.&lt;/p&gt;

&lt;h2&gt;
  
  
  After installation
&lt;/h2&gt;

&lt;p&gt;Of course, minor things were still missing or not configured according to my needs, which I install or configure one after another. For example, LibreOffice was missing, I installed it using &lt;code&gt;pacman -S libreoffice-fresh&lt;/code&gt;. My keyboard layout was set to default US, but I prefer "US International" (which allows me to type many more special characters), this I configured in the settings provided to my by Plasma. Japanese characters in browser and mail were missing, so I installed additional &lt;a href="https://wiki.archlinux.org/title/Localization/Japanese#Fonts" rel="noopener noreferrer"&gt;fonts&lt;/a&gt; and Japanese characters could be displayed on my screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;As of writing this article, this is basically my first day of actually using Arch Linux with Plasma, after I have been using Linux Mint with Cinnamon for many, many years. As of now I'm very happy with everything and I'm looking forward gathering more experience with Arch Linux - hopefully mostly positive ones.&lt;/p&gt;

&lt;p&gt;Do you have experience with Arch Linux? What do you think about Arch Linux, compared to easier-to-use systems like Ubuntu or Linux Mint? Let me know in the comments!&lt;/p&gt;

</description>
      <category>archlinux</category>
    </item>
    <item>
      <title>My personal folder hierarchy</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Thu, 12 Sep 2024 18:34:22 +0000</pubDate>
      <link>https://dev.to/tenry/my-folder-hierarchy-3mlg</link>
      <guid>https://dev.to/tenry/my-folder-hierarchy-3mlg</guid>
      <description>&lt;p&gt;On computers, you deal with files and folders. You download something on the internet, it appears in your personal &lt;strong&gt;Downloads&lt;/strong&gt; folder. You copy your favorite photos from your phone to your computer, you put them in your personal &lt;strong&gt;Pictures&lt;/strong&gt; folder. Your favorite music is stored in your personal &lt;strong&gt;Music&lt;/strong&gt; folder. You start working on a new project, you put it in... where do you actually put it? Do you put it into &lt;strong&gt;Documents&lt;/strong&gt;? But it's not a bare document you are creating. Maybe creating a &lt;strong&gt;Projects&lt;/strong&gt; folder? What if you have multiple accounts (e.g. for private and work) on the same computer and want to share files, such as your music, across these? Do you put these into the one account's share folder, the other one?&lt;/p&gt;

&lt;p&gt;These are more are questions I often stumbled upon when I started doing more and more on computer, making games, websites, music and more. And across multiple operating systems too (Windows and Linux). In this article I want to give you some insights into how I am managing the files on my computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  My folder hierarchy
&lt;/h2&gt;

&lt;p&gt;It all started when I had a Linux computer I used for both work and private stuff. At home, I downloaded music I also liked listening to in the office. At home, sometimes I coded some stuff I would like to try in the office. So, I had a bunch of files of my computer I wouldn't strictly consider belonging to either my work or my private account. A new root folder had to be created.&lt;/p&gt;

&lt;h3&gt;
  
  
  The birth of /files
&lt;/h3&gt;

&lt;p&gt;So, I went &lt;em&gt;sudo&lt;/em&gt; and created a root &lt;strong&gt;/files&lt;/strong&gt; directory, making sure my casual accounts have regular reading and writing access to it. I created a few base directories for different purposes. For example, there was &lt;strong&gt;/files/dev&lt;/strong&gt; for all my development stuff, I had another directory for all my "personal" stuff and another one from the stuff from the internet, each once again divided into music, videos etc.&lt;/p&gt;

&lt;p&gt;Over time, I noticed my structure wasn't ideal yet. All my programming stuff went into &lt;strong&gt;/files/dev&lt;/strong&gt;, but when I made some music for my game project, I often put it into my personal music folder, since the music project is no coding. I also like casually listening to the music I created myself, but it was separate from all the music from the internet. So recently I revised the structure underneath &lt;strong&gt;/files&lt;/strong&gt; and this is what I came up with:&lt;/p&gt;

&lt;h3&gt;
  
  
  My folder hierarchy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;/files/inbox&lt;/strong&gt;: Here I put all kind of random stuff I didn't sort into anywhere else yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/files/library&lt;/strong&gt;: This is where I put all kind of resources, music, videos etc. that is not "personal". The resources can be created by myself, such as music I published or Blender templates I created for later use. These files should be "ready to use", so I put my finished MP3 here, not the Cubase project file. Most of the files here however are simply files downloaded from the internet.&lt;/p&gt;

&lt;p&gt;I divide this folder into &lt;strong&gt;fonts&lt;/strong&gt;, &lt;strong&gt;games&lt;/strong&gt;, &lt;strong&gt;icons&lt;/strong&gt;, &lt;strong&gt;music&lt;/strong&gt;, &lt;strong&gt;pictures&lt;/strong&gt;, &lt;strong&gt;soundfonts&lt;/strong&gt;, &lt;strong&gt;sounds&lt;/strong&gt;, &lt;strong&gt;textures&lt;/strong&gt;, &lt;strong&gt;videos&lt;/strong&gt;, &lt;strong&gt;vst&lt;/strong&gt; and &lt;strong&gt;wallpapers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/files/personal&lt;/strong&gt;: This one is very similar to the library folder, having nearly the same structure. The main difference is that this folder contains personal and sensitive files such as private photos, contracts or videos of that party recently where I have not been at.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/files/projects&lt;/strong&gt;: Finally, there is my projects folder. In the past, when it was still called "dev", I only created game and app projects in here. I repurposed it to also contain music projects, 3D projects and more, since these projects may also require multiple files per project and I work on them over time.&lt;/p&gt;

&lt;p&gt;What do you think about this hierarchy? How do you organize your files? Let me know in the comments :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: Other devices
&lt;/h3&gt;

&lt;p&gt;Most of my work is done on my Linux computer, having &lt;strong&gt;/files&lt;/strong&gt; in the root. In some cases however I have to work on a Windows computer, for example when using my favorite DAW, which is only available on Windows. However, I still wanted to have all my project files on a central location, which (currently) is my Linux computer. So I started sharing my &lt;strong&gt;/files&lt;/strong&gt; directory on the local network using SMB. That way, I can easily access my Linux files from my Windows computer. I mounted it to a dedicated drive letter &lt;strong&gt;F:&lt;/strong&gt;. So music projects, I do on my Windows computer, go to &lt;strong&gt;F:\projects\music&lt;/strong&gt; and I'll find it on my Linux computer at &lt;strong&gt;/files/projects/music&lt;/strong&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Comparison of audio formats for games</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Sun, 31 Oct 2021 19:05:23 +0000</pubDate>
      <link>https://dev.to/tenry/comparison-of-audio-formats-for-games-jak</link>
      <guid>https://dev.to/tenry/comparison-of-audio-formats-for-games-jak</guid>
      <description>&lt;p&gt;When you want to make games, like I do, you may stumble upon the question which audio format to use. There is MP3, there is MIDI and much more!&lt;/p&gt;

&lt;p&gt;This article ist mostly written for developers who create their own engine, such as in C or C++. Existing game engines, such as Unity, Unreal or GameMaker, may be more restricted in which formats you can use and how you can play back the audio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audio stream (MP3, WAV etc.)
&lt;/h2&gt;

&lt;p&gt;This category of audio is probably the most well known one. Essentially, these files simply contains a single stream of raw audio data. The audio data may be given for a single (mono) channel, for two (stereo) channels or more. The bit depth may be 8-bit, 16-bit or more. The samplerate may be 44100 Hz, 48000 Hz or something else.&lt;/p&gt;

&lt;p&gt;Since raw audio can be quite big in file size, most audio stream formats use some sort of compression, usually lossy by removing frequencies that are (possibly) not heard by the human ear and more compression magic.&lt;/p&gt;

&lt;p&gt;The most well known audio formats I know about are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WAV (.wav)&lt;/li&gt;
&lt;li&gt;MP3 (.mp3)&lt;/li&gt;
&lt;li&gt;Ogg Vorbis (.ogg)&lt;/li&gt;
&lt;li&gt;Ogg Opus (.opus)&lt;/li&gt;
&lt;li&gt;FLAC (.flac)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  WAV
&lt;/h3&gt;

&lt;p&gt;The WAV format is probably the simplest audio format of all. The format is &lt;a href="https://en.wikipedia.org/wiki/WAV#Specification" rel="noopener noreferrer"&gt;quite simple&lt;/a&gt; and if the audio is not compressed in any way (that's the usual case), you can write a WAV encoder and decoder easily yourself.&lt;/p&gt;

&lt;h4&gt;
  
  
  C/C++ integration
&lt;/h4&gt;

&lt;p&gt;If you want to use a library for WAV encoding or decoding, I can suggest &lt;a href="https://github.com/erikd/libsndfile/" rel="noopener noreferrer"&gt;libsndfile&lt;/a&gt;. It also supports many other audio formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  MP3
&lt;/h3&gt;

&lt;p&gt;MP3 is probably the most known audio type in the world. But it also has the poorest quality of those formats I know. The only benefits of MP3 I can think of are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smaller file size than WAV and maybe FLAC&lt;/li&gt;
&lt;li&gt;everybody knows MP3, anybody can play MP3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if you are working on your own game engine, you can decide yourself which audio format to choose. So I would strongly suggest to use Vorbis or Opus instead.&lt;/p&gt;

&lt;h4&gt;
  
  
  C/C++ integration
&lt;/h4&gt;

&lt;p&gt;If you want to decode MP3 files, there are to libraries I can recommend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/erikd/libsndfile/" rel="noopener noreferrer"&gt;libsndfile&lt;/a&gt; (also supports many other formats)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lame.sourceforge.io/using.php" rel="noopener noreferrer"&gt;LAME&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ogg Vorbis and Opus
&lt;/h3&gt;

&lt;p&gt;For me those two formats are similar, since they are both usually used in an "ogg" container and are both developed by ther Xiph.Org Foundation. Opus appeared after Vorbis and is meant to replace Vorbis.&lt;/p&gt;

&lt;p&gt;Both Vorbis and Opus have better audio quality and smaller file size than MP3.&lt;/p&gt;

&lt;h4&gt;
  
  
  C/C++ integration
&lt;/h4&gt;

&lt;p&gt;For Vorbis and Opus, there are easy to use &lt;a href="https://xiph.org/downloads/" rel="noopener noreferrer"&gt;official libraries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you intend to integrate also other audio formats, such as FLAC, MP3 or WAV, I recommend the use of &lt;a href="https://github.com/erikd/libsndfile/" rel="noopener noreferrer"&gt;libsndfile&lt;/a&gt;, which supports all of these formats with a uniform interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  FLAC
&lt;/h3&gt;

&lt;p&gt;FLAC stands for Free Lossless Audio Codec. Unlike most other formats, and like WAV, this format provides lossless audio. It uses a good compression algorithm to be smaller than usual WAV files, but it will be bigger than with Vorbis and Opus for example.&lt;/p&gt;

&lt;h4&gt;
  
  
  C/C++ integration
&lt;/h4&gt;

&lt;p&gt;There is the &lt;a href="https://xiph.org/flac/developers.html" rel="noopener noreferrer"&gt;official library&lt;/a&gt; by xiph.org.&lt;/p&gt;

&lt;p&gt;If you intend to integrate also other audio formats, such as Opus or WAV, I recommend the use of &lt;a href="https://github.com/erikd/libsndfile/" rel="noopener noreferrer"&gt;libsndfile&lt;/a&gt;, which supports all of these formats with a uniform interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  MIDI
&lt;/h2&gt;

&lt;p&gt;This is probably the second well known audio format. Unlike sampled audio streams, like MP3 or WAV, this file format only contains music instructions. You can basically imagine its contents like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;play note C5 at 3 seconds on channel 1 using instrument 7&lt;/li&gt;
&lt;li&gt;stop note on channel 1 at 4 seconds&lt;/li&gt;
&lt;li&gt;and so on...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This this format does not include any audio samples, it is also the smallest of all file formats. However, in order to play a MIDI file, you will also need a so called &lt;a href="https://en.wikipedia.org/wiki/SoundFont" rel="noopener noreferrer"&gt;SoundFont&lt;/a&gt;, which actually includes the instrument audio data that can be played.&lt;/p&gt;

&lt;p&gt;If you have a MIDI file on your machine and play it with an audio player, it may sound different using different audio players or machines, since each player and each system may have a different default sound font they use for audio playback. If you want your MIDI file to sound the same for any player, you should provide your own sound font with your game. Luckily, you only need a single sound font (assuming it contains all instruments you need) and can have hundreds of little MIDI files in your game you can play.&lt;/p&gt;

&lt;h3&gt;
  
  
  C/C++ integration
&lt;/h3&gt;

&lt;p&gt;For playing MIDI files, I suggest &lt;a href="https://www.fluidsynth.org/" rel="noopener noreferrer"&gt;FluidSynth&lt;/a&gt;. You can load a sound font into it and then either play back an existing MIDI file or programmatically send MIDI commands to the library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module / Tracker music
&lt;/h2&gt;

&lt;p&gt;These file formats are basically a combination of a MIDI file and a sound font (although the technical details are completely different).&lt;/p&gt;

&lt;p&gt;A module file contains a list of audio commands to play and all the instrument (audio) data so a standalone module file can be played back. This makes a module file smaller than audio streams, but larger than MIDI files (if you don't count the sound font).&lt;/p&gt;

&lt;p&gt;The four best known tracker formats are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MOD&lt;/li&gt;
&lt;li&gt;XM ("extended module" by Triton's FastTracker 2)&lt;/li&gt;
&lt;li&gt;S3M (ScreamTracker 3 Module)&lt;/li&gt;
&lt;li&gt;IT (Impulse Tracker)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  C/C++ integration
&lt;/h3&gt;

&lt;p&gt;If you want to play tracker music, I can recommend &lt;a href="https://lib.openmpt.org/libopenmpt/" rel="noopener noreferrer"&gt;libopenmpt&lt;/a&gt;, or, if you need more control about the playback and event syncing, &lt;a href="https://www.un4seen.com/bassmod.html" rel="noopener noreferrer"&gt;BASSMOD&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple layers
&lt;/h2&gt;

&lt;p&gt;If you want to use music in your game, you might want to work with several audio layers and adjusting a layer's volume depending on the area you are in the game. Let's say, you have the same music (tempo, length) for your overworld and underwater, but using different instruments.&lt;/p&gt;

&lt;p&gt;If you work with audio streams such as Vorbis or Opus, you will need to have one file per layer and make sure that all layers are started playing exactly synchronously, but all layers except for one being muted. During the gameplay, you can adjust the layers' volumes dynamically.&lt;/p&gt;

&lt;p&gt;MIDI and tracker files both work with multiple channels for different instruments. Depending on the options your library has, you can work with a single audio file containing all layers and adjust a channels volume dynamically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loops
&lt;/h2&gt;

&lt;p&gt;Audio streams normally do not support loop points. Depending on the music, you may simply loop the whole music and it sounds well. But if you have a music with an intro that shall only be played once, you will need a dedicated solution. The best way to go is to write down the music's loop points somewhere (such as a meta file) and after decoding the last audio sample, instead of jumping back to sample 0 of the file, you jump back to the specified loop point.&lt;/p&gt;

&lt;p&gt;MIDI normally also do not have loop points. However, it's possible to add for example "cue" points to a MIDI file. You can remember the cue point's location and jump back to that when the end of music is reached.&lt;/p&gt;

&lt;p&gt;Tracker music basically all support loop points. They either include a "restart position" property in the file header or a "jump to" command within the music itself. Tracker libraries will make use of these loop points and you don't need to do anything here.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>c</category>
      <category>cpp</category>
    </item>
    <item>
      <title>When your C++ code complains about undefined references</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Wed, 09 Dec 2020 18:56:41 +0000</pubDate>
      <link>https://dev.to/tenry/when-your-c-code-complains-about-undefined-references-3gf0</link>
      <guid>https://dev.to/tenry/when-your-c-code-complains-about-undefined-references-3gf0</guid>
      <description>&lt;p&gt;Usually, when you compile and link your code and your compiler complains about undefined references, you check which references are missing and usually quickly find out which library you forgot to link.&lt;/p&gt;

&lt;p&gt;Today, however, I encountered a strange issue where the compiler complained even though the (static) library, which provides the symbols in question, was clearly added to the command line that links the final binary. So what was going on?&lt;/p&gt;

&lt;p&gt;In my specific case, I built the &lt;a href="https://www.lua.org/" rel="noopener noreferrer"&gt;Lua&lt;/a&gt; library, and got some files in the end, including some header files like &lt;code&gt;lua.h&lt;/code&gt; or &lt;code&gt;lauxlib.h&lt;/code&gt; and of course the &lt;code&gt;liblua.a&lt;/code&gt;. I wrote some basic code to verify that Lua is actually working. Following some quickstart tutorial on the internet, my C++ code somewhat looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;lua.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;lauxlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;lualib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;lua_State&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;luaL_newstate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;luaopen_base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;luaL_loadstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"(some lua code)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// and so on...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I put everything in a &lt;a href="https://cmake.org/" rel="noopener noreferrer"&gt;CMake&lt;/a&gt; file, compiled and bam, undefined references. I enabled verbose output to verify it's actually linking the &lt;code&gt;liblua.a&lt;/code&gt; file. I verified it's the right location and the file actually exist.&lt;/p&gt;

&lt;p&gt;Didn't I compile the Lua library correctly? Were the symbols in question missing? Using &lt;code&gt;nm&lt;/code&gt; showed me that the symbols in questions are there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nm liblua.a | grep luaL_loadstring
0000000000002d60 T luaL_loadstring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, why does it complain? It took like like half an hour to figure out &lt;em&gt;where&lt;/em&gt; the issue is.&lt;/p&gt;

&lt;h1&gt;
  
  
  The solution
&lt;/h1&gt;

&lt;p&gt;The issue is C++. C++ uses &lt;a href="https://en.wikipedia.org/wiki/Name_mangling" rel="noopener noreferrer"&gt;name mangling&lt;/a&gt; which differs from the generated names in C. Lua is a C library and I compiled it as C. Since I include the C header file &lt;code&gt;lua.h&lt;/code&gt; in a C++ file, it's treated as C++ code, hence the compiler is looking for C++ names.&lt;/p&gt;

&lt;p&gt;Luckily, Lua also provides a C++ header file, &lt;code&gt;lua.hpp&lt;/code&gt;. I replaced my &lt;code&gt;#include &amp;lt;lua.h&amp;gt;&lt;/code&gt; by &lt;code&gt;#include &amp;lt;lua.hpp&amp;gt;&lt;/code&gt; and et voilà, it works!&lt;/p&gt;

&lt;p&gt;What does &lt;code&gt;lua.hpp&lt;/code&gt; actually do? Not much:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"lua.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"lualib.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"lauxlib.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have some experience with coding in C++, you might already have used other C libs, also simply &lt;code&gt;#include &amp;lt;somelib.h&amp;gt;&lt;/code&gt;, without having any issues. So, what do others do? Checking the C header file of another lib, the outline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;
&lt;span class="c1"&gt;// all the declarations go here&lt;/span&gt;

&lt;span class="cp"&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;__cplusplus&lt;/code&gt; is only defined if this file is processed as a C++ file. For some reason, the &lt;code&gt;lua.h&lt;/code&gt; file does not do that, so that's why they provided a dedicated C++ header file.&lt;/p&gt;

</description>
      <category>cpp</category>
    </item>
    <item>
      <title>How I work with Linux and Windows together</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Tue, 08 Dec 2020 11:56:30 +0000</pubDate>
      <link>https://dev.to/tenry/how-i-work-with-linux-and-windows-together-4171</link>
      <guid>https://dev.to/tenry/how-i-work-with-linux-and-windows-together-4171</guid>
      <description>&lt;p&gt;I am a hobby programmer who loves to make games, desktop applications and websites. For some task, I use Linux, while for others I use Windows. But how do I manage to work with two different systems and file management? I'll give you an insight into my computer setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  My main workstation
&lt;/h2&gt;

&lt;p&gt;Personally I love Linux. It's very easy to code for it: &lt;code&gt;apt-get install g++&lt;/code&gt; and you're ready to compile your C++ program. &lt;code&gt;apt-get install terminator&lt;/code&gt; and I'm ready to use my favorite terminal.&lt;/p&gt;

&lt;p&gt;But I don't only use this computer for programming. Nearly everything else I do on a computer, such as watching videos or chatting with friends, I do here. I can do almost everything I need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Linux only is not sufficient
&lt;/h2&gt;

&lt;p&gt;Unfortunately, there are some things I can't do on my Linux computer or what simply works better on Windows. Some computer games for example. Or some programs for creating games or music such as Unity or Cubase.&lt;/p&gt;

&lt;p&gt;For that reason, I bought a second computer only for running Windows. I'm aware of dual-booting. I could simply shut down Linux, switch to Windows and vice versa. But it's too much time consuming, especially, if I only want to quickly test something out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two computers, one keyboard
&lt;/h2&gt;

&lt;p&gt;If you think about working with two computers, you might probably imagine also having two keyboards and two mice on your desk, or at least switching the cables every time you want to switch the computer. I don't have this!&lt;/p&gt;

&lt;p&gt;On my desk, there's only one keyboard, only one mouse, and I can switch between the two computers instantly. There's a program on the internet that allows me to do so: &lt;a href="https://symless.com/synergy" rel="noopener noreferrer"&gt;Synergy&lt;/a&gt;. I install that programm on my Linux and on my Windows computer, configure it and tell the Linux instance, that this is my host. This is where my keyboard and mouse is physically connected to.&lt;/p&gt;

&lt;p&gt;Now, I simply move with my mouse to the right out of the Linux monitor and it appears on my Windows monitor. All keyboard and mouse input is now redirected to my Windows comptuer. I move my mouse back to the left where my Linux monitor is and all keyboard and mouse input goes back to my host system. It's incredible magic and working really great!&lt;/p&gt;

&lt;p&gt;By the way, it also allows me to copy and paste text :)&lt;/p&gt;

&lt;h2&gt;
  
  
  File sharing
&lt;/h2&gt;

&lt;p&gt;Now that I can seamlessly create my 3D models on Linux and create a Unity game on Windows, or code my game in C++ on Linux and make the music for it in Cubase on Windows, how do I get the files from one computer to the other?&lt;/p&gt;

&lt;h3&gt;
  
  
  NAS
&lt;/h3&gt;

&lt;p&gt;One thing I tried is a &lt;a href="https://en.wikipedia.org/wiki/Network-attached_storage" rel="noopener noreferrer"&gt;network-attached storage&lt;/a&gt;, or NAS for short. It works really fine for moving individual files and folders between my computers and backing up my files on the NAS.&lt;/p&gt;

&lt;p&gt;However, when it's about to have whole projects living on the NAS instead on one of the computers, I feel the bottleneck - at least for my NAS. I created a new Unity project on Windows and I selected a folder on the NAS. I immediately noticed how much slower Unity was working if the whole project is living on the (local) network. I couldn't work really well with that, so I need a different solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  rsync
&lt;/h3&gt;

&lt;p&gt;The next solution, I came up with quite recently, is working with &lt;a href="https://en.wikipedia.org/wiki/Rsync" rel="noopener noreferrer"&gt;rsync&lt;/a&gt; on my Linux computer. First, I chose a folder on my Windows computer to share on the network. On my Linux computer, I can now mount that shared folder by adding a configuration into my &lt;a href="https://en.wikipedia.org/wiki/Fstab" rel="noopener noreferrer"&gt;fstab&lt;/a&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//192.168.0.4/share /windows cifs username=share,uid=tenry,gid=tenry,noauto,nofail,exec,dev,suid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My Windows computer is on a specific local IP address, let's say &lt;code&gt;192.168.0.4&lt;/code&gt; for example. On the Windows share settings, I called the shared folder &lt;code&gt;share&lt;/code&gt;, and I want it to be mounted on my Linux computer at &lt;code&gt;/windows&lt;/code&gt; in the root.&lt;/p&gt;

&lt;p&gt;Now I can easily access the shared Windows files on my Linux computer as if they were actually on my Linux computer.&lt;/p&gt;

&lt;p&gt;Unfortunatly, I didn't find a way (yet) to share a whole drive (e.g. &lt;code&gt;C:&lt;/code&gt; or &lt;code&gt;D:&lt;/code&gt;) on the network, but maybe it's better to not do so. Instead, I created a new folder &lt;code&gt;share&lt;/code&gt; where I put nearly everything I create or work with on Windows.&lt;/p&gt;

&lt;p&gt;Now, that my Windows share folder is mounted, I can start working with rsync! I created a few shell script that allows me to quickly "push" some files from Linux → Windows or "pull" from Windows → Linux. So, let's say, I have a new project at &lt;code&gt;/path/to/my/project&lt;/code&gt;, I simply &lt;code&gt;cd&lt;/code&gt; into that directory on Linux, call my &lt;em&gt;push&lt;/em&gt; script with no arguments or &lt;code&gt;.&lt;/code&gt; for the current directory, and everything in the current folder becomes available as a copy on my Windows computer at &lt;code&gt;share\path\to\my\project&lt;/code&gt;. And when I did some work on my Windows computer, I simply call my &lt;em&gt;pull&lt;/em&gt; script on Linux.&lt;/p&gt;

&lt;p&gt;I might go more into the details of my script in a different articel if you're interested.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's still not perfect
&lt;/h2&gt;

&lt;p&gt;If I do something on one computer, the files are not immediately available on the other computer. I push and pull manually all the time, and all the files are just copies.&lt;/p&gt;

&lt;p&gt;Also, my script does not delete any files I deleted from one of the systems for security reasons (unless I explicitly tell it to do so) and I'm not sure how good rsync is at detecting renames of files and folders.&lt;/p&gt;

&lt;p&gt;What I would like the best is if both computers would actually access the very same storage, without any network bottleneck. But I already see two major issues here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux working with an ext filesystem and having everything at &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Windows working with an NTFS filesystem and having something at &lt;code&gt;C:\&lt;/code&gt;, &lt;code&gt;D:\&lt;/code&gt; etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any tips or tricks for me regarding the file management, I'm happy to know about them! I hope this article well help some of you setting up your own multi-computer systems.&lt;/p&gt;




&lt;p&gt;Update (2024): As of today, I share my Linux primary folder, where I put all my projects etc., via SMB, so I can mount it on my Windows computer at "F:". "F:\projects\music" on Windows is now the same as "/files/projects/music" on Linux. Even though it's still working via network, it doesn't appear to be such a bottleneck than it used to be with my NAS before. Perhaps my NAS simply didn't have enough power to be fast enough for that job.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Bash arguments</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Tue, 08 Dec 2020 10:35:42 +0000</pubDate>
      <link>https://dev.to/tenry/bash-arguments-36d0</link>
      <guid>https://dev.to/tenry/bash-arguments-36d0</guid>
      <description>&lt;p&gt;When executing a shell script, you can pass any number of arguments. Let's say, you invoke a bash script like this: &lt;code&gt;./script.sh "foo bar" baz"&lt;/code&gt;&lt;br&gt;
What does the shell script see?&lt;/p&gt;
&lt;h2&gt;
  
  
  Variables
&lt;/h2&gt;

&lt;p&gt;Command line arguments are visible in the shell script from &lt;code&gt;$0&lt;/code&gt; to &lt;code&gt;$9&lt;/code&gt;, where &lt;code&gt;$0&lt;/code&gt; is always the path to the shell script the way it was called:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;./script.sh&lt;/code&gt; → &lt;code&gt;$0&lt;/code&gt; contains &lt;code&gt;./script.sh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;path/to/script.sh&lt;/code&gt; → &lt;code&gt;$0&lt;/code&gt; contains &lt;code&gt;path/to/script.sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, this is the path to the script relative to the working directory or an absolute path.&lt;/p&gt;

&lt;p&gt;In the example in the introduction of this article, &lt;code&gt;$1&lt;/code&gt; would contain &lt;code&gt;foo bar&lt;/code&gt; and &lt;code&gt;$2&lt;/code&gt; &lt;code&gt;baz&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The special variable &lt;code&gt;$@&lt;/code&gt; contains all arguments passed to the script, excluding &lt;code&gt;$0&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Passing arguments to another script
&lt;/h2&gt;

&lt;p&gt;Let's say, we have script1.sh, which calls script2.sh and passes all arguments over. In script1.sh, you pass &lt;code&gt;$@&lt;/code&gt; to script2.sh. But note there's a significant difference if the argument is quoted or not:&lt;/p&gt;

&lt;p&gt;If you do &lt;code&gt;./script1.sh "foo bar" baz&lt;/code&gt; and that script does &lt;code&gt;./script2.sh $@&lt;/code&gt;, it would be substituted to &lt;code&gt;./script2.sh foo bar baz&lt;/code&gt;. While we originally only passed 2 arguments to script1.sh, script2.sh would receive 3 arguments.&lt;/p&gt;

&lt;p&gt;If the first script would instead quote the argument, &lt;code&gt;./script2.sh "$@"&lt;/code&gt;, it would be substituted to &lt;code&gt;./script2.sh "foo bar" baz&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Looping over arguments
&lt;/h2&gt;

&lt;p&gt;The following example shows how to loop over all arguments passed to a shell script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;arg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;do
  if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"--help"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"-h"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Help argument detected."&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>bash</category>
    </item>
    <item>
      <title>Terminal colors in C/C++</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Mon, 07 Dec 2020 10:44:32 +0000</pubDate>
      <link>https://dev.to/tenry/terminal-colors-in-c-c-3dgc</link>
      <guid>https://dev.to/tenry/terminal-colors-in-c-c-3dgc</guid>
      <description>&lt;p&gt;When developing cross-platform terminal applications or using terminal output for logging or debugging, it's useful to color the output in order to not lose the overview.&lt;/p&gt;

&lt;p&gt;This article shows how to color the terminal output on various platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux
&lt;/h2&gt;

&lt;p&gt;On Linux, you can change the current foreground and background color by writing special character sequences into the output. Write the &lt;a href="https://en.wikipedia.org/wiki/Escape_character#ASCII_escape_character" rel="noopener noreferrer"&gt;ESC&lt;/a&gt; escape character (octal &lt;code&gt;"\033"&lt;/code&gt;, hex &lt;code&gt;\x1b&lt;/code&gt;), followed by an opening square bracket &lt;code&gt;[&lt;/code&gt;. The color definition will follow next, termniated by a lowercase &lt;code&gt;m&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The color definition is a series of numbers, separated by semicolons. In order to make the text color red (number 31), you can write &lt;code&gt;"\033[31m"&lt;/code&gt; which will make any following output red. If you want yellow text (33) on blue background (44), you write &lt;code&gt;"\033[31;44m"&lt;/code&gt;. To reset everything back to the default colors, you write &lt;code&gt;"\033[0m"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\033&lt;/span&gt;&lt;span class="s"&gt;[31mred text&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\033&lt;/span&gt;&lt;span class="s"&gt;[33;44myellow on blue&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\033&lt;/span&gt;&lt;span class="s"&gt;[0mdefault colors&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://man7.org/linux/man-pages/man5/terminal-colors.d.5.html" rel="noopener noreferrer"&gt;terminal-colors.d manual&lt;/a&gt; gives you an overview over the available codes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows
&lt;/h2&gt;

&lt;p&gt;On Windows, coloring the terminal output, works a bit different. Instead of writing special character sequences into the output, you have to call special functions from the windows library. &lt;code&gt;#include &amp;lt;windows.h&amp;gt;&lt;/code&gt; in order to access the Windows functions. This provides the &lt;a href="https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute" rel="noopener noreferrer"&gt;&lt;code&gt;SetConsoleTextAttribute()&lt;/code&gt;&lt;/a&gt; function that can be used to color the text. You also need to get a handle to the stdout console using &lt;code&gt;GetStdHandle(STD_OUTPUT_HANDLE)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following code shows how to color the text red and yellow on blue background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;HANDLE&lt;/span&gt; &lt;span class="n"&gt;hConsole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetStdHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STD_OUTPUT_HANDLE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;SetConsoleTextAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hConsole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;FOREGROUND_RED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"red text&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;SetConsoleTextAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hConsole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;FOREGROUND_RED&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;FOREGROUND_GREEN&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;BACKGROUND_BLUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"yellow on blue&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike Linux, where each foreground and background color has an individual number, you work with the red, green and blue channels on Windows. As you can see with yellow, it's a combination of red and green for example.&lt;/p&gt;

&lt;p&gt;You can check available color values &lt;a href="https://docs.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>c</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Predefined C/C++ macros for cross-platform development</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Sun, 06 Dec 2020 19:10:09 +0000</pubDate>
      <link>https://dev.to/tenry/predefined-c-c-macros-43id</link>
      <guid>https://dev.to/tenry/predefined-c-c-macros-43id</guid>
      <description>&lt;p&gt;I do a lot of cross platform development in C/C++, targeting Linux, Windows, macOS, using GCC, MSVC, clang etc.&lt;/p&gt;

&lt;p&gt;In order to have cross platform support, it is sometimes needed to add platform dependent or compiler dependent code. I compiled a list of the most important macros I use. This might be helpful for some others as well.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Macro&lt;/th&gt;
&lt;th&gt;Definition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__linux__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Linux and Linux-derived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__ANDROID__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#if defined(__linux__) &amp;amp;&amp;amp; !defined(__ANDROID__)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Linux (non-Android)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__APPLE__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Darwin (macOS and iOS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_WIN32&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Windows (32- and 64-bit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_WIN64&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Windows 64-bit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_MSC_VER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Visual Studio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__GNUC__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;gcc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__clang__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;clang&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__EMSCRIPTEN__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;emscripten&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__MINGW32__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MinGW 32, MinGW-w64 32-bit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__MINGW64__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MinGW-w64 64-bit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ARM9&lt;/code&gt; (1)&lt;/td&gt;
&lt;td&gt;Nintendo DS (ARM9)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;__NDS__&lt;/code&gt; (1)&lt;/td&gt;
&lt;td&gt;Nintendo DS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;__3DS__&lt;/code&gt; (1)&lt;/td&gt;
&lt;td&gt;Nintendo 3DS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;_3DS&lt;/code&gt; (deprecated) (1)&lt;/td&gt;
&lt;td&gt;Nintendo 3DS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;__SWITCH__&lt;/code&gt; (1)&lt;/td&gt;
&lt;td&gt;Nintendo Switch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;N64&lt;/code&gt; (2)&lt;/td&gt;
&lt;td&gt;Nintendo 64&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(1) These are defined by the makefiles provided by &lt;a href="https://devkitpro.org/" rel="noopener noreferrer"&gt;devkitpro&lt;/a&gt; using the &lt;code&gt;-D&lt;/code&gt; option, they are not built into the compilers.&lt;br&gt;
(2) Defined by the makefiles provided by &lt;a href="https://github.com/DragonMinded/libdragon" rel="noopener noreferrer"&gt;libdragon&lt;/a&gt; using the &lt;code&gt;-D&lt;/code&gt; option, they are not built into the compilers.&lt;/p&gt;

</description>
      <category>c</category>
      <category>cpp</category>
    </item>
    <item>
      <title>How I started coding</title>
      <dc:creator>Tenry</dc:creator>
      <pubDate>Sun, 06 Dec 2020 12:44:06 +0000</pubDate>
      <link>https://dev.to/tenry/how-i-started-coding-53b0</link>
      <guid>https://dev.to/tenry/how-i-started-coding-53b0</guid>
      <description>&lt;p&gt;Why did I start coding, how did I get there and what am I doing today? In this article, I'll give you a little insight about how I got there where I am.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F357knog9t0ktoh7cphpf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F357knog9t0ktoh7cphpf.png" alt="Alt Text" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My childhood
&lt;/h2&gt;

&lt;p&gt;I always loved to "create" my own things. In my childhood, I enjoyed drawing, I had a lot of fun building stuff with LEGO and played with other toys. My family is a bunch of gamers. I grew up playing a lot of Nintendo 64, and also some SNES or Game Boy. What I created on paper or LEGO was often inspired by my favorite games. I'd like to create my own games.&lt;/p&gt;

&lt;h2&gt;
  
  
  The PC era
&lt;/h2&gt;

&lt;p&gt;When I was around 12 years old when I started using the Windows XP PC from my father. I enjoyed creating formatted RTF documents and drawing in paint. Writing down ideas for games or taking notes about my favorite games, such as character stats or cheat codes.&lt;/p&gt;

&lt;p&gt;Eventually, when searching for ways about how to create own games, I found &lt;strong&gt;Game Editor&lt;/strong&gt; and &lt;strong&gt;Game Maker&lt;/strong&gt;. Since our computer also had Ubuntu as a secondary OS installed, I was sometimes on Linux and sometimes on Windows. On Linux, I used Game Editor, since Game Maker was only available for Windows. When I was on Windows, I preferred Game Maker.&lt;/p&gt;

&lt;p&gt;During this time, I discovered many other technologies. I got familiar with &lt;strong&gt;HTML&lt;/strong&gt;, &lt;strong&gt;PHP&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt;. Also, I found a very interesting programming language which many game developers seem to use: &lt;strong&gt;C++&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There was a German website teaching everything about C++. How to compile code, what are data types, functions, parameters, return values, classes, how to write something into the console and more. I believe almost everything I know about coding I learned from that single website.&lt;/p&gt;

&lt;p&gt;I wrote some simple terminal programs, such as a "guess the number" game. Unfortunately, it took quite a while until I found out how to actually create a window and draw on it. Everything the C/C++ standard libraries provided were related to the terminal, files or data structures.&lt;/p&gt;

&lt;p&gt;One day, it suddenly became clear to me: there is a so called "library" that allows you for playing music. The download contains .h header files, but there was also a .lib file. Somehow I managed to "link" that lib file into my project, call functions as described in the lib's documentation and compile. And there it was! I had a console window actually playing back some music! Now I thought I know everything I need! Find another library for creating a window and drawing on it, and finally you can really create anything you want!&lt;/p&gt;

&lt;p&gt;So my first graphics library I found was &lt;strong&gt;Allegro&lt;/strong&gt;. It allowed me for creating a window, draw something on the screen and do something on user input. I created my own Pac-Man clone this way and it's still enjoyable to play.&lt;/p&gt;

&lt;h2&gt;
  
  
  More C++ stuff
&lt;/h2&gt;

&lt;p&gt;I believe I used Allegro only for that single project only. I discovered &lt;strong&gt;SDL&lt;/strong&gt; soon (it was still version 1) and I started quite a lot games I wanted to make. One of my projects even had more than 10 complete restarts from scratch. I was always unhappy with some aspect of the coding or I had an idea how it should work even better.&lt;/p&gt;

&lt;p&gt;In the middle, I also found &lt;strong&gt;SFML&lt;/strong&gt; as an alternative for SDL and did some stuff on that, just to switch back to SDL later again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web development
&lt;/h2&gt;

&lt;p&gt;Independent of my game development experiences, I also started on web development. I originally started coding with &lt;strong&gt;PHP&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt;. In the beginning I didn't use any kind of frameworks at all.&lt;/p&gt;

&lt;p&gt;I was around 20 when I learned about &lt;strong&gt;JavaScript&lt;/strong&gt; during apprenticeship. The most confusing aspects about that language for me were callback functions / closures plus them using variables from the outer scope. But, it didn't take long until I started to learn that language really much!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;node.js&lt;/strong&gt; got my attention, I found an alternative to PHP for coding the backend of a website. I started to create a few projects based on node.js. Later, there appeared &lt;strong&gt;TypeScript&lt;/strong&gt; which allows for types and interfaces. I love the impressive and exact code completion available in editors like &lt;strong&gt;Visual Studio Code&lt;/strong&gt; when working with TypeScript, while missing that accuracy in JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Electron&lt;/strong&gt;, a framework that allows for creating desktop applications using web technology appeared into my life. I was wondering: should I stick to C++ for game development or shall I switch to Electron?&lt;/p&gt;

&lt;h2&gt;
  
  
  C++ vs. Electron
&lt;/h2&gt;

&lt;p&gt;I started coding applications as well as games in Electron + TypeScript. Some of the best points of game development in this combination in my eyes are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;easy to code&lt;/li&gt;
&lt;li&gt;awesome debugger&lt;/li&gt;
&lt;li&gt;finished program can be distributed to Windows, Linux, macOS and even the web out of the box!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, C++ also has some benefits to offer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smaller binaries&lt;/li&gt;
&lt;li&gt;more control over everything&lt;/li&gt;
&lt;li&gt;if done right, better performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I was struggling what to actually use for my game development. The story is not over yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where are my games?
&lt;/h2&gt;

&lt;p&gt;I created a few games in Game Editor, Game Maker and C++. Many of them are really small, based on existing graphics and sounds, and most of them aren't even nearly finished. I'm not particularly proud on any of those old projects, so I don't really advertise them.&lt;/p&gt;

&lt;p&gt;There are a few ideas for different games I want to develop and I'm eager to get those games that way I imagine them. I hope, soon one and another of those will eventually become finished and shared with the world. Having people all over the world playing games I've been imaginating since childhood might be my greatest dream.&lt;/p&gt;

&lt;p&gt;Thank you very much for reading! Feel free to leave comments below :)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
