Build and environment Archives - Grape Programmer https://grapeprogrammer.com Axel Fortun's blog - Passion for Software! Sun, 19 Feb 2023 11:45:22 +0000 en-US hourly 1 https://wordpress.org/?v=6.8 https://grapeprogrammer.com/wp-content/uploads/2021/07/cropped-GrapeProgrammerFavIcon_Min-1.png Build and environment Archives - Grape Programmer https://grapeprogrammer.com 32 32 C++ – Functional programming and OOP: A great article from John Carmack (2012) https://grapeprogrammer.com/c-functional-programming-and-oop-a-great-article-from-john-carmack-2012/ Sun, 19 Feb 2023 11:43:40 +0000 https://grapeprogrammer.com/?p=16123

Hi all!

I would like to share this blog article from John Carmack, a legendary figure of the video game industry – with the development of DOOM, Quake... (https://en.wikipedia.org/wiki/John_Carmack)

Although this article was written ten years ago, this one is still relevant about the advantages of functional programming and the parallel with OOP. This concerns the disadvantages of “OOP programming” vs “functional programming”, mainly because it is hard to detect multithreaded and race conditions issues. Also, it delivers a beginning of solution with “how to mitigate it by doing “functional programming””.

Here is a little summary wrote in the article:

My pragmatic summary: A large fraction of the flaws in software development are due to programmers not fully understanding all the possible states their code may execute in. In a multithreaded environment, the lack of understanding and the resulting problems are greatly amplified, almost to the point of panic if you are paying attention. Programming in a functional style makes the state presented to your code explicit, which makes it much easier to reason about, and, in a completely pure system, makes thread race conditions impossible.

John Carmack


In my opinion, C++ is better and better (especially in the last versions of the standard) to execute a first set of “functional programming”, despite the OOP pragmatism and construction around C++.

Don’t hesitate to read it here: http://sevangelatos.com/john-carmack-on/

]]>
CMake: How to generate sources while building https://grapeprogrammer.com/cmake-generate-sources-build/ Mon, 23 Nov 2020 07:00:00 +0000 https://grapeprogrammer.com/?p=5025

Today, I feature to you a short tutorial about CMake. How to generate source files during a build! During this post, we will create a binary with CMake and generated files. Don’t hesitate to review my short tutorial about CMake basis here.

The issue - CMAKE returns an error on the generated source file

Sometimes, you could build an application with a generated files. Unfortunately, those files could be sources.

If those files don't exist during the CMake configuration, then it results in an error “No rule to make target 'GeneratedFile.cpp'”.

The Solution - Define a custom command, and change the file property

The solution is done in three steps:

  • Create a custom command with the instruction “add_custom_command”. You will launch your file generator here. 
  • "Make depends" on this new custom target . CMake will be able to launch this target ONLY if those source files are not present.
  • In your target, change the file property to “GENERATED”.
  • EXTRA: In your custom command, you can also add a “DEPENDS” instruction. This command helps CMake to control your custom target and then apply launching rules when dependencies change.

If you apply it, your CMake can control perfectly your file generator!

The Example - A simple C++ file

CMAKE - Generate source file with custom target

cmake_minimum_required(VERSION 3.8)

project(GeneratedFileProject)

# Set generated file
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/GeneratedFile.cpp PROPERTIES GENERATED 1)

add_executable(GeneratedExecutable GeneratedFile.cpp)

#Generator definition - Custom Target
add_custom_command(COMMAND  ${CMAKE_CURRENT_SOURCE_DIR}/fileGenerator.sh
                  OUTPUT    ${CMAKE_CURRENT_BINARY_DIR}/GeneratedFile.cpp
                  DEPENDS   ${CMAKE_CURRENT_SOURCE_DIR}/fileGenerator.sh
                  COMMENT   "Generating GeneratedFile.cpp"
                  )
        
add_custom_target(gen_bar DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp)

As you see here, I applied the instructions:

  1. I create a custom target to launch my fileGenerator.sh
  2. I make depends on this custom target to the generated file.
  3. I set this file as “GENERATED” in my new target.
  4. I make DEPENDS it directly on my file generator script to relaunch it in case of modification.

Now, I can launch my CMake configuration and build the program!

CMake build with generated sources

As you see, the configuration is pretty simple!

]]>
Old post review “C Security” and “WSL” https://grapeprogrammer.com/post_review_c_security_wsl/ Mon, 26 Oct 2020 07:00:00 +0000 https://grapeprogrammer.com/?p=4806

Today I feature to you a quick review of my previous posts. I feature to you two posts I appreciated with some special experiences about them. Don’t hesitate to review and enjoy them!

WSL and IDE.

I discovered the WSL (Windows Subsystem for Linux) during the beta. First, I was surprised and mitigated. Then, I discovered a great connection with my IDEs. Finally, I work directly with it.

Each time I write a code, I am using the WSL. The reason is simplicity. I like video games, programming, and Linux systems. Unfortunately, video games are in majority on Windows. WSL avoids the installation of a dual boot or virtual machine.

​Hey! Welcome to my Tutorial ​about WSL and how to develop Linux application with Visual Studio Code. ​I'll feature to you a great way to develop your Linux application with a Windows environment. ​This environment is configured without dual boot, virtual machine or ​Docker installed on your system. I'll stay

Read More

Three security errors in C:

I really appreciated writing this post. It was a great occasion to test the pure C application. C is my first programming language. Even if it looks hard to use, I appreciate so much the performance and interaction with the system.

Moreover, it was a great occasion to see some attacks. Like a simple buffer overflow modify or binary analysis.

I fixed some typo errors in my post. I hope you will enjoy it!

Here is a list of three classic security errors in C I saw during my carrier. At first, C is a great language: performant, perfect for memory management, and perfect for embedded systems... However, C is an old programming language (The first version appeared in 1972!) and it was created

Read More

Photo in banner by Cookie the Pom on Unsplash

]]>
Git: Is it a good idea to push binary assets? https://grapeprogrammer.com/git-large_file/ Mon, 12 Oct 2020 06:00:00 +0000 https://grapeprogrammer.com/?p=4661

Did you already put a large file on git?
Do you know it can decrease your performance? Unluckily, a large file stored on git is not a good practice. Many developers don't recommend this and propose alternatives.

A binary under control is useless on GIT

Git is a powerful version control system. Thanks to commit and patch files, git has several advantages:

  • Usage of “patches” to avoid “macro-management” between files.
  • Powerful comparison.
  • Branch management and conflict management.

Those advantages are true by using text files. It can be sources, headers, configuration files...
But, what about the binary ones? Git is unable to create diff files and cannot manage correctly those.
Consequences: Your git repository will upload/download your complete file. When you request for a pull, change branches, clone…

I think you got the point. This kind of storage has those defaults:

  1. You cannot check the version used… You should use “workaround” like a text file to describe the version. Or use a single commit exclusive to your binary.
  2. A binary file can be large. Over 1MBytes. It will add bandwidth for each clone, checkout, or pull request.
  3. Concerning conflicts, how to resolve it if two developers push two different versions?

Even if you have unlimited bandwidth, a binary slow would down your git performances. It is too bad to use Git as a basic binary manager!

One or two binary files will not specially modify your repository performance… However, what about 50 files?

Fortunately, you have great alternatives to manage those files

GIT LFS

Git LFS (for Git “Large File Storage”) is a tool to store your binaries, images, or archives.

Git LFS will simply store your files on a remote server. It will optimize your data transfer and avoid some strange behavior that could occur with a simple Git.

Instead, Git LFS will store on git a text “pointer of file” to download the correct file remotely. Thanks to that, your Git repository didn't get polluted by large binaries and images.

GIT LFs large file

Use a package manager

To manage your external libraries or modules, there is a cool solution: Package managers.
For some languages, a package manager goes with your programming language. For instance:

  • Crate for Rust.
  • Nuget for C#.
  • pip for Python.
  • And others...

Sadly, C++ doesn’t support easily those package managers. This specificity is due to the divergences between developers during the 30 last years. It concerns library usage, includes, or build systems. But, some package managers are in development for C++: Conan and vcpkg. And it works pretty well!

The big advantage of those package managers is to maintain a dependency tree. This is one of the best suitable solutions to manage third party libraries and binaries.

As you saw, you have multiple tools to track those big files. Git LFS is great to store large files as images and binaries. Concerning the package manager, it is a suitable solution for all binaries and third-party libraries.

]]>
Different kinds of libraries in C/C++ https://grapeprogrammer.com/different-kinds-of-libraries-in-c-c/ Sun, 26 Jul 2020 10:40:00 +0000 https://grapeprogrammer.com/?p=1361

Do you know the different kinds of libraries in C/C++? .dll, .lib. .a, .so... All those extensions depend on your OS but can signify the same thing: A static or a shared library.

Static Library - Copy in executable

First, let see the static library. A static library contains a set of routine/function available and copied in the executable binary at linkage time.
In result, this is a binary launchable without any supplementary dependencies! However, due to this series of routine copied, the executable is larger.

Static library creation in Linux (GCC)

In Linux, a static library is named an "archive" (.a).
The creation of a static library is done by the archiver "ar" and not gcc/g++. With the option rcs:

  • "r": Insert the files member... into archive (with replacement). This operation differs from q in that any previously existing members are deleted if their names match those being added.
  • "c"Create the archive. The specified archive is always created if it did not exist, when you request an update. But a warning is issued unless you specify in advance that you expect to create it, by using this modifier. 
  • "s": Write an object-file index into the archive, or update an existing one, even if no other change is made to the archive.
ar -rsc myLibrary.a myObject.o

Static library creation in Windows (MSCV)

In Windows, a static library is named ".lib". Be careful, this is exactly the same extension as the "import library".
The static library with MSCV can be created thanks to the executable "lib":

lib /out:myLibrary.lib myObject.obj
Pros:
  • Easy to launch - No dependencies needed at runtime.
  • Routine copied in executable.
Cons:
  • Executable larger.
  • Routine to load in memory. Slower compared to Shared Library.

Shared Library - Export in separate object

Second kind of library. Comparing to the "Static Library", the routines/functions available are not copied in the executable. Instead, the "Shared Library" will only includes the address of the library (which is light)!
Concerning the functions execution, they are loaded at runtime!

Shared library creation in Linux (GCC)

In Linux, the shared library has the extension ".so" (for "Shared Object"). GCC can create a shared library with the option "-shared":

g++ -shared -o myLibrary.so MyObject.o

During runtime, your OS should be able to access to the .so. You can do this configuration with ldconfig.

Shared library creation in Windows (MSCV)

In Windows, two files are created:

  • .lib, similar to the "static" one but without the function routines. This is the "Import Library", used to import instruction in your executable during linkage.
  • .dll, meaning "Dynamic Link Library". This is the file loaded at runtime.

To export functions in your DLL, you should have the "__dllexport" mark at each function declaration you want to "export". To build a shared library:

link /DLL /OUT:myDLL.dll myLibrary.o
Pros:
  • Smaller executable. Optimized if several executable uses the same library.
  • Faster, shared library code is already in the memory.
Cons:
  • Loaded at runtime, dependency and configuration needed.

Header-Only Library - Neither static nor shared library

Currently, there is another kind of library used in C/C++: The "Header Only". In the fact, Header-Only libraries are not a kind of library.

The name is meaningful, this "library" contains only headers and no shared object or static archive. The power of this kind of library is they can be "OS agnostic" and easier to includes compared to the static and shared one.
However, those advantages are balanced by a longer compilation time and the routine/function copied in the executable. This kind of library is perfect for short functions/classes.

Pros:
  • Easy to include.
  • Can be easily OS agnostic for delivery.
  • Routine copied in executable.
  • Easy to launch - No dependencies needed at runtime.
Cons:
  • Longer compilation time.
  • Not adapted for large library.
  • Executable larger, routine to load in memory.
]]>
How to build Linux program with Windows https://grapeprogrammer.com/build_linux_program_on_windows/ Fri, 19 Jun 2020 19:17:18 +0000 https://grapeprogrammer.com/?p=464

Hey! Welcome to my Tutorial about WSL and how to develop Linux application with Visual Studio Code.

I'll feature to you a great way to develop your Linux application with a Windows environment.

This environment is configured without dual boot, virtual machine or Docker installed on your system. I'll stay focus on the WSL (Windows Subsystem for Linux) and feature a great way to build your application simply with Visual Studio Code!

You know, I love the Linux environment. However, I am also a regular video game player. The fact is the video game development on Linux is, in my opinion, not yet mature. Of course, great improvement had been done in the last years! But many games work only on Windows.

If like me, you appreciate the Linux environment and Video games, this tutorial is perfect for you!

Let's go!

What is WSL?

Windows Subsystem for Linux (WSL) allows launching a GNU/Linux environment directly on your Windows system. This kind of environment avoids the usage of a Virtual Machine, Docker, or Dual Boot to code on Linux.

The fact is that you'll get access to a Bash CLI directly on your Windows.

One year ago, WLS2 had been announced by Microsoft. WSL2 provides high performant file management plus a complete Linux Kernel compare to WLS1. Don't hesitate to read the documentation!

https://docs.microsoft.com/en-us/windows/wsl/compare-versions

During this tutorial, we'll focus on WSL1.

Activate and run WSL.

Activate WSL.

You can active WSL in the Windows feature panel:

You can also use command-line through the PowerShell:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

After reboot, you'll be able to install your Linux distribution!

Select and Install your distribution.

For this procedure, you should go to the Microsoft Store

Then, search a distribution name, for instance, Ubuntu:


Then select and install your distribution. For my configuration, I took "Ubuntu 18.04 LTS".

First configuration for a build environment.

Launch your Linux Distribution like a classic application (Don't hesitate to type in the search bar). For my case, I'll search "Ubuntu"

For the first launch, the environment asks you to configure a username and a password.

The installation of your Linux Environment is minimal. Don't hesitate to installation all the requirements for development.

In my case, I types the following command to install a complete build environment for C/C++:

sudo apt-get install build-essential

Configure Visual Studio Code to develop through the WSL instance

If you reached this step, you should have a complete Linux environment configured on Windows. Moreover, your Linux environment had been configured to build C/C++ program.

Now, let's interface your WSL environment with Visual Studio Code

Visual Studio Code extension installation.

Open "Visual Studio Code" and go to the "Extension" tab. Then, install the extension "Remote - WSL":

When your extension is installed, it is time to launch a Visual Studio Code instance in your WSL environment!

This step is pretty simple:

Go to the "Remote Explorer" tab and select your WSL distribution. Click on "Connect to WSL".


A new Visual Studio Code is opened! This is the one launched inside your WSL instance. Don't hesitate to reinstall your personal extensions, they are compatible!

TIP: You can open a Bash terminal linked to your WSL with the shortcut Ctrl+Shift+ù

A simple Linux program.

I created a very simple C++ program in my WSL instance:

#include <unistd.h>
#include <iostream>

int main() {
    std::cout << "Preparing my sentence..." << std::endl;
    
    for (size_t i=0; i < 3; ++i)
    {
        sleep(1);
        std::cout << i << "..." << std::endl;
    }
    std::cout << "Hello World!" << std::endl;
}

Now, let's build it with g++ and run the binary!

At this step, you should have an environment able to build and run a Linux application.

Personally, I switched one year ago to an environment with WSL. As I use Linux for my personal development, I didn't launch my Linux Virtual Machine for a long time (excepted for one of my servers running on a CentOs environment!).

]]>
CMAKE: Tutorial for a quick implementation with examples https://grapeprogrammer.com/cmake-tutorial-with-examples/ Sat, 06 Jun 2020 09:15:32 +0000 https://grapeprogrammer.com/?p=324

​Welcome to ​a tutorial about the basic of CMake! I want to introduce to you some great functionalities and a very simple example of CMakeLists, code organization and public includes!

Introduction

​For this project, We will follow a "Little Kennel" project which contains three types of animals (Bunnies, Cats and Dogs)!

Those animals are provided by an external package "AnimalPackage". This package provides the animals API. "MyLittleKennel" is the ​executable, this one is linked to the "AnimalPackage" library. To ​​complete this, I add an external binary, from one of my previous review, the "Multithread-glog" test. Then we have:

  • One shared Library - AnimalPackage
  • ​Two executable -
    • MyLittleKennel which depends ​on AnimalPackage.
    • Multithread-glog which is independent.


​Shared library ​creation

The creation of a shared library is pretty simple with CMake. I created the "AnimalPackage" module with the following file architecture:

​Let's focus on the CMakeLists.txt in RED - The one which defines the build of the shared library.

cmake_minimum_required(VERSION 3.8)

set(SRCS
AnimalInterface.cpp
Bunny.cpp
Cat.cpp
Dog.cpp)

add_library(AnimalPackage SHARED ${SRCS} )

target_include_directories(AnimalPackage
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include
)
  • set([VariableName] [Content]) -
    It is a CMake variable. I created the SRCS variable to reference all the cpp files to compile.
    - set documentation

  • add_library([TARGET] [​SHARED/STATIC/MODULE] [​SOURCES LIST]) -
    It declares a new TARGET defined as a Library. ​The [TYPE] "SHARED" gives to CMake the ​data that I want ​to create this "SHARED" library.
    - ​add_library documentation

  • target_include_directories([TARGET] [PUBLIC|PRIVATE|INTERFACE]
    [HEADER ​PATHS]) -
    ​In my example, I ​give the path "Animal/include" as a header directory. The PUBLIC mark guarantees that each project which will use this TARGET will inherit of those include directories. We will see this ​a next chapter !
    ​Concerning "CMAKE_CURRENT_SOURCE_DIR", this macro gives an absolute link to ​my current CMakeList.txt repository (the one in red !).
    ​- target_include_directories documentation

So, this CMakeLists is defined to create a new shared library "AnimalPackages" based on the "SRCS" cpp files. Let's print the GCC instruction with the following commands to build:

cmake ..         # Generate my CMake project
make VERBOSE=1   #Build with VERBOSE = 1 to print my GCC commands generated by CMake



​Now my CMake project to create my shared library is created. Now, let's link this to my binary MyLittleKennel.

​Executable/Binary creation

Now let's create the executable "MyLittleKennel". ​I organized the CMake lists as the followings:

​The ​"Animal" folder contains the "AnimalPackage" target created in the previous chapter.

Concerning the two ​​CMakeLists.txt:

  • The green one is what I like to name a "connector", we'll see this in the next chapter!
  • The red one is used to describe how the executable "MyLittleKennel" is created. Nothing complicated here:
cmake_minimum_required(VERSION 3.8)

set(SRCS
MyLittleKennel.cpp)

add_executable(MyLittleKennel ${SRCS} )

target_link_libraries(MyLittleKennel
PRIVATE
AnimalPackage
)
  • ​add_executable(​[TARGET] ​[​SOURCES LIST]) -
    ​It declares a new TARGET defined as an executable.
    - add_executable documentation

  • ​target_link_libraries([TARGET] [​SHARED/STATIC/MODULE] [​LIB LIST]) -
    It declares all the libraries link to my TARGET. This CMake command is powerful: Thanks to the "AnimalPackage" link, CMake​ can generate a build order. Then, for a "MyLittleKennel" generation, our build will start to check if the "AnimalPackage" library is available. If not, "AnimalPackage" is built before the "MyLittleKennel" linkage.
    - ​target_link_libraries documentation

​It is great! Now we have an executable defined and linked with another target (the library "AnimalPackage")...

However, something is missing:

How CMake can link the "AnimalPackage" and "MyLittleKennel" target? In this state, CMake is unable to know what is the "AnimalPackage" in the "MyLittleKennel" ​​CMakeLists.txt. It is the point for the ​next chapter of this tutorial:

​Link the directories. Generation of the build order

In the previous chapters, you ​saw some ​​CMakeLists.txt in green rectangles. Those ​​CMakeLists.txt are used to link the modules ​sub-directories to browse them successively. Now, I'll show the complete project with the last independent ​executable "MultithreadLog_Glog".

All those ​​CMakeLists.txt in green boxes are "connectors" between all the project. So, if I launch a build from the root, the "Main ​​CMakeLists.txt" is able to retrieve my complete project. Let's see the "Main ​​CMakeLists.txt", which is similar to the other "connectors":

cmake_minimum_required(VERSION 3.8)

project(MyLittleKennelAndGlog)

add_subdirectory(CMakeExample)
add_subdirectory(Multithread-logger)

​add_subdirectory will simply request to our ​​CMakeLists.txt to find other CMakeFile.txt in this folder. ​add_subdirectory documentation

Now, ​the project is linked, let's build it from the project root !

Thanks to this work, CMake was able to construct a simple (but complete!) build order. At first, it built the "MyLittleKennel" dependency ​plus the independent executable "MultithreadLog_Glog". Then, when the "AnimalPackage" is completed, "MyLittleKennel" build can be launched! For the last chapter, we'll review our MyLittleKennel build instruction.

​Link the ​targets

Do you remember the ​CMakeLists.txt from "MyLittleKennel"?

cmake_minimum_required(VERSION 3.8)

set(SRCS
MyLittleKennel.cpp)

add_executable(MyLittleKennel ${SRCS} )

target_link_libraries(MyLittleKennel
PRIVATE
AnimalPackage
)

Here we'll see why the "target_link_libraries" instruction is powerful and will help you to generate simple CMakeLists.txt​. "MyLittleKennel" module contains a simple cpp file with the following code:

#include <AnimalInterface.hpp>
#include <iostream>

int main()
{
    AnimalInterface Bunny(AnimalInterface::BUNNY);
    AnimalInterface Cat(AnimalInterface::CAT);
    AnimalInterface Dog(AnimalInterface::DOG);

    std::cout << "The Bunny says " << Bunny.letHearThisAnimal() << std::endl;
    std::cout << "The Cat says " << Dog.letHearThisAnimal() << std::endl;
    std::cout << "The Dog says " << Cat.letHearThisAnimal() << std::endl;
}

​Now, let's see the instruction generated by CMake with a "make VERBOSE=1":

cd /home/jafie/grapeProgrammer/GrapeProgrammer_ExampleCode/build/CMakeExample/MyLittleKennel && /usr/bin/c++   -I/home/jafie/grapeProgrammer/GrapeProgrammer_ExampleCode/CMakeExample/Animal/src/../include   -o CMakeFiles/MyLittleKennel.dir/MyLittleKennel.cpp.o -c /home/jafie/grapeProgrammer/GrapeProgrammer_ExampleCode/CMakeExample/MyLittleKennel/MyLittleKennel.cpp

​You see in bold here an extra instruction which was not present in our CMakeList.txt... ​An include instruction from AnimalPackage had been retrieved! It was a consequence of the "PUBLIC" instruction from "AnimalPackage", remember:

cmake_minimum_required(VERSION 3.8)

set(SRCS
AnimalInterface.cpp
Bunny.cpp
Cat.cpp
Dog.cpp)

add_library(AnimalPackage SHARED ${SRCS} )

target_include_directories(AnimalPackage
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include
)

​This is one of the great advantage of CMake:

​Thanks to the PUBLIC mark and the "target_link_libraries", "MyLittleKennel" inherited ​the"AnimalPackage" includes - ​And only the PUBLIC part! ​​​​This kind of configuration can be done with libraries too!

​"MyLittleKennel" can only retrieve the "AnimalInterface" header, the others like "Bunny.hpp" and "Cat.hpp" are not accessible from "MyLittleKennel". It avoids that my executable include another header from "AnimalPackage".  ​In concequence, all the internal header from "AnimalInterface" are ​PRIVATE. Let's run our binary generated by CMake!

./MyLittleKennel 
The Bunny says Honk-honk
The Cat says Woof woof
The Dog says Meeeew !

​Conclusion

​With this kind of simple architecture, you'll be able to construct a complete project with CMake easily. More of that, CMake will generate for you a  powerful build order!

​I hope you liked this first tutorial! I'll complete this one with my next posts concerning CMake (and specially the usage of find_package)!

]]>