Skip to content

Commit

Permalink
[develop2] Fixing issues with test_package output folder (#12992)
Browse files Browse the repository at this point in the history
* [develop2] Fixing issues with test_package output folder

* fix tests

* fix tests

* wip

* wip

* wip

* wip

* wip

* wip
  • Loading branch information
memsharded authored Jan 31, 2023
1 parent 36b1060 commit 7c7e1c3
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 33 deletions.
13 changes: 7 additions & 6 deletions conan/cli/commands/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,14 @@ def test_package(conan_api, deps_graph, test_conanfile_path, tested_python_requi
"package being created.".format(test_conanfile_path))
conanfile_folder = os.path.dirname(test_conanfile_path)
conanfile = deps_graph.root.conanfile
output_folder = os.path.join(conanfile_folder, conanfile.folders.test_output)
if conanfile.folders.test_output:
shutil.rmtree(output_folder, ignore_errors=True)
mkdir(output_folder)
if conanfile.build_folder and conanfile.build_folder != conanfile.source_folder:
# should be the same as build folder, but we can remove it
shutil.rmtree(conanfile.build_folder, ignore_errors=True)
mkdir(conanfile.build_folder)
conanfile.output.info(f"Test package build: {conanfile.folders.build}")
conanfile.output.info(f"Test package build folder: {conanfile.build_folder}")
conan_api.install.install_consumer(deps_graph=deps_graph,
source_folder=conanfile_folder,
output_folder=output_folder)
source_folder=conanfile_folder)

out.title("Testing the package: Building")
app = ConanApp(conan_api.cache_folder)
Expand Down
10 changes: 7 additions & 3 deletions conan/tools/cmake/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def cmake_layout(conanfile, generator=None, src_folder=".", build_folder="build"

conanfile.cpp.source.includedirs = ["include"]

if multi and not user_defined_build:
if multi:
conanfile.cpp.build.libdirs = ["{}".format(build_type)]
conanfile.cpp.build.bindirs = ["{}".format(build_type)]
else:
Expand All @@ -51,8 +51,12 @@ def cmake_layout(conanfile, generator=None, src_folder=".", build_folder="build"

def get_build_folder_custom_vars(conanfile):

build_vars = conanfile.conf.get("tools.cmake.cmake_layout:build_folder_vars",
default=[], check_type=list)
if conanfile.tested_reference_str:
build_vars = ["settings.compiler", "settings.compiler.version", "settings.arch",
"settings.compiler.cppstd", "settings.build_type", "options.shared"]
else:
build_vars = conanfile.conf.get("tools.cmake.cmake_layout:build_folder_vars",
default=[], check_type=list)
ret = []
for s in build_vars:
group, var = s.split(".", 1)
Expand Down
1 change: 0 additions & 1 deletion conan/tools/google/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ def bazel_layout(conanfile, generator=None, src_folder="."):
"""The layout for bazel is very limited, it builds in the root folder even specifying
"bazel --output_base=xxx" in the other hand I don't know how to inject a custom path so
the build can load the dependencies.bzl from the BazelDeps"""
conanfile.folders.test_output = ""
conanfile.folders.build = ""
conanfile.folders.generators = ""
# used in test package for example, to know where the binaries are (editables not supported yet)
Expand Down
1 change: 0 additions & 1 deletion conan/tools/microsoft/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ def vs_layout(conanfile):
:param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.
"""
conanfile.folders.test_output = ""
subproject = conanfile.folders.subproject
conanfile.folders.source = subproject or "."
conanfile.folders.generators = os.path.join(subproject, "conan") if subproject else "conan"
Expand Down
1 change: 0 additions & 1 deletion conans/model/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ def __init__(self):
# Relative location of the project root, if the conanfile is not in that project root, but
# in a subfolder: e.g: If the conanfile is in a subfolder then self.root = ".."
self.root = None
self.test_output = "test_output"
# The relative location with respect to the project root of the subproject containing the
# conanfile.py, that makes most of the output folders defined in layouts (cmake_layout, etc)
# start from the subproject again
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def package_info(self):
client.save({"conanfile.py": conanfile})
client.run("create .")
host_arch = client.get_default_host_profile().settings['arch']
t = os.path.join("test_package", "test_output", "build", "Release", "generators",
build_folder = client.created_test_build_folder("hello/1.0")
t = os.path.join("test_package", build_folder, "generators",
f"hello-release-{host_arch}-data.cmake")
target_data_cmake_content = client.load(t)
assert 'set(hello_SHARED_LINK_FLAGS_RELEASE "-z now;-z relro")' in target_data_cmake_content
Expand Down
3 changes: 2 additions & 1 deletion conans/test/functional/toolchains/cmake/test_cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ def test_simple_cmake_mingw():
compiler.cppstd=17
"""})
client.run("create . --profile=mingw")
build_folder = client.created_test_build_folder("hello/1.0")
# FIXME: Note that CI contains 10.X, so it uses another version rather than the profile one
# and no one notices. It would be good to have some details in confuser.py to be consistent
check_exe_run(client.out, "hello/1.0:", "gcc", None, "Release", "x86_64", "17",
subsystem="mingw64", extra_msg="Hello World", cxx11_abi="1")
check_vs_runtime("test_package/test_output/build/Release/example.exe", client, "15",
check_vs_runtime(f"test_package/{build_folder}/example.exe", client, "15",
build_type="Release", static_runtime=False, subsystem="mingw64")

# TODO: How to link with mingw statically?
Expand Down
13 changes: 7 additions & 6 deletions conans/test/functional/toolchains/cmake/test_shared_cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def test(self):

# We can run the exe from the test package directory also, without environment
# because there is an internal RPATH in the exe with an abs path to the "hello"
exe_folder = os.path.join("test_package", "test_output", "build", "release")
build_folder = client.created_test_build_folder("hello/0.1")
exe_folder = os.path.join("test_package", build_folder)
client.test_exe_folder = exe_folder
assert os.path.exists(os.path.join(client.current_folder, exe_folder, "example"))
client.run_command(os.path.join(exe_folder, "example"))

Expand All @@ -108,7 +110,7 @@ def test_shared_same_dir_using_tool(test_client_shared):
If we build an executable in Mac and we want it to locate the shared libraries in the same
directory, we have different alternatives, here we use the "install_name_tool"
"""
exe_folder = os.path.join("test_package", "test_output", "build", "release")
exe_folder = test_client_shared.test_exe_folder
# Alternative 1, add the "." to the rpaths so the @rpath from the exe can be replaced with "."
test_client_shared.current_folder = os.path.join(test_client_shared.current_folder, exe_folder)
test_client_shared.run_command("install_name_tool -add_rpath '.' example")
Expand Down Expand Up @@ -155,8 +157,7 @@ class Pkg(ConanFile):
def generate(self):
# The exe is installed by cmake at test_package/bin
# FIXME: This is a bit weird folder management
dest = os.path.join(self.folders.base_build, "bin")
dest = os.path.join(self.recipe_folder, "bin")
for dep in self.dependencies.values():
copy(self, "*.dylib", dep.cpp_info.libdirs[0], dest)
Expand All @@ -182,7 +183,7 @@ def test(self):
test_client_shared.save({"test_package/CMakeLists.txt": cmake, "test_package/conanfile.py": cf})
test_client_shared.run("create . -o hello*:shared=True")
test_client_shared.run("remove '*' -c")
exe_folder = os.path.join("test_package", "test_output", "bin")
exe_folder = os.path.join("test_package", "bin")
test_client_shared.run_command(os.path.join(exe_folder, "test"))


Expand All @@ -196,7 +197,7 @@ def test_shared_same_dir_using_env_var_current_dir(test_client_shared):
"""

# Alternative 3, FAILING IN CI, set DYLD_LIBRARY_PATH in the current dir
exe_folder = os.path.join("test_package", "test_output", "build", "release")
exe_folder = test_client_shared.test_exe_folder
rmdir(os.path.join(test_client_shared.current_folder, exe_folder))
test_client_shared.run("create . -o hello*:shared=True")
test_client_shared.run("remove '*' -c")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ def test_autotools_lib_template():
client.save({}, clean_first=True)
client.run("new autotools_lib -d name=hello -d version=0.1")
client.run("create . -o hello/*:shared=True")
build_folder = client.created_test_build_folder("hello/0.1")
assert "hello/0.1: Hello World Release!" in client.out
if platform.system() == "Darwin":
client.run_command("otool -l test_package/test_output/build-release/main")
client.run_command(f"otool -l test_package/{build_folder}/main")
assert "@rpath/libhello.0.dylib" in client.out
else:
client.run_command("ldd test_package/test_output/build-release/main")
client.run_command(f"ldd test_package/{build_folder}/main")
assert "libhello.so.0" in client.out


Expand Down Expand Up @@ -95,6 +96,7 @@ def test_autotools_relocatable_libs_darwin():
client.run("new autotools_lib -d name=hello -d version=0.1")
client.run("create . -o hello/*:shared=True")

build_folder = client.created_test_build_folder("hello/0.1")
package_id = re.search(r"Package (\S+) created", str(client.out)).group(1)
package_id = package_id.replace("'", "")
ref = RecipeReference.loads("hello/0.1")
Expand All @@ -105,22 +107,23 @@ def test_autotools_relocatable_libs_darwin():
if platform.system() == "Darwin":
client.run_command("otool -l {}".format(dylib))
assert "@rpath/libhello.0.dylib" in client.out
client.run_command("otool -l {}".format("test_package/test_output/build-release/main"))
client.run_command("otool -l {}".format(f"test_package/{build_folder}/main"))
assert package_folder in client.out

# will work because rpath set
client.run_command("test_package/test_output/build-release/main")
client.run_command(f"test_package/{build_folder}/main")
assert "hello/0.1: Hello World Release!" in client.out

# move to another location so that the path set in the rpath does not exist
# then the execution should fail
shutil.move(os.path.join(package_folder, "lib"), os.path.join(client.current_folder, "tempfolder"))
# will fail because rpath does not exist
client.run_command("test_package/test_output/build-release/main", assert_error=True)
client.run_command(f"test_package/{build_folder}/main", assert_error=True)
assert "Library not loaded: @rpath/libhello.0.dylib" in str(client.out).replace("'", "")

# Use DYLD_LIBRARY_PATH and should run
client.run_command("DYLD_LIBRARY_PATH={} test_package/test_output/build-release/main".format(os.path.join(client.current_folder, "tempfolder")))
client.run_command("DYLD_LIBRARY_PATH={} test_package/{}/main".format(os.path.join(client.current_folder, "tempfolder"),
build_folder))
assert "hello/0.1: Hello World Release!" in client.out


Expand Down
2 changes: 1 addition & 1 deletion conans/test/integration/command/test_package_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,4 @@ def test_folder_output():
# c.run("create .")
c.run("test test_package hello/0.1@")
assert os.path.exists(os.path.join(c.current_folder,
"test_package/test_output/hello-config.cmake"))
"test_package/hello-config.cmake"))
11 changes: 5 additions & 6 deletions conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,10 +972,9 @@ def test(self):
"test_package/conanfile.py": test_conanfile})
config = "-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.compiler.cppstd\"]'"
client.run(f"create . {config} -s compiler.cppstd=14")
assert os.path.exists(os.path.join(client.current_folder, "test_package/test_output/build/14"))
build_folder = client.created_test_build_folder("pkg/0.1")
assert os.path.exists(os.path.join(client.current_folder, "test_package", build_folder))
client.run(f"create . {config} -s compiler.cppstd=17")
assert os.path.exists(os.path.join(client.current_folder, "test_package/test_output/build/17"))
# FIXME: We need to review this, it is counter-intuitive that you define a layout and it is
# simply erased at every conan create invocation
assert not os.path.exists(os.path.join(client.current_folder,
"test_package/test_output/build/14"))
build_folder2 = client.created_test_build_folder("pkg/0.1")
assert os.path.exists(os.path.join(client.current_folder, "test_package", build_folder2))
assert build_folder != build_folder2
5 changes: 5 additions & 0 deletions conans/test/utils/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,11 @@ def assert_listed_binary(self, requires, build=False, test=False):
else:
raise AssertionError(f"Cant find {r}-{kind} in {reqs}")

def created_test_build_folder(self, ref):
build_folder = re.search(r"{} \(test package\): Test package build: (.*)".format(str(ref)),
str(self.out)).group(1)
return build_folder.replace("\\", "/")

def created_package_id(self, ref):
package_id = re.search(r"{}: Package '(\S+)' created".format(str(ref)),
str(self.out)).group(1)
Expand Down

0 comments on commit 7c7e1c3

Please sign in to comment.