Skip to content
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

[fix] CONAN_TOOLCHAIN_ARGS_FILE as configuration file #9225

3 changes: 2 additions & 1 deletion conan/tools/__init__.py
@@ -1 +1,2 @@
CONAN_TOOLCHAIN_ARGS_FILE = "conanbuild.json"
CONAN_TOOLCHAIN_ARGS_FILE = "conanbuild.conf"
CONAN_TOOLCHAIN_ARGS_SECTION = "toolchain"
15 changes: 6 additions & 9 deletions conan/tools/cmake/cmake.py
@@ -1,9 +1,9 @@
import json
import os
import os
import platform

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools.cmake.utils import is_multi_configuration
from conan.tools.files import load_toolchain_args
from conan.tools.gnu.make import make_jobs_cmd_line_arg
from conan.tools.meson.meson import ninja_jobs_cmd_line_arg
from conan.tools.microsoft.msbuild import msbuild_verbosity_cmd_line_arg, \
Expand All @@ -12,7 +12,7 @@
from conans.client.tools.files import chdir
from conans.client.tools.oss import cpu_count, args_to_string
from conans.errors import ConanException
from conans.util.files import mkdir, load
from conans.util.files import mkdir


def _validate_recipe(conanfile):
Expand Down Expand Up @@ -66,13 +66,10 @@ def __init__(self, conanfile, parallel=True):
# Store a reference to useful data
self._conanfile = conanfile
self._parallel = parallel
self._generator = None

args_file = os.path.join(self._conanfile.generators_folder, CONAN_TOOLCHAIN_ARGS_FILE)
if os.path.exists(args_file):
json_args = json.loads(load(args_file))
self._generator = json_args.get("cmake_generator")
self._toolchain_file = json_args.get("cmake_toolchain_file")
toolchain_file_content = load_toolchain_args(self._conanfile.generators_folder)
self._generator = toolchain_file_content.get("cmake_generator")
self._toolchain_file = toolchain_file_content.get("cmake_toolchain_file")

self._cmake_program = "cmake" # Path to CMake should be handled by environment

Expand Down
5 changes: 2 additions & 3 deletions conan/tools/cmake/toolchain.py
@@ -1,4 +1,3 @@
import json
import os
import re
import textwrap
Expand All @@ -7,10 +6,10 @@
import six
from jinja2 import Template

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools._check_build_profile import check_using_build_profile
from conan.tools._compilers import architecture_flag, use_win_mingw
from conan.tools.cmake.utils import is_multi_configuration, get_file_name
from conan.tools.files import save_toolchain_args
from conan.tools.microsoft import VCVars
from conan.tools.microsoft.visual import vs_ide_version
from conans.errors import ConanException
Expand Down Expand Up @@ -741,7 +740,7 @@ def _writebuild(self, toolchain_file):
result["cmake_toolchain_file"] = toolchain_file or self.filename

if result:
save(CONAN_TOOLCHAIN_ARGS_FILE, json.dumps(result))
save_toolchain_args(result)

def _get_generator(self, recipe_generator):
# Returns the name of the generator to be used by CMake
Expand Down
2 changes: 1 addition & 1 deletion conan/tools/files/__init__.py
@@ -1,4 +1,4 @@
from conan.tools.files.files import load, save, mkdir, ftp_download, download, get, rename, \
load_build_json, save_build_json
load_toolchain_args, save_toolchain_args
from conan.tools.files.patches import patch, apply_conandata_patches
from conan.tools.files.cpp_package import CppPackage
47 changes: 37 additions & 10 deletions conan/tools/files/files.py
@@ -1,10 +1,10 @@
import configparser
import errno
import json
import os
import platform
import subprocess

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE, CONAN_TOOLCHAIN_ARGS_SECTION
from conans.client.downloaders.download import run_downloader
from conans.client.tools.files import unzip, which
from conans.errors import ConanException
Expand Down Expand Up @@ -185,13 +185,40 @@ def rename(conanfile, src, dst):
raise ConanException("rename {} to {} failed: {}".format(src, dst, err))


def load_build_json(conanfile):
path = os.path.join(conanfile.generators_folder, CONAN_TOOLCHAIN_ARGS_FILE)
contents = load(conanfile, path)
data = json.loads(contents)
return data
def load_toolchain_args(generators_folder=None):
"""
Helper function to load the content of any CONAN_TOOLCHAIN_ARGS_FILE

:param generators_folder: `str` folder where is located the CONAN_TOOLCHAIN_ARGS_FILE.
:return: <class 'configparser.SectionProxy'>
"""
args_file = os.path.join(generators_folder, CONAN_TOOLCHAIN_ARGS_FILE) if generators_folder \
else CONAN_TOOLCHAIN_ARGS_FILE
toolchain_config = configparser.ConfigParser()
toolchain_file = toolchain_config.read(args_file)
if not toolchain_file:
raise ConanException("The file %s does not exist. Please, make sure that it was not"
" generated in another folder." % args_file)
try:
return toolchain_config[CONAN_TOOLCHAIN_ARGS_SECTION]
except KeyError:
raise ConanException("The primary section [%s] does not exist in the file %s. Please, add it"
" as the default one of all your configuration variables." %
(CONAN_TOOLCHAIN_ARGS_SECTION, args_file))


def save_build_json(conanfile, contents):
path = os.path.join(conanfile.generators_folder, CONAN_TOOLCHAIN_ARGS_FILE)
save(conanfile, path, json.dumps(contents))
def save_toolchain_args(content, generators_folder=None):
"""
Helper function to save the content into the CONAN_TOOLCHAIN_ARGS_FILE

:param content: `dict` all the information to be saved into the toolchain file.
:param generators_folder: `str` folder where is located the CONAN_TOOLCHAIN_ARGS_FILE
"""
# Let's prune None values
content_ = {k: v for k, v in content.items() if v is not None}
args_file = os.path.join(generators_folder, CONAN_TOOLCHAIN_ARGS_FILE) if generators_folder \
else CONAN_TOOLCHAIN_ARGS_FILE
toolchain_config = configparser.ConfigParser()
toolchain_config[CONAN_TOOLCHAIN_ARGS_SECTION] = content_
with open(args_file, "w") as f:
toolchain_config.write(f)
16 changes: 4 additions & 12 deletions conan/tools/gnu/autotools.py
@@ -1,25 +1,17 @@
import json
import os
import platform

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools._compilers import use_win_mingw
from conan.tools.files import load_toolchain_args
from conan.tools.gnu.make import make_jobs_cmd_line_arg
from conan.tools.microsoft import unix_path
from conans.client.build import join_arguments
from conans.util.files import load


class Autotools(object):

def __init__(self, conanfile):
self._conanfile = conanfile

args_path = os.path.join(conanfile.generators_folder, CONAN_TOOLCHAIN_ARGS_FILE)
if os.path.isfile(args_path):
args = json.loads(load(args_path))
self._configure_args = args.get("configure_args")
self._make_args = args.get("make_args")
toolchain_file_content = load_toolchain_args(self._conanfile.generators_folder)
self._configure_args = toolchain_file_content.get("configure_args")
self._make_args = toolchain_file_content.get("make_args")

def configure(self):
"""
Expand Down
7 changes: 2 additions & 5 deletions conan/tools/gnu/autotoolstoolchain.py
@@ -1,13 +1,10 @@
import json

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools._check_build_profile import check_using_build_profile
from conan.tools._compilers import architecture_flag, build_type_flags, cppstd_flag
from conan.tools.apple.apple import apple_min_version_flag, to_apple_arch, \
apple_sdk_path
from conan.tools.cross_building import cross_building, get_cross_building_settings
from conan.tools.env import Environment
from conan.tools.files import save
from conan.tools.files import save_toolchain_args
from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
from conans.tools import args_to_string

Expand Down Expand Up @@ -168,4 +165,4 @@ def generate_args(self):
args = {"configure_args": args_to_string(configure_args),
"make_args": args_to_string(self.make_args)}

save(self._conanfile, CONAN_TOOLCHAIN_ARGS_FILE, json.dumps(args))
save_toolchain_args(args)
15 changes: 4 additions & 11 deletions conan/tools/google/bazel.py
@@ -1,8 +1,5 @@
import os
import json
from conan.tools.files import load_toolchain_args

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conans.util.files import load

class Bazel(object):
def __init__(self, conanfile):
Expand Down Expand Up @@ -40,10 +37,6 @@ def build(self, args=None, label=None):
self._conanfile.run(command)

def _get_bazel_project_configuration(self):
self._bazel_config = None
self._bazelrc_path = None

if os.path.exists(CONAN_TOOLCHAIN_ARGS_FILE):
conan_toolchain_args = json.loads(load(CONAN_TOOLCHAIN_ARGS_FILE))
self._bazel_config = conan_toolchain_args.get("bazel_config", None)
self._bazelrc_path = conan_toolchain_args.get("bazelrc_path", None)
toolchain_file_content = load_toolchain_args(self._conanfile.generators_folder)
self._bazel_config = toolchain_file_content.get("bazel_config")
self._bazelrc_path = toolchain_file_content.get("bazelrc_path")
16 changes: 5 additions & 11 deletions conan/tools/google/toolchain.py
@@ -1,8 +1,5 @@
import json

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools._check_build_profile import check_using_build_profile
from conans.util.files import save
from conan.tools.files import save_toolchain_args


class BazelToolchain(object):
Expand All @@ -12,10 +9,7 @@ def __init__(self, conanfile):
check_using_build_profile(self._conanfile)

def generate(self):
bazel_config = self._conanfile.conf["tools.google.bazel:config"]
bazelrc_path = self._conanfile.conf["tools.google.bazel:bazelrc_path"]

save(CONAN_TOOLCHAIN_ARGS_FILE, json.dumps({
"bazel_config": bazel_config,
"bazelrc_path": bazelrc_path
}))
save_toolchain_args({
"bazel_config": self._conanfile.conf["tools.google.bazel:config"],
"bazelrc_path": self._conanfile.conf["tools.google.bazel:bazelrc_path"]
})
5 changes: 3 additions & 2 deletions conans/test/functional/toolchains/cmake/test_ninja.py
Expand Up @@ -4,6 +4,7 @@
import pytest

from conan.tools.cmake import CMakeToolchain
from conan.tools.files import load_toolchain_args
from conans.test.assets.cmake import gen_cmakelists
from conans.test.assets.genconanfile import GenConanfile
from conans.test.assets.sources import gen_function_h, gen_function_cpp
Expand Down Expand Up @@ -219,8 +220,8 @@ def test_ninja_conf():
client.save({"conanfile.py": conanfile,
"profile": profile})
client.run("install . -pr=profile")
conanbuild = client.load("conanbuild.json")
assert '"cmake_generator": "Ninja"' in conanbuild
conanbuild = load_toolchain_args(client.current_folder)
assert conanbuild["cmake_generator"] == "Ninja"
vcvars = client.load("conanvcvars.bat")
assert "2017" in vcvars

Expand Down
7 changes: 4 additions & 3 deletions conans/test/functional/toolchains/gnu/autotools/test_ios.py
Expand Up @@ -3,6 +3,7 @@

import pytest

from conan.tools.files import load_toolchain_args
from conans.client.tools.apple import XCRun, to_apple_arch
from conans.test.assets.autotools import gen_makefile_am, gen_configure_ac
from conans.test.assets.sources import gen_function_cpp
Expand Down Expand Up @@ -72,6 +73,6 @@ def build(self):
client.run_command("lipo -info main")
assert "Non-fat file: main is architecture: arm64" in client.out

js = client.load("conanbuild.json")
assert '--host=aarch64-apple-ios' in js
assert '--build=x86_64-apple-darwin' in js
conanbuild = load_toolchain_args(client.current_folder)
configure_args = conanbuild["configure_args"]
assert configure_args == "'--host=aarch64-apple-ios' '--build=x86_64-apple-darwin'"
11 changes: 4 additions & 7 deletions conans/test/functional/toolchains/test_bazel_toolchain.py
@@ -1,6 +1,6 @@
import json
import textwrap

from conan.tools.files import load_toolchain_args
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient

Expand All @@ -14,10 +14,8 @@ def test_toolchain_empty_config():
client.save({"conanfile.py": conanfile})
client.run("install .")

config = json.loads(client.load("conanbuild.json"))

assert config['bazel_config'] is None
assert config['bazelrc_path'] is None
config = load_toolchain_args(client.current_folder)
assert not config


def test_toolchain_loads_config_from_profile():
Expand All @@ -39,7 +37,6 @@ def test_toolchain_loads_config_from_profile():
})
client.run("install . -pr=test_profile")

config = json.loads(client.load("conanbuild.json"))

config = load_toolchain_args(client.current_folder)
assert config['bazel_config'] == "test_config"
assert config['bazelrc_path'] == "/path/to/bazelrc"
6 changes: 3 additions & 3 deletions conans/test/functional/toolchains/test_cmake_toolchain.py
@@ -1,9 +1,9 @@
import json
import os
import platform

import pytest

from conan.tools.files import load_toolchain_args
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient
from conans.util.files import save
Expand Down Expand Up @@ -61,5 +61,5 @@ def test_cmake_toolchain_custom_toolchain():
client.save({"conanfile.py": conanfile})
client.run("install .")
assert not os.path.exists(os.path.join(client.current_folder, "conan_toolchain.cmake"))
buildjson = json.loads(client.load("conanbuild.json"))
assert "mytoolchain.cmake" == buildjson["cmake_toolchain_file"]
build_content = load_toolchain_args(client.current_folder)
assert "mytoolchain.cmake" == build_content["cmake_toolchain_file"]
Expand Up @@ -2,10 +2,9 @@

from mock import Mock

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools.files import save_toolchain_args
from conan.tools.gnu import Autotools
from conans import ConanFile
from conans.client.tools.files import save
from conans.model.conf import Conf
from conans.test.unittests.util.tools_test import RunnerMock
from conans.test.utils.mocks import MockSettings
Expand All @@ -15,10 +14,10 @@
def test_configure_arguments():
tmp = temp_folder()
os.chdir(tmp)
save(CONAN_TOOLCHAIN_ARGS_FILE, """
{"configure_args": "my_configure_args",
"make_args": "my_make_args"}
""")
save_toolchain_args({
"configure_args": "my_configure_args",
"make_args": "my_make_args"}
)
runner = RunnerMock()
conanfile = ConanFile(Mock(), runner=runner)
conanfile.settings = MockSettings({})
Expand Down
@@ -1,10 +1,9 @@
import json
import platform
from os import chdir

import pytest

from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE
from conan.tools.files import load_toolchain_args
from conan.tools.gnu import AutotoolsToolchain
from conans.errors import ConanException
from conans.model.conf import Conf
Expand Down Expand Up @@ -45,9 +44,7 @@ def test_target_triple():
be = AutotoolsToolchain(conanfile)
be.make_args = ["foo", "var"]
be.generate_args()
with open(CONAN_TOOLCHAIN_ARGS_FILE) as f:
obj = json.load(f)

obj = load_toolchain_args()
assert "--host=x86_64-linux-gnu" in obj["configure_args"]
assert "--build=i686-solaris" in obj["configure_args"]
assert obj["make_args"].replace("'", "") == "foo var"
Expand Down Expand Up @@ -75,7 +72,7 @@ def test_cppstd():
"cppstd": "17"})
be = AutotoolsToolchain(conanfile)
env = be.environment()
assert not "-std=c++17" in env["CXXFLAGS"]
assert "-std=c++17" not in env["CXXFLAGS"]

# Using "compiler.cppstd" works
conanfile.settings = MockSettings(
Expand Down