Repository: conan-io/conan-center-index

Issue:
[request] flex/2.6.4 crosscompile support
### Package Details
According to the release notes of flex 2.6.4 "Flex can be cross compiled."
https://github.com/westes/flex/releases/tag/v2.6.4

The above mentioned version is not yet available as a recipe. Please add this version.



Discussion:

Resolving patch:
diff --git a/recipes/flex/all/conanfile.py b/recipes/flex/all/conanfile.py
--- a/recipes/flex/all/conanfile.py
+++ b/recipes/flex/all/conanfile.py
@@ -1,34 +1,44 @@
 from conans import ConanFile, AutoToolsBuildEnvironment, tools
 from conans.errors import ConanInvalidConfiguration
-import contextlib
+import functools
 import os
 
+required_conan_version = ">=1.33.0"
+
 
 class FlexConan(ConanFile):
     name = "flex"
     url = "https://github.com/conan-io/conan-center-index"
     homepage = "https://github.com/westes/flex"
     description = "Flex, the fast lexical analyzer generator"
-    topics = ("conan", "flex", "lex", "lexer", "lexical analyzer generator")
-    license = "BSD-2-Clause"    
+    topics = ("lex", "lexer", "lexical analyzer generator")
+    license = "BSD-2-Clause"
 
     settings = "os", "arch", "compiler", "build_type"
-    options = {"shared": [True, False], "fPIC": [True, False]}
-    default_options = {"shared": False, "fPIC": True}
-
-    _autotools = None
+    options = {
+        "shared": [True, False],
+        "fPIC": [True, False],
+    }
+    default_options = {
+        "shared": False,
+        "fPIC": True,
+    }
 
     @property
     def _source_subfolder(self):
         return "source_subfolder"
 
     def source(self):
-        tools.get(**self.conan_data["sources"][self.version])
-        extracted_dir = self.name + "-" + self.version
-        os.rename(extracted_dir, self._source_subfolder)
+        tools.get(**self.conan_data["sources"][self.version],
+                  destination=self._source_subfolder, strip_root=True)
 
     def requirements(self):
-        self.requires("m4/1.4.18")
+        self.requires("m4/1.4.19")
+
+    def build_requirements(self):
+        self.build_requires("m4/1.4.19")
+        if hasattr(self, "settings_build") and tools.cross_building(self):
+            self.build_requires(f"{self.name}/{self.version}")
 
     def config_options(self):
         if self.settings.os == "Windows":
@@ -42,55 +52,36 @@ def configure(self):
         if self.settings.os == "Windows":
             raise ConanInvalidConfiguration("Flex package is not compatible with Windows. Consider using winflexbison instead.")
 
+    @functools.lru_cache(1)
     def _configure_autotools(self):
-        if self._autotools:
-            return self._autotools
-        self._autotools = AutoToolsBuildEnvironment(self)
+        autotools = AutoToolsBuildEnvironment(self)
         yes_no = lambda v: "yes" if v else "no"
         configure_args = [
             "--enable-shared={}".format(yes_no(self.options.shared)),
             "--enable-static={}".format(not yes_no(self.options.shared)),
             "--disable-nls",
+            "--disable-bootstrap",
             "HELP2MAN=/bin/true",
             "M4=m4",
-        ]
-
-        if self.settings.os == "Linux":
             # https://github.com/westes/flex/issues/247
-            configure_args.extend(["ac_cv_func_malloc_0_nonnull=yes", "ac_cv_func_realloc_0_nonnull=yes"])
+            "ac_cv_func_malloc_0_nonnull=yes", "ac_cv_func_realloc_0_nonnull=yes",
             # https://github.com/easybuilders/easybuild-easyconfigs/pull/5792
-            configure_args.append("ac_cv_func_reallocarray=no")
-
-        # stage1flex must be built on native arch: https://github.com/westes/flex/issues/78
-        # This requires flex to depend on itself.
-        # conan does not support this (currently), so cross build of flex is not possible atm
-
-        self._autotools.configure(args=configure_args, configure_dir=self._source_subfolder)
-        return self._autotools
+            "ac_cv_func_reallocarray=no",
+        ]
 
-    @contextlib.contextmanager
-    def _build_context(self):
-        env = {}
-        # FIXME: when conan receives full cross building support, fetch CC_FOR_BUILD from build context
-        if tools.get_env("CC") and not tools.get_env("CC_FOR_BUILD"):
-            env["CC_FOR_BUILD"] = tools.get_env("CC")
-        with tools.environment_append(env):
-            yield
+        autotools.configure(args=configure_args, configure_dir=self._source_subfolder)
+        return autotools
 
     def build(self):
-        if tools.cross_building(self.settings, skip_x64_x86=True):
-            raise ConanInvalidConfiguration("This recipe does not support cross building atm (missing conan support)")
-        with self._build_context():
-            autotools = self._configure_autotools()
-            autotools.make()
+        autotools = self._configure_autotools()
+        autotools.make()
 
     def package(self):
-        self.copy(pattern="COPYING", dst="licenses", src=self._source_subfolder)
-        with self._build_context():
-            autotools = self._configure_autotools()
-            autotools.install()
+        self.copy("COPYING", src=self._source_subfolder, dst="licenses")
+        autotools = self._configure_autotools()
+        autotools.install()
         tools.rmdir(os.path.join(self.package_folder, "share"))
-        os.unlink(os.path.join(self.package_folder, "lib", "libfl.la"))
+        tools.remove_files_by_mask(os.path.join(self.package_folder, "lib"), "*.la")
 
     def package_info(self):
         self.cpp_info.libs = ["fl"]


Test patch:
diff --git a/recipes/flex/all/test_package/CMakeLists.txt b/recipes/flex/all/test_package/CMakeLists.txt
--- a/recipes/flex/all/test_package/CMakeLists.txt
+++ b/recipes/flex/all/test_package/CMakeLists.txt
@@ -1,12 +1,20 @@
 cmake_minimum_required(VERSION 3.1)
 project(test_package)
 
+# Find FLEX before `conanbuildinfo.cmake` because that file will let `find_program`
+# look for  executables in host packages (let's hope conan 2.0 fixes this)
+find_package(FLEX REQUIRED)
+
 include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
-conan_basic_setup()
+conan_basic_setup(TARGETS)
 
 find_package(FLEX REQUIRED)
 
 flex_target(flex_scanner basic_nr.l "${PROJECT_BINARY_DIR}/basic_nr.cpp")
 
 add_executable(${PROJECT_NAME} basic_nr.cpp)
-target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
+target_include_directories(${PROJECT_NAME} PRIVATE ${FLEX_INCLUDE_DIRS})
+target_link_libraries(${PROJECT_NAME} PRIVATE ${FLEX_LIBRARIES})
+
+add_executable(test_yywrap test_yywrap.c)
+target_link_libraries(test_yywrap PRIVATE ${FLEX_LIBRARIES})
diff --git a/recipes/flex/all/test_package/basic_nr.l b/recipes/flex/all/test_package/basic_nr.l
--- a/recipes/flex/all/test_package/basic_nr.l
+++ b/recipes/flex/all/test_package/basic_nr.l
@@ -1,20 +1,20 @@
 /*
  * This file is part of flex.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 
+ *
  * Neither the name of the University nor the names of its contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -86,4 +86,4 @@ int main( int argc, const char *argv[]) {
 	while(lexer->yylex() != 0)
 		;
 	return 0;
-	}
+}
diff --git a/recipes/flex/all/test_package/conanfile.py b/recipes/flex/all/test_package/conanfile.py
--- a/recipes/flex/all/test_package/conanfile.py
+++ b/recipes/flex/all/test_package/conanfile.py
@@ -4,23 +4,31 @@
 
 
 class TestPackageConan(ConanFile):
-    settings = "os", "compiler", "build_type", "arch"
+    settings = "os", "arch", "compiler", "build_type"
     generators = "cmake"
+    test_type = "build_requires", "requires"
 
     def build(self):
-        if not tools.cross_building(self.settings, skip_x64_x86=True):
-            self.run("flex --version", run_environment=True)
-
+        if not hasattr(self, "settings_build"):
+            # Only test location of flex executable when not cross building
             flex_bin = tools.which("flex")
             if not flex_bin.startswith(self.deps_cpp_info["flex"].rootpath):
                 raise ConanException("Wrong flex executable captured")
+
+        if not tools.cross_building(self, skip_x64_x86=True) or hasattr(self, "settings_build"):
+            self.run("flex --version", run_environment=not hasattr(self, "settings_build"))
+
+            print(os.environ["PATH"])
             cmake = CMake(self)
             cmake.definitions["FLEX_ROOT"] = self.deps_cpp_info["flex"].rootpath
             cmake.configure()
             cmake.build()
 
     def test(self):
-        if not tools.cross_building(self.settings, skip_x64_x86=True):
+        if not tools.cross_building(self, skip_x64_x86=True):
             bin_path = os.path.join("bin", "test_package")
             src = os.path.join(self.source_folder, "basic_nr.txt")
             self.run("{} {}".format(bin_path, src), run_environment=True)
+
+            test_yywrap = os.path.join("bin", "test_yywrap")
+            self.run(test_yywrap, run_environment=True)
diff --git a/recipes/flex/all/test_package/test_yywrap.c b/recipes/flex/all/test_package/test_yywrap.c
new file mode 100644
--- /dev/null
+++ b/recipes/flex/all/test_package/test_yywrap.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+int yywrap(void);
+int yylex(void) {
+    return 0;
+}
+
+int main() {
+    printf("yywrap() returned: %d.\n", yywrap());
+}