How to Install the Solidity Compiler with npm?

In this article, we’ll sail through the installation of the solc-js, a variant of Solidity Compiler. As always, along with the main topic, there will be some other useful and supporting topics, so let’s stick together and make one more bold step forward 😉

As you watch the video or go through this tutorial, feel free to download the following slides as well — for your convenience:

Note that you can either read this tutorial as a stand-alone tutorial, or go through the whole crash course. This is Part 7 of our Solidity Crash Course:

🌍 Full Course Curriculum and Overview: Solidity Crash Course

Note that if you want to install the Solidity compiler via Docker on Ubuntu, check out this Finxter article instead (or in addition to the article you’re currently reading).

👉 If you want to find out more ways to install the Solidity compiler, check out our full guide on the Finxter blog.

Versioning

The official Solidity documentation informs us that Solidity follows a standard called Semantic versioning. In short, a semantic versioning summary helps us retain control over our projects by taking into account how we version our projects and dependencies.

Semantic versioning

I won’t go into detail on semantic versioning, as excellent information can be found in the original document. However, knowing that, for some readers, such technical documentation can be very dry material to read, I find it useful to hand-pick a few key terms and clarify them before we continue with the main topic.

When we engage ourselves in larger and older projects, it’s virtually inevitable we’ll come upon multiple versions of different parts of the system, such as libraries and other dependencies. Sadly, when parts of the system are not versioned properly, we’re likely to encounter a state of the project (and more often than not, a likewise state of mind) called dependency hell.

💡 Dependency hell is a combination of both or either one of the two possible states: version lock and version promiscuity.

  • Version lock is a term that describes a phenomenon of making the dependency specifications for a package too strict. The consequence of a version lock is “the inability to upgrade a package without having to release new versions of every dependent package”. In other words, the entire dependency hierarchy has to be rebuilt and re-released.
  • Version promiscuity is a term that describes the opposite phenomenon, of making the dependency specifications for a package too loose. In other words, when we as developers assume compatibility with more future versions than is reasonable, the reality proves us to be wrong, i.e. unexpected incompatibilities arise.

The authors of the Semantic Versioning specification (T. Preston-Werner and others) propose a solution to the dependency hell problem in the form of

“A simple set of rules and requirements that dictate how version numbers are assigned and incremented. These rules are based on but not necessarily limited to pre-existing widespread common practices in both closed and open-source software.”.

The official Semantic versioning documentation summarizes as follows (https://semver.org):

Given a version number MAJOR.MINOR.PATCH, increment the:

  • MAJOR version when you make incompatible API changes
  • MINOR version when you add functionality in a backward compatible manner
  • PATCH version when you make backward compatible bug fixes

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

By making a concise overview of what semantic versioning is, we’re continuing with the main topic in focus: the installation of the Solidity compiler.

🌍 Recommended Tutorial: Layout of a Solidity File

Solidity versioning details

It’s important to point out that Solidity patch-level releases with significant version number A, e.g. A.x.y never contain breaking modifications or improvements.

In other words, code that compiles with version A.x.y will always compile with A.x.z (with a condition z > y). When A = 0, it is considered a significant version for initial development, meaning that it is especially prone to changes.

The Solidity documentation additionally states that, besides releases, nightly development builds are also available. Nightly development builds enable developers to try out the upcoming features and provide early feedback to the Solidity developers, which is a great way for field testing. However, we should be aware that, regardless of the stability of the nightly builds, there is no guarantee that the code will always work.

💡 Note: nightly development builds should never be included in production use.

On that note, the contract deployment process should use the latest released version of Solidity, which, by definition regularly includes all the breaking changes, new features, and bug fixes.

Remix

Remix is an integrated development environment (IDE) for developing, deploying, and administering smart contracts for Ethereum-like blockchains.

It is also commonly used as a learning platform, such as in our article-following exercises.

Remix exists in three flavors, i.e. as a web application available online (https://remix.ethereum.org/), a desktop application (https://github.com/ethereum/remix-desktop/releases), or a live deployment (https://github.com/ethereum/remix-live/tree/gh-pages).

As Solidity authors say, “We recommend Remix for small contracts and for quickly learning Solidity.”

Regardless of the flavor, Remix is a convenient choice for testing nightly deployment builds of Solidity.

🌍 Recommended Tutorial: Solidity Crash Course

Solidity Compiler Software

In the following sections, we’ll walk through the installation of several local (offline) variants of Solidity command line compilers. The operating systems on which I will do the installations in the follow-up are Windows 10.0.19043.1889 and Ubuntu Linux 20.04.4 LTS.

Command line compilers are the best choice when we’re working on projects involving large contracts or when we need more compilation options besides those available in e.g. Remix.

solc-js – an npm / Node.js variant on Ubuntu

Before we use npm, a package manager for Node.js packages (modules), we have to check if it is already available by typing npm in the command line:

$ npm
Command 'npm' not found, but can be installed with:
sudo apt install npm

My Ubuntu environment currently doesn’t have npm installed, therefore I’ll go on and install it.

ℹ️ Info: Node.js is an asynchronous, event-driven JavaScript runtime (https://nodejs.org/en/about/).

💡 Note: Have in mind that the output listed below has only a symbolic purpose, and it will probably look different in other environments:

$ sudo apt install npm
[sudo] password for matija: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
gyp libc-ares2 libjs-inherits libjs-is-typedarray libjs-psl 
# … (there is an exhaustive list of the packages to be installed, but I’ll leave out the remainder since it has no real value for us as readers)
Need to get 14,9 MB of archives.
After this operation, 76,0 MB of additional disk space will be used.
Do you want to continue? [Y/n] y

After the npm installation finishes, we may proceed and globally (-g) install solc-js.

sudo npm install -g solc

We have stepped into an area of technology that I haven’t mentioned previously, so I’ve compiled a few note/info blocks, just to introduce and clarify these new parts of the story for us.

💡 Note: Although the command mentions the solc compiler, what gets installed is the solc-js compiler (notice the “js” as in Javascript). Solc-js is a spinoff project of the C++ solc by using Emscripten, meaning that both solc and solc-js use the same compiler source code. However, solc-js can be used in JavaScript projects, e.g. Remix. The main downside of the solc-js is that it doesn’t utilize the solc compiler functionality in its entirety, i.e. solc-js compiler has fewer features than the solc compiler supports.

ℹ️ Info: “Emscripten is a complete compiler toolchain to WebAssembly, using LLVM, with a special focus on speed, size, and the Web platform.” (https://emscripten.org/). Emscripten enables us to compile projects written in C, C++, or any language that uses LLVM, to browsers, Node.js, or wasm (WebAssembly) runtime.

ℹ️ Info: “The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.” (https://llvm.org/). LLVM was originally an acronym for the low-level virtual machine. However, the project has grown beyond its original scope and only the name was kept.

ℹ️ Info: “WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.” (https://webassembly.org/). WebAssembly is low-level, assembly-like language code produced from the code we write in C/C++, C#, and Rust programming languages. WebAssembly is intended to be run in web browsers with near-native performance.

Sometimes we need to update Node.js, e.g. when we get a warning from npm during solc-js installation, saying that the node version is too low (a message mentioning v8.x, and ≥ v12 is required).

In that case, we may follow these steps and update Node.js:

Step 1: Clean the npm cache:

sudo npm cache clean -f

Step 2: Install n, Node’s version manager:

sudo npm install -g n

Step 3: Install the latest stable version:

sudo n stable

Step 4: Check the version of your Node.js installation:

node -v

If the command above still shows the old node version, make the system forget the remembered locations:

hash -r

ℹ️ Info: “Hash command in Linux system is the built-in command of bash which is used to maintain a hash table of recently executed programs.” (https://www.geeksforgeeks.org/hash-command-in-linux-with-examples/)

When you recheck the version of your Node.js installation, it should now show the latest stable version:

$ node -v
v16.17.0

Now that our node  (Node.js) version is up-to-date, we can check the installed version of solc-js:

$ solcjs --version
0.8.16+commit.07a7930e.Emscripten.clang

Our current solcjs version is listed above, and the check shows that we have installed the latest solcjs version (I’ve kept only the relevant columns in the output):

npm search solc | grep -w "solc"
NAME   | DATE       |VERSION | DESCRIPTION
solc   | 2022-08-08 | 0.8.16 | ethereum solidity compiler
…

This last step finishes our procedure of installing Solidity compiler solc-js.

The Conclusion

In this article, we have started a multi-article topic on using and installing the Solidity compiler.

🌍 Related Tutorials:

There are several approaches, of which we have investigated the one of installing the Solidity compiler via npm, a Node.js packet manager, solc-js.

First, we looked at what semantic versioning is, both from a general point of view and the point of view concerning Solidity. There is much more information on versioning available in other literature and online sources, but with our main topic in mind, there was no need to go any further at this point.

Second, we shortly revisited the topic of Remix: what it is, how it is used, and in what forms it is available for use.

Third, we dedicated a significant portion of our attention to the installation of Solidity compiler solc-js via npm,  a Node.js packet manager. Besides the main thought, we’ve also examined a possible problem with inadequate i.e. old version of Node.js and made a series of steps to rectify the problem and bring our system to an up-to-date state.