All Products
Search
Document Center

Alibaba Cloud Linux:Install and use Alibaba Cloud Compiler

Last Updated:Feb 28, 2024

Alibaba Cloud Compiler is a C++ compiler that is developed by Alibaba Cloud based on Clang/LLVM 13, which is an open source community version of Clang/LLVM. Alibaba Cloud Compiler inherits all options and parameters from Clang/LLVM 13, is deeply optimized for Alibaba Cloud infrastructure, and provides additional features to deliver better user experience. This topic describes how to install and use Alibaba Cloud Compiler on Alibaba Cloud Linux 3 to build high-performance C++ applications in a quick manner.

Background information

  • Compared with GNU Compiler Collection (GCC) and other Clang/LLVM versions, Alibaba Cloud Compiler provides significant improvements in pure compilation and build speed.

    • Different techniques, such as profile-guided optimization (PGO), are used in Alibaba Cloud Compiler to tune the Clang/LLVM compiler for faster compilation. Alibaba Cloud Compiler builds large-scale C++ code much faster than other compilers, such as GCC.

    • The Clang/LLVM linker (LLD) outperforms the GNU linker used by GCC, especially in processing large binary files.

    • Alibaba Cloud Compiler supports C++20 Modules and allows a standard C++ library to be modularized into a std module. Business code can be transformed by using the std module at a low cost to accelerate compilation.

  • Alibaba Cloud Compiler leverages technologies, such as Alibaba Cloud Compiler (LLVM) ThinLTO, AutoFDO, and CoreBolt, to improve program performance. Alibaba Cloud Compiler can run on different architectures, such as x86 and Arm64, and is tuned for YiTian 710 processors to attain additional performance gains.

  • Alibaba Cloud Compiler supports Coroutines and Modules and provides modularized standard libraries. Alibaba Cloud provides yaLanTingLibs that includes components commonly used by C++ developers, such as the coroutine library, serialization library, Remote Procedure Call (RPC) library, and HTTP feature.

    Note

    yaLanTingLibs is a collection of modern C++ utility libraries, including the truct_pack, struct_json, struct_xml, struct_yaml, struct_pb, easylog, coro_rpc, coro_io, coro_http, and async_simple libraries. yaLanTingLibs also includes high-performance, easy-to-use C++ utilities and can help C++ developers build modern, high-performance C++ applications.

Prerequisites

An Elastic Compute Service (ECS) instance that runs Alibaba Cloud Linux 3 is created. For information about how to create an ECS instance, see Create an instance on the Custom Launch tab.

Note

You can use Alibaba Cloud Compiler only on Alibaba Cloud Linux 3.

Install and use Alibaba Cloud Compiler

  1. Connect to the ECS instance on which you want to install Alibaba Cloud Compiler.

    For more information, see Connect to a Linux instance by using a password or key.

  2. Run the following command to install Alibaba Cloud Compiler:

    sudo yum install -y alibaba-cloud-compiler
  3. Run the following command to import environment variables:

    export PATH=/opt/alibaba-cloud-compiler/bin:$PATH
  4. Use Alibaba Cloud Compiler.

    Simple compilation example

    # The C++ program.
    cat hello.cpp
    #include <iostream>
    int main() {
      std::cout << "hello C++" << std::endl;
      return 0;
    }
    # Compile the preceding hello.cpp program.
    clang++ -O2 hello.cpp -o hello.cpp.out

    Use C++20 Coroutines and Modules to compile

    Alibaba Cloud Compiler supports C++20 Coroutines and Modules, which allow C++ developers to compile in a more efficient manner and improve compilation performance. For information about examples of coroutines, see the Use a standard C++ RPC library and Use a standard C++ HTTP library sections in this topic.

    Note
    • Coroutines are a programming concept that allows you to suspend function execution and then resume the execution at a later time. Traditionally, functions run to completion after the functions are called. Coroutines provide a more flexible control flow mechanism that simplifies asynchronous programming and generator pattern implementation.

    • In the traditional C++ programming paradigm, code is organized into header files (.h/.hpp) and source files (.cpp). To use the declarations that are made in a header file in a source file, use the #include preprocessor directive to insert a copy of the header file into the source file. Compilers may repeatedly parse the same header files due to this convention. As a result, compilation time increases. Modules are introduced as an approach to optimize code organization and increase compilation efficiency.

    When you use Clang to compile C++ programs, you can configure parameters. The following table describes the parameters.

    Parameter

    Description

    -std=

    Specifies the C++ language standard used for compilation. C++ Coroutines and Modules take effect if you set -std to c++20.

    --precompile

    Compiles module units into binary module interface (BMI) files.

    -fprebuilt-module-path

    Specifies the path in which to search for BMI files.

    -fstd-modules

    Specifies that files for std modules are compiled.

    -fmodules-export-all

    Marks all declarations in the current modules as export.

    -fmodules-export-macros

    Enables modules to export macros.

    -try-load-bmi-when-preprocessing

    Searches for BMI files during preprocessing.

    -fstd-module-path

    Specifies the path in which to search for std modules.

    -fcoro-aligned-allocation

    Prefers aligned allocation for C++ Coroutines.

    Compilation example:

    # The Modules code.
    cat Hello.cppm
    module;
    #include <iostream>
    export module Hello;
    export void hello() {
      std::cout << "Hello World!\n";
    }
    cat use.cpp
    import Hello;
    int main() {
      hello();
      return 0;
    }
    # Compile the preceding sample Modules code.
    clang++ -std=c++20 Hello.cppm --precompile -o Hello.pcm
    clang++ -std=c++20 use.cpp -fprebuilt-module-path=. Hello.pcm -o Hello.out
    ./Hello.out
    Hello World!

(Optional) Use yaLanTingLibs

You can use yaLanTingLibs, which is a collection of standard C++ libraries that provide the coroutine library, serialization library, RPC library, and HTTP feature based on C++20 Coroutines and the C++ template metaprogramming feature. For more information about yaLanTingLibs, see yalantinglibs and async_simple.

  • The serialization library is a software library used to serialize and deserialize data. Serialization is the process of converting a data structure or object status into a form that can be stored in files or buffers or transmitted over networks. Deserialization is the process in which data is restructured from its serialized form into the original data structure or object status.

  • RPC is a library that is used for interprocess communication (IPC). RPC allows C++ programs to execute functions or methods that reside on a remote machine as if the functions or methods were local. RPC abstracts away from details, such as network transmission, serialization, deserialization, and routes, and allows developers to focus on the business logic of their applications.

  • HTTP is an application-layer protocol for distributed, collaborative, hypermedia information systems. coro_http is a high-performance, easy-to-use HTTP library that uses C++20 Coroutines to implement an HTTP server and client. coro_http can help you quickly develop HTTP applications.

  1. Run the following command to install yaLanTingLibs:

    sudo yum install -y yalantinglibs-devel
  2. Use the serialization library, RPC library, and HTTP library of yaLanTingLibs.

    Use the serialization library

    1. Create a code file named test.cpp that includes the following code snippet:

      #include <iostream>
      #include "ylt/struct_pack.hpp"
      struct person {
        int age;
        std::string name;
      };
      
      int main() {
        person tom{.age=20,.name="tom"};
        auto buffer = struct_pack::serialize(tom);
        auto tom2 = struct_pack::deserialize<person>(buffer);
        std::cout<<"age: "<<tom2.value().age<<", name: "<<tom2.value().name<<std::endl;
        return 0;
      }

      The preceding code snippet serializes and deserializes the person data structure.

    2. Run the following command to compile the program:

      clang++ test.cpp -std=c++20 -o test
    3. Run the following command to run the program:

      ./test

      The following output is returned:

      age: 20, name: tom

    Use the RPC library

    1. Create a code file named server.cpp that includes the following code snippet on a server:

      #include "ylt/coro_rpc/coro_rpc_server.hpp"
      std::string ping(std::string ping) {
       return "Receive: " + ping + ". Return pong.";
      }
      int main() {
       coro_rpc::coro_rpc_server server{1 , 8801};
       server.register_handler<ping>();
       return server.start();
      }

      The preceding code snippet starts an RPC server named coro_rpc that continuously runs on the server. The RPC server listens to RPC requests on port 8801 and registers the ping function that is used to respond to RPCs.

    2. Create a code file named client.cpp that includes the following code snippet on a client:

      #include <iostream>
      #include "ylt/coro_rpc/coro_rpc_client.hpp" 
      std::string ping(std::string);
      async_simple::coro::Lazy<void> example(){
          coro_rpc::coro_rpc_client client;
          auto ec = co_await client.connect("localhost","8801");
          assert(!ec);
          auto ret = co_await client.call<ping>("ping");
          std::cout << ret.value() << std::endl;
          co_return;
      };
      int main(){
          async_simple::coro::syncAwait(example());
          return 0;
      }

      The preceding code snippet starts an RPC client that is used to connect to the RPC sever, call the ping function, and display the function outputs.

    3. Run the following command to compile the server-side program:

      clang++ server.cpp  -I /usr/include/ylt/thirdparty -std=c++20  -o server -lpthread
    4. Run the following command to compile the client-side program.

      Note

      Before you compile the client-side program, make sure that Alibaba Cloud Compiler is installed on the client and environment variables are imported to the client. For more information, see the Install and use Alibaba Cloud Compiler section in this topic.

      clang++ client.cpp  -I /usr/include/ylt/thirdparty -std=c++20  -o client -lpthread
    5. Run the following command on the server and the client to start the RPC server and client:

      ./server & ./client

      The following log entries are returned by the server-side and client-side programs:

      2024-02-02 16:47:11.496 INFO     [11960] [coro_rpc_server.hpp:289] begin to listen
      2024-02-02 16:47:11.496 INFO     [11961] [coro_rpc_client.hpp:412] client_id 0 begin to connect 8801
      2024-02-02 16:47:11.496 INFO     [11960] [coro_rpc_server.hpp:318] listen port 8801 successfully
      2024-02-02 16:47:11.497 INFO     [11967] [coro_rpc_server.hpp:348] new client conn_id 1 coming
      2024-02-02 16:47:11.497 INFO     [11967] [router.hpp:293] route function name: ping
      Receive: ping. Return pong.
      2024-02-02 16:47:11.497 INFO     [11968] [coro_rpc_client.hpp:356] client_id 0 close
      2024-02-02 16:47:11.497 INFO     [11967] [coro_connection.hpp:166] connection 1 close: End of file

      The preceding log entries describe the entire process from starting the RPC server, the RPC server listening to RPC requests, the RPC client sending RPC requests, the RPC server processing the RPC requests, to the RPC client closing the connection.

    Use the HTTP library

    1. Create a code file named http.cpp that includes the following code snippet:

      #include <iostream>
        
      #include "ylt/coro_http/coro_http_client.hpp"
      #include "ylt/coro_http/coro_http_server.hpp"
      
      using namespace std::chrono_literals;
      using namespace coro_http;
      
      async_simple::coro::Lazy<void> basic_usage() {
        coro_http_server server(1, 9001);
        server.set_http_handler<GET>(
            "/get", [](coro_http_request &req, coro_http_response &resp) {
              resp.set_status_and_content(status_type::ok, "ok");
            });
      
        server.async_start();
        std::this_thread::sleep_for(300ms);
      
        coro_http_client client{};
        auto result = co_await client.async_get("http://127.0.0.1:9001/get");
        assert(result.status == 200);
        assert(result.resp_body == "ok");
        for (auto [key, val] : result.resp_headers) {
          std::cout << key << ": " << val << "\n";
        }
      }
      
      int main() {
        async_simple::coro::syncAwait(basic_usage());
      }

      The preceding code snippet starts an HTTP server and registers an HTTP GET service to listen to HTTP requests on port 9001. Then, the code creates an HTTP client to request the HTTP GET service and receive the data returned by the service.

    2. Run the following command to compile the HTTP program:

      clang++ http.cpp -I /usr/include/ylt/thirdparty -std=c++20 -o http -lpthread
    3. Run the following command to run the HTTP program:

      ./http

      The following log entries are returned by the program:

      2024-02-02 09:07:26.622 INFO [8098] [coro_http_server.hpp:444] begin to listen
      2024-02-02 09:07:26.622 INFO [8098] [coro_http_server.hpp:472] listen port 9001 successfully
      2024-02-02 09:07:26.923 DEBUG [8101] [coro_http_server.hpp:501] new connection comming, id: 1
      Server: cinatra
      Content-Length: 2
      Date: Fri, 02 Feb 2024 01:07:26 GMT
      2024-02-02 09:07:26.923 INFO [8103] [coro_http_server.hpp:37] coro_http_server will quit
      2024-02-02 09:07:26.923 INFO [8101] [coro_http_server.hpp:491] accept failed, error: Operation aborted.
      2024-02-02 09:07:26.923 INFO [8103] [coro_http_server.hpp:112] wait for server's thread-pool finish all work.
      2024-02-02 09:07:26.923 INFO [8103] [coro_http_server.hpp:115] server's thread-pool finished.
      2024-02-02 09:07:26.923 INFO [8103] [coro_http_server.hpp:117] stop coro_http_server ok