# Liscopelens: License Scope Lens

Liscopelens is a command-line tool for static analysis of open-source license compatibility. It helps developers identify and prevent potential license conflicts within their software projects, particularly C/C++ projects that use the `gn` build system.

## About The Project

Managing open-source licenses in a large project can be complex. Dependencies can introduce a web of different licenses, each with its own set of obligations and restrictions. A failure to ensure license compatibility can lead to legal risks and costly remediation efforts.

Liscopelens addresses this challenge by automating the process of license analysis. It analyzes a project's dependency graph, understands the licenses involved, and identifies conflicts based on a configurable knowledge base of license compatibility rules.

## How It Works

Liscopelens operates on a pipeline architecture, processing the project's dependency and license information in several stages:

1.  **Dependency Graph Construction**: The tool ingests a JSON dependency graph generated by the `gn` build system and constructs an in-memory representation of the project's structure using a graph library.
2.  **License Annotation**: It then parses a JSON report from `scancode-toolkit` to identify the licenses of all source files and dependencies, annotating the corresponding nodes in the dependency graph with this license information.
3.  **Obligation Propagation**: Liscopelens traverses the dependency graph from the bottom up. At each node, it calculates the combined license obligations inherited from its dependencies. The rules for this propagation (e.g., how copyleft licenses affect code linked statically vs. dynamically) are defined in configuration files.
4.  **Conflict Detection**: Finally, the tool checks each component for conflicts between its own license and the propagated obligations it has inherited. This check is performed against a comprehensive knowledge graph of license compatibility rules.

The final output is a `results.json` file that details every conflict found, allowing developers to trace the issue back to the specific files and dependencies that caused it.

## Getting Started

To use Liscopelens, you first need to generate the required input files from your project.

### Prerequisites

1.  **GN Dependency Graph**: A JSON file representing your project's dependency graph. You can generate this using the `gn` build system.
    ```sh
    gn gen out/Default --ide=json
    ```
    This will create a `project.json` in the `out/Default` directory.

2.  **Scancode License Report**: A JSON report of all licenses in your project, generated by `scancode-toolkit`.
    ```sh
    scancode -l -c -f json-pp --strip-root project/ > scancode-output.json
    ```

### Usage

Once you have the input files, you can run the main analysis command:

```sh
liscopelens clang \
    --gn path/to/your/project.json \
    --scancode path/to/your/scancode-output.json
```

## Input Files

Liscopelens requires two JSON files as input:

1.  **GN JSON (`--gn`)**: This file describes the dependency graph of your project. It contains information about targets, sources, and the relationships between them.
2.  **Scancode JSON (`--scancode`)**: This file contains the results of a license scan of your codebase. For each file, it lists the detected licenses and other related information.

## Output

The tool generates a `results.json` file in the working directory. This file contains a list of all license compatibility conflicts found during the analysis. For each conflict, the report includes:

*   The component (e.g., library, executable) where the conflict occurred.
*   The conflicting licenses involved.
*   A trace of the dependencies that propagated the conflicting license obligations.

This detailed report helps developers quickly identify the root cause of a license conflict and take corrective action.

## API Usage

Beyond the command line, you can use Liscopelens programmatically in your own Python scripts. This allows for integration into larger toolchains or custom analysis workflows.

The core logic for a specific analysis pipeline (like the `clang` command) is encapsulated in a `ParserEntry` class. You can import this class, provide it with the necessary arguments, and run the analysis directly.

Here is an example of how to run the `clang` analysis from a Python script:

```python
import argparse
from pathlib import Path
from liscopelens.parser.clang.entry import CParserEntry
from liscopelens.utils import load_config

# 1. Define the arguments required by the parser.
#    This mimics the command-line arguments.
args = argparse.Namespace(
    gn="path/to/your/project.json",
    scancode="path/to/your/scancode-output.json",
    # Add other necessary arguments as needed
)

# 2. Load the configuration.
#    You can load the default config or provide a path to a custom .toml file.
config = load_config()

# 3. Define the project path. This argument is not part of the parser-specific
#    args but is required by the .parse() method.
project_path = Path("/path/to/your/project_root").resolve()

# 4. Instantiate the parser entry and run the analysis.
#    The results will be written to 'results.json' in the current directory.
parser_instance = CParserEntry(args, config)
parser_instance.parse(project_path)

print("Analysis complete. Check results.json for the output.")

```

This approach gives you full control over the analysis process from within your Python code.

## License

This project is licensed under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for details.
