diff --git a/recipes/libmicrohttpd/all/conandata.yml b/recipes/libmicrohttpd/all/conandata.yml new file mode 100644 index 0000000000000..baf8560b8d3f1 --- /dev/null +++ b/recipes/libmicrohttpd/all/conandata.yml @@ -0,0 +1,9 @@ +sources: + "0.9.75": + url: "https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.75.tar.gz" + sha256: "9278907a6f571b391aab9644fd646a5108ed97311ec66f6359cebbedb0a4e3bb" +patches: + "0.9.75": + - patch_file: "patches/0.9.75-0001-msbuild-RuntimeLibrary.patch" + patch_description: "Remove RuntimeLibrary from vcxproject + use conantoolchain.props" + patch_type: "conan" diff --git a/recipes/libmicrohttpd/all/conanfile.py b/recipes/libmicrohttpd/all/conanfile.py new file mode 100644 index 0000000000000..8c7a9d8fa18cb --- /dev/null +++ b/recipes/libmicrohttpd/all/conanfile.py @@ -0,0 +1,199 @@ +from conan import ConanFile, Version +from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rm, rmdir +from conan.tools.gnu import Autotools, AutotoolsToolchain, PkgConfigDeps +from conan.tools.microsoft import MSBuild, MSBuildToolchain, is_msvc, vs_layout +from conan.tools.layout import basic_layout +from conan.errors import ConanInvalidConfiguration +import os + +required_conan_version = ">=1.52.0" + + +class LibmicrohttpdConan(ConanFile): + name = "libmicrohttpd" + description = "A small C library that is supposed to make it easy to run an HTTP server" + homepage = "https://www.gnu.org/software/libmicrohttpd/" + topics = ("httpd", "server", "service") + license = "LGPL-2.1" + url = "https://github.com/conan-io/conan-center-index" + settings = "os", "arch", "compiler", "build_type" + options = { + "shared": [True, False], + "fPIC": [True, False], + "with_https": [True, False], + "with_error_messages": [True, False], + "with_postprocessor": [True, False], + "with_digest_authentification": [True, False], + "epoll": [True, False], + "with_zlib": [True, False], + } + default_options = { + "shared": False, + "fPIC": True, + "with_https": False, # FIXME: should be True, but gnutls is not yet available in cci + "with_error_messages": True, + "with_postprocessor": True, + "with_digest_authentification": True, + "epoll": True, + "with_zlib": True, + } + + @property + def _settings_build(self): + return getattr(self, "settings_build", self.settings) + + def config_options(self): + if self.settings.os != "Linux": + try: + del self.options.fPIC + except Exception: + pass + del self.options.epoll + if is_msvc(self): + del self.options.with_https + del self.options.with_error_messages + del self.options.with_postprocessor + del self.options.with_digest_authentification + del self.options.with_zlib + + def configure(self): + if self.options.shared: + try: + del self.options.fPIC + except Exception: + pass + try: + del self.settings.compiler.libcxx + except Exception: + pass + try: + del self.settings.compiler.cppstd + except Exception: + pass + + def validate(self): + if is_msvc(self): + if self.info.settings.arch not in ("x86", "x86_64"): + raise ConanInvalidConfiguration("Unsupported architecture (only x86 and x86_64 are supported)") + if self.info.settings.build_type not in ("Release", "Debug"): + raise ConanInvalidConfiguration("Unsupported build type (only Release and Debug are supported)") + + def requirements(self): + if self.options.get_safe("with_zlib", False): + self.requires("zlib/1.2.13") + if self.options.get_safe("with_https", False): + raise ConanInvalidConfiguration("gnutls is not (yet) available in cci") + + def build_requirements(self): + if self._settings_build.os == "Windows" and not is_msvc(self): + self.win_bash = True + if not self.conf.get("tools.microsoft.bash:path", default=False, check_type=str): + self.tool_requires("msys2/cci.latest") + + def source(self): + get(self, **self.conan_data["sources"][self.version], + destination=self.source_folder, strip_root=True) + + def export_sources(self): + export_conandata_patches(self) + + def layout(self): + if is_msvc(self): + vs_layout(self) + else: + basic_layout(self) + + def generate(self): + if is_msvc(self): + tc = MSBuildToolchain(self) + tc.configuration = self._msvc_configuration + tc.generate() + else: + yes_no = lambda v: "yes" if v else "no" + pkg = PkgConfigDeps(self) + pkg.generate() + autotools = AutotoolsToolchain(self) + autotools.configure_args.extend([ + f"--enable-shared={yes_no(self.options.shared)}", + f"--enable-static={yes_no(not self.options.shared)}", + f"--enable-https={yes_no(self.options.with_https)}", + f"--enable-messages={yes_no(self.options.with_error_messages)}", + f"--enable-postprocessor={yes_no(self.options.with_postprocessor)}", + f"--enable-dauth={yes_no(self.options.with_digest_authentification)}", + f"--enable-epoll={yes_no(self.options.get_safe('epoll'))}", + "--disable-doc", + "--disable-examples", + "--disable-curl", + ]) + if self.settings.os == "Windows": + if self.options.with_zlib: + # This fixes libtool refusing to build a shared library when it sees `-lz` + libdir = self.deps_cpp_info["zlib"].lib_paths[0] + autotools.extra_ldflags.extend([os.path.join(libdir, lib).replace("\\", "/") for lib in os.listdir(libdir)]) + autotools.generate() + + @property + def _msvc_configuration(self): + return f"{self.settings.build_type}-{'dll' if self.options.shared else 'static'}" + + @property + def _msvc_sln_folder(self): + if self.settings.compiler == "Visual Studio": + if Version(self.settings.compiler.version) >= 16: + subdir = "VS-Any-Version" + else: + subdir = "VS2017" + else: + subdir = "VS-Any-Version" + return os.path.join("w32", subdir) + + @property + def _msvc_arch(self): + return { + "x86": "Win32", + "x86_64": "x64", + }[str(self.settings.arch)] + + def _patch_sources(self): + apply_conandata_patches(self) + + def build(self): + self._patch_sources() + if is_msvc(self): + msbuild = MSBuild(self) + msbuild.build_type = self._msvc_configuration + msbuild.build(sln=os.path.join(self._msvc_sln_folder, "libmicrohttpd.sln"), targets=["libmicrohttpd"]) + else: + autotools = Autotools(self) + autotools.configure() + autotools.make() + + def package(self): + copy(self, "COPYING", os.path.join(self.source_folder), os.path.join(self.package_folder, "licenses")) + if is_msvc(self): + copy(self, "*.lib", os.path.join(self.build_folder, self._msvc_sln_folder, "Output", self._msvc_arch), os.path.join(self.package_folder, "lib")) + copy(self, "*.dll", os.path.join(self.build_folder, self._msvc_sln_folder, "Output", self._msvc_arch), os.path.join(self.package_folder, "bin")) + copy(self, "*.h", os.path.join(self.build_folder, self._msvc_sln_folder, "Output", self._msvc_arch), os.path.join(self.package_folder, "include")) + else: + autotools = Autotools(self) + autotools.install() + + rm(self, "*.la", os.path.join(self.package_folder, "lib")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + + def package_info(self): + self.cpp_info.set_property("pkg_config_name", "libmicrohttps") + libname = "microhttpd" + if is_msvc(self): + libname = "libmicrohttpd" + if self.options.shared: + libname += "-dll" + if self.settings.build_type == "Debug": + libname += "_d" + self.cpp_info.libs = [libname] + if self.settings.os in ("FreeBSD", "Linux"): + self.cpp_info.system_libs = ["pthread"] + elif self.settings.os == "Windows": + if self.options.shared: + self.cpp_info.defines.append("MHD_W32DLL") + self.cpp_info.system_libs = ["ws2_32"] diff --git a/recipes/libmicrohttpd/all/patches/0.9.75-0001-msbuild-RuntimeLibrary.patch b/recipes/libmicrohttpd/all/patches/0.9.75-0001-msbuild-RuntimeLibrary.patch new file mode 100644 index 0000000000000..b3dc82df26fa9 --- /dev/null +++ b/recipes/libmicrohttpd/all/patches/0.9.75-0001-msbuild-RuntimeLibrary.patch @@ -0,0 +1,35 @@ +--- w32/common/common-build-settings.vcxproj ++++ w32/common/common-build-settings.vcxproj +@@ -5,7 +5,7 @@ + Only 0 and 1 are used currently --> + 0 + 1 +- ++ + + $(SolutionDir);$(MhdW32Common);$(MhdSrc)include;$(IncludePath) + +--- w32/common/libmicrohttpd-build-settings.vcxproj ++++ w32/common/libmicrohttpd-build-settings.vcxproj +@@ -31,8 +31,8 @@ + + + _LIB;MHD_W32LIB;%(PreprocessorDefinitions) +- MultiThreadedDebug +- MultiThreaded ++ + + + Ws2_32.lib +@@ -45,8 +45,8 @@ + + + _USRDLL;MHD_W32DLL;%(PreprocessorDefinitions) +- MultiThreadedDebugDLL +- MultiThreadedDLL ++ + + + Ws2_32.lib;%(AdditionalDependencies) diff --git a/recipes/libmicrohttpd/all/test_package/CMakeLists.txt b/recipes/libmicrohttpd/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..534adba0c584f --- /dev/null +++ b/recipes/libmicrohttpd/all/test_package/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.1) +project(test_package LANGUAGES C) + +find_package(libmicrohttpd REQUIRED CONFIG) + +add_executable(${PROJECT_NAME} test_package.c) +target_link_libraries(${PROJECT_NAME} PRIVATE libmicrohttpd::libmicrohttpd) diff --git a/recipes/libmicrohttpd/all/test_package/conanfile.py b/recipes/libmicrohttpd/all/test_package/conanfile.py new file mode 100644 index 0000000000000..f72d1f660e19f --- /dev/null +++ b/recipes/libmicrohttpd/all/test_package/conanfile.py @@ -0,0 +1,30 @@ +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout +import os + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeDeps", "VirtualRunEnv" + test_type = "explicit" + + def layout(self): + cmake_layout(self) + + def requirements(self): + self.requires(self.tested_reference_str) + + def generate(self): + tc = CMakeToolchain(self) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") + self.run(bin_path, env="conanrun") diff --git a/recipes/libmicrohttpd/all/test_package/test_package.c b/recipes/libmicrohttpd/all/test_package/test_package.c new file mode 100644 index 0000000000000..cb40829c7a43b --- /dev/null +++ b/recipes/libmicrohttpd/all/test_package/test_package.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +#define PORT 8888 +#define PAGE \ + "" \ + "" \ + "libmicrohttpd demo" \ + "" \ + "" \ + "libmicrohttpd demo" \ + "" \ + "" + +static enum MHD_Result ahc_echo(void * cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + long unsigned int *upload_data_size, + void **con_cls) { + struct MHD_Response *response; + int ret; + + if (strcmp(method, "GET") != 0) { + /** + * unexpected method + */ + return MHD_NO; + } + if (*con_cls == NULL) { + /** + * The first time only the headers are valid, + * do not respond in the first round. + * But accept the connection. + */ + *con_cls = connection; + return MHD_YES; + } + if (*upload_data_size != 0) { + /** + * upload data in a GET!? + */ + return MHD_NO; + } + response = MHD_create_response_from_buffer(strlen(PAGE), (void*)PAGE, MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response(connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); + return ret; +} + +int main(int argc, char *argv[]) { + struct MHD_Daemon *daemon; + + // Don't open a port and do not block so CI isn't interrupted. +#if 0 + daemon = MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, + PORT, NULL, NULL, + &ahc_echo, NULL, MHD_OPTION_END); + if (daemon == NULL) { + return 1; + } + + (void)getchar(); +#else + daemon = NULL; +#endif + + MHD_stop_daemon(daemon); + return 0; +} diff --git a/recipes/libmicrohttpd/all/test_v1_package/CMakeLists.txt b/recipes/libmicrohttpd/all/test_v1_package/CMakeLists.txt new file mode 100644 index 0000000000000..0b95e58322269 --- /dev/null +++ b/recipes/libmicrohttpd/all/test_v1_package/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.1) +project(test_package LANGUAGES C) + +include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") +conan_basic_setup(TARGETS) + +find_package(libmicrohttpd REQUIRED CONFIG) + +add_executable(${PROJECT_NAME} ../test_package/test_package.c) +target_link_libraries(${PROJECT_NAME} PRIVATE libmicrohttpd::libmicrohttpd) diff --git a/recipes/libmicrohttpd/all/test_v1_package/conanfile.py b/recipes/libmicrohttpd/all/test_v1_package/conanfile.py new file mode 100644 index 0000000000000..38f4483872d47 --- /dev/null +++ b/recipes/libmicrohttpd/all/test_v1_package/conanfile.py @@ -0,0 +1,17 @@ +from conans import ConanFile, CMake, tools +import os + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "cmake", "cmake_find_package_multi" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if not tools.cross_building(self): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) diff --git a/recipes/libmicrohttpd/config.yml b/recipes/libmicrohttpd/config.yml new file mode 100644 index 0000000000000..48e6a23d34df6 --- /dev/null +++ b/recipes/libmicrohttpd/config.yml @@ -0,0 +1,3 @@ +versions: + "0.9.75": + folder: all