<?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: Dmitry Linov</title>
    <description>The latest articles on DEV Community by Dmitry Linov (@optimalux).</description>
    <link>https://dev.to/optimalux</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%2F524208%2F47b910b7-8136-41d3-b3ad-4518eea495cc.jpg</url>
      <title>DEV Community: Dmitry Linov</title>
      <link>https://dev.to/optimalux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/optimalux"/>
    <language>en</language>
    <item>
      <title>Submodules That Don’t Suck</title>
      <dc:creator>Dmitry Linov</dc:creator>
      <pubDate>Thu, 17 Feb 2022 15:23:49 +0000</pubDate>
      <link>https://dev.to/optimalux/submodules-that-dont-suck-54g6</link>
      <guid>https://dev.to/optimalux/submodules-that-dont-suck-54g6</guid>
      <description>&lt;p&gt;&lt;em&gt;Git X-Modules lets you enjoy the speed, scale and simple sharing of Git submodules without the bit that drives you to delirious madness&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Look out: Git submodules are a trap
&lt;/h2&gt;

&lt;p&gt;It starts out so innocently. &lt;/p&gt;

&lt;p&gt;You have two applications. They share a lot of code. The last thing you want is to waste time developing different versions of that code. You want a way to work on everything together.&lt;/p&gt;

&lt;p&gt;Well, that’s just what Git submodules are for, right? The shared code has its own repository, which sits inside a parent repository for every application that uses it.&lt;/p&gt;

&lt;p&gt;You don’t even have to install anything. It’s already in the tool. You type one command and it’s up and running. Easy peasy.&lt;/p&gt;

&lt;p&gt;That might have been as much as you thought about it. After all, this wasn’t the bit that really excited you. Your mind was on what you wanted to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  It slowly dawns on you that Git is really complicated
&lt;/h2&gt;

&lt;p&gt;And now you – and your whole team – have no choice but to be really good at it.&lt;/p&gt;

&lt;p&gt;Much of the difficulty comes down to this: Git submodules don’t just sit inside parent repositories. Every version of the parent repository is tied to a particular version of the submodule.&lt;/p&gt;

&lt;p&gt;So, if a developer updates a submodule used in five other repositories, the developer has to update every single one of them.&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%2Fuploads%2Farticles%2Ffkupk6p7a7h8dg4v06sw.jpeg" 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%2Fuploads%2Farticles%2Ffkupk6p7a7h8dg4v06sw.jpeg" alt="Submodules vs X-Modules 1.jpg" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If that sounds tedious, that’s because it is. But it has to be managed meticulously or projects can break and hours of work can just vanish.&lt;/p&gt;

&lt;p&gt;Other times, different sets of changes from different developers wind up in different versions of the submodule, across different instances of the repository. Putting this all together for code review becomes a massive headache.&lt;/p&gt;

&lt;p&gt;You might mutter to yourself that the entire point of having version control was to avoid this exact situation. But here you are, juggling multiple versions of the same files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remembering the good old days when we all knew what to type
&lt;/h2&gt;

&lt;p&gt;Suddenly, all the commands you used to know must be done differently and with more of them. Here’s just a taste:&lt;/p&gt;

&lt;h3&gt;
  
  
  The familiar way
&lt;/h3&gt;

&lt;p&gt;Clone&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git://example.org/repos.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The submodule way
&lt;/h3&gt;

&lt;p&gt;Clone&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git://example.org/repos.git
git submodule init
git submodule update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone --recurse -submodules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit /*in each submodule*/
git add /*in the parent repository for each module*/ 
git commit /*in the parent repository*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push /*in each submodule*/
git push /*in the parent repository*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/*Create a branch in each submodule and in the parent repository*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This all has to be done precisely, and in the precise order too, or else the problems multiply.&lt;/p&gt;

&lt;p&gt;It’s so mundane and repetitive that it feels obvious to just write some quick scripts for and be done with it. Except you’ll never really be done with it. You just have a growing list of scripts that need regular attention as projects grow and change.&lt;/p&gt;

&lt;p&gt;There’s no getting around the fact that submodules are a very involved way of thinking about projects, which your whole team has to engage with all the time.&lt;/p&gt;

&lt;p&gt;And if you’d rather use a graphical tool like Github Desktop? You might be out of luck. Some tools don’t support submodules well. Others don’t support them at all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Using Git submodules, it doesn’t take a big external shock to derail projects
&lt;/h3&gt;

&lt;p&gt;All you really need is for someone to be distracted or have a bad day.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  It’s an expensive way to be miserable
&lt;/h2&gt;

&lt;p&gt;The simple way to start tracking your losses is to add up all the time spent dealing with version control and fixing mistakes. And remember: everyone is losing time to this.&lt;/p&gt;

&lt;p&gt;Then ask yourself: what is this doing to your team’s focus and momentum? Their morale and pride in their work?&lt;/p&gt;

&lt;p&gt;That’s harder to measure, but it’s still very real.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pity is that a modular approach  should be amazing
&lt;/h2&gt;

&lt;p&gt;There’s so much to like about the idea of separating different projects into their own repository.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  It’s fast
&lt;/h3&gt;

&lt;p&gt;Commands take milliseconds, not minutes.&lt;br&gt;
Developers can search and edit a whole repository on their local machine.&lt;/p&gt;
&lt;h3&gt;
  
  
  It scales
&lt;/h3&gt;

&lt;p&gt;It grows with you from 3 developers to 3,000 and beyond.&lt;br&gt;
There’s no worry about what happens when 100 developers commit to the same repository at the same time.&lt;/p&gt;
&lt;h3&gt;
  
  
  It’s so easy to share
&lt;/h3&gt;

&lt;p&gt;It makes it simple to work with external contractors without granting access to all your code.&lt;br&gt;
If you want to publish open-source projects without publishing all of them like Richard Stallman, that’s just as simple.&lt;/p&gt;
&lt;h3&gt;
  
  
  It’s in one place
&lt;/h3&gt;

&lt;p&gt;You always have a single, authoritative version of the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These are solid benefits. It’s tough to give them up. So, little wonder that Git submodules still have advocates who will tell you to just deal with it and get used to the headaches and mounting technical debt.&lt;/p&gt;

&lt;h3&gt;
  
  
  But let’s get real about one thing
&lt;/h3&gt;

&lt;p&gt;Look, it’s not impossible to find developers who get excited by great version control. I mean, we’re some of them.&lt;/p&gt;

&lt;p&gt;But most developers aren’t. They’ve worked too hard to build their own areas of focus.&lt;/p&gt;

&lt;p&gt;They’ll deal with version control just enough to hold a job down and avoid disaster. But it’s never going to be the thing they’re passionate about, that inspires them to their very best.&lt;/p&gt;

&lt;p&gt;It can be thankless too. About the best they can hope for is to do everything perfectly and then see nobody notice because nothing went wrong.&lt;/p&gt;

&lt;p&gt;And really.. are developers even wrong to want this off their plate?&lt;/p&gt;

&lt;p&gt;Why shouldn’t they have all their attention on their code?&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Git X-Modules
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gitmodules.com/" rel="noopener noreferrer"&gt;An X-Module&lt;/a&gt; sits as an ordinary directory inside a regular Git repository. Developers can treat it just like any other directory, without having to think about it any deeper.&lt;/p&gt;

&lt;p&gt;Server-side software keeps this X-Module directory in sync with an external repository, pushing changes in both directions automatically.&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%2Fuploads%2Farticles%2F9qdcpi0o8867bjwpe107.jpeg" 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%2Fuploads%2Farticles%2F9qdcpi0o8867bjwpe107.jpeg" alt="Submodules vs X-Modules 2.jpg" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if there’s a conflict? X-Modules accepts one set of changes, turning the other into a pull request.&lt;/p&gt;

&lt;p&gt;And if you don’t want to synchronise certain files? You can exclude them either individually, or by extension. So it’s easy not to have those 7-gigabyte .iso files clogging up the bandwidth.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Code review made simple
&lt;/h3&gt;

&lt;p&gt;With X-Modules, all the changes are submitted to one place.&lt;br&gt;
Once they’re approved, they’re synchronised across all repositories automatically.&lt;/p&gt;
&lt;h3&gt;
  
  
  It’s the modular Monorepo
&lt;/h3&gt;

&lt;p&gt;You’re welcome to think of X-Modules as a kind of monorepo. Because there really is one big repository that everything synchronises to.&lt;br&gt;
You’re also welcome to treat them as separate repositories. You still enjoy all the speed, scale and simple sharing of a modular approach.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Your team already knows how to use it
&lt;/h2&gt;

&lt;p&gt;The best thing about X-Modules is that your team doesn’t have to even pay it much notice.&lt;/p&gt;

&lt;p&gt;They just interact with it like any other repository, working exactly the same as all the repositories they’ve used before.&lt;/p&gt;

&lt;p&gt;All the familiar commands just work. They can use any third-party tools with no special requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  So who else wants the server-side solution that syncs your code and stays out of your way?
&lt;/h2&gt;

&lt;p&gt;Git X-Modules is available as a &lt;a href="https://github.com/marketplace/git-x-modules" rel="noopener noreferrer"&gt;cloud app for GitHub&lt;/a&gt;. You can use it for free while it’s still in beta. Support for GitLab and Bitbucket Cloud will be added soon!&lt;br&gt;
There's also an &lt;a href="https://marketplace.atlassian.com/apps/1223696/git-x-modules-for-bitbucket-server" rel="noopener noreferrer"&gt;on-premises app for Bitbucket Data Center&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Seriously, you should try it out.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Text by &lt;a href="https://www.handsomegenius.com.au/" rel="noopener noreferrer"&gt;James Mawson&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>bitbucket</category>
      <category>monorepo</category>
    </item>
    <item>
      <title>Embedded development project structure with Git X-Modules</title>
      <dc:creator>Dmitry Linov</dc:creator>
      <pubDate>Mon, 21 Dec 2020 11:18:10 +0000</pubDate>
      <link>https://dev.to/optimalux/embedded-development-project-structure-with-git-x-modules-5c7i</link>
      <guid>https://dev.to/optimalux/embedded-development-project-structure-with-git-x-modules-5c7i</guid>
      <description>&lt;p&gt;Embedded development, just like any other, often depends on shared code components such as libraries for specific hardware. However, there's no de-facto industry standard for managing modular projects in this area.  We are going to describe one of the ways to do it on a Git repository level.   We will mostly concentrate on project organization topics rather than on particular questions of embedded development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;p&gt;As an example,  we will create a simple program that blinks the LEDs of &lt;a href="https://www.st.com/en/evaluation-tools/stm32f4discovery.html" rel="noopener noreferrer"&gt;STM32F4DISCOVERY&lt;/a&gt; board by STMicroelectronics.  I assume we have a STM32F4DISCOVERY board with &lt;a href="https://www.st.com/en/microcontrollers-microprocessors/stm32f407-417.html" rel="noopener noreferrer"&gt;ST32F407VGT6&lt;/a&gt; MCU. I'm using Debian 10.6, but for any other OS, the steps are similar. I have 'stlink-tools' and 'gcc-arm-none-eabi' packages installed. The former is a collection of tools (and 'st-flash' in particular) to work with the Discovery board (e.g. 'st-flash' writes the compiled binary file to the MCU's flash using STLink protocol). The latter is a generic ARM cross-compiler as ST32F407VGT6 is ARM Cortex M4 based MCU.&lt;/p&gt;

&lt;p&gt;If you don't have these packages installed do that now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; sudo apt install stlink-tools gcc-arm-none-eabi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;STMicroelectronics provides a standard library for ST32F407VGT6 (&lt;a href="https://www.st.com/content/st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32-standard-peripheral-libraries/stsw-stm32065.html" rel="noopener noreferrer"&gt;STSW-STM32065&lt;/a&gt;). But instead of using it (not everybody is happy with its APIs), we will develop our own library by using MCU datasheets directly. Another reason to develop our own library is to demonstrate a typical scenario when libraries are developed together with the main project itself and can be reused in other projects.&lt;/p&gt;

&lt;p&gt;Although we will have only one project in this post, we will assume there're other projects reusing the same library. In particular, fixes and updates to the library should get into these projects as well.&lt;/p&gt;

&lt;p&gt;We will assume the code to be stored in Git and Atlassian &lt;a href="https://www.atlassian.com/software/bitbucket/download" rel="noopener noreferrer"&gt;Bitbucket Server&lt;/a&gt;/&lt;a href="https://www.atlassian.com/enterprise/data-center/bitbucket" rel="noopener noreferrer"&gt;Data Center&lt;/a&gt; is used on the server's side. This is not necessary but would give us a nice UI.&lt;/p&gt;

&lt;p&gt;## Project Structure ##&lt;br&gt;
Our project will consist of the following major components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;main project source file;&lt;/li&gt;
&lt;li&gt;generic library supporting ST32F407VGT6 MCU;&lt;/li&gt;
&lt;li&gt;files and compiler options needed to cross-compile the C code to the ARM platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To cross-compile a project, one has to use a number of specific compiler options and also a startup and a linker script file. When having several projects for the same MCU, it makes sense to share these files and options across projects. Thus we will have a common component dedicated to these compilation-related files. We will name this component &lt;strong&gt;'common'&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will name the library &lt;strong&gt;'stm32'&lt;/strong&gt; component. The main project will be named &lt;strong&gt;'embedded-example'&lt;/strong&gt;.&lt;br&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%2Fuploads%2Farticles%2Fyhmlzripdsfbss22d7w7.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%2Fuploads%2Farticles%2Fyhmlzripdsfbss22d7w7.png" alt="01-structure|690x269" width="800" height="312"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1. Create the 'stm32' project
&lt;/h2&gt;

&lt;p&gt;Create 'stm32' Git repositrory with Atlassian Bitbucket Server/Data Center UI &lt;br&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%2Fuploads%2Farticles%2Fpabknwc3rwbf3vlvd82y.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%2Fuploads%2Farticles%2Fpabknwc3rwbf3vlvd82y.png" alt="02-create-stm32-repository|653x500" width="800" height="612"&gt;&lt;/a&gt; &lt;br&gt;
and clone it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/ee/stm32.git stm32/
cd stm32/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create CMakeLists.txt file there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(stm32)

add_library(stm32 pin.c gpio.c util.c)
target_include_directories(stm32 PUBLIC .)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This CMakeLists.txt file describes a project with three C files and tells all the projects that would include it that the include directory is at the project root. So the files structure will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── CMakeLists.txt
├── gpio.c
├── gpio.h
├── pin.c
├── pin.h
├── util.c
└── util.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create these files and their headers: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://support.tmatesoft.com/uploads/short-url/yECbnDvc85xTjha0nzKwYJj2bT8.h" rel="noopener noreferrer"&gt;util.h&lt;/a&gt; &amp;amp; &lt;a href="https://support.tmatesoft.com/uploads/short-url/iySFXJyPbs5GgowkwUCfysOnJu7.c" rel="noopener noreferrer"&gt;util.c&lt;/a&gt; - they contain convenience functions to set and get special bits;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.tmatesoft.com/uploads/short-url/iDFjZCjuxX6sz1c5qP6oGKUe7X0.h" rel="noopener noreferrer"&gt;gpio.h&lt;/a&gt; &amp;amp; &lt;a href="https://support.tmatesoft.com/uploads/short-url/wJaspm7z1Pl1q178PeUUXKSebfM.c" rel="noopener noreferrer"&gt;gpio.c&lt;/a&gt; - they contain a dull and straightforward implementation of ST32F407VGT6 datasheet GPIO specifications;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.tmatesoft.com/uploads/short-url/t3MMaCZjA7qrduIpmzeCcwyGYBs.h" rel="noopener noreferrer"&gt;pin.h&lt;/a&gt; &amp;amp; &lt;a href="https://support.tmatesoft.com/uploads/short-url/wV6KyqgSBTju41yXc2ggYCF9u0p.c" rel="noopener noreferrer"&gt;pin.c&lt;/a&gt; - they define pin names like &lt;code&gt;hw_pin_PD12&lt;/code&gt; and their convenience equivalents like &lt;code&gt;hw_pin_led_green&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, on STM32F4DISCOVERY PD12 pin of the MCU is connected to the green LED, that's why it's convenient to define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define hw_pin_led_green hw_pin_PD12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add, commit, and push the changes to 'stm32' library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add *.c
git add *.h
git add CMakeLists.txt
git commit -m "Initial."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2F3g2xakh99amry91o44bn.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%2Fuploads%2Farticles%2F3g2xakh99amry91o44bn.png" alt="03-stm32-repository-toc|436x499" width="723" height="829"&gt;&lt;/a&gt; &lt;br&gt;
I would note that as this library is self-contained, one can even compile (but not cross-compile, so far) it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir build
cd build
cmake ..
make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything compiles, it's a good indicator, though a pretty useless property as our target platform is ARM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Create the 'common' project
&lt;/h2&gt;

&lt;p&gt;This project will contain the common configuration that is shared between projects. It's also convenient to put it into a separate Git repository and insert it into each project repository to be included by the project CMakeLists.txt.&lt;/p&gt;

&lt;p&gt;Create  the 'common' repository with Atlassian Bitbucket Server/Data Center &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%2Fuploads%2Farticles%2Fxbcjd70y4o9akrpb0w3m.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%2Fuploads%2Farticles%2Fxbcjd70y4o9akrpb0w3m.png" alt="04-create-common-repository|659x500" width="800" height="606"&gt;&lt;/a&gt; &lt;br&gt;
and clone the newly created repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/ee/common.git common/
cd common/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create &lt;code&gt;vars.cmake&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set(CMAKE_SYSTEM_NAME      Generic)
set(CMAKE_SYSTEM_VERSION   1)
set(CMAKE_SYSTEM_PROCESSOR arm-eabi)

set(CMAKE_C_COMPILER       arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER     arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER     arm-none-eabi-as)
set(CMAKE_OBJCOPY          arm-none-eabi-objcopy)
set(CMAKE_OBJDUMP          arm-none-eabi-objdump)

set(CMAKE_C_FLAGS "-mthumb -mcpu=cortex-m4 -fno-builtin -Wall -Wno-pointer-to-int-cast -std=gnu99 -fdata-sections -ffunction-sections" CACHE INTERNAL "c compiler flags")
set(CMAKE_CXX_FLAGS "-mthumb -mcpu=cortex-m4 -fno-builtin -Wall -Wno-pointer-to-int-cast -fdata-sections -ffunction-sections" CACHE INTERNAL "cxx compiler flags")
set(CMAKE_ASM_FLAGS "-mthumb -mcpu=cortex-m4" CACHE INTERNAL "asm compiler flags")

set(CMAKE_EXE_LINKER_FLAGS "-nostartfiles -Wl,--gc-sections -mthumb -mcpu=cortex-m4" CACHE INTERNAL "exe link flags")
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS CACHE INTERNAL "reset default flags")

set(STM32_STLINK_CLI_EXECUTABLE "st-flash")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file defines various variables needed for the cross-compilation of sources with ARM as the target platform. It sets compiler flags and a path to the 'st-flash' utility that writes binary files to MCU.&lt;/p&gt;

&lt;p&gt;Also add &lt;code&gt;stm32f407vg_flash.ld&lt;/code&gt;, &lt;code&gt;startup_stm32f40xx.s&lt;/code&gt;, and &lt;code&gt;stm32f4xx.h&lt;/code&gt; files. I will not cite them here, but they are quite standard and distributed by STMicroelectronics.&lt;/p&gt;

&lt;p&gt;So the repository content becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── startup_stm32f40xx.s
├── stm32f407vg_flash.ld
├── stm32f4xx.h
└── vars.cmake
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add vars.cmake stm32f4xx.h startup_stm32f40xx.s stm32f407vg_flash.ld
git commit -m "Initial."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fjaw79wj6yepu9gtzcx2n.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%2Fuploads%2Farticles%2Fjaw79wj6yepu9gtzcx2n.png" alt="05-common-repository-toc|576x500" width="750" height="650"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. The project repository
&lt;/h2&gt;

&lt;p&gt;Now let's create the main project repository. The repository will have the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── CMakeLists.txt
├── common   &amp;lt;--- here common.git will be inserted
├── libs
│   └── stm32  &amp;lt;--- here stm32.git will be inserted
│
└── src
    └── main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So create an empty Git repository using Atlassian Bitbucket Server/Data Center UI&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%2Fuploads%2Farticles%2Fc73k6nirxo61vtuzrgg5.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%2Fuploads%2Farticles%2Fc73k6nirxo61vtuzrgg5.png" alt="06-create-embedded-example-repository|660x500" width="800" height="605"&gt;&lt;/a&gt; &lt;br&gt;
and clone it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/ee/embedded-example.git embedded-example/
cd embedded-example/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;CMakeLists.txt&lt;/code&gt; there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
include(common/vars.cmake)
project(embedded-example)
enable_language(C ASM)

add_subdirectory(libs/stm32)

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T${CMAKE_SOURCE_DIR}/common/stm32f407vg_flash.ld")

add_executable(${PROJECT_NAME}.elf
    ${CMAKE_SOURCE_DIR}/common/startup_stm32f40xx.s
    ${CMAKE_SOURCE_DIR}/src/main.c)
target_include_directories(${PROJECT_NAME}.elf PRIVATE stm32)
target_link_libraries(${PROJECT_NAME}.elf PRIVATE stm32)

add_custom_target(${PROJECT_NAME}.hex DEPENDS ${PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Oihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex)
add_custom_target(${PROJECT_NAME}.bin DEPENDS ${PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin)
set(STLINK_CMD ${STM32_STLINK_CLI_EXECUTABLE} write ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin 0x8000000)
add_custom_target(write-flash DEPENDS ${PROJECT_NAME}.bin COMMAND ${STLINK_CMD})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's important to call &lt;code&gt;include()&lt;/code&gt; on the file with common variables before &lt;code&gt;project()&lt;/code&gt; call otherwise CMake falls into an infinite loop (I would consider this strange behavior as a CMake bug). It's also important to specify the linker script that we've put into the 'common.git' project.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;add_subdirectory()&lt;/code&gt; call includes the library. We can include several libraries there. The libraries will be inserted in the &lt;code&gt;libs/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;The last line creates a &lt;code&gt;make write-flash&lt;/code&gt; target that will not only create a binary file for the MCU but also will write it into its flash using STLink protocol. &lt;code&gt;${STM32_STLINK_CLI_EXECUTABLE}&lt;/code&gt; is defined in the 'common' project.&lt;/p&gt;

&lt;p&gt;Now create &lt;code&gt;src/main.c&lt;/code&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;#include &amp;lt;gpio.h&amp;gt;

hw_pin_t leds[] = {
  hw_pin_led_red,
  hw_pin_led_green,
  hw_pin_led_blue,
//  hw_pin_led_orange
};

int leds_count = sizeof(leds) / sizeof(hw_pin_t);

void SystemInit() {
}

int main() {
  hw_gpio_configure(hw_pin_led_blue, hw_gpio_mode_output_pull_push, hw_gpio_speed_2mhz, hw_gpio_alternate_function_none);
  hw_gpio_configure(hw_pin_led_green, hw_gpio_mode_output_pull_push, hw_gpio_speed_2mhz, hw_gpio_alternate_function_none);
  hw_gpio_configure(hw_pin_led_orange, hw_gpio_mode_output_pull_push, hw_gpio_speed_2mhz, hw_gpio_alternate_function_none);
  hw_gpio_configure(hw_pin_led_red, hw_gpio_mode_output_pull_push, hw_gpio_speed_2mhz, hw_gpio_alternate_function_none);

  int current_led = 0;

  while (TRUE) {  
    hw_gpio_set(leds[current_led], FALSE);
    current_led = (current_led + 1) % leds_count;
    hw_gpio_set(leds[current_led], TRUE);

    int delay = 1000000;
    while (delay--) {
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file is simple: it initializes pins related to LEDs and blinks with red, green, and blue pins. We've commented out the orange pin as default STM32F4DISCOVERY firmware blinks with all 4 LEDs and we want to differ from that.&lt;/p&gt;

&lt;p&gt;Commit and push the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add src/main.c
git add CMakeLists.txt
git commit -m "Initial."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fepj8gvn4k98d921c0hr7.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%2Fuploads%2Farticles%2Fepj8gvn4k98d921c0hr7.png" alt="07-embedded-example-repository-toc|682x500" width="734" height="538"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Insert 'common.git' and 'stm32.git' repositories into 'embedded-example.git'
&lt;/h2&gt;

&lt;p&gt;To insert one repository to another we will use Git &lt;a href="http://tmatesoft.com/x-modules/" rel="noopener noreferrer"&gt;X-Modules&lt;/a&gt;. For Atlassian Bitbucket Server/Data Center there's a dedicated app with a nice UI. For other Git servers use the: Git X-Modules Command-Line Tool.&lt;/p&gt;

&lt;p&gt;Make sure you have X-Modules app installed into Atlassian Bitbucket Server/Data Center. If not, visit &lt;code&gt;Administration | Find new apps | Search the [Marketplace](https://marketplace.atlassian.com/apps/1223696/git-x-modules-for-bitbucket-server)&lt;/code&gt; and type "X-Modules" from Bitbucket Server/Data Center UI.&lt;br&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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.png" alt="07-install-x-modules-app|690x203" width="800" height="236"&gt;&lt;/a&gt; &lt;br&gt;
Go to  the 'embedded-example' Git repository page. When the Git X-Modules app is installed there's  a Git X-Modules button on the left panel, click it.&lt;br&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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.png" alt="09-x-modules-button|690x181" width="795" height="209"&gt;&lt;/a&gt; &lt;br&gt;
Then click 'Add Module' to add the first module (let it be 'common.git').&lt;br&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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.png" alt="11-x-modules-add-first-module|690x275" width="800" height="319"&gt;&lt;/a&gt; &lt;br&gt;
Choose 'common' repository and 'master' branch. Make sure "This Repository Path:" is 'common'. It's the path where the repository will be inserted:&lt;br&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%2Fuploads%2Farticles%2Fcb4uie4dlskpaazg0u39.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%2Fuploads%2Farticles%2Fcb4uie4dlskpaazg0u39.png" alt="11-x-modules-add-common-preview|690x443" width="800" height="513"&gt;&lt;/a&gt; &lt;br&gt;
Click 'Add Module'. Without applying the changes click 'Add Module' again to add 'stm32' repository as module.&lt;br&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%2Fuploads%2Farticles%2F8mlu8oc9bpbfidd793h7.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%2Fuploads%2Farticles%2F8mlu8oc9bpbfidd793h7.png" alt="12-x-modules-add-second-module|690x422" width="800" height="489"&gt;&lt;/a&gt; &lt;br&gt;
Choose 'stm32' repository and 'master' branch.&lt;br&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%2Fuploads%2Farticles%2Fpljkjits4wdr2m79jmo2.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%2Fuploads%2Farticles%2Fpljkjits4wdr2m79jmo2.png" alt="13-x-modules-choose-stm32-repository|690x464" width="800" height="539"&gt;&lt;/a&gt; &lt;br&gt;
Make sure "This Repository Path:" is "libs/stm32", this is the insertion path for 'stm32.git' repository.&lt;br&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%2Fuploads%2Farticles%2Fexfds54lap5imyk6rul8.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%2Fuploads%2Farticles%2Fexfds54lap5imyk6rul8.png" alt="14-x-modules-choose-stm32-module-path|690x453" width="800" height="525"&gt;&lt;/a&gt; &lt;br&gt;
Click 'Add Module' and apply the changes.&lt;br&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%2Fuploads%2Farticles%2Fujmduv8agnwz9208nibd.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%2Fuploads%2Farticles%2Fujmduv8agnwz9208nibd.png" alt="15-x-modules-apply-changes|664x500" width="800" height="601"&gt;&lt;/a&gt; &lt;br&gt;
Now the repositories are inserted as X-Modules.&lt;br&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%2Fuploads%2Farticles%2Fj76tduhills0t8z8urod.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%2Fuploads%2Farticles%2Fj76tduhills0t8z8urod.png" alt="16-embedded-example-repository-toc|560x500" width="736" height="656"&gt;&lt;/a&gt; &lt;br&gt;
This means that 'common.git' and 'stm32.git' are synchronized with corresponding directories ('common' and 'libs/stm32' respectively) of 'embedded-example.git'.&lt;/p&gt;

&lt;p&gt;Fetch the changes from 'embedded-example':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd embedded-example/
git pull --rebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the project contains everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── CMakeLists.txt
├── common
│   ├── startup_stm32f40xx.s
│   ├── stm32f407vg_flash.ld
│   ├── stm32f4xx.h
│   └── vars.cmake
├── libs
│   └── stm32
│       ├── CMakeLists.txt
│       ├── gpio.c
│       ├── gpio.h
│       ├── pin.c
│       ├── pin.h
│       ├── util.c
│       └── util.h
└── src
    └── main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that the project compiles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir build
cd build
cmake ..
make
make write-flash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fhrv8y5ngn4w2glvb7hsb.gif" 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%2Fuploads%2Farticles%2Fhrv8y5ngn4w2glvb7hsb.gif" width="210" height="320"&gt;&lt;/a&gt;&lt;br&gt;
At the moment of running &lt;code&gt;make write-flash&lt;/code&gt;, the STM32F4DISCOVERY board should be connected. If you do everything correctly, you'll see 3 LEDs blinking.&lt;/p&gt;

&lt;p&gt;This repository structure can be reused for any other ST32F407VGT6-based project, it's enough to insert 'common' and 'stm32' at the corresponding places. Moreover, the directories are bi-directionally synchronized with the inserted repositories, so one can change, see the results, and modify 'stm32' directly from the project repository.&lt;/p&gt;

</description>
      <category>git</category>
      <category>embedded</category>
      <category>xmodules</category>
    </item>
    <item>
      <title>Setting up multi-module Python environment with X-Modules and Develop Mode</title>
      <dc:creator>Dmitry Linov</dc:creator>
      <pubDate>Wed, 09 Dec 2020 10:42:18 +0000</pubDate>
      <link>https://dev.to/optimalux/setting-up-multi-module-python-environment-with-x-modules-and-develop-mode-ofp</link>
      <guid>https://dev.to/optimalux/setting-up-multi-module-python-environment-with-x-modules-and-develop-mode-ofp</guid>
      <description>&lt;p&gt;Quite often a Python project consists not only of an app but also of some libraries that could also be used by other projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On one hand, it's very convenient to work with the app repository independently of libraries assuming the libraries are installed on the system (&lt;a href="https://docs.python.org/3/library/venv.html" rel="noopener noreferrer"&gt;virtual environment&lt;/a&gt;). &lt;/li&gt;
&lt;li&gt;On the other hand, this creates a painful problem of "change the library" -&amp;gt; "install the library" -&amp;gt; "check the change from the app development setup" cycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post shows, how you can manage this setup with &lt;a href="https://gitmodules.com" rel="noopener noreferrer"&gt;Git X-Modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the Git server, we will use Atlassian &lt;a href="https://www.atlassian.com/software/bitbucket/download" rel="noopener noreferrer"&gt;Bitbucket Server&lt;/a&gt;/&lt;a href="https://www.atlassian.com/enterprise/data-center/bitbucket" rel="noopener noreferrer"&gt;Data Center&lt;/a&gt; --- one of the most popular self-hosting Git solutions. It's also convenient because there's a special &lt;a href="https://marketplace.atlassian.com/apps/1223696" rel="noopener noreferrer"&gt;Git X-Modules App&lt;/a&gt; for it. If you are on any other Git Server, you may still use Git X-Modules as a &lt;a href="https://gitmodules.com" rel="noopener noreferrer"&gt;command-line tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The configuration.&lt;/strong&gt; As an example, we'll create an app (let's call it &lt;strong&gt;'qsolver'&lt;/strong&gt;) that solves quadratic equations. I will also create a library (&lt;strong&gt;'qsolverlib&lt;/strong&gt;) that performs mathematical calculations, so the 'qsolver' app will use it to output the solution.&lt;/p&gt;

&lt;p&gt;Finally, there will be a &lt;strong&gt;'qsolver-project'&lt;/strong&gt; containing both components. This will help us to pinpoint the version of 'qsolverlib' used by 'qsolver' because otherwise 'qsolver' would use 'qsolverlib' installed on the system that could be of the wrong version. This is especially useful in real life when some problem happens to some older version of the application and it's important to deduce the library version used for that application.&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%2Fuploads%2Farticles%2Fjxdcraygbkvvbqp4e3hg.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%2Fuploads%2Farticles%2Fjxdcraygbkvvbqp4e3hg.png" alt="01-structure|434x264" width="434" height="264"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We will create 3 Git repositories: for 'qsolverlib', 'qsolver', and 'qsolver-project'.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Create 'qsolverlib' Git repository.&lt;br&gt;
Create 'qsolverlib' Git repository on Atlassian Bitbucket Server/Data Center.&lt;br&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%2Fuploads%2Farticles%2Fjae5cruevt6kuddn0lil.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%2Fuploads%2Farticles%2Fjae5cruevt6kuddn0lil.png" alt="02-create-qsolverlib-repository|658x500" width="800" height="607"&gt;&lt;/a&gt; &lt;br&gt;
Clone this empty Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/qsolver/qsolverlib.git qsolverlib/
cd qsolverlib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside this Git repository create the 'qsolverlib' subdirectory and create the &lt;code&gt;solve.py&lt;/code&gt; file in it with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"""Quadratic equation solver."""

import math

def solve(a, b, c):
    """Solve equation ax^2 + bx + c = 0, return a root or a list with roots"""
    D = b * b - 4 * a * c
    if D &amp;lt; 0:
        return None
    elif D == 0:
        return -b / (2 * a)
    else:
        return [(-b - math.sqrt(D)) / (2 * a), (-b + math.sqrt(D)) / (2 * a)]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also create an empty "__init__.py" file in the "qsolverlib" subdirectory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch qsolverlib/__init__.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, create "setup.py" at the root of the Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"""Setup file for qsolverlib."""

import setuptools

setuptools.setup(
    name="qsolverlib",
    version="0.0.1",
    description="A library solving quadratic equations",
    url="http://example.org/scm/qsolver/qsolverlib.git",
    author="Dmitry Pavlenko",
    author_email="pavlenko@tmatesoft.com",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python"
    ],
    packages=setuptools.find_packages(),
    python_requires="&amp;gt;=3.7"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the resulting structure looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── qsolverlib
│   ├── __init__.py
│   └── solve.py
└── setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push the package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Initial."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fmn19ms9ghrp4vanefu2n.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%2Fuploads%2Farticles%2Fmn19ms9ghrp4vanefu2n.png" alt="03-qsolverlib-repository-toc|560x500" width="731" height="652"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; Create Python virtual environment and install the package there.&lt;/p&gt;

&lt;p&gt;Python virtual environment allows installing python packages locally into some directory without requiring to install them at the system-wide level. To create the environment run (not inside the Git repository but inside it parent directory):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;virtualenv .venv/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 -m venv .venv/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As result, the ".venv/" directory will be created. This environment should be activated to be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that "(.venv)" will be prepended to the command prompt indicating that we're working with the virtual environment.&lt;/p&gt;

&lt;p&gt;Now install the 'qsolverlib' package into this environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install qsolverlib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For me it prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
  error: invalid command 'bdist_wheel'

  ----------------------------------------
  Failed building wheel for qsolverlib
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be resolved by installing the 'wheel' package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install wheel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then retrying&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install qsolverlib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is successful. Now the library can be used by an app if the app is running within the same virtual environment.&lt;/p&gt;

&lt;p&gt;The virtual environment can be de-activated with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deactivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Create a 'qsolver' app.&lt;/p&gt;

&lt;p&gt;Create 'qsolver' Git repository on Atlassian Bitbucket Server/Data Center.&lt;br&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%2Fuploads%2Farticles%2Fip3ei6p158c95z7xfo6t.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%2Fuploads%2Farticles%2Fip3ei6p158c95z7xfo6t.png" alt="04-create-qsolver-repository|622x500" width="800" height="642"&gt;&lt;/a&gt; &lt;br&gt;
Clone this empty Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/qsolver/qsolver.git qsolver/
cd qsolver/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;app.py&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from qsolverlib import solve

def main():
    print(solve.solve(1, -3, 2))

if __name__ == "__main__":
    main()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I.e. it solves: x^2 - 3x + 2 = 0&lt;/p&gt;

&lt;p&gt;Commit and push this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add app.py
git commit -m "Initial."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that the app works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 app.py 
[1.0, 2.0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indeed, x^2 - 3x + 2 = (x - 1)(x - 2)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4.&lt;/strong&gt; Develop mode of package.&lt;/p&gt;

&lt;p&gt;If we now want to change the "solve()" function, we have to edit solve.py in the 'qsolverlib' repository, install the package, and only then test how it works in app.py in 'qsolver'. This is too inconvenient. "Develop mode" is the solution.&lt;/p&gt;

&lt;p&gt;To install 'qsolverlib' in develop mode run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install -e qsolverlib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It logically links qsolverlib installed in the virtual environment with the sources of 'qsolverlib', so any changes to 'qsolverlib' sources become effective for the app immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5.&lt;/strong&gt; Create a parent project to pinpoint versions of 'qsolverlib' and 'qsolver'.&lt;/p&gt;

&lt;p&gt;Create 'qsolver-project' Git repository on Atlassian Bitbucket Server/Data Center.&lt;br&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%2Fuploads%2Farticles%2Ff510fz8spa3uovs1bl5i.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%2Fuploads%2Farticles%2Ff510fz8spa3uovs1bl5i.png" alt="06-create-qsolver-project-repository|649x500" width="800" height="616"&gt;&lt;/a&gt; &lt;br&gt;
Now we will use &lt;a href="https://tmatesoft.com/x-modules" rel="noopener noreferrer"&gt;Git X-Modules&lt;/a&gt;, make sure you have it installed. To do that, go to &lt;code&gt;Administration | Find new apps | Search the&lt;/code&gt;&lt;a href="https://marketplace.atlassian.com/apps/1223696/git-x-modules-for-bitbucket-server?hosting=server&amp;amp;tab=overview" rel="noopener noreferrer"&gt;Marketplace&lt;/a&gt; and type "X-Modules".&lt;br&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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.png" alt="07-install-x-modules-app|690x203" width="800" height="236"&gt;&lt;/a&gt; &lt;br&gt;
Go to the 'qsolver-project' repository page on Bitbucket. As the app is now installed, there's an X-Modules button, click it.&lt;br&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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.png" alt="09-x-modules-button|690x181" width="795" height="209"&gt;&lt;/a&gt; &lt;br&gt;
The repository is empty, so click "Create Default Branch" to create the "master" branch.&lt;br&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%2Fuploads%2Farticles%2Fcjl5ybyp8ilr9bki9v06.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%2Fuploads%2Farticles%2Fcjl5ybyp8ilr9bki9v06.png" alt="10-x-modules-create-default-branch|690x285" width="800" height="331"&gt;&lt;/a&gt; &lt;br&gt;
Click "Add Module" to add 'qsolverlib' as the first module.&lt;br&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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.png" alt="11-x-modules-add-first-module|690x275" width="800" height="319"&gt;&lt;/a&gt; &lt;br&gt;
Choose the 'qsolverlib' repository and the master branch.&lt;br&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%2Fuploads%2Farticles%2Fq7qbh23xhkdpxs92uxwm.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%2Fuploads%2Farticles%2Fq7qbh23xhkdpxs92uxwm.png" alt="11-x-modules-choose-qsolverlib|690x461" width="800" height="534"&gt;&lt;/a&gt; &lt;br&gt;
Make sure "This Repository Path" is 'qsolverlib'. It's a path for the insertion point of the 'qsolverlib' module. Click "Add Module".&lt;br&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%2Fuploads%2Farticles%2Fxo5x51yi5fxivi1ksrbw.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%2Fuploads%2Farticles%2Fxo5x51yi5fxivi1ksrbw.png" alt="12-x-modules-add-second-module|690x427" width="800" height="494"&gt;&lt;/a&gt; &lt;br&gt;
Instead of applying changes immediately click "Add Module" again, to add the second module (for the app).&lt;/p&gt;

&lt;p&gt;Choose the 'qsolver' repository and the master branch.&lt;br&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%2Fuploads%2Farticles%2F67yow8cpcu9o7szqxj8u.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%2Fuploads%2Farticles%2F67yow8cpcu9o7szqxj8u.png" alt="13-x-modules-choose-qsolver|690x457" width="800" height="530"&gt;&lt;/a&gt; &lt;br&gt;
Make sure "This Repository Path" is 'qsolver'. Again, this is a path for the insertion point of the 'qsolver' module.&lt;br&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%2Fuploads%2Farticles%2F62tpp7ccggs9u152tyvc.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%2Fuploads%2Farticles%2F62tpp7ccggs9u152tyvc.png" alt="14-x-modules-second-module-preview|690x465" width="800" height="539"&gt;&lt;/a&gt; &lt;br&gt;
Click "Add Module".&lt;br&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%2Fuploads%2Farticles%2Fts5jbpvoq6so8f6md8mn.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%2Fuploads%2Farticles%2Fts5jbpvoq6so8f6md8mn.png" alt="15-x-modules-apply-changes|690x456" width="800" height="528"&gt;&lt;/a&gt; &lt;br&gt;
Now apply the changes.&lt;/p&gt;

&lt;p&gt;Now 'qsolver-project' repository contains both 'qsolverlib' and 'qsolver' X-Modules. These are regular Git directories that are synchronized with the corresponding repositories.&lt;br&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%2Fuploads%2Farticles%2Fqb29l53ry0m8wenmphox.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%2Fuploads%2Farticles%2Fqb29l53ry0m8wenmphox.png" alt="16-qsolver-project-toc|575x499" width="761" height="661"&gt;&lt;/a&gt; &lt;br&gt;
So now one can clone the 'qsolver-project' repository and both 'qsolverlib' and 'qsolver' components will be there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6.&lt;/strong&gt; Quickstart script.&lt;/p&gt;

&lt;p&gt;Suppose you have a new colleague who wants to start working on both 'qsolverlib' and 'qsolver' as soon as possible. For this purpose, we will create a "create-virtualenv.sh" script that would set up the development environment.&lt;/p&gt;

&lt;p&gt;Clone 'qsolver-project':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/qsolver/qsolver-project.git qsolver-project
cd qsolver-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current structure of 'qsolver-project' is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── qsolver
│   └── app.py
└── qsolverlib
    ├── qsolverlib
    │   ├── __init__.py
    │   └── solve.py
    └── setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It already contains 'qsolverlib' and 'qsolver' components, so one doesn't need to clone them separately.&lt;/p&gt;

&lt;p&gt;Create "create-virtualenv.sh" script with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh

if [ -z "$1" ]; then
    echo "Path for the virtual environment required, e.g.:"
    echo ""
    echo "    $0 .venv/"
    echo ""
    exit 1
fi

python3 -m venv "$1"
$1/bin/pip3 install wheel
$1/bin/pip3 install -e qsolverlib/

echo "Virtual environment created at $1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add, commit, and push this script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add create-virtualenv.sh
git commit -m "create-virtualenv.sh script added."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now for a new colleague, it will be enough to clone 'qsolver-project' and run this script to start working on the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sh create-virtualenv.sh .venv/
source .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 7.&lt;/strong&gt; An example: make a change to 'qsolverlib'.&lt;/p&gt;

&lt;p&gt;Now let's improve our solve() function to handle the case a=0, i.e. to solve bx+c=0 equation.&lt;/p&gt;

&lt;p&gt;Edit qsolverlib/qsolverlib/solve.py and qsolver/app.py:&lt;br&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%2Fuploads%2Farticles%2Fbw22ujwm9cuj1a5pznu7.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%2Fuploads%2Farticles%2Fbw22ujwm9cuj1a5pznu7.png" alt="17-git-diff|656x500" width="800" height="609"&gt;&lt;/a&gt; &lt;br&gt;
Commit and push the changes with to both 'qsolverlib' and 'qsolver' as a single commit in 'qsolver-project'.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -a -m "solve() improved to handle linear equations as well."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can look at 'qsolverlib' and 'qsolver' histories on Bitbucket: they are updated!&lt;br&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%2Fuploads%2Farticles%2Fqir5ty5r3ov60m0106dh.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%2Fuploads%2Farticles%2Fqir5ty5r3ov60m0106dh.png" alt="18-qsolverlib-history|690x267" width="800" height="309"&gt;&lt;/a&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%2Fuploads%2Farticles%2Fevrt88sxvptedgj73kg7.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%2Fuploads%2Farticles%2Fevrt88sxvptedgj73kg7.png" alt="19-qsolver-history|690x265" width="800" height="306"&gt;&lt;/a&gt; &lt;br&gt;
The synchronization is bi-directional, updates of 'qsolverlib' and 'qsolver' also get into 'qsolver-project' automatically.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Multi-component CMake-based project with Git X-Modules</title>
      <dc:creator>Dmitry Linov</dc:creator>
      <pubDate>Sun, 06 Dec 2020 14:33:08 +0000</pubDate>
      <link>https://dev.to/optimalux/multi-component-cmake-based-project-with-git-x-modules-55ik</link>
      <guid>https://dev.to/optimalux/multi-component-cmake-based-project-with-git-x-modules-55ik</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;How to build a multi-component project without installing all libraries.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the time of writing this, there's no default solution for dependency management in the C world. There're several competing tools like &lt;a href="https://bazel.build/" rel="noopener noreferrer"&gt;Basel&lt;/a&gt;, &lt;a href="https://mesonbuild.com/" rel="noopener noreferrer"&gt;Meson&lt;/a&gt;, &lt;a href="https://conan.io/" rel="noopener noreferrer"&gt;conan&lt;/a&gt;, etc but none of them is recognized as standard de facto like Maven in Java world.&lt;/p&gt;

&lt;p&gt;In this post, we will describe a &lt;a href="https://cmake.org/" rel="noopener noreferrer"&gt;CMake&lt;/a&gt;-based setup of a project consisting of several modules, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;can be built and installed independently;&lt;/li&gt;
&lt;li&gt;can be build together, so all the app and library sources can be edited, debugged, and committed simultaneously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup resolves the pain of "fix and build the library" -&amp;gt; "install the library" -&amp;gt; "build the app with the library" -&amp;gt; "test the fix from the app" cycle.&lt;/p&gt;

&lt;p&gt;As an example, we will create an app that computes SHA-1 checksum of its argument. To compute SHA-1 checksum we will use an external &lt;a href="https://github.com/clibs/sha1" rel="noopener noreferrer"&gt;library&lt;/a&gt; by Steve Reid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project structure&lt;/strong&gt;.&lt;br&gt;
Currently, the SHA-1 library in question has only a Makefile to build the project. We want to add a CMake-related build file (CMakeLists.txt) to this library. As we don't have write access to this repository we will fork this project to our Git server. For that, we will use Atlassian &lt;a href="https://www.atlassian.com/software/bitbucket/download" rel="noopener noreferrer"&gt;Bitbucket Server&lt;/a&gt;/&lt;a href="https://www.atlassian.com/enterprise/data-center/bitbucket" rel="noopener noreferrer"&gt;Data Center&lt;/a&gt; as one of the most popular self-hosting Git solutions.  It's also convenient because there's a special &lt;a href="https://marketplace.atlassian.com/apps/1223696" rel="noopener noreferrer"&gt;Git X-Modules App&lt;/a&gt; for it. If you are on any other Git Server, you may still use Git X-Modules as a &lt;a href="https://gitmodules.com" rel="noopener noreferrer"&gt;command-line tool&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The SHA-1 library component  will be called &lt;strong&gt;'sha-1'&lt;/strong&gt;.  Then we will create a &lt;strong&gt;'checksum'&lt;/strong&gt; component that uses 'sha-1' library and produces an executable file. One should be able to build this component independently assuming 'sha-1' library is installed (into &lt;code&gt;/usr/lib and /usr/include&lt;/code&gt; or any other OS-specific directory for libraries).&lt;/p&gt;

&lt;p&gt;Finally, we will create a &lt;strong&gt;'checksum-project'&lt;/strong&gt; that includes both 'sha-1' and 'checksum' components and can be built &lt;em&gt;without&lt;/em&gt; having to install 'sha-1' library to the system. This will allow us to open, edit, and build all components in an IDE.&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%2Fuploads%2Farticles%2F8g3r64bqqi6r4s471y4o.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%2Fuploads%2Farticles%2F8g3r64bqqi6r4s471y4o.png" alt="22-structure|434x264" width="434" height="264"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;From the Git perspective, one can use Git submodules for that. But this solution causes a lot of problems. For example, the Projectile package of Emacs doesn't currently work well with submodules. We will use a better solution: &lt;a href="https://tmatesoft.com/x-modules.html" rel="noopener noreferrer"&gt;Git X-Modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt;&lt;br&gt;
Create 'sha-1' repository with Atlassian Bitbucket Server/Data Center interface.&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%2Fuploads%2Farticles%2Fec79zvziz9sz9adcqdej.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%2Fuploads%2Farticles%2Fec79zvziz9sz9adcqdej.png" alt="01-create-sha-1-repository|449x500" width="612" height="681"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We want now to fork &lt;a href="https://github.com/clibs/sha1" rel="noopener noreferrer"&gt;https://github.com/clibs/sha1&lt;/a&gt; project there. To do that, clone the sha1 project from GitHub and push it to our self-hosted Bitbucket Server repository (we assume it's running on example.org domain):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/clibs/sha1.git sha-1
cd sha-1
git remote set-url origin http://example.org/scm/checksum/sha-1.git
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;. Add our custom CMakeLists.txt to 'sha-1' project with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(sha1)

add_library(sha1 sha1.c)
target_include_directories(sha1 PUBLIC .)
set_target_properties(sha1 PROPERTIES PUBLIC_HEADER "sha1.h")
install(TARGETS sha1 LIBRARY DESTINATION lib ARCHIVE DESTINATION lib PUBLIC_HEADER DESTINATION include)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;install()&lt;/code&gt; command tells CMake to install the library to /usr/local/lib and the header to /usr/local/include, so it can be easily included by the app.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;target_include_directories()&lt;/code&gt; call is not necessary to build this project but will be useful later for the multi-module project structure.&lt;/p&gt;

&lt;p&gt;Commit and push the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add CMakeLists.txt
git commit -m "CMakeLists.txt added."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fulnxcpth35w4akokr58m.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%2Fuploads%2Farticles%2Fulnxcpth35w4akokr58m.png" alt="02-sha-1-repository-toc|615x500" width="788" height="640"&gt;&lt;/a&gt; &lt;br&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%2Fuploads%2Farticles%2F6cvvfe5l97ffsh94siou.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%2Fuploads%2Farticles%2F6cvvfe5l97ffsh94siou.png" alt="03-sha-1-repository-history|690x180" width="800" height="208"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Make sure CMake can build the project. We can use these old-fashioned commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir build
cd build
cmake ..
make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install the library into the system one can use "sudo make install" command but later we will describe how to create a multi-component structure that doesn't need installation. So we &lt;strong&gt;do not&lt;/strong&gt; install the library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Create a Git repository for our app.&lt;/p&gt;

&lt;p&gt;Create a 'checksum' repository using Atlassian Bitbucket Server/Data Center interface.&lt;br&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%2Fuploads%2Farticles%2Fca94jbgddn99xgnfqgdg.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%2Fuploads%2Farticles%2Fca94jbgddn99xgnfqgdg.png" alt="04-create-checksum-repository|446x500" width="610" height="683"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Clone and "cd" into the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/checksum/checksum.git checksum
cd checksum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the &lt;code&gt;main.c&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;sha1.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define SHA1_SIZE_IN_BYTES 20

void print_usage(char* command) {
  fprintf(stderr, "Usage: %s STRING\n", command);
}

void print_hex(char* buffer, int buffer_size) {
  for(int i = 0; i &amp;lt; buffer_size; i++) {
    printf("%02x", buffer[i] &amp;amp; 0xff);
  }
}

int main(int argc, char** argv) {
  if (argc != 2) {
    print_usage(argv[0]);
    return 1;
  }
  char sha1[SHA1_SIZE_IN_BYTES + 1];
  char* str = argv[1];

  SHA1(sha1, str, strlen(str));
  sha1[SHA1_SIZE_IN_BYTES] = '\0';

  print_hex(sha1, SHA1_SIZE_IN_BYTES);
  printf("\n");

  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create CMakeLists.txt file with this content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(checksum)

add_executable(checksum main.c)

target_include_directories(checksum PRIVATE sha1)
target_link_libraries(checksum PRIVATE sha1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;main.c&lt;/code&gt; is simple: it just calls &lt;code&gt;SHA1()&lt;/code&gt; function from 'sha-1' library and CMakeLists.txt adds a dependency on 'sha-1' library. Commit and push the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add main.c CMakeLists.txt
git commit -m "Initial commit."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2F4i2p0l8f83vxemzh4686.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%2Fuploads%2Farticles%2F4i2p0l8f83vxemzh4686.png" alt="05-checksum-repository-toc|690x358" width="735" height="382"&gt;&lt;/a&gt; &lt;br&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%2Fuploads%2Farticles%2Flzzjwpa0k678g3f0es8d.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%2Fuploads%2Farticles%2Flzzjwpa0k678g3f0es8d.png" alt="06-checksum-repository-history|653x316" width="653" height="316"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If 'sha-1' is installed on the system with "sudo make install" command of "Step 2", our &lt;code&gt;checksum&lt;/code&gt; app can be build using CMake. But if 'sha-1' is not installed, CMake build command will fail because it can't find the header file for the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir build
cd build
cmake ..
make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scanning dependencies of target checksum
[ 50%] Building C object CMakeFiles/checksum.dir/main.c.o
/home/dmit10/work/blog/02-cmake-post/checksum/main.c:1:10: fatal error: sha1.h: No such file or directory
 #include &amp;lt;sha1.h&amp;gt;
          ^~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/checksum.dir/build.make:63: CMakeFiles/checksum.dir/main.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/checksum.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4.&lt;/strong&gt; Multi-module structure.&lt;br&gt;
Now we want to create a multi-module repository 'checksum-project' with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CMakeLists.txt
checksum/    &amp;lt;-- 'checksum' module insertion point
libs/sha-1/  &amp;lt;-- 'sha-1' library insertion point 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't have the &lt;a href="https://marketplace.atlassian.com/apps/1223696/git-x-modules-for-bitbucket-server?ho" rel="noopener noreferrer"&gt;Git X-Modules app&lt;/a&gt; for Bitbucket installed, install it now. To do so,  go to &lt;code&gt;Administration | Find new apps | Search the Marketplace&lt;/code&gt; and type "X-Modules".&lt;br&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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.png" alt="07-install-x-modules-app|690x203" width="800" height="236"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now create a new Git repository and name it 'checksum-project'.&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%2Fuploads%2Farticles%2Ffoghcnbp24bwec2959e1.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%2Fuploads%2Farticles%2Ffoghcnbp24bwec2959e1.png" alt="08-create-checksum-project-repository|449x500" width="612" height="681"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once the Git X-Modules app is installed, there will be an X-Modules button on the Git repository page. Click it.&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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.png" alt="09-x-modules-button|690x181" width="795" height="209"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As the repository is empty, click "Create Default Branch".&lt;br&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%2Fuploads%2Farticles%2Fcjl5ybyp8ilr9bki9v06.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%2Fuploads%2Farticles%2Fcjl5ybyp8ilr9bki9v06.png" alt="10-x-modules-create-default-branch|690x285" width="800" height="331"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then click "Add Module" to add the 'sha-1' library.&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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.png" alt="11-x-modules-add-first-module|690x275" width="800" height="319"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Choose the 'sha-1' repository.&lt;br&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%2Fuploads%2Farticles%2F5eetkiwy0cekls9q9tau.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%2Fuploads%2Farticles%2F5eetkiwy0cekls9q9tau.png" alt="12-x-modules-choose-sha-1-repository|690x426" width="800" height="494"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Choose the 'master' branch in the 'sha-1' repository.&lt;br&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%2Fuploads%2Farticles%2Ffebm96jowgcs9xt5rlye.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%2Fuploads%2Farticles%2Ffebm96jowgcs9xt5rlye.png" alt="13-x-modules-choose-sha-1-branch|690x420" width="800" height="487"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Make sure the 'sha-1' module is inserted into 'libs/sha-1' so "This Repository Path" should be 'libs/sha-1'.&lt;br&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%2Fuploads%2Farticles%2Fq75sg4q9fh3gv3x5onzp.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%2Fuploads%2Farticles%2Fq75sg4q9fh3gv3x5onzp.png" alt="14-x-modules-choose-sha-1-module-path|690x452" width="800" height="524"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Click "Add Module". Do not "Apply Changes" yet.&lt;/p&gt;

&lt;p&gt;Now add another module to add 'checksum' app to our multi-module structure. To do that click 'Add Module' again:&lt;br&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%2Fuploads%2Farticles%2Ffzn8ykga27wwzfn6x9pn.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%2Fuploads%2Farticles%2Ffzn8ykga27wwzfn6x9pn.png" alt="15-x-modules-add-second-module|690x428" width="800" height="496"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then choose the 'checksum' repository.&lt;br&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%2Fuploads%2Farticles%2Fqxocldu2t03r7fy5lnoz.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%2Fuploads%2Farticles%2Fqxocldu2t03r7fy5lnoz.png" alt="16-x-modules-choose-checksum-repository|690x462" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose the 'master' branch in it.&lt;br&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%2Fuploads%2Farticles%2Fzoy8ev2yngfslk93137o.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%2Fuploads%2Farticles%2Fzoy8ev2yngfslk93137o.png" alt="17-x-modules-choose-checksum-branch|690x425" width="800" height="493"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Make sure the 'checksum' repository is inserted into the 'checksum' directory, so "This Repository Path" should be 'checksum'. The directory name is arbitrary (as well as "libs/sha-1"), we will specify it later in &lt;code&gt;add_subdirectory()&lt;/code&gt; call.&lt;br&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%2Fuploads%2Farticles%2Fepyjny517bttt1ch69z4.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%2Fuploads%2Farticles%2Fepyjny517bttt1ch69z4.png" alt="18-x-modules-choose-checksum-module-path|690x460" width="800" height="533"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Click 'Add Module'&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%2Fuploads%2Farticles%2Fvvtup8fonht9j1tz4ddj.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%2Fuploads%2Farticles%2Fvvtup8fonht9j1tz4ddj.png" alt="19-x-modules-apply-changes|690x460" width="800" height="533"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Apply the changes.&lt;/p&gt;

&lt;p&gt;Now 'checksum-project' repository contains 2 directories: 'checksum' with 'checksum' module and 'libs/sha-1' with 'sha-1' library. They are inserted into 'checksum-project' as normal directories in Git.&lt;br&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%2Fuploads%2Farticles%2Fhw4hvspo5xwn1wcnkvql.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%2Fuploads%2Farticles%2Fhw4hvspo5xwn1wcnkvql.png" alt="20-checksum-project-repository-toc|677x500" width="733" height="541"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5.&lt;/strong&gt; Create a multi-module CMake configuration in 'checksum-project'.&lt;/p&gt;

&lt;p&gt;Clone and 'cd' into the 'checksum-project':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone http://example.org/scm/checksum/checksum-project.git checksum-project/
cd checksum-project/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create CMakeLists.txt with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(checksum-project)

add_subdirectory(libs/sha-1)
add_subdirectory(checksum)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add CMakeLists.txt
git commit -m "CMakeLists.txt configuration added."
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all!&lt;/p&gt;

&lt;p&gt;The project can now be built without installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir build
cd build
cmake ..
make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ 25%] Building C object libs/sha-1/CMakeFiles/sha1.dir/sha1.c.o
[ 50%] Linking C static library libsha1.a
[ 50%] Built target sha1
[ 75%] Building C object checksum/CMakeFiles/checksum.dir/main.c.o
[100%] Linking C executable checksum
[100%] Built target checksum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's try our app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checksum/checksum foobar
8843d7f92416211de9ebb963ff4ce28125932878
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and compare it with standard 'sha1sum' utility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -n foobar | sha1sum
8843d7f92416211de9ebb963ff4ce28125932878  -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All sources are in the same repository as normal Git directories. Now one can modify 'libs/sha-1' and 'checksum/' inside the 'checksum-project' directly and these changes will be synchronized with corresponding 'sha-1' and 'checksum' repositories. And vice versa.&lt;br&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%2Fuploads%2Farticles%2For2vk2cgrphx6gvsxslq.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%2Fuploads%2Farticles%2For2vk2cgrphx6gvsxslq.png" alt="21-structure|600x395" width="600" height="395"&gt;&lt;/a&gt; &lt;br&gt;
Have fun!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>git</category>
      <category>submodules</category>
      <category>xmodules</category>
    </item>
    <item>
      <title>How to develop an Android library together with the apps using it</title>
      <dc:creator>Dmitry Linov</dc:creator>
      <pubDate>Wed, 02 Dec 2020 11:46:51 +0000</pubDate>
      <link>https://dev.to/optimalux/how-to-develop-an-android-library-together-with-the-apps-using-it-326j</link>
      <guid>https://dev.to/optimalux/how-to-develop-an-android-library-together-with-the-apps-using-it-326j</guid>
      <description>&lt;p&gt;Imagine that you are developing a taxi service like Uber, with two separate apps (one for passengers, another for drivers). However, they are might be using the same shared libraries (e.g. for network protocols or UI animation), and both teams need access to it. Did you know, that monorepo is not the only way to handle this?&lt;/p&gt;

&lt;p&gt;This post describes a way to organize sources of 2 Android apps ('&lt;strong&gt;app1&lt;/strong&gt;' and '&lt;strong&gt;app2&lt;/strong&gt;') using the same common library ('&lt;strong&gt;commonlib&lt;/strong&gt;'). The configuration will allow one to work on the library sources together with both apps. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do you need this?&lt;/strong&gt; &lt;br&gt;
A common approach would be to put the common library to the Maven and to use it as a binary dependency for each of the apps. This approach makes it difficult to quickly test changes in the library code: to do that one has to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fix the 'commonlib',&lt;/li&gt;
&lt;li&gt;build and upload changes to the Maven (often this is done by CI and involves runnings tests),&lt;/li&gt;
&lt;li&gt;obtain the updated artifact from the 'app1' or 'app2' project, &lt;/li&gt;
&lt;li&gt; and, finally, build and re-run the app to see what's different now.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the changes do not work as intended, one has to repeat.&lt;/p&gt;

&lt;p&gt;Another approach would be to put the 'commonlib', code into the same repository and project as 'app1' or 'app2'. With just one app that would have worked. But with two or more apps it would be an obvious code duplication and therefore not an option.&lt;/p&gt;

&lt;p&gt;Finally, there's the "monorepo" approach: put all code - ('app1', 'app2', and 'commonlib') into the same Git repository and manage it together. But, besides other well-known &lt;a href="https://medium.com/@mattklein123/monorepos-please-dont-e9a279be011b" rel="noopener noreferrer"&gt;drawbacks of the monorepo approach&lt;/a&gt;, it's the best practice to place all code components inside one project directory - yet the 'commonlib' can't be inside the same directory with 'app1' and 'app2' at the same time&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution sketch.&lt;/strong&gt; &lt;br&gt;
We will adopt a modification of the second approach because it's natural to the Android Studio. When you create an Android library in the Android Studio, it puts the library as another module into the same app project.&lt;/p&gt;

&lt;p&gt;Android app projects are usually built with Gradle. They are organized as Gradle projects containing Gradle modules. One of the modules is the app module itself, while libraries it uses could be added as separate modules (together with their sources if developed simultaneously with the app itself) or as binary Maven dependencies (and then one cannot change their sources on the fly).&lt;/p&gt;

&lt;p&gt;In our example, we will create 2 projects: 'app1' and 'app2'. Each of them would contain an app-related module (named 'app' by default) and a 'commonlib' module with the sources of the library. We just need to make sure that the 'commonlib' module of both 'app1' and 'app2' projects uses the same sources.&lt;/p&gt;

&lt;p&gt;A possible solution would be to put the 'commonlib' module into a separate Git repository and insert it as a Git &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules" rel="noopener noreferrer"&gt;submodule&lt;/a&gt; into the other two Git repositories: 'app1' and 'app2' (corresponding to Gradle projects with the same names). But you know...&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%2Fuploads%2Farticles%2F2tgmpy6r3qggunpxii0t.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%2Fuploads%2Farticles%2F2tgmpy6r3qggunpxii0t.png" alt="02-submodules-tweets|690x250" width="720" height="261"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Git submodules have &lt;a href="https://ayende.com/blog/4746/the-problem-with-git-submodules" rel="noopener noreferrer"&gt;too&lt;/a&gt; &lt;a href="https://codingkilledthecat.wordpress.com/2012/04/28/why-your-company-shouldnt-use-git-submodules/" rel="noopener noreferrer"&gt;many&lt;/a&gt; &lt;a href="https://medium.com/@uttamkini/sharing-code-and-why-git-submodules-is-a-bad-idea-1efd24eb645d" rel="noopener noreferrer"&gt;disadvantages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So we will use &lt;a href="https://tmatesoft.com/x-modules" rel="noopener noreferrer"&gt;Git X-Modules&lt;/a&gt; instead. This is a drop-in replacement for Git submodules,  working at the server's side. From the Git perspective, they are just regular directories.&lt;br&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%2Fuploads%2Farticles%2Ffdhpc3chovhokedxrnzw.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%2Fuploads%2Farticles%2Ffdhpc3chovhokedxrnzw.png" alt="29-structure|690x486" width="697" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure.&lt;/strong&gt; For the purpose of this post I will use Atlassian &lt;a href="https://www.atlassian.com/software/bitbucket/download" rel="noopener noreferrer"&gt;Bitbucket Server&lt;/a&gt;/&lt;a href="https://www.atlassian.com/enterprise/data-center/bitbucket" rel="noopener noreferrer"&gt;Data Center&lt;/a&gt; as Git server software. It's one of the most popular self-hosted Git solutions and Git X-Modules has a &lt;a href="https://marketplace.atlassian.com/apps/1223696/" rel="noopener noreferrer"&gt;dedicated app with a nice UI&lt;/a&gt; for it. Yet the same solution would also work for almost any other Git server software - there's a command-line version of it with the same capabilities, just without the GUI.&lt;/p&gt;

&lt;p&gt;I'm using Android Studio 4.4.1 and Gradle 6.7.1. Both are the latest versions to date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Create the 'app1' project.&lt;/p&gt;

&lt;p&gt;Create a new project, choose "Basic Activity" as the template.&lt;br&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%2Fuploads%2Farticles%2Fo8nakcjon3b0hatbldx7.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%2Fuploads%2Farticles%2Fo8nakcjon3b0hatbldx7.png" alt="01-choose-template|656x500" width="800" height="609"&gt;&lt;/a&gt; &lt;br&gt;
Choose the name of the app (App1), click Finish.&lt;br&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%2Fuploads%2Farticles%2Fsd7583fqnm6ab2brwk3r.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%2Fuploads%2Farticles%2Fsd7583fqnm6ab2brwk3r.png" alt="02-choose-app1-name|663x500" width="800" height="602"&gt;&lt;/a&gt; &lt;br&gt;
Run the project to make sure everything works smoothly.&lt;br&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%2Fuploads%2Farticles%2Fe2d26a54ox6g2vih08dq.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%2Fuploads%2Farticles%2Fe2d26a54ox6g2vih08dq.png" alt="03-make-sure-app1-can-be-built|690x461" width="800" height="534"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; Create the 'commonlib' library.&lt;/p&gt;

&lt;p&gt;Choose &lt;code&gt;File | New | New Module...&lt;/code&gt;&lt;br&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%2Fuploads%2Farticles%2F7vebdrt46c2r45d0kqs8.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%2Fuploads%2Farticles%2F7vebdrt46c2r45d0kqs8.png" alt="04-create-new-module|465x499" width="720" height="773"&gt;&lt;/a&gt; &lt;br&gt;
Choose "Android library" as the module type.&lt;br&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%2Fuploads%2Farticles%2Fy7eec22s0hp1mp9z3o3s.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%2Fuploads%2Farticles%2Fy7eec22s0hp1mp9z3o3s.png" alt="05-choose-module-type-library|663x500" width="800" height="603"&gt;&lt;/a&gt; &lt;br&gt;
Choose the module name: 'commonlib'.&lt;br&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%2Fuploads%2Farticles%2Fe587xf5wofb4zcx9s3v3.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%2Fuploads%2Farticles%2Fe587xf5wofb4zcx9s3v3.png" alt="06-choose-commonlib-name|664x500" width="800" height="602"&gt;&lt;/a&gt; &lt;br&gt;
Create CommonLib class in the 'commonlib' module with a method.&lt;br&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%2Fuploads%2Farticles%2F8w7yk31ato8je9fj8fxf.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%2Fuploads%2Farticles%2F8w7yk31ato8je9fj8fxf.png" alt="07-create-commonlib-class|616x500" width="800" height="649"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Add a dependency for the default ('app') module on the 'commonlib' module and use the method in the application.&lt;br&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%2Fuploads%2Farticles%2Faozd6j4jb0mmth1rhbdn.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%2Fuploads%2Farticles%2Faozd6j4jb0mmth1rhbdn.png" alt="08-use-commonlib-in-app1|689x396" width="800" height="459"&gt;&lt;/a&gt; &lt;br&gt;
Run the application to make sure everything works smoothly.&lt;br&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%2Fuploads%2Farticles%2F1u50cppjbi40ntdrcaqa.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%2Fuploads%2Farticles%2F1u50cppjbi40ntdrcaqa.png" alt="09-app1-with-commonlib-emulator|235x500" width="406" height="863"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Create 'app1' and 'commonlib' Git repositories.&lt;/p&gt;

&lt;p&gt;The 'App1' project now has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── app
├── build.gradle
├── commonlib     &amp;lt;--- this should go to commonlib.git
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create the 'commonlib' Git repository and put the 'commonlib' subdirectory there. All other files (except those that shouldn't be in Git at all) will go to the 'app1' Git repository. After that, the 'commonlib' repository will be inserted into the 'app1' Git repository.&lt;/p&gt;

&lt;p&gt;Create the 'commonlib' Git repository using the Atlassian Bitbucket Server/Data Center interface.&lt;br&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%2Fuploads%2Farticles%2Fo1al8l9wb9mnf2fss028.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%2Fuploads%2Farticles%2Fo1al8l9wb9mnf2fss028.png" alt="10-create-commonlib-repository|658x500" width="800" height="607"&gt;&lt;/a&gt; &lt;br&gt;
Copy the Git URL of this newly created repository, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://example.org/scm/android/commonlib.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simplest way to push 'commonlib' content (except the 'build' directory) to this Git repository is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd commonlib/
git init .
$ git add src
git add build.gradle 
git add consumer-rules.pro
git add proguard-rules.pro
git commit -m "Initial."
git push http://example.org/scm/android/commonlib.git master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fp081qjpd3i7s3angjhc1.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%2Fuploads%2Farticles%2Fp081qjpd3i7s3angjhc1.png" alt="11-commonlib-repository-toc|541x500" width="713" height="658"&gt;&lt;/a&gt; &lt;br&gt;
Now create the 'app1' Git repository with Atlassian Bitbucket Server/Data Center.&lt;br&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%2Fuploads%2Farticles%2Fz8h3mfmvvrpyc8mki9ly.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%2Fuploads%2Farticles%2Fz8h3mfmvvrpyc8mki9ly.png" alt="12-create-app1-repository|657x500" width="800" height="608"&gt;&lt;/a&gt; &lt;br&gt;
Suppose its URL is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://example.org/scm/android/app1.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put everything except &lt;code&gt;commonlib&lt;/code&gt;, &lt;code&gt;app/build&lt;/code&gt;, and &lt;code&gt;local.properties&lt;/code&gt; to this repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ..
git init .
git add app/build.gradle 
git add app/libs
git add app/proguard-rules.pro 
git add app/src
git add gradle
git add gradlew
git add gradlew.bat 
git add gradle.properties 
git add build.gradle
git add settings.gradle 
git commit -m "Initial."
git push http://example.org/scm/android/app1.git master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fuploads%2Farticles%2Fq2e2xi10roqykfpogc0n.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%2Fuploads%2Farticles%2Fq2e2xi10roqykfpogc0n.png" alt="13-app1-repository-toc|512x500" width="800" height="780"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4.&lt;/strong&gt; Insert 'commonlib' into the 'app1' repository.&lt;/p&gt;

&lt;p&gt;We will be using  &lt;a href="https://tmatesoft.com/x-modules" rel="noopener noreferrer"&gt;Git X-Modules&lt;/a&gt;. It inserts one repository into another on the server's side as Git trees. So, for the Git client, the module will be just a part of a regular Git tree.&lt;/p&gt;

&lt;p&gt;If you don't have the Git X-Modules app installed, go to &lt;code&gt;Administration | Find new apps | Search the Marketplace&lt;/code&gt; and type "X-Modules" in the Bitbucket Server/Data Center UI to install this app.&lt;br&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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.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%2Fuploads%2Farticles%2Fptnvd0vay6ip9brchm4s.png" alt="07-install-x-modules-app|690x203" width="800" height="236"&gt;&lt;/a&gt; &lt;br&gt;
Now go to the 'app1' Git repository page. Click the "Git X-Modules" button on the sidebar. &lt;br&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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.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%2Fuploads%2Farticles%2F7yj0jfu79gfxxj9t39f4.png" alt="09-x-modules-button|690x181" width="795" height="209"&gt;&lt;/a&gt; &lt;br&gt;
Now click "Add Module" to add 'commonlib' to the project.&lt;br&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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.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%2Fuploads%2Farticles%2F1tn6p976ub7474203zlr.png" alt="11-x-modules-add-first-module|690x275" width="800" height="319"&gt;&lt;/a&gt; &lt;br&gt;
Choose the 'commonlib' repository.&lt;br&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%2Fuploads%2Farticles%2Fjhwl28s9cdmwnvfiah5l.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%2Fuploads%2Farticles%2Fjhwl28s9cdmwnvfiah5l.png" alt="17-x-modules-choose-commonlib|606x500" width="800" height="659"&gt;&lt;/a&gt; &lt;br&gt;
And the 'master' branch.&lt;br&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%2Fuploads%2Farticles%2F0rjxeperkixutpd0whfi.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%2Fuploads%2Farticles%2F0rjxeperkixutpd0whfi.png" alt="18-x-modules-choose-master-branch|690x409" width="800" height="473"&gt;&lt;/a&gt; &lt;br&gt;
Make sure "This Repository Path" is 'commonlib'. It's the path in 'app1' where the 'commonlib' repository will be inserted.&lt;br&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%2Fuploads%2Farticles%2Fzhdnuk64d87jcdnakb3v.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%2Fuploads%2Farticles%2Fzhdnuk64d87jcdnakb3v.png" alt="19-x-modules-apply-changes|690x426" width="800" height="493"&gt;&lt;/a&gt; &lt;br&gt;
Click "Add Module" and apply changes. Now 'app1' Git repository has 'commonlib' directory with 'commonlib' Git repository inserted there.&lt;br&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%2Fuploads%2Farticles%2Fke7ikq9kopttldm508y4.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%2Fuploads%2Farticles%2Fke7ikq9kopttldm508y4.png" alt="19-app1-repository-toc|398x500" width="692" height="869"&gt;&lt;/a&gt; &lt;br&gt;
Now any team member can clone the 'app1' Git repository, create &lt;code&gt;local.properties&lt;/code&gt;, and build it with &lt;code&gt;./gradlew build&lt;/code&gt;. Alternatively one could add &lt;code&gt;local.properties.example&lt;/code&gt; into the repository to make it simpler to start working with the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5.&lt;/strong&gt; Create the 'app2' repository.&lt;/p&gt;

&lt;p&gt;In the same way as with 'App1', create the 'App2' application project.&lt;br&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%2Fuploads%2Farticles%2Fo8nakcjon3b0hatbldx7.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%2Fuploads%2Farticles%2Fo8nakcjon3b0hatbldx7.png" alt="01-choose-template|656x500" width="800" height="609"&gt;&lt;/a&gt; &lt;br&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%2Fuploads%2Farticles%2Fm0jn7747g118r99rfch6.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%2Fuploads%2Farticles%2Fm0jn7747g118r99rfch6.png" alt="21-choose-app2-name|656x500" width="800" height="609"&gt;&lt;/a&gt; &lt;br&gt;
Create the 'app2' Git repository using Bitbucket Server/Data Center UI.&lt;br&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%2Fuploads%2Farticles%2F6yi5mstpbk9q2a8057xv.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%2Fuploads%2Farticles%2F6yi5mstpbk9q2a8057xv.png" alt="22-create-app2-repository|658x500" width="800" height="607"&gt;&lt;/a&gt; &lt;br&gt;
Put 'App1' project content to the 'app1' Git repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd app2
git init .
git add app/
git add build.gradle
git add gradle/
git add gradle. properties
git add gradlew
git add gradlew.bat
git add settings.gradle
git add .gitignore
git commit -m "Initial."
git remote set-url origin http://example.org/scm/android/app1.git
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;http://example.org/scm/android/app2.git&lt;/code&gt; is the Git URL of the 'app2' repository.&lt;br&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%2Fuploads%2Farticles%2Fgngtgugmyj3j9cn32hmv.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%2Fuploads%2Farticles%2Fgngtgugmyj3j9cn32hmv.png" alt="22-app2-repository-toc|426x500" width="740" height="867"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6.&lt;/strong&gt; Insert 'commonlib' into the 'app2' repository using Git X-Modules.&lt;/p&gt;

&lt;p&gt;In a similar way, click the Git X-Modules button on the 'app2' repository page, add the 'commonlib' repository as X-Module to the 'commonlib' directory ("This repository path").&lt;br&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%2Fuploads%2Farticles%2F3b4p4yzsbbdcc2s79b2t.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%2Fuploads%2Farticles%2F3b4p4yzsbbdcc2s79b2t.png" alt="23-x-modules-app2-preview|690x462" width="800" height="535"&gt;&lt;/a&gt; &lt;br&gt;
Apply the changes.&lt;br&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%2Fuploads%2Farticles%2F1n09sbwmny1p0hajqybw.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%2Fuploads%2Farticles%2F1n09sbwmny1p0hajqybw.png" alt="23-x-modules-apply-changes|690x432" width="800" height="500"&gt;&lt;/a&gt; &lt;br&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%2Fuploads%2Farticles%2F98r6lbf9a7gy9jljoaue.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%2Fuploads%2Farticles%2F98r6lbf9a7gy9jljoaue.png" alt="23-app2-repository-toc|411x500" width="740" height="900"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7.&lt;/strong&gt; Add dependency for 'app2' on 'commonlib'.&lt;/p&gt;

&lt;p&gt;To fetch the changes, run from 'app2':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote set-url origin http://example.org/scm/android/app2.git
git pull --rebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;settings.gradle' to include ':commonlib' subdirectory.&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;br&gt;
include ':app'&lt;br&gt;
include ':commonlib'&lt;br&gt;
rootProject.name = "App2"&lt;br&gt;
&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;app/build.gradle&lt;/code&gt; to add:&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
   implementation project(path: ':commonlib')&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
to the dependencies list.&lt;br&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%2Fuploads%2Farticles%2Fiprheswlikj3ph04s8on.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%2Fuploads%2Farticles%2Fiprheswlikj3ph04s8on.png" alt="24-diff|690x460" width="800" height="533"&gt;&lt;/a&gt; &lt;br&gt;
Commit and push the changes:&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git add app/build.gradle&lt;br&gt;
git add settings.gradle&lt;br&gt;
git commit -m "Add dependency on 'commonlib'."&lt;br&gt;
git push origin master&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8.&lt;/strong&gt; Test using 'commonlib' in 'app2'.&lt;/p&gt;

&lt;p&gt;Change MainActivity in 'app2' to call &lt;code&gt;CommonLib.helloFromCommonLib()&lt;/code&gt;.&lt;br&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%2Fuploads%2Farticles%2F4lyje6e7lexo8m1s69ab.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%2Fuploads%2Farticles%2F4lyje6e7lexo8m1s69ab.png" alt="25-change-app2|690x313" width="800" height="363"&gt;&lt;/a&gt; &lt;br&gt;
Run the result in the emulator to see how it works.&lt;br&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%2Fuploads%2Farticles%2Fc37gybvq28u60c5045kd.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%2Fuploads%2Farticles%2Fc37gybvq28u60c5045kd.png" alt="26-changed-app2-emulator|233x500" width="404" height="864"&gt;&lt;/a&gt; &lt;br&gt;
Commit and push the changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 9.&lt;/strong&gt; Test changing 'commonlib'.&lt;/p&gt;

&lt;p&gt;Change 'commonlib' in the 'app2' repository,&lt;br&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%2Fuploads%2Farticles%2Ftgxy8yz177fve85m3mer.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%2Fuploads%2Farticles%2Ftgxy8yz177fve85m3mer.png" alt="27-update-commonlib|690x395" width="800" height="458"&gt;&lt;/a&gt; &lt;br&gt;
push the changes, get the changes in 'app1' and make sure it's updated.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
git commit -a -m "'commonlib' updated"&lt;br&gt;
git push origin master&lt;br&gt;
cd ..&lt;br&gt;
rm -rf app1&lt;br&gt;
git clone http://example.org/scm/android/app1.git app1/&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run 'app1' to make sure 'commonlib' is automatically updated.&lt;br&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%2Fuploads%2Farticles%2Fxvjh7ew136xp8i3hjlur.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%2Fuploads%2Farticles%2Fxvjh7ew136xp8i3hjlur.png" alt="28-updated-commonlib-app1-emulator|233x500" width="402" height="860"&gt;&lt;/a&gt; &lt;br&gt;
As you may see, the 'commonlib' is now automatically synchronized between both apps.&lt;/p&gt;

</description>
      <category>git</category>
      <category>android</category>
      <category>submodules</category>
      <category>xmodules</category>
    </item>
  </channel>
</rss>
