Repository: conan-io/conan

Issue:
[feature+bug] conan.tools.gnu.autotools.Autotools can only configure in root source folder
Some times, configure scripts can be found in subdirectories.
Right now, `ConanFile.source_folder` is hard coded at
https://github.com/conan-io/conan/blob/916cb10b99ed92d319cd0719462708ee0501ecd4/conan/tools/gnu/autotools.py#L25

It would be VERY useful to be able to change this.

### Environment Details (include every applicable attribute)
  * Operating System+version: all
  * Compiler+version: all
  * Conan version: 1.39.0
  * Python version: 3.9.6




Discussion:
Sure, let's do it.

Same as the new CMake one:

```
    def configure(self, source_folder=None):
        ...

        source = self._conanfile.source_folder
        if source_folder:
            source = os.path.join(self._conanfile.source_folder, source_folder)
```
I'm not properly versed in Conan's layout model,
but should Autotools follow it too?
Yes, I meant that the `conan.tools.gnu.autotools.Autotools` should do something similar to the current CMake one.

Resolving patch:
diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py
--- a/conan/tools/cmake/cmake.py
+++ b/conan/tools/cmake/cmake.py
@@ -73,14 +73,14 @@ def __init__(self, conanfile, parallel=True):
 
         self._cmake_program = "cmake"  # Path to CMake should be handled by environment
 
-    def configure(self, source_folder=None):
+    def configure(self, build_script_folder=None):
         # TODO: environment?
         if not self._conanfile.should_configure:
             return
 
-        source = self._conanfile.source_folder
-        if source_folder:
-            source = os.path.join(self._conanfile.source_folder, source_folder)
+        cmakelist_folder = self._conanfile.source_folder
+        if build_script_folder:
+            cmakelist_folder = os.path.join(self._conanfile.source_folder, build_script_folder)
 
         build_folder = self._conanfile.build_folder
         generator_folder = self._conanfile.generators_folder
@@ -101,7 +101,7 @@ def configure(self, source_folder=None):
             arg_list.append('-DCMAKE_INSTALL_PREFIX="{}"'.format(pkg_folder))
         if platform.system() == "Windows" and self._generator == "MinGW Makefiles":
             arg_list.append('-DCMAKE_SH="CMAKE_SH-NOTFOUND"')
-        arg_list.append('"{}"'.format(source))
+        arg_list.append('"{}"'.format(cmakelist_folder))
 
         command = " ".join(arg_list)
         self._conanfile.output.info("CMake command: %s" % command)
diff --git a/conan/tools/gnu/autotools.py b/conan/tools/gnu/autotools.py
--- a/conan/tools/gnu/autotools.py
+++ b/conan/tools/gnu/autotools.py
@@ -1,3 +1,4 @@
+import os
 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
@@ -13,7 +14,7 @@ def __init__(self, conanfile):
         self._configure_args = toolchain_file_content.get("configure_args")
         self._make_args = toolchain_file_content.get("make_args")
 
-    def configure(self):
+    def configure(self, build_script_folder=None):
         """
         http://jingfenghanmax.blogspot.com.es/2010/09/configure-with-host-target-and-build.html
         https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html
@@ -22,7 +23,11 @@ def configure(self):
         if not self._conanfile.should_configure:
             return
 
-        configure_cmd = "{}/configure".format(self._conanfile.source_folder)
+        source = self._conanfile.source_folder
+        if build_script_folder:
+            source = os.path.join(self._conanfile.source_folder, build_script_folder)
+
+        configure_cmd = "{}/configure".format(source)
         configure_cmd = unix_path(self._conanfile, configure_cmd)
         cmd = "{} {}".format(configure_cmd, self._configure_args)
         self._conanfile.output.info("Calling:\n > %s" % cmd)


Test patch:
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py
@@ -72,9 +72,12 @@ class AppleframeworkConan(ConanFile):
                 name = "mylibrary"
                 version = "1.0"
 
+                def layout(self):
+                    self.folders.source = "src"
+
                 def build(self):
                     cmake = CMake(self)
-                    cmake.configure(source_folder="src")
+                    cmake.configure()
                     cmake.build()
                     cmake.install()
                     self.run("otool -L '%s/hello.framework/hello'" % self.build_folder)
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py
@@ -173,9 +173,12 @@ class Recipe(ConanFile):
             exports_sources = ["src/*", "build-module.cmake"]
             generators = "cmake"
 
+            def layout(self):
+                self.folders.source = "src"
+
             def build(self):
                 cmake = CMake(self)
-                cmake.configure(source_folder="src")
+                cmake.configure()
                 cmake.build()
 
             def package(self):
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components_names.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components_names.py
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components_names.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components_names.py
@@ -36,7 +36,7 @@ class GreetingsConan(ConanFile):
 
             def build(self):
                 cmake = CMake(self)
-                cmake.configure(source_folder="src")
+                cmake.configure(build_script_folder="src")
                 cmake.build()
 
             def package(self):
@@ -143,7 +143,7 @@ class Chat(ConanFile):
 
             def build(self):
                 cmake = CMake(self)
-                cmake.configure(source_folder="src")
+                cmake.configure(build_script_folder="src")
                 cmake.build()
 
             def package(self):
@@ -359,7 +359,7 @@ class HelloConan(ConanFile):
 
             def build(self):
                 cmake = CMake(self)
-                cmake.configure(source_folder="src")
+                cmake.configure(build_script_folder="src")
                 cmake.build()
 
             def package(self):
@@ -531,7 +531,7 @@ class Conan(ConanFile):
 
                 def build(self):
                     cmake = CMake(self)
-                    cmake.configure(source_folder="src")
+                    cmake.configure(build_script_folder="src")
                     cmake.build()
 
                 def package(self):
@@ -587,7 +587,7 @@ class Conan(ConanFile):
 
                 def build(self):
                     cmake = CMake(self)
-                    cmake.configure(source_folder="src")
+                    cmake.configure(build_script_folder="src")
                     cmake.build()
 
                 def package(self):
@@ -616,7 +616,7 @@ class Conan(ConanFile):
 
                 def build(self):
                     cmake = CMake(self)
-                    cmake.configure(source_folder="src")
+                    cmake.configure(build_script_folder="src")
                     cmake.build()
                     self.run(".%smain" % os.sep)
             """.format("CMakeDeps"))
diff --git a/conans/test/unittests/tools/gnu/autotools_test.py b/conans/test/unittests/tools/gnu/autotools_test.py
new file mode 100644
--- /dev/null
+++ b/conans/test/unittests/tools/gnu/autotools_test.py
@@ -0,0 +1,26 @@
+import os
+import textwrap
+
+from conan.tools.files import save_toolchain_args
+from conan.tools.gnu import Autotools
+from conans.test.utils.mocks import ConanFileMock
+from conans.test.utils.test_files import temp_folder
+
+
+def test_source_folder_works():
+    folder = temp_folder()
+    os.chdir(folder)
+    save_toolchain_args({
+        "configure_args": "-foo bar",
+        "make_args": ""}
+    )
+    conanfile = ConanFileMock()
+    conanfile.folders.set_base_install(folder)
+    sources = "/path/to/sources"
+    conanfile.folders.set_base_source(sources)
+    autotools = Autotools(conanfile)
+    autotools.configure(build_script_folder="subfolder")
+    assert conanfile.command.replace("\\", "/") == "/path/to/sources/subfolder/configure -foo bar"
+
+    autotools.configure()
+    assert conanfile.command.replace("\\", "/") == "/path/to/sources/configure -foo bar"