sentenz / convention

General articles, conventions, and guides.
https://sentenz.github.io/convention/
Apache License 2.0
4 stars 2 forks source link

Modify article `Build Systems` #293

Open sentenz opened 9 months ago

sentenz commented 9 months ago

Build Systems

A build system is a set of tools and processes designed to automate the compilation and assembly of source code into executable programs or libraries.

1. Category

1.1. CMake

  1. Layout and Structure

    • Project Layout

      CMake requires a CMakeLists.txt file in the root directory of the project. This file contains the project name. The CMakeLists.txt file can also include other CMakeLists.txt files in subdirectories with source files to build. Configuration and build options can be specified in the CMakePresets.json file.

      /bit
      ├── /src
      │   ├── bit.h
      │   ├── bit.c
      │   ├── bit_test.cc
      │   └── CMakeLists.txt
      │
      ├── CMakeLists.txt
      └── CMakePresets.json
  2. Commands and Operations

    • List Presets

      List all available presets.

      cmake --list-presets=all .
    • Configure Presets

      Configure the project using the specified preset.

      cmake --preset <configurePreset-name>
    • Build Presets

      Build the project using the specified preset.

      cmake --build --preset <buildPreset-name>
    • Execute Tests

      Execute the tests using the specified preset.

      ctest --preset <testPreset-name>
  3. Files and Folders

    • CMakeLists.txt

      Define the project name and language in CMakeLists.txt file.

      cmake_minimum_required(VERSION 3.23)
      
      # Specify project and language
      project(bit)
      
      # Build the test
      if(BIT_BUILD_TEST)
      enable_testing()
      
      # Create target for testing
      add_executable(${PROJECT_NAME}-test)
      
      # Add a test to the project to be run by `ctest()`
      add_test(NAME ${PROJECT_NAME}-test COMMAND ${PROJECT_NAME}-test)
      
      # External dependencies
      find_package(GTest CONFIG REQUIRED)
      
      # Link the static libraries to this target
      target_link_libraries(
        ${PROJECT_NAME}-test PRIVATE GTest::gtest GTest::gtest_main GTest::gmock
                                    GTest::gmock_main ${PROJECT_NAME})
      
      # Specify the required C++ standard for this target
      target_compile_features(${PROJECT_NAME}-test PUBLIC cxx_std_20)
      endif()
      
      # Add source directories
      add_subdirectory(src)
    • src/CMakeLists.txt

      Define the source files and target in src/CMakeLists.txt file.

      if(BIT_BUILD_TEST)
      target_sources(${PROJECT_NAME}-test PRIVATE bit.c bit_test.cc)
      endif()
    • CMakePresets.json

      Define the configuration and build presets in CMakePresets.json file.

      {
      "version": 6,
      "cmakeMinimumRequired": {
        "major": 3,
        "minor": 23,
        "patch": 0
      },
      "configurePresets": [
        {
          "name": "vcpkg",
          "displayName": "Dependency Manager",
          "description": "C++ Library Manager for Windows, Linux, and MacOS",
          "hidden": true,
          "environment": {
            "VCPKG_ROOT": "$env{HOME}/vcpkg"
          },
          "cacheVariables": {
            "VCPKG_INSTALLED_DIR": "${sourceDir}/external",
            "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
          }
        },
        {
          "name": "cache",
          "displayName": "Compiler Cache",
          "description": "Avoid recompilation for the same C and C++ object files by fetching result from a cache directory",
          "hidden": true,
          "cacheVariables": {
            "CMAKE_C_COMPILER_LAUNCHER": "ccache",
            "CMAKE_CXX_COMPILER_LAUNCHER": "ccache"
          }
        },
        {
          "name": "coverage",
          "displayName": "Coverage",
          "description": "Enable code coverage analysis using gcov",
          "hidden": true,
          "cacheVariables": {
            "CMAKE_C_FLAGS": "--coverage -O0",
            "CMAKE_CXX_FLAGS": "--coverage -O0"
          }
        },
        {
          "name": "sanitizer",
          "displayName": "Sanitizer",
          "description": "Enable sanitizer using AddressSanitizer (ASan) and UndefinedBehaviorSanitizer (UBSan)",
          "hidden": true,
          "cacheVariables": {
            "CMAKE_C_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer",
            "CMAKE_CXX_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer",
            "CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address,undefined",
            "CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address,undefined"
          }
        },
        {
          "name": "default",
          "displayName": "Default Configuration",
          "description": "Default configuration with Ninja generator",
          "hidden": true,
          "generator": "Ninja",
          "binaryDir": "${sourceDir}/build/${presetName}",
          "cacheVariables": {
            "CMAKE_C_COMPILER": "gcc",
            "CMAKE_CXX_COMPILER": "g++",
            "CMAKE_ARCHIVE_OUTPUT_DIRECTORY": "${sourceDir}/build/${presetName}/lib",
            "CMAKE_LIBRARY_OUTPUT_DIRECTORY": "${sourceDir}/build/${presetName}/lib",
            "CMAKE_RUNTIME_OUTPUT_DIRECTORY": "${sourceDir}/build/${presetName}/bin",
            "CMAKE_EXPORT_COMPILE_COMMANDS": true
          },
          "inherits": [
            "vcpkg",
            "cache"
          ]
        },
        {
          "name": "testing",
          "displayName": "Testing",
          "description": "Configuration with testing information",
          "cacheVariables": {
            "CMAKE_BUILD_TYPE": "Debug",
            "BIT_BUILD_TEST": true
          },
          "inherits": [
            "default",
            "coverage",
            "sanitizer"
          ]
        }
      ],
      "buildPresets": [
        {
          "name": "testing",
          "displayName": "Testing",
          "description": "Build GNU (Testing) using vcpkg",
          "configurePreset": "testing",
          "configuration": "Debug",
          "targets": [
            "bit-test"
          ]
        }
      ],
      "testPresets": [
        {
          "name": "testing",
          "displayName": "Testing",
          "description": "Test GNU (Testing) using vcpkg",
          "configurePreset": "testing",
          "configuration": "Debug"
        }
      ]
      }

1.1.1. Dependency Manager

Dependency manager is a tool that automates the process of installing, upgrading, configuring, and removing dependencies.

  1. Tools and Frameworks

    NOTE Refer dependency manager for details.

    • vcpkg

      C/C++ Package Manager for Windows, Linux, and MacOS.

    • conan

      C/C++ Package Manager for Windows, Linux, and MacOS.

  2. Files and Folders

    • CMakePresets.json

      Define the dependency manager in CMakePresets.json file. The vcpkg preset can be inherited by other presets.

      "configurePresets": [
      {
        "name": "vcpkg",
        "displayName": "Dependency Manager",
        "description": "C++ Library Manager for Windows, Linux, and MacOS",
        "hidden": true,
        "environment": {
          "VCPKG_ROOT": "$env{HOME}/vcpkg"
        },
        "cacheVariables": {
          "VCPKG_INSTALLED_DIR": "${sourceDir}/external",
          "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
        }
      }
      ]

1.1.2. Compiler Cache

Compiler cache is a tool that speeds up recompilation by caching previous compilations and detecting when the same compilation is being done again.

  1. Tools and Frameworks

    • ccache

      Compiler Cache for C and C++.

    • sccache

      Compiler Cache for C/C++, Rust with cloud storage support (AWS S3, Google Cloud Storage, Azure Blob Storage).

  2. Files and Folders

    • CMakePresets.json

      Define the cache variables in CMakePresets.json file. The cache preset can be inherited by other presets.

      "configurePresets": [
      {
        "name": "cache",
        "displayName": "Compiler Cache",
        "description": "Avoid recompilation for the same C and C++ object files by fetching result from a cache directory",
        "hidden": true,
        "cacheVariables": {
          "CMAKE_C_COMPILER_LAUNCHER": "ccache",
          "CMAKE_CXX_COMPILER_LAUNCHER": "ccache"
        }
      }
      ]

1.1.3. Sanitizer

Sanitizers are tools that help find memory errors, undefined behavior, and other problems in C and C++ source code.

  1. Tools and Frameworks

    NOTE Refer software analysis for details.

    • AddressSanitizer (ASan)

      A fast memory error detector. It finds out-of-bounds access to memory, use-after-free, and use-after-return bugs.

    • ThreadSanitizer (TSan)

      ThreadSanitizer (TSan) is a data race detector for C/C++. A data race occurs when two threads access the same variable concurrently and at least one of the accesses is write.

    • UndefinedBehaviorSanitizer (UBSan)

      UndefinedBehaviorSanitizer (UBSan) is a fast undefined behavior detector. It finds undefined behavior bugs in C and C++ programs.

    • MemorySanitizer (MSan)

      MemorySanitizer (MSan) is a detector of uninitialized reads. It finds uses of uninitialized values in C/C++ programs.

  2. Files and Folders

    • CMakePresets.json

      Define the sanitizer variables in CMakePresets.json file. The sanitizer preset can be inherited by other presets.

      "configurePresets": [
      {
        "name": "sanitizer",
        "displayName": "Sanitizer",
        "description": "Enable sanitizer using AddressSanitizer (ASan) and UndefinedBehaviorSanitizer (UBSan)",
        "hidden": true,
        "cacheVariables": {
          "CMAKE_C_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer",
          "CMAKE_CXX_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer",
          "CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address,undefined",
          "CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address,undefined"
        }
      }
      ]

1.1.4. Coverage

Coverage is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs.

  1. Tools and Frameworks

    NOTE Refer software metrics for details.

    • gcov

      A test coverage program for C and C++.

    • lcov

      A graphical front-end for GCC's coverage testing tool gcov.

    • gcovr

      A Python script that uses gcov to provide a utility for reporting code coverage information.

  2. Commands and Operations

    • Generate Coverage Report

      Generate the coverage report using gcovr and gcovr.cfg file.

      gcovr --xml-pretty --output "log/coverage/coverage.xml" --html="log/coverage/"
  3. Files and Folders

    • gcovr.cfg

      Define the coverage options in gcovr.cfg file.

      filter = src/
      
      exclude = .*/tests/.*
      exclude = .*/tools/.*
      exclude = .*Test.*
      exclude = .*test.*
      exclude-lines = .*assert.*
      exclude-unreachable-branches = yes
      exclude-throw-branches = yes
      
      print-summary = yes
      
      gcov-parallel = 20
      gcov-ignore-errors = all
      gcov-ignore-parse-errors = all
      
      html = yes
      html-title = Code Coverage Report
      html-details = yes  # info about each source file
      html-self-contained = yes
    • CMakePresets.json

      Define the coverage variables in CMakePresets.json file. The coverage preset can be inherited by other presets.

      "configurePresets": [
      {
        "name": "coverage",
        "displayName": "Coverage",
        "description": "Enable code coverage analysis using gcov",
        "hidden": true,
        "cacheVariables": {
          "CMAKE_C_FLAGS": "--coverage -O0",
          "CMAKE_CXX_FLAGS": "--coverage -O0"
        }
      }
      ]

1.1.5. Test Frameworks

Test frameworks are used to write and run unit tests.

  1. Tools and Frameworks

    NOTE Refer test frameworks for details.

    • Google Test

      Google's C++ testing and mocking framework.

    • CUnit

      A lightweight system for writing, administering, and running unit tests in C.

  2. Files and Folders

    • CMakeLists.txt

      The CMakeLists.txt file with test framework variables. The BUILD_TEST variable is used to enable the test framework.

      if(BUILD_TEST)
      enable_testing()
      
      # Create target for testing
      add_executable(${PROJECT_NAME}-test)
      
      # Add a test to the project to be run by `ctest()`
      add_test(NAME ${PROJECT_NAME}-test COMMAND ${PROJECT_NAME}-test)
      
      # External dependencies
      find_package(GTest CONFIG REQUIRED)
      
      # Link the static libraries to this target
      target_link_libraries(
        ${PROJECT_NAME}-test PRIVATE GTest::gtest GTest::gtest_main GTest::gmock
                                    GTest::gmock_main ${PROJECT_NAME})
      
      # Specify the required C++ standard for this target
      target_compile_features(${PROJECT_NAME}-test PUBLIC cxx_std_20)
      endif()
    • CMakePresets.json

      Define the test framework variables in CMakePresets.json file. The testing preset can inherit other presets, such as default, coverage, and sanitizer.

      "configurePresets": [
      {
        "name": "testing",
        "displayName": "Testing",
        "description": "Configuration with testing information",
        "cacheVariables": {
          "CMAKE_BUILD_TYPE": "Debug",
          "BUILD_TEST": true
        },
        "inherits": [
          "default",
          "coverage",
          "sanitizer"
        ]
      }
      ],
      "buildPresets": [
      {
        "name": "testing",
        "displayName": "Testing",
        "description": "Build GNU (Testing) using vcpkg",
        "configurePreset": "testing",
        "configuration": "Debug",
        "targets": [
          "bit-test"
        ]
      }
      ],
      "testPresets": [
      {
        "name": "testing",
        "displayName": "Testing",
        "description": "Test GNU (Testing) using vcpkg",
        "configurePreset": "testing",
        "configuration": "Debug"
      }
      ]

1.2. Ninja

Ninja is a build system designed for speed and simplicity. It's particularly efficient for large projects with numerous source files.

  1. Layout and Structure

    • Project Layout

      Ninja requires a build.ninja file in the root directory of the project. This file contains the build rules, dependencies, and build targets. The build.ninja file can also include other build.ninja files in subdirectories with source files to build.

      /bit
      ├── /src
      │   ├── main.c
      │   ├── bit.h
      │   └── bit.c
      │
      └── build.ninja
  2. Commands and Operations

    • Build Project

      Build the project. This command creates a build directory and generates the build artifacts in it.

      ninja
    • Parallel Builds

      Build the project in parallel using N threads. The default value of N is the number of CPU cores.

      ninja -j N
    • Clean Build Artifacts

      Clean the build artifacts. This command removes the build directory.

      ninja -t clean
  3. Files and Folders

    • build.ninja

      Define compilation rules, dependencies, and build targets in build.ninja file.

      # Variables
      CC = gcc
      CFLAGS = -Wall -Wextra -std=c17
      
      # Directories
      SRC_DIR = src
      BUILD_DIR = build
      OBJ_DIR = $(BUILD_DIR)/obj
      
      # Source files
      SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
      OBJ_FILES = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRC_FILES))
      
      # Targets
      TARGET = $(BUILD_DIR)/bit
      
      # Rule to compile object files
      rule compile
      command = $CC $CFLAGS -c $in -o $out
      description = CC $in
      
      # Rule to link the executable
      rule link
      command = $CC $in -o $out
      description = LINK $out
      
      # Build targets
      build: $(TARGET)
      
      $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
      compile
      
      $(TARGET): $(OBJ_FILES) | $(BUILD_DIR)
      link
      
      # Create build and obj directories
      $(BUILD_DIR) $(OBJ_DIR):
      mkdir -p $@
      
      # Clean rule
      clean:
      rm -rf $(BUILD_DIR)
      
      # Phony targets
      .PHONY: build clean

1.3. Makefile

A Makefile is a build automation tool used to compile and build projects.

  1. Layout and Structure

    • Project Layout

      Makefile requires a Makefile file in the root directory of the project. This file contains the build rules, dependencies, and build targets. The Makefile file can also include other Makefile files in subdirectories with source files to build.

      /bit
      ├── /src
      │   ├── main.c
      │   ├── bit.h
      │   └── bit.c
      │
      └── Makefile
  2. Commands and Operations

    • Build Project

      Build the project. This command creates a build directory and generates the build artifacts in it.

      make
    • Clean Build Artifacts

      Clean the build artifacts. This command removes the build directory.

      make clean
  3. Files and Folders

    • Makefile

      Define compilation rules, dependencies, and build targets in Makefile file.

      # Compiler and flags
      CC = gcc
      CFLAGS = -Wall -Wextra -std=c17
      
      # Directories
      SRC_DIR = src
      BUILD_DIR = build
      OBJ_DIR = $(BUILD_DIR)/obj
      
      # Source files
      SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
      OBJ_FILES = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRC_FILES))
      
      # Target executable
      TARGET = $(BUILD_DIR)/bit
      
      # Main target
      all: $(TARGET)
      
      # Rule to compile object files
      $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
        $(CC) $(CFLAGS) -c $< -o $@
      
      # Rule to link the executable
      $(TARGET): $(OBJ_FILES) | $(BUILD_DIR)
        $(CC) $(OBJ_FILES) -o $@
      
      # Create build and obj directories
      $(BUILD_DIR) $(OBJ_DIR):
        mkdir -p $@
      
      # Clean rule
      clean:
        rm -rf $(BUILD_DIR)
      
      # Phony targets
      .PHONY: all clean

1.4. Gradle

Gradle is a build system commonly used in Java and Android development. It offers a flexible and powerful build automation framework. Gradle uses a Groovy-based domain-specific language (DSL) to define the build scripts. It supports dependency management, task parallelization, and incremental builds.

  1. Layout and Structure

    • Project Layout

      Gradle requires a build.gradle file in the root directory of the project. This file contains the project configuration, dependencies, and build tasks. The build.gradle file can also include source code in the src/ directory with the main and test source files.

      MyProject/
      ├── build.gradle
      └── src/
        ├── main/
        │   └── java/
        │       └── com/
        │           └── example/
        │               └── MyApplication.java
        └── test/
            └── java/
                └── com/
                    └── example/
                        └── MyApplicationTest.java
  2. Files and Folders

    • build.gradle

      Define the project configuration, dependencies, and tasks in the build.gradle file.

      plugins {
        id 'java'
      }
      
      group 'com.example'
      version '1.0.0'
      
      repositories {
        mavenCentral()
      }
      
      dependencies {
        implementation 'com.google.guava:guava:30.1-jre'
        testImplementation 'junit:junit:4.13.2'
      }
      
      tasks.test {
        useJUnit()
      }
      
      task runApplication(type: JavaExec) {
        mainClassName = 'com.example.MyApplication'
        classpath = sourceSets.main.runtimeClasspath
      }
      • build.gradle: The Gradle build script file that defines the project configuration, dependencies, and tasks.
      • src/: The directory that contains the source code for the project.
      • main/: The directory for main source code.
        • java/: The directory for Java source files.
        • com/: The package structure for the project.
          • example/: The package for the project's classes.
          • MyApplication.java: The main Java class file for the project.
      • test/: The directory for test source code.
        • java/: The directory for Java test source files.
        • com/: The package structure for the test code.
          • example/: The package for the project's test classes.
          • MyApplicationTest.java: The Java test class file for the project.

1.5. Maven

Maven is a build automation and dependency management tool primarily used for Java projects. It emphasizes convention over configuration and follows the Project Object Model (POM) approach. Maven manages project dependencies, builds the project using predefined lifecycle phases, and provides plugins for various tasks.

  1. Layout and Structure

    • Project Layout

      Maven requires a pom.xml file in the root directory of the project. This file contains the project configuration, dependencies, and build settings. The pom.xml file can also include source code in the src/ directory with the main and test source files.

      /<project>
      ├── src/
      │   ├── main/
      │   │   └── java/
      │   │       └── com/
      │   │           └── example/
      │   │               └── MyApp.java
      │   └── test/
      │       └── java/
      │           └── com/
      │               └── example/
      │                   └── MyAppTest.java
      └── pom.xml
  2. Files and Folders

    • pom.xml

      Define the project configuration, dependencies, and build settings in the pom.xml file.

      <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example</groupId>
        <artifactId>MyProject</artifactId>
        <version>1.0.0</version>
      
        <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
      
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13.2</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
      
      </project>
      • src/: The directory that contains the source code for the project.
      • main/: The directory for main source code.
        • java/: The directory for Java source files.
        • com/: The package structure for the project.
          • example/: The package for the project's classes.
          • MyApp.java: The main Java class file for the project.
      • test/: The directory for test source code.
        • java/: The directory for Java test source files.
        • com/: The package structure for the test code.
          • example/: The package for the project's test classes.
          • MyAppTest.java: The Java test class file for the project.
      • pom.xml: The Project Object Model (POM) file that contains project configuration and dependencies.

1.6. Ant

Ant (Another Neat Tool) is a Java-based build system that uses XML-based build scripts. It provides a flexible and customizable approach to building, testing, and deploying applications.

  1. Layout and Structure

    • Project Layout

      Ant requires a build.xml file in the root directory of the project. This file contains the project configuration and build targets. The build.xml file can also include source code in the src/ directory with the main source files.

      MyProject/
      ├── build.xml
      └── src/
        └── com/
            └── example/
                └── MyApp.java
  2. Files and Folders

    • build.xml

      Define the project configuration and build targets in the build.xml file.

      <project name="MyProject" default="build">
      
        <!-- Define properties -->
        <property name="src.dir" value="src"/>
        <property name="build.dir" value="build"/>
        <property name="dist.dir" value="dist"/>
      
        <!-- Clean the build directory -->
        <target name="clean">
            <delete dir="${build.dir}"/>
            <delete dir="${dist.dir}"/>
        </target>
      
        <!-- Compile Java source files -->
        <target name="compile" depends="clean">
            <mkdir dir="${build.dir}"/>
            <javac srcdir="${src.dir}" destdir="${build.dir}"/>
        </target>
      
        <!-- Create a JAR file -->
        <target name="jar" depends="compile">
            <mkdir dir="${dist.dir}"/>
            <jar destfile="${dist.dir}/MyProject.jar" basedir="${build.dir}">
                <manifest>
                    <attribute name="Main-Class" value="com.example.MyApp"/>
                </manifest>
            </jar>
        </target>
      
        <!-- Default target -->
        <target name="build" depends="jar"/>
      
      </project>
      • build.xml: The Ant build script file that contains the project configuration and build targets.
      • src/: The directory that contains the source code for the project.
      • com/: The package structure for the project.
        • example/: The package for the project's classes.
        • MyApp.java: The Java source file for the project.

1.7. Bazel

Bazel is an open-source build system developed by Google. It focuses on scalability and supports large-scale projects with multiple programming languages. Bazel uses a declarative language to define build targets and dependencies. It provides caching, parallel execution, and incremental builds.

Bazel allows to customize the build configuration based on the project's specific requirements. It allows to define additional build targets, specify compiler flags, include additional libraries. Bazel's flexibility and extensibility provide the ability to create complex build configurations for large-scale projects.

  1. Layout and Structure

    • Project Layout

      Bazel requires a WORKSPACE file and BUILD files in the project directory structure. The WORKSPACE file defines the project and external dependencies, while the BUILD files specify build targets and dependencies.

      MyProject/
      ├── WORKSPACE
      ├── BUILD
      └── src/
        ├── main.cc
        └── BUILD
  2. Files and Folders

    • WORKSPACE

      The Bazel workspace file that defines the project and its external dependencies.

      workspace(name = "MyProject")
      
      # External dependency declarations
      load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
      
      http_archive(
        name = "googletest",
        url = "https://github.com/google/googletest/archive/refs/tags/release-1.11.0.zip",
        sha256 = "9be78e475e8e262ecf1a1a205ffe05db9e6a65b7003d6b2cccbc960c5e7ed23e",
        strip_prefix = "googletest-release-1.11.0",
      )

      In the example, we define a Bazel workspace named "MyProject" and declare an external dependency on Google Test (googletest). The http_archive rule is used to download and configure the external dependency.

    • BUILD

      The project-level Bazel build file that specifies build targets and dependencies.

      cc_binary(
        name = "myapp",
        srcs = ["main.cc"],
        deps = ["@googletest//:gtest_main"],
      )

      In the project-level BUILD file, we define a C++ binary target named "myapp" using the cc_binary rule. The srcs attribute specifies the source files, and the deps attribute declares the dependency on the Google Test framework.

    • src/BUILD

      The package-level Bazel build file that specifies build targets and dependencies for the src/ directory.

      cc_library(
        name = "mylib",
        srcs = ["main.cc"],
        hdrs = ["main.h"],
        visibility = ["//src:__pkg__"],
      )