spot_img
HomeEducationCross-compiling Dart CLI purposes with Codemagic | Codemagic Weblog Acquire US

Cross-compiling Dart CLI purposes with Codemagic | Codemagic Weblog Acquire US

This text is written by Dmitry Zhifarsky

CLI stands for command-line interface, a text-based interface you need to use to enter instructions and carry out varied operations. For those who’ve ever used the dart or flutter instructions in your console, you’ve used a CLI.

Generally, although, you could find yourself writing a CLI of your personal.

Why write a CLI in Dart?

When may it is advisable to write a CLI? If you wish to statically analyze your code for potential points (like dart_code_metrics does), automate a few of your each day repeated actions (for instance, scaffolding a template, like very_good_cli does), or refactor a bunch of code without delay (which is named a codemod), writing a CLI is an efficient possibility to start out with.

You’d doubtless need it to work throughout a number of working programs, so it might be greatest to make use of a language that lets you compile your CLI for all of them with none issues. The Dart programming language can be a wonderful alternative for this case. So, on this article, we are going to clarify write a CLI in Dart and cross-compile it for varied platforms utilizing Codemagic.

Whereas Dart is usually used for writing Flutter apps, it’s a general-purpose language that you need to use to create different varieties of apps as properly. For instance, you need to use Dart to jot down back-end apps (utilizing packages like dart_frog or shelf) and CLI apps. VGV’s and DCM’s examples already show that Dart can and has been used to jot down superb (pun meant) CLIs.

Cross-compilation: Getting executables for all main platforms

At the moment, there are 3 ways to name a Dart CLI software from the console:

  • The primary is so as to add a package deal with the executable as a dependency to the goal package deal after which name dart run package_name:executable_name <args>. Whereas this can be a good possibility to start out with, once you name the CLI app this fashion, it should want a while to compile earlier than the execution. Relying on the capabilities of the system you run the code on, it would take tens of seconds simply to compile the executable.

  • The second possibility is to activate the package deal executable globally by way of dart pub international activate. This command wants compilation solely as soon as after the activation (and for every model replace) however requires extra consciousness of the package deal model you need to activate. It’s because, by default, it prompts the most recent model of the package deal accessible. So, for those who use a package deal this fashion in your CI/CD and the package deal has a more recent main model with a breaking change, it would break your pipeline. Additionally, the platform ought to have the Dart SDK accessible to activate and compile the package deal.

  • The third possibility is to supply a compiled executable by way of dart compile exe that may be downloaded and added to the PATH atmosphere straight or distributed by way of package deal managers like Homebrew, Chocolatey, or apt. Whereas this method takes extra time to arrange, compiling the package deal this fashion affords higher efficiency in contrast with different choices.

The issue is that Dart doesn’t support cross-compilation itself, that means that the executable you get after calling dart compile exe can solely be run on the identical platform you compile it on. That’s why we want 4 totally different platforms to compile our executable: Home windows, Linux, macOS Intel, and macOS Arm. However as an alternative of shopping for bodily units or organising a number of digital machines, we will use CI/CD platforms like Codemagic that present all of them whereas additionally integrating the compilation course of into our improvement circulate.

So, let’s see how we will configure Codemagic to compile our Dart CLI apps.

Codemagic configuration for Dart CLI apps

To finish this activity, we want a Codemagic account. For those who don’t have one, you may sign up here.

Sign up

We shall be utilizing the codemagic.yaml configuration.

Each codemagic.yaml file ought to begin with the workflows part. We’d like 4 workflows (one for every goal platform) to compile our executable.

workflows:
  compile-mac:
    
  compile-mac-m1:
    
  compile-windows:
    
  compile-linux:
    

Let’s take a more in-depth have a look at how the compile-mac workflow is outlined:

compile-mac:
    instance_type: mac_pro
    max_build_duration: 10
    atmosphere:
      flutter: steady

First, we have to set instance_type to mac_pro since we’re compiling for Intel Macs, restrict our construct time (to keep away from builds that take unexpectedly lengthy, burning the time for nothing) with max_build_duration, and arrange the atmosphere to have Flutter accessible. We don’t want Flutter itself, however we do require the dart executable to be accessible in order that we will later name dart compile exe.

Subsequent, let’s outline when the compilation occurs. Since we don’t must compile the executable on each push, let’s use tags as a set off for compilation.

compile-mac:
  
  triggering:
      occasions:
        - tag
      tag_patterns:
        - sample: "*"
          embrace: true
      cancel_previous_builds: true

We’ve added cancel_previous_builds, which permits us to cancel earlier builds if we push a brand new tag earlier than the compilation is accomplished, saving some construct time.

And that’s all we have to do to arrange the atmosphere.

Now, let’s check out the scripts part:

  scripts:
      - title: Set up dependencies
        script: dart pub get

      - title: Create goal listing
        script: mkdir macos

      - title: Compile executable
        script: dart compile exe <path_to_dart_file> -o macos/compiled_executable

Step one installs the dependencies for our app. Then we create a goal listing the place the compiled executable shall be positioned. The final step compiles the executable.

Be aware: When you’ve got a monorepository, simply working a dart pub get command received’t give you the results you want. To arrange dependency decision for monorepo, you need to use the very_good_cli package deal. Right here’s how the setup may look:

      - title: Set up Very Good CLI
        script: dart pub international activate very_good_cli

      - title: Set up dependencies
        script: very_good packages get -r

Final however not least, we’ll take care of artifacts. The artifacts part lets you obtain the compiled executable from a Codemagic construct web page.

Full workflow code:

  compile-mac:
    instance_type: mac_pro
    max_build_duration: 10
    atmosphere:
      flutter: steady
    triggering:
      occasions:
        - tag
      tag_patterns:
        - sample: "*"
          embrace: true
      cancel_previous_builds: true
    scripts:
      - title: Set up dependencies
        script: dart pub get

      - title: Create goal listing
        script: mkdir macos

      - title: Compile executable
        script: dart compile exe <path_to_dart_file> -o macos/compiled_executable

    artifacts:
      - macos/**

Publishing to GitHub Releases

By default, our executable recordsdata shall be accessible as a ZIP archive. However what if we need to have them revealed to a different platform, comparable to GitHub? Codemagic may help us with that as properly.

First, we have to add a GitHub token to our workflow atmosphere to have entry to GitHub Releases. To generate a token, go to and click on “Generate new token”. Be aware that the GitHub API presently helps solely basic tokens, so that you’ll must generate a basic token. Then sort the token title (Codemagic, for instance) and select the “repo” scope.

Cross-compiling Dart CLI purposes with Codemagic | Codemagic Weblog Acquire US Obtain US

After saving the token, copy its worth and open your Codemagic app atmosphere settings.

Cross-compiling Dart CLI purposes with Codemagic | Codemagic Weblog Acquire US Obtain US

Add a brand new atmosphere variable. Set the variable title to GITHUB_TOKEN, paste the token you copied earlier than within the “variable worth” subject, and choose (or create) a bunch. Then click on “add”.

After that, we have to replace the workflow atmosphere configuration:

   atmosphere:
      teams:
        - GitHub

Be aware: I exploit a bunch title right here as a extra handy approach to take care of variables.

Now, we have to arrange a publishing part in our codemagic.yaml file:

    publishing:
      scripts:
        - title: Publish to GitHub
          script: |
            #!/usr/bin/env zsh
            gh launch create -d "$CM_TAG" 
              --title "$CM_TAG" 
              macos/compiled_executable            

This script will create a brand new draft launch utilizing the tag knowledge with our executables connected as belongings.

Cross-compiling Dart CLI purposes with Codemagic | Codemagic Weblog Acquire US Obtain US
.

Full workflow code with publishing to GitHub Releases

workflows:
  compile-mac:
    instance_type: mac_pro
    max_build_duration: 10
    atmosphere:
      flutter: steady
      teams:
        - GitHub
    triggering:
      occasions:
        - tag
      tag_patterns:
        - sample: "*"
          embrace: true
      cancel_previous_builds: true

    scripts:
      - title: Set up dependencies
        script: dart pub get

      - title: Create goal listing
        script: mkdir macos

      - title: Compile executable
        script: dart compile exe <path_to_dart_file> -o macos/compiled_executable

    artifacts:
      - macos/**

    publishing:
      scripts:
        - title: Publish to GitHub
          script: |
            #!/usr/bin/env zsh
            gh launch create -d "$CM_TAG" 
              --title "$CM_TAG" 
              macos/compiled_executable            

This workflow builds our CLI as an executable for Intel-based Mac machines and publishes it to GitHub Releases. Just like how we have now created this workflow, we will add three extra workflows for Apple silicon Mac, Linux, and Home windows machines, respectively. You will discover the complete codemagic.yaml file with all of the workflows within the final part of this text.

Caveats (aka characteristic requests for the Codemagic dev group)

No approach to watch for the workflows to finish

Codemagic presently doesn’t help ready for the workflows to finish, that means that if in case you have arrange publishing to GitHub Releases and need to create a launch provided that all of the workflows have handed efficiently, you’ll want extra code to make it work. When you’ve got questions, you may be part of this dialogue:

No help for matrixes

Matrixes are one other helpful characteristic in relation to writing workflows for a number of platforms when a number of steps are repeated. With out them, the configuration file may get too bloated with the copied steps. Codemagic doesn’t but have help for matrixes. Nevertheless, this doesn’t stop us from constructing the pipeline — it simply makes the YAML file longer.

Conclusion

When you’ve got adopted the steps on this article, you now know construct a Codemagic pipeline to cross-compile your CLI in Dart for all the most important platforms it might be wanted on.

As a creator of 1 such CLI you could even use, Dart Code Metrics, I encourage you to experiment and construct one thing of your personal. And for those who discover it useful, don’t hesitate to share it with the group to assist others who encounter related issues.


Dmitry Zhifarsky is a passionate software program engineer specializing in varied front-end frameworks, in addition to Dart and Flutter. He’s additionally the co-creator of DCM. You will discover him on Twitter, GitHub, or deeply immersed in VS Code. Don’t disturb him if it’s the latter.

Full codemagic.yaml instance

workflows:
  compile-mac: &base_workflow
    instance_type: mac_pro
    max_build_duration: 10
    atmosphere: &base_environment
      flutter: steady
      teams:
        - GitHub
      vars: &base_vars
        DART_FILE_PATH: "my/dart/file" # Enter the trail to your dart file  
        TARGET_DIR: macos
        TARGET_FILE: compiled_executable
    triggering:
      occasions:
        - tag
      tag_patterns:
        - sample: "*"
          embrace: true
      cancel_previous_builds: true    
    scripts: &scripts
      - title: Set up dependencies
        script: dart pub get

      - title: Create goal listing
        script: mkdir $TARGET_DIR

      - title: Compile executable
        script: dart compile exe $DART_FILE_PATH -o $TARGET_DIR/$TARGET_FILE

    artifacts:
      - $TARGET_DIR/**
    publishing:
      scripts:
        - title: Publish to GitHub
          script: |
            #!/usr/bin/env zsh
            gh launch create -d "$CM_TAG" 
              --title "$CM_TAG" 
              $TARGET_DIR/$TARGET_FILE            

  compile-mac-m1:
    instance_type: mac_mini_m1
    <<: *base_workflow
    atmosphere:
      <<: *base_environment
      vars:
        TARGET_DIR: macos-m1
        <<: *base_vars
        

  compile-windows:
    instance_type: windows_x2
    <<: *base_workflow
    atmosphere:
      <<: *base_environment
      vars:
        TARGET_DIR: home windows
        TARGET_FILE: compiled_executable.exe
        <<: *base_vars

  compile-linux:
    instance_type: linux_x2
    <<: *base_workflow
    atmosphere:
      <<: *base_environment
      vars:
        TARGET_DIR: linux
        <<: *base_vars 


#Crosscompiling #Dart #CLI #purposes #Codemagic #Codemagic #Weblog

RELATED ARTICLES
Continue to the category

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -spot_img

Most Popular

Recent Comments