8000 Support the application of Conan's BuildEnv/RunEnv by hackenbergstefan · Pull Request #44 · afri-bit/vsconan · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Support the application of Conan's BuildEnv/RunEnv #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: 'Build & Test'

on:
push:

pull_request:
branches:
- main
Expand All @@ -18,6 +18,8 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '16.x'
- name: Install and setup conan
run: pip install conan && conan profile detect
- run: npm install
- run: npm run compile
- run: npm run test
- run: npm run test
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## 1.3.0 - unreleased

* [#36](https://github.com/afri-bit/vsconan/issues/36) Support the application of Conan's BuildEnv/RunEnv (Conan 2 only)

## 1.2.0 - 2024-08-03

### Added
Expand Down
20 changes: 19 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,22 @@ We use GitHub issues to track public bugs. Report a bug by [opening a new issue]
By contributing, you agree that your contributions will be licensed under its MIT License.

## References
This document was adapted from the open-source contribution guidelines for [Facebook's Draft]()
This document was adapted from the open-source contribution guidelines for [Facebook's Draft]()

## Setup

This repository follows the standard layout of a VS Code extension.
More information can be found [here](https://code.visualstudio.com/api/get-started/extension-anatomy).

### Tests

In addition to the standard setup for VS Code extension development [./test/conan/readEnv.test.ts](./test/conan/readEnv.test.ts) requires a proper Conan 2 installation.
This can be achieved e.g. by using a Python virtual environment:

```sh
python -m venv .venv
. .venv/bin/activate
# or on Windows
# .venv/Scripts/activate
pip install "conan>=2"
```
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,25 @@ The default configuration file can be seen as following. You can extend the list
}
```

#### Application of Conan's buildEnv/runEnv (currently Conan 2 only)

VSConan provides the commands

* `VSConan: Activate BuildEnv`
* `VSConan: Activate RunEnv`
* `VSConan: Deactivate BuildEnv/RunEnv`

to adjust VSCode's process and terminal environment to the respective Conan environment.

This is useful if you have tool dependencies in your Conanfile, e.g. CMake, a specific Compiler toolchain, etc and want to use these tools also in VSCode, e.g. the [CMake Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools).

##### A note if using the [Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) in parallel

The [Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) overrides the `PATH` environment variable to add the currently selected Python interpreter.
In order to use `PATH` modifications by Conan BuildEnv/RunEnv the VSConan extension provides the option to generate a `.env`-file which is respected by the Python extension.

This option is enabled by default and can be managed by `vsconan.conan.env.dotenv`.

### Additional Support Features

* `VSConan: Create Workspace Configuration (JSON)`
Expand Down
1 change: 1 addition & 0 deletions doc/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
* Add editable package
* Remove editable package
* Automatic selection of Python interpreter using the ms-python.python extension
* Application of Conan's buildEnv/runEnv

## General
* Define multiple conan profiles inside `settings.json` that you can use for the extension.
Expand Down
19 changes: 18 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vsconan",
"displayName": "VSConan",
"description": "Conan local cache and workspace manager.",
"version": "1.2.0",
"version": "1.3.0",
"publisher": "afri-bit",
"repository": {
"type": "git",
Expand Down Expand Up @@ -122,6 +122,18 @@
"command": "vsconan.conan.profile.switch",
"title": "VSConan: Switch Conan Profile"
},
{
"command": "vsconan.conan.buildenv",
"title": "VSConan: Activate BuildEnv"
},
{
"command": "vsconan.conan.runenv",
"title": "VSConan: Activate RunEnv"
},
{
"command": "vsconan.conan.deactivateenv",
"title": "VSConan: Deactivate BuildEnv/RunEnv"
},
{
"command": "vsconan.config.workspace.create",
"title": "VSConan: Create Workspace Configuration (JSON)"
Expand Down Expand Up @@ -786,6 +798,11 @@
"type": "string",
"default": "default",
"markdownDescription": "Conan profile default / selection"
},
"vsconan.conan.env.dotenv": {
"markdownDescription": "Manage `.env` file when activating Conan environments using `vsconan.conan.buildenv` or `vsconan.conan.runenv`. This is required if `ms-python.python` extension manages your terminal environment.",
"type": "boolean",
"default": true
}
}
},
Expand Down
88 changes: 88 additions & 0 deletions resources/print_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import argparse
import os
import sys

from conan.api import conan_api
from conan.api.output import ConanOutput
from conan.cli.args import common_graph_args, validate_common_graph_args
from conan.errors import ConanException
from conan.tools.env import VirtualBuildEnv, VirtualRunEnv


def print_env(conan_api, whichenv, args):
"""
Print requested environment.

More or less a copy of https://github.com/conan-io/conan/blob/917ce14b5e4d9e9c7bb78c47fc0ba785f690f8ac/conan/cli/commands/install.py#L43
"""
# basic paths
cwd = os.getcwd()
path = (
conan_api.local.get_conanfile_path(args.path, cwd, py=None)
if args.path
else None
)

# Basic collaborators: remotes, lockfile, profiles
remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []
overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None
lockfile = conan_api.lockfile.get_lockfile(
lockfile=args.lockfile,
conanfile_path=path,
cwd=cwd,
partial=args.lockfile_partial,
overrides=overrides,
)
profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)

# Graph computation (without installation of binaries)
gapi = conan_api.graph
deps_graph = gapi.load_graph_consumer(
path,
args.name,
args.version,
args.user,
args.channel,
profile_host,
profile_build,
lockfile,
remotes,
args.update,
# is_build_require=args.build_require,
)
gapi.analyze_binaries(
deps_graph, args.build, remotes, update=args.update, lockfile=lockfile
)
# print_graph_packages(deps_graph)
conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)

conanfile = deps_graph.root.conanfile

if whichenv == "BuildEnv":
env = VirtualBuildEnv(conanfile)
vars = env.vars(scope="build")
else:
env = VirtualRunEnv(conanfile)
vars = env.vars(scope="run")
return dict(vars.items())


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("whichenv", choices=("BuildEnv", "RunEnv"))
common_graph_args(parser)
args = parser.parse_args()
validate_common_graph_args(args)
if not args.path:
raise ConanException("Please specify a path to a conanfile")
args.no_remote = True

ConanOutput.define_log_level("quiet")
env = print_env(conan_api.ConanAPI(), args.whichenv, args)
env["PATH"] = os.pathsep.join(
(os.path.dirname(sys.executable), env.get("PATH", os.environ["PATH"]))
)

import json

print(json.dumps(env))
53 changes: 35 additions & 18 deletions src/conans/conan2/api/conanAPI.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { execSync } from "child_process";
import * as fs from "fs";
import * as vscode from 'vscode';
import { ConanAPI, ConanExecutionMode } from "../../api/base/conanAPI";
import { RecipeFolderOption } from "../../conan/api/conanAPI";
import { ConanPackage } from "../../model/conanPackage";
Expand Down Expand Up @@ -47,8 +48,9 @@ export class Conan2API extends ConanAPI {
}

public override getConanHomePath(): string | undefined {
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
try {
let homePath = execSync(`${this.conanExecutor} config home`).toString();
let homePath = execSync(`${this.conanExecutor} config home`, options).toString();
return homePath.trim(); // Remove whitespace and new lines
}
catch (err) {
Expand Down Expand Up @@ -81,13 +83,15 @@ export class Conan2API extends ConanAPI {
}

public override getRecipePath(recipe: string): string | undefined {
let recipePath = execSync(`${this.conanExecutor} cache path ${recipe}`).toString().trim();
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
let recipePath = execSync(`${this.conanExecutor} cache path ${recipe}`, options).toString().trim();

return recipePath;
}

public override getPackagePath(recipe: string, packageId: string): string | undefined {
let packagePath = execSync(`${this.conanExecutor} cache path ${recipe}:${packageId}`).toString().trim();
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
let packagePath = execSync(`${this.conanExecutor} cache path ${recipe}:${packageId}`, options).toString().trim();

return packagePath;
}
Expand All @@ -96,7 +100,8 @@ export class Conan2API extends ConanAPI {
let listOfRecipes: Array<ConanRecipe> = [];

try {
let jsonStdout = execSync(`${this.conanExecutor} list *#* --format json`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
let jsonStdout = execSync(`${this.conanExecutor} list *#* --format json`, options);
let jsonObject = JSON.parse(jsonStdout.toString());

let localCache = jsonObject["Local Cache"];
Expand All @@ -118,7 +123,8 @@ export class Conan2API extends ConanAPI {
public override getProfiles(): string[] {

try {
let stdout = execSync(`${this.conanExecutor} profile list --format json`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
let stdout = execSync(`${this.conanExecutor} profile list --format json`, options);
let jsonObject = JSON.parse(stdout.toString());
return jsonObject;
}
Expand All @@ -133,7 +139,8 @@ export class Conan2API extends ConanAPI {

try {
if (recipe) {
let jsonStdout = execSync(`${this.conanExecutor} list ${recipe}:* --format json`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
let jsonStdout = execSync(`${this.conanExecutor} list ${recipe}:* --format json`, options);
let jsonObject = JSON.parse(jsonStdout.toString());

let recipeRevisionSplit = recipe.split("#");
Expand Down Expand Up @@ -202,11 +209,13 @@ export class Conan2API extends ConanAPI {
}

public override removePackage(recipe: string, packageId: string): void {
execSync(`${this.conanExecutor} remove ${recipe}:${packageId} -c`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remove ${recipe}:${packageId} -c`, options);
}

public override removeRecipe(recipe: string): void {
execSync(`${this.conanExecutor} remove ${recipe} -c`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remove ${recipe} -c`, options);
}

public override removeProfile(profile: string): void {
Expand All @@ -222,28 +231,33 @@ export class Conan2API extends ConanAPI {
}

public override addRemote(remote: string, url: string): void {
execSync(`${this.conanExecutor} remote add ${remote} ${url}`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remote add ${remote} ${url}`, options);
}

public override removeRemote(remote: string): void {
execSync(`${this.conanExecutor} remote remove ${remote}`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remote remove ${remote}`, options);
}

public override enableRemote(remote: string, enable: boolean): void {
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
if (enable) {
execSync(`${this.conanExecutor} remote enable ${remote}`);
execSync(`${this.conanExecutor} remote enable ${remote}`, options);
}
else {
execSync(`${this.conanExecutor} remote disable ${remote}`);
execSync(`${this.conanExecutor} remote disable ${remote}`, options);
}
}

public override renameRemote(remoteName: string, newName: string): void {
execSync(`${this.conanExecutor} remote rename ${remoteName} ${newName}`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remote rename ${remoteName} ${newName}`, options);
}

public override updateRemoteURL(remoteName: string, url: string): void {
execSync(`${this.conanExecutor} remote update ${remoteName} --url ${url}`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remote update ${remoteName} --url ${url}`, options);
}

public override renameProfile(oldProfileName: string, newProfileName: string): void {
Expand Down Expand Up @@ -324,7 +338,8 @@ export class Conan2API extends ConanAPI {

try {
if (recipe && packageId) {
let jsonStdout = execSync(`${this.conanExecutor} list ${recipe}:${packageId}#* --format json`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
let jsonStdout = execSync(`${this.conanExecutor} list ${recipe}:${packageId}#* --format json`, options);
let jsonObject = JSON.parse(jsonStdout.toString());

let recipeRevisionSplit = recipe.split("#");
Expand Down Expand Up @@ -356,7 +371,8 @@ export class Conan2API extends ConanAPI {
let packageRevisionPath: string | undefined = undefined;

try {
packageRevisionPath = execSync(`${this.conanExecutor} cache path ${recipe}:${packageId}#${revisionId}`).toString().trim();
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
packageRevisionPath = execSync(`${this.conanExecutor} cache path ${recipe}:${packageId}#${revisionId}`, options).toString().trim();
}
catch (err) {
console.log((err as Error).message);
Expand All @@ -366,6 +382,7 @@ export class Conan2API extends ConanAPI {
}

public removePackageRevision(recipe: string, packageId: string, revisionId: string): void {
execSync(`${this.conanExecutor} remove ${recipe}:${packageId}#${revisionId} -c`);
const options = { 'cwd': vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined };
execSync(`${this.conanExecutor} remove ${recipe}:${packageId}#${revisionId} -c`, options);
}
}
}
Loading
Loading
0