[DO-981] qt package (!15)

Co-authored-by: aleksandr.vodyanov <aleksandr.vodyanov@avroid.tech>
Reviewed-on: https://git.avroid.tech/Conan/conan_build/pulls/15
This commit is contained in:
Aleksandr Vodyanov
2025-02-13 12:25:48 +03:00
parent 60445ac09e
commit 3759e1163f
228 changed files with 16106 additions and 12 deletions

View File

@@ -0,0 +1,63 @@
sources:
"3.8.2":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_gnu_org/gnu/bison/bison-3.8.2.tar.gz"
sha256: "06c9e13bdf7eb24d4ceb6b59205a4f67c2c7e7213119644430fe82fbd14a0abb"
"3.7.6":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_gnu_org/gnu/bison/bison-3.7.6.tar.gz"
sha256: "69dc0bb46ea8fc307d4ca1e0b61c8c355eb207d0b0c69f4f8462328e74d7b9ea"
"3.7.1":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_gnu_org/gnu/bison/bison-3.7.1.tar.gz"
sha256: "1dd952839cf0d5a8178c691eeae40dc48fa50d18dcce648b1ad9ae0195367d13"
"3.5.3":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_gnu_org/gnu/bison/bison-3.5.3.tar.gz"
sha256: "34e201d963156618a0ea5bc87220f660a1e08403dd3c7c7903d4f38db3f40039"
patches:
"3.8.2":
- patch_file: "patches/0001-3.8-create_pipe-uses-O_TEXT-not-O_BINARY-mode.patch"
patch_description: "use O_TEXT instead of O_BINARY for pipe"
patch_type: "portability"
- patch_file: "patches/0002-3.7.6-open-source-file-in-binary-mode-MS-ftell-bug-ks-68337.patch"
patch_description: "windows: open source file in binary mode"
patch_type: "portability"
- patch_file: "patches/0005-gnulib-limit-search-range-of-_setmaxstdio.patch"
patch_description: "msvc: limit search range of _setmaxstdio"
patch_type: "portability"
"3.7.6":
- patch_file: "patches/0001-create_pipe-uses-O_TEXT-not-O_BINARY-mode.patch"
patch_description: "use O_TEXT instead of O_BINARY for pipe"
patch_type: "portability"
- patch_file: "patches/0002-3.7.6-open-source-file-in-binary-mode-MS-ftell-bug-ks-68337.patch"
patch_description: "windows: open source file in binary mode"
patch_type: "portability"
- patch_file: "patches/0005-gnulib-limit-search-range-of-_setmaxstdio.patch"
patch_description: "msvc: limit search range of _setmaxstdio"
patch_type: "portability"
"3.7.1":
- patch_file: "patches/0001-create_pipe-uses-O_TEXT-not-O_BINARY-mode.patch"
patch_description: "use O_TEXT instead of O_BINARY for pipe"
patch_type: "portability"
- patch_file: "patches/0002-3.7.1-open-source-file-in-binary-mode-MS-ftell-bug-ks-68337.patch"
patch_description: "windows: open source file in binary mode"
patch_type: "portability"
- patch_file: "patches/0005-gnulib-limit-search-range-of-_setmaxstdio.patch"
patch_description: "msvc: limit search range of _setmaxstdio"
patch_type: "portability"
- patch_file: "patches/0006-dont-link-bison-against-libreadline.patch"
patch_description: "Don't link bison against libreadline"
patch_type: "portability"
"3.5.3":
- patch_file: "patches/0001-create_pipe-uses-O_TEXT-not-O_BINARY-mode.patch"
patch_description: "use O_TEXT instead of O_BINARY for pipe"
patch_type: "portability"
- patch_file: "patches/0002-3.5.3-open-source-file-in-binary-mode-MS-ftell-bug-ks-68337.patch"
patch_description: "windows: open source file in binary mode"
patch_type: "portability"
- patch_file: "patches/0003-3.5.3-msvc-changes.patch"
patch_description: "windows: fix build"
patch_type: "portability"
- patch_file: "patches/0004-3.5.3-relocatable.patch"
patch_description: "Relocatable"
patch_type: "portability"
- patch_file: "patches/0005-gnulib-limit-search-range-of-_setmaxstdio.patch"
patch_description: "msvc: limit search range of _setmaxstdio"
patch_type: "portability"

View File

@@ -0,0 +1,168 @@
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.env import VirtualBuildEnv
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rename, replace_in_file
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.layout import basic_layout
from conan.tools.microsoft import is_msvc, unix_path
import os
required_conan_version = ">=1.54.0"
class BisonConan(ConanFile):
name = "bison"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://www.gnu.org/software/bison/"
description = "Bison is a general-purpose parser generator"
topics = ("bison", "parser")
license = "GPL-3.0-or-later"
settings = "os", "arch", "compiler", "build_type"
options = {
"fPIC": [True, False],
}
default_options = {
"fPIC": True,
}
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
self.settings.rm_safe("compiler.cppstd")
self.settings.rm_safe("compiler.libcxx")
def layout(self):
basic_layout(self, src_folder="src")
def requirements(self):
self.requires("m4/1.4.19")
def validate(self):
if is_msvc(self) and self.version == "3.8.2":
raise ConanInvalidConfiguration(
f"{self.ref} is not yet ready for Visual Studio, use previous version "
"or open a pull request on https://github.com/conan-io/conan-center-index/pulls"
)
def build_requirements(self):
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
if is_msvc(self):
self.tool_requires("automake/1.16.5")
if self.settings.os != "Windows":
self.tool_requires("flex/2.6.4")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
tc = AutotoolsToolchain(self)
tc.configure_args.extend([
"--enable-relocatable",
"--disable-nls",
"--datarootdir=${prefix}/res",
])
if self.settings.compiler == "apple-clang":
tc.configure_args.append("gl_cv_compiler_check_decl_option=")
if is_msvc(self):
# Avoid a `Assertion Failed Dialog Box` during configure with build_type=Debug
# Visual Studio does not support the %n format flag:
# https://docs.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions
# Because the %n format is inherently insecure, it is disabled by default. If %n is encountered in a format string,
# the invalid parameter handler is invoked, as described in Parameter Validation. To enable %n support, see _set_printf_count_output.
tc.configure_args.extend([
"gl_cv_func_printf_directive_n=no",
"gl_cv_func_snprintf_directive_n=no",
"gl_cv_func_snprintf_directive_n=no",
])
tc.extra_cflags.append("-FS")
env = tc.environment()
if is_msvc(self):
automake_conf = self.dependencies.build["automake"].conf_info
compile_wrapper = unix_path(self, automake_conf.get("user.automake:compile-wrapper", check_type=str))
ar_wrapper = unix_path(self, automake_conf.get("user.automake:lib-wrapper", check_type=str))
env.define("CC", f"{compile_wrapper} cl -nologo")
env.define("CXX", f"{compile_wrapper} cl -nologo")
env.define("LD", "link -nologo")
env.define("AR", f"{ar_wrapper} lib")
env.define("NM", "dumpbin -symbols")
env.define("OBJDUMP", ":")
env.define("RANLIB", ":")
env.define("STRIP", ":")
tc.generate(env)
def _patch_sources(self):
apply_conandata_patches(self)
makefile = os.path.join(self.source_folder, "Makefile.in")
yacc = os.path.join(self.source_folder, "src", "yacc.in")
if self.settings.os == "Windows":
# replace embedded unix paths by windows paths
replace_in_file(self, makefile,
"echo '#define BINDIR \"$(bindir)\"';",
"echo '#define BINDIR \"$(shell cygpath -m \"$(bindir)\")\"';")
replace_in_file(self, makefile,
"echo '#define PKGDATADIR \"$(pkgdatadir)\"';",
"echo '#define PKGDATADIR \"$(shell cygpath -m \"$(pkgdatadir)\")\"';")
replace_in_file(self, makefile,
"echo '#define DATADIR \"$(datadir)\"';",
"echo '#define DATADIR \"$(shell cygpath -m \"$(datadir)\")\"';")
replace_in_file(self, makefile,
"echo '#define DATAROOTDIR \"$(datarootdir)\"';",
"echo '#define DATAROOTDIR \"$(shell cygpath -m \"$(datarootdir)\")\"';")
replace_in_file(self, makefile,
"dist_man_MANS = $(top_srcdir)/doc/bison.1",
"dist_man_MANS =")
replace_in_file(self, yacc, "@prefix@", "$CONAN_BISON_ROOT")
replace_in_file(self, yacc, "@bindir@", "$CONAN_BISON_ROOT/bin")
def build(self):
self._patch_sources()
autotools = Autotools(self)
autotools.configure()
autotools.install()
def package(self):
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
autotools = Autotools(self)
autotools.install()
if is_msvc(self):
rename(self, os.path.join(self.package_folder, "lib", "liby.a"),
os.path.join(self.package_folder, "lib", "y.lib"))
def package_info(self):
self.cpp_info.includedirs = []
self.cpp_info.libs = ["y"]
self.cpp_info.resdirs = ["res"]
bison_root = self.package_folder.replace("\\", "/")
self.buildenv_info.define_path("CONAN_BISON_ROOT", bison_root)
pkgdir = os.path.join(self.package_folder, "res", "bison")
self.buildenv_info.define_path("BISON_PKGDATADIR", pkgdir)
# yacc is a shell script, so requires a shell (such as bash)
yacc = os.path.join(self.package_folder, "bin", "yacc").replace("\\", "/")
self.conf_info.define("user.bison:yacc", yacc)
# TODO: to remove in conan v2
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))
self.env_info.CONAN_BISON_ROOT = self.package_folder.replace("\\", "/")
self.env_info.BISON_PKGDATADIR = pkgdir
self.user_info.YACC = yacc

View File

@@ -0,0 +1,29 @@
From dffa2a21edeba243ef76b75e0c2081ec15fe95bd Mon Sep 17 00:00:00 2001
From: SSE4 <tomskside@gmail.com>
Date: Wed, 3 Apr 2019 19:48:12 +0700
Subject: [PATCH 3/4] 0003
---
lib/spawn-pipe.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/spawn-pipe.c b/lib/spawn-pipe.c
index 3af5167..09e9cad 100644
--- a/lib/spawn-pipe.c
+++ b/lib/spawn-pipe.c
@@ -213,10 +213,10 @@ create_pipe (const char *progname,
xalloc_die ();
if (pipe_stdout)
- if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
+ if (pipe2_safer (ifd, O_TEXT | O_CLOEXEC) < 0)
error (EXIT_FAILURE, errno, _("cannot create pipe"));
if (pipe_stdin)
- if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
+ if (pipe2_safer (ofd, O_TEXT | O_CLOEXEC) < 0)
error (EXIT_FAILURE, errno, _("cannot create pipe"));
/* Data flow diagram:
*
--
2.7.4.windows.1

View File

@@ -0,0 +1,29 @@
From dffa2a21edeba243ef76b75e0c2081ec15fe95bd Mon Sep 17 00:00:00 2001
From: SSE4 <tomskside@gmail.com>
Date: Wed, 3 Apr 2019 19:48:12 +0700
Subject: [PATCH 3/4] 0003
---
lib/spawn-pipe.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/spawn-pipe.c b/lib/spawn-pipe.c
index 3af5167..09e9cad 100644
--- a/lib/spawn-pipe.c
+++ b/lib/spawn-pipe.c
@@ -137,10 +137,10 @@ create_pipe (const char *progname,
prog_argv = prepare_spawn (prog_argv);
if (pipe_stdout)
- if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0)
+ if (pipe2_safer (ifd, O_TEXT | O_CLOEXEC) < 0)
error (EXIT_FAILURE, errno, _("cannot create pipe"));
if (pipe_stdin)
- if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0)
+ if (pipe2_safer (ofd, O_TEXT | O_CLOEXEC) < 0)
error (EXIT_FAILURE, errno, _("cannot create pipe"));
/* Data flow diagram:
*
--
2.7.4.windows.1

View File

@@ -0,0 +1,26 @@
--- src/location.c
+++ src/location.c
@@ -268,6 +268,14 @@ caret_free (void)
static bool
caret_set_file (const char *file)
{
+#if defined(_WIN32)
+ /* ftell() is unusable on Windows in the face of text files
+ that use just LF and not Windows-style CR-LF as newlines
+ http://support.microsoft.com/kb/68337 */
+ char fopen_mode[3] = "rb";
+#else
+ char fopen_mode[2] = "r";
+#endif
/* If a different file than before, close and let the rest open
the new one. */
if (caret_info.pos.file && caret_info.pos.file != file)
@@ -278,7 +278,7 @@ caret_set_file (const char *file)
if (!caret_info.pos.file)
{
caret_info.pos.file = file;
- if ((caret_info.file = fopen (caret_info.pos.file, "r")))
+ if ((caret_info.file = fopen (caret_info.pos.file, fopen_mode)))
{
/* If the file is not regular (imagine #line 1 "/dev/stdin"
in the input file for instance), don't try to quote the

View File

@@ -0,0 +1,26 @@
--- src/location.c
+++ src/location.c
@@ -256,6 +256,14 @@ caret_free (void)
static bool
caret_set_file (const char *file)
{
+#if defined(_WIN32)
+ /* ftell() is unusable on Windows in the face of text files
+ that use just LF and not Windows-style CR-LF as newlines
+ http://support.microsoft.com/kb/68337 */
+ char fopen_mode[3] = "rb";
+#else
+ char fopen_mode[2] = "r";
+#endif
/* If a different file than before, close and let the rest open
the new one. */
if (caret_info.pos.file && caret_info.pos.file != file)
@@ -266,7 +266,7 @@ caret_set_file (const char *file)
if (!caret_info.pos.file)
{
caret_info.pos.file = file;
- if ((caret_info.file = fopen (caret_info.pos.file, "r")))
+ if ((caret_info.file = fopen (caret_info.pos.file, fopen_mode)))
{
/* If the file is not regular (imagine #line 1 "/dev/stdin"
in the input file for instance), don't try to quote the

View File

@@ -0,0 +1,26 @@
--- src/location.c
+++ src/location.c
@@ -258,6 +258,14 @@
static bool
caret_set_file (const char *file)
{
+#if defined(_WIN32)
+ /* ftell() is unusable on Windows in the face of text files
+ that use just LF and not Windows-style CR-LF as newlines
+ http://support.microsoft.com/kb/68337 */
+ char fopen_mode[3] = "rb";
+#else
+ char fopen_mode[2] = "r";
+#endif
/* If a different file than before, close and let the rest open
the new one. */
if (caret_info.pos.file && caret_info.pos.file != file)
@@ -268,7 +268,7 @@
if (!caret_info.pos.file)
{
caret_info.pos.file = file;
- if ((caret_info.file = fopen (caret_info.pos.file, "r")))
+ if ((caret_info.file = fopen (caret_info.pos.file, fopen_mode)))
{
/* If the file is not regular (imagine #line 1 "/dev/stdin"
in the input file for instance), don't try to quote the

View File

@@ -0,0 +1,261 @@
src/parse-gram.y and src/scan-gram.l should be modified as well,
but aren't to avoid a dependency on a already-built flex and bison.
--- src/location.c
+++ src/location.c
@@ -25,9 +25,13 @@
#include <mbswidth.h>
#include <quotearg.h>
#include <stdio.h> /* fileno */
+#ifndef _WIN32
#include <sys/ioctl.h>
+#endif
#include <sys/stat.h> /* fstat */
+#ifndef _WIN32
#include <termios.h>
+#endif
#ifdef WINSIZE_IN_PTEM
# include <sys/stream.h>
--- src/parse-gram.c
+++ src/parse-gram.c
@@ -991,7 +991,7 @@ tron (yyo);
case 43: /* "character literal" */
#line 217 "src/parse-gram.y"
- { fputs (char_name (((*yyvaluep).CHAR)), yyo); }
+ { fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
#line 996 "src/parse-gram.c"
break;
@@ -1027,7 +1027,7 @@ tron (yyo);
case 56: /* "integer" */
#line 234 "src/parse-gram.y"
- { fprintf (yyo, "%d", ((*yyvaluep).INT)); }
+ { fprintf (yyo, "%d", ((*yyvaluep).INTEGER)); }
#line 1032 "src/parse-gram.c"
break;
@@ -2216,13 +2216,13 @@ yyreduce:
case 12:
#line 330 "src/parse-gram.y"
- { expected_sr_conflicts = (yyvsp[0].INT); }
+ { expected_sr_conflicts = (yyvsp[0].INTEGER); }
#line 2221 "src/parse-gram.c"
break;
case 13:
#line 331 "src/parse-gram.y"
- { expected_rr_conflicts = (yyvsp[0].INT); }
+ { expected_rr_conflicts = (yyvsp[0].INTEGER); }
#line 2227 "src/parse-gram.c"
break;
@@ -2775,7 +2775,7 @@ yyreduce:
case 102:
#line 679 "src/parse-gram.y"
- { grammar_current_rule_dprec_set ((yyvsp[0].INT), (yylsp[0])); }
+ { grammar_current_rule_dprec_set ((yyvsp[0].INTEGER), (yylsp[0])); }
#line 2780 "src/parse-gram.c"
break;
@@ -2787,13 +2787,13 @@ yyreduce:
case 104:
#line 683 "src/parse-gram.y"
- { grammar_current_rule_expect_sr ((yyvsp[0].INT), (yylsp[0])); }
+ { grammar_current_rule_expect_sr ((yyvsp[0].INTEGER), (yylsp[0])); }
#line 2792 "src/parse-gram.c"
break;
case 105:
#line 685 "src/parse-gram.y"
- { grammar_current_rule_expect_rr ((yyvsp[0].INT), (yylsp[0])); }
+ { grammar_current_rule_expect_rr ((yyvsp[0].INTEGER), (yylsp[0])); }
#line 2798 "src/parse-gram.c"
break;
@@ -2860,9 +2860,9 @@ yyreduce:
complain_indent (&loc, complaint, &indent,
_("definition of %s"), var);
}
- (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR)), (yylsp[0]));
+ (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR_LITERAL)), (yylsp[0]));
symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
- symbol_user_token_number_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0]));
+ symbol_user_token_number_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
}
#line 2868 "src/parse-gram.c"
break;
--- src/parse-gram.h
+++ src/parse-gram.h
@@ -122,7 +122,7 @@ extern int gram_debug;
BRACED_CODE = 40,
BRACED_PREDICATE = 41,
BRACKETED_ID = 42,
- CHAR = 43,
+ CHAR_LITERAL = 43,
COLON = 44,
EPILOGUE = 45,
EQUAL = 46,
@@ -135,7 +135,7 @@ extern int gram_debug;
TAG = 53,
TAG_ANY = 54,
TAG_NONE = 55,
- INT = 56,
+ INTEGER = 56,
PERCENT_PARAM = 57,
PERCENT_UNION = 58,
PERCENT_EMPTY = 59
@@ -162,7 +162,7 @@ union GRAM_STYPE
/* code_props_type */
code_props_type code_props_type;
/* "integer" */
- int INT;
+ int INTEGER;
/* int.opt */
int yytype_81;
/* named_ref.opt */
@@ -226,7 +226,7 @@ union GRAM_STYPE
/* variable */
uniqstr variable;
/* "character literal" */
- unsigned char CHAR;
+ unsigned char CHAR_LITERAL;
/* value */
value_type value;
#line 233 "src/parse-gram.h"
--- src/reader.c
+++ src/reader.c
@@ -803,7 +803,7 @@ check_and_convert_grammar (void)
$accept: %start $end. */
{
- symbol_list *p = symbol_list_sym_new (accept, empty_loc);
+ symbol_list *p = symbol_list_sym_new (bison_accept, empty_loc);
p->rhs_loc = grammar->rhs_loc;
p->next = symbol_list_sym_new (startsymbol, empty_loc);
p->next->next = symbol_list_sym_new (endtoken, empty_loc);
--- src/reduce.c
+++ src/reduce.c
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
bitset Pp = bitset_create (nrules, BITSET_FIXED);
/* If the start symbol isn't useful, then nothing will be useful. */
- if (bitset_test (N, accept->content->number - ntokens))
+ if (bitset_test (N, bison_accept->content->number - ntokens))
{
- bitset_set (V, accept->content->number);
+ bitset_set (V, bison_accept->content->number);
while (1)
{
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
if (ISVAR (*rhsp))
*rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]);
- accept->content->number = nterm_map[accept->content->number - ntokens];
+ bison_accept->content->number = nterm_map[bison_accept->content->number - ntokens];
}
nsyms -= nuseless_nonterminals;
@@ -381,7 +381,7 @@ reduce_grammar (void)
{
reduce_print ();
- if (!bitset_test (N, accept->content->number - ntokens))
+ if (!bitset_test (N, bison_accept->content->number - ntokens))
complain (&startsymbol_loc, fatal,
_("start symbol %s does not derive any sentence"),
startsymbol->tag);
--- src/scan-gram.c
+++ src/scan-gram.c
@@ -2223,12 +2223,12 @@ YY_RULE_SETUP
case 65:
YY_RULE_SETUP
#line 308 "/Users/akim/src/gnu/bison/src/scan-gram.l"
-RETURN_VALUE (INT, scan_integer (yytext, 10, *loc));
+RETURN_VALUE (INTEGER, scan_integer (yytext, 10, *loc));
YY_BREAK
case 66:
YY_RULE_SETUP
#line 309 "/Users/akim/src/gnu/bison/src/scan-gram.l"
-RETURN_VALUE (INT, scan_integer (yytext, 16, *loc));
+RETURN_VALUE (INTEGER, scan_integer (yytext, 16, *loc));
YY_BREAK
/* Identifiers may not start with a digit. Yet, don't silently
accept "1FOO" as "1 FOO". */
@@ -2575,21 +2575,21 @@ YY_RULE_SETUP
{
STRING_FINISH;
loc->start = token_start;
- val->CHAR = last_string[0];
+ val->CHAR_LITERAL = last_string[0];
/* FIXME: Eventually, make these errors. */
if (last_string[0] == '\0')
{
complain (loc, Wother, _("empty character literal"));
/* '\0' seems dangerous even if we are about to complain. */
- val->CHAR = '\'';
+ val->CHAR_LITERAL = '\'';
}
else if (last_string[1] != '\0')
complain (loc, Wother,
_("extra characters in character literal"));
STRING_FREE;
BEGIN INITIAL;
- return CHAR;
+ return CHAR_LITERAL;
}
YY_BREAK
case 95:
--- src/symtab.c
+++ src/symtab.c
@@ -52,7 +52,7 @@ static semantic_type **semantic_types_sorted = NULL;
symbol *errtoken = NULL;
symbol *undeftoken = NULL;
symbol *endtoken = NULL;
-symbol *accept = NULL;
+symbol *bison_accept = NULL;
symbol *startsymbol = NULL;
location startsymbol_loc;
@@ -843,9 +843,9 @@ symbols_new (void)
symbol_free);
/* Construct the accept symbol. */
- accept = symbol_get ("$accept", empty_loc);
- accept->content->class = nterm_sym;
- accept->content->number = nvars++;
+ bison_accept = symbol_get ("$accept", empty_loc);
+ bison_accept->content->class = nterm_sym;
+ bison_accept->content->number = nvars++;
/* Construct the error token */
errtoken = symbol_get ("error", empty_loc);
--- src/symtab.h
+++ src/symtab.h
@@ -248,7 +248,7 @@ extern symbol *endtoken;
/** The genuine start symbol.
$accept: start-symbol $end */
-extern symbol *accept;
+extern symbol *bison_accept;
/** The user start symbol. */
extern symbol *startsymbol;
--- src/ielr.c
+++ src/ielr.c
@@ -429,7 +429,7 @@
check all predecessors' goto follows for the LHS. */
if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{
- aver (lhs != accept->content->number);
+ aver (lhs != bison_accept->content->number);
for (state **predecessor = predecessors[s->number];
*predecessor;
++predecessor)

View File

@@ -0,0 +1,753 @@
--- Makefile.in
+++ Makefile.in
@@ -637,10 +637,10 @@ am_src_bison_OBJECTS = src/bison-AnnotationList.$(OBJEXT) \
src/bison-main.$(OBJEXT) src/bison-muscle-tab.$(OBJEXT) \
src/bison-named-ref.$(OBJEXT) src/bison-nullable.$(OBJEXT) \
src/bison-output.$(OBJEXT) src/bison-parse-gram.$(OBJEXT) \
- src/bison-print-graph.$(OBJEXT) src/bison-print-xml.$(OBJEXT) \
- src/bison-print.$(OBJEXT) src/bison-reader.$(OBJEXT) \
- src/bison-reduce.$(OBJEXT) src/bison-relation.$(OBJEXT) \
- src/bison-scan-code-c.$(OBJEXT) \
+ src/bison-pathtools.$(OBJEXT) src/bison-print-graph.$(OBJEXT) \
+ src/bison-print-xml.$(OBJEXT) src/bison-print.$(OBJEXT) \
+ src/bison-reader.$(OBJEXT) src/bison-reduce.$(OBJEXT) \
+ src/bison-relation.$(OBJEXT) src/bison-scan-code-c.$(OBJEXT) \
src/bison-scan-gram-c.$(OBJEXT) \
src/bison-scan-skel-c.$(OBJEXT) src/bison-state.$(OBJEXT) \
src/bison-symlist.$(OBJEXT) src/bison-symtab.$(OBJEXT) \
@@ -878,6 +878,7 @@ am__depfiles_remade = examples/c++/$(DEPDIR)/simple-simple.Po \
src/$(DEPDIR)/bison-named-ref.Po \
src/$(DEPDIR)/bison-nullable.Po src/$(DEPDIR)/bison-output.Po \
src/$(DEPDIR)/bison-parse-gram.Po \
+ src/$(DEPDIR)/bison-pathtools.Po \
src/$(DEPDIR)/bison-print-graph.Po \
src/$(DEPDIR)/bison-print-xml.Po src/$(DEPDIR)/bison-print.Po \
src/$(DEPDIR)/bison-reader.Po src/$(DEPDIR)/bison-reduce.Po \
@@ -3169,6 +3170,8 @@ src_bison_SOURCES = \
src/output.c \
src/output.h \
src/parse-gram.y \
+ src/pathtools.c \
+ src/pathtools.h \
src/print-graph.c \
src/print-graph.h \
src/print-xml.c \
@@ -3992,6 +3995,8 @@ src/bison-output.$(OBJEXT): src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/bison-parse-gram.$(OBJEXT): src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
+src/bison-pathtools.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
src/bison-print-graph.$(OBJEXT): src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/bison-print-xml.$(OBJEXT): src/$(am__dirstamp) \
@@ -4317,6 +4322,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-nullable.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-output.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-parse-gram.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-pathtools.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-print-graph.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-print-xml.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bison-print.Po@am__quote@ # am--include-marker
@@ -7283,6 +7289,20 @@ src/bison-parse-gram.obj: src/parse-gram.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bison_CPPFLAGS) $(CPPFLAGS) $(src_bison_CFLAGS) $(CFLAGS) -c -o src/bison-parse-gram.obj `if test -f 'src/parse-gram.c'; then $(CYGPATH_W) 'src/parse-gram.c'; else $(CYGPATH_W) '$(srcdir)/src/parse-gram.c'; fi`
+src/bison-pathtools.o: src/pathtools.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bison_CPPFLAGS) $(CPPFLAGS) $(src_bison_CFLAGS) $(CFLAGS) -MT src/bison-pathtools.o -MD -MP -MF src/$(DEPDIR)/bison-pathtools.Tpo -c -o src/bison-pathtools.o `test -f 'src/pathtools.c' || echo '$(srcdir)/'`src/pathtools.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/bison-pathtools.Tpo src/$(DEPDIR)/bison-pathtools.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pathtools.c' object='src/bison-pathtools.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bison_CPPFLAGS) $(CPPFLAGS) $(src_bison_CFLAGS) $(CFLAGS) -c -o src/bison-pathtools.o `test -f 'src/pathtools.c' || echo '$(srcdir)/'`src/pathtools.c
+
+src/bison-pathtools.obj: src/pathtools.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bison_CPPFLAGS) $(CPPFLAGS) $(src_bison_CFLAGS) $(CFLAGS) -MT src/bison-pathtools.obj -MD -MP -MF src/$(DEPDIR)/bison-pathtools.Tpo -c -o src/bison-pathtools.obj `if test -f 'src/pathtools.c'; then $(CYGPATH_W) 'src/pathtools.c'; else $(CYGPATH_W) '$(srcdir)/src/pathtools.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/bison-pathtools.Tpo src/$(DEPDIR)/bison-pathtools.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pathtools.c' object='src/bison-pathtools.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bison_CPPFLAGS) $(CPPFLAGS) $(src_bison_CFLAGS) $(CFLAGS) -c -o src/bison-pathtools.obj `if test -f 'src/pathtools.c'; then $(CYGPATH_W) 'src/pathtools.c'; else $(CYGPATH_W) '$(srcdir)/src/pathtools.c'; fi`
+
src/bison-print-graph.o: src/print-graph.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_bison_CPPFLAGS) $(CPPFLAGS) $(src_bison_CFLAGS) $(CFLAGS) -MT src/bison-print-graph.o -MD -MP -MF src/$(DEPDIR)/bison-print-graph.Tpo -c -o src/bison-print-graph.o `test -f 'src/print-graph.c' || echo '$(srcdir)/'`src/print-graph.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/bison-print-graph.Tpo src/$(DEPDIR)/bison-print-graph.Po
@@ -9079,6 +9099,7 @@ distclean: distclean-recursive
-rm -f src/$(DEPDIR)/bison-nullable.Po
-rm -f src/$(DEPDIR)/bison-output.Po
-rm -f src/$(DEPDIR)/bison-parse-gram.Po
+ -rm -f src/$(DEPDIR)/bison-pathtools.Po
-rm -f src/$(DEPDIR)/bison-print-graph.Po
-rm -f src/$(DEPDIR)/bison-print-xml.Po
-rm -f src/$(DEPDIR)/bison-print.Po
@@ -9464,6 +9485,7 @@ maintainer-clean: maintainer-clean-recursive
-rm -f src/$(DEPDIR)/bison-nullable.Po
-rm -f src/$(DEPDIR)/bison-output.Po
-rm -f src/$(DEPDIR)/bison-parse-gram.Po
+ -rm -f src/$(DEPDIR)/bison-pathtools.Po
-rm -f src/$(DEPDIR)/bison-print-graph.Po
-rm -f src/$(DEPDIR)/bison-print-xml.Po
-rm -f src/$(DEPDIR)/bison-print.Po
--- src/files.c
+++ src/files.c
@@ -1,4 +1,5 @@
/* Open and close files for Bison.
+ rse-gram.Po
Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2020 Free
Software Foundation, Inc.
@@ -35,6 +36,7 @@
#include "files.h"
#include "getargs.h"
#include "gram.h"
+#include "pathtools.h"
/* Initializing some values below (such SPEC_NAME_PREFIX to 'yy') is
tempting, but don't do that: for the time being our handling of the
@@ -417,7 +419,11 @@ pkgdatadir (void)
else
{
char const *cp = getenv ("BISON_PKGDATADIR");
- return cp ? cp : relocate2 (PKGDATADIR, &relocate_buffer);
+ if (cp) {
+ return cp;
+ }
+ const char *_dir = single_path_relocation(BINDIR, PKGDATADIR);
+ return _dir;
}
}
--- src/local.mk
+++ src/local.mk
@@ -71,6 +71,8 @@ src_bison_SOURCES = \
src/output.c \
src/output.h \
src/parse-gram.y \
+ src/pathtools.c \
+ src/pathtools.h \
src/print-graph.c \
src/print-graph.h \
src/print-xml.c \
--- src/output.c
+++ src/output.c
@@ -21,6 +21,7 @@
#include <config.h>
#include "system.h"
+#include <configmake.h>
#include <filename.h> /* IS_PATH_WITH_DIR */
#include <get-errno.h>
#include <path-join.h>
@@ -41,6 +42,7 @@
#include "scan-skel.h"
#include "symtab.h"
#include "tables.h"
+#include "pathtools.h"
static struct obstack format_obstack;
@@ -573,7 +575,7 @@ static void
output_skeleton (void)
{
/* Compute the names of the package data dir and skeleton files. */
- char const *m4 = (m4 = getenv ("M4")) ? m4 : M4;
+ char const *m4 = (m4 = getenv ("M4")) ? m4 : "m4" EXEEXT; //single_path_relocation(BINDIR, M4);
char const *datadir = pkgdatadir ();
char *skeldir = xpath_join (datadir, "skeletons");
char *m4sugar = xpath_join (datadir, "m4sugar/m4sugar.m4");
--- /dev/null
+++ src/pathtools.c
@@ -0,0 +1,536 @@
+/*
+ .Some useful path tools.
+ .ASCII only for now.
+ .Written by Ray Donnelly in 2014.
+ .Licensed under CC0 (and anything.
+ .else you need to license it under).
+ .No warranties whatsoever.
+ .email: <mingw.android@gmail.com>.
+ */
+
+#include "config.h"
+#if defined(__APPLE__)
+#include <stdlib.h>
+#else
+#include <stddef.h>
+#include <malloc.h>
+#endif
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(__linux__)
+#include <alloca.h>
+#endif
+#include <unistd.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+/* If you don't define this, then get_executable_path()
+ can only use argv[0] which will often not work well */
+#define IMPLEMENT_SYS_GET_EXECUTABLE_PATH
+
+#if defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH)
+#if defined(__linux__)
+/* Nothing needed, unistd.h is enough. */
+#elif defined(__APPLE__)
+#include <mach-o/dyld.h>
+#elif defined(_WIN32)
+#define WIN32_MEAN_AND_LEAN
+#include <windows.h>
+#include <psapi.h>
+#endif
+#endif /* defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) */
+
+#include "pathtools.h"
+
+char *
+malloc_copy_string(char const * original)
+{
+ char * result = (char *) malloc (sizeof (char*) * strlen (original)+1);
+ if (result != NULL)
+ {
+ strcpy (result, original);
+ }
+ return result;
+}
+
+void
+sanitise_path(char * path)
+{
+ size_t path_size = strlen (path);
+
+ /* Replace any '\' with '/' */
+ char * path_p = path;
+ while ((path_p = strchr (path_p, '\\')) != NULL)
+ {
+ *path_p = '/';
+ }
+ /* Replace any '//' with '/' */
+ path_p = path;
+ while ((path_p = strstr (path_p, "//")) != NULL)
+ {
+ memmove (path_p, path_p + 1, path_size--);
+ }
+ return;
+}
+
+char *
+get_relative_path(char const * from_in, char const * to_in)
+{
+ size_t from_size = (from_in == NULL) ? 0 : strlen (from_in);
+ size_t to_size = (to_in == NULL) ? 0 : strlen (to_in);
+ size_t max_size = (from_size + to_size) * 2 + 4;
+ char * scratch_space = (char *) alloca (from_size + 1 + to_size + 1 + max_size + max_size);
+ char * from;
+ char * to;
+ char * common_part;
+ char * result;
+ size_t count;
+
+ /* No to, return "./" */
+ if (to_in == NULL)
+ {
+ return malloc_copy_string ("./");
+ }
+
+ /* If alloca failed or no from was given return a copy of to */
+ if ( from_in == NULL
+ || scratch_space == NULL )
+ {
+ return malloc_copy_string (to_in);
+ }
+
+ from = scratch_space;
+ strcpy (from, from_in);
+ to = from + from_size + 1;
+ strcpy (to, to_in);
+ common_part = to + to_size + 1;
+ result = common_part + max_size;
+ simplify_path (from);
+ simplify_path (to);
+
+ result[0] = '\0';
+
+ size_t match_size_dirsep = 0; /* The match size up to the last /. Always wind back to this - 1 */
+ size_t match_size = 0; /* The running (and final) match size. */
+ size_t largest_size = (from_size > to_size) ? from_size : to_size;
+ int to_final_is_slash = (to[to_size-1] == '/') ? 1 : 0;
+ char from_c;
+ char to_c;
+ for (match_size = 0; match_size < largest_size; ++match_size)
+ {
+ /* To simplify the logic, always pretend the strings end with '/' */
+ from_c = (match_size < from_size) ? from[match_size] : '/';
+ to_c = (match_size < to_size) ? to[match_size] : '/';
+
+ if (from_c != to_c)
+ {
+ if (from_c != '\0' || to_c != '\0')
+ {
+ match_size = match_size_dirsep;
+ }
+ break;
+ }
+ else if (from_c == '/')
+ {
+ match_size_dirsep = match_size;
+ }
+ }
+ strncpy (common_part, from, match_size);
+ common_part[match_size] = '\0';
+ from += match_size;
+ to += match_size;
+ size_t ndotdots = 0;
+ char const* from_last = from + strlen(from) - 1;
+ while ((from = strchr (from, '/')) && from != from_last)
+ {
+ ++ndotdots;
+ ++from;
+ }
+ for (count = 0; count < ndotdots; ++count)
+ {
+ strcat(result, "../");
+ }
+ if (strlen(to) > 0)
+ {
+ strcat(result, to+1);
+ }
+ /* Make sure that if to ends with '/' result does the same, and
+ vice-versa. */
+ size_t size_result = strlen(result);
+ if ((to_final_is_slash == 1)
+ && (!size_result || result[size_result-1] != '/'))
+ {
+ strcat (result, "/");
+ }
+ else if (!to_final_is_slash
+ && size_result && result[size_result-1] == '/')
+ {
+ result[size_result-1] = '\0';
+ }
+
+ return malloc_copy_string (result);
+}
+
+void
+simplify_path(char * path)
+{
+ ssize_t n_toks = 1; /* in-case we need an empty initial token. */
+ ssize_t i, j;
+ size_t tok_size;
+ size_t in_size = strlen (path);
+ int it_ended_with_a_slash = (path[in_size - 1] == '/') ? 1 : 0;
+ char * result = path;
+ sanitise_path(result);
+ char * result_p = result;
+
+ do
+ {
+ ++n_toks;
+ ++result_p;
+ } while ((result_p = strchr (result_p, '/')) != NULL);
+
+ result_p = result;
+ char ** toks = (char **) alloca (sizeof (char const*) * n_toks);
+ n_toks = 0;
+ do
+ {
+ if (result_p > result)
+ {
+ *result_p++ = '\0';
+ }
+ else if (*result_p == '/')
+ {
+ /* A leading / creates an empty initial token. */
+ toks[n_toks++] = result_p;
+ *result_p++ = '\0';
+ }
+ toks[n_toks++] = result_p;
+ } while ((result_p = strchr (result_p, '/')) != NULL);
+
+ /* Remove all non-leading '.' and any '..' we can match
+ with an earlier forward path (i.e. neither '.' nor '..') */
+ for (i = 1; i < n_toks; ++i)
+ {
+ int removals[2] = { -1, -1 };
+ if ( strcmp (toks[i], "." ) == 0)
+ {
+ removals[0] = i;
+ }
+ else if ( strcmp (toks[i], ".." ) == 0)
+ {
+ /* Search backwards for a forward path to collapse.
+ If none are found then the .. also stays. */
+ for (j = i - 1; j > -1; --j)
+ {
+ if ( strcmp (toks[j], "." )
+ && strcmp (toks[j], ".." ) )
+ {
+ removals[0] = j;
+ removals[1] = i;
+ break;
+ }
+ }
+ }
+ for (j = 0; j < 2; ++j)
+ {
+ if (removals[j] >= 0) /* Can become -2 */
+ {
+ --n_toks;
+ memmove (&toks[removals[j]], &toks[removals[j]+1], (n_toks - removals[j])*sizeof (char*));
+ --i;
+ if (!j)
+ {
+ --removals[1];
+ }
+ }
+ }
+ }
+ result_p = result;
+ for (i = 0; i < n_toks; ++i)
+ {
+ tok_size = strlen(toks[i]);
+ memcpy (result_p, toks[i], tok_size);
+ result_p += tok_size;
+ if ((!i || tok_size) && ((i < n_toks - 1) || it_ended_with_a_slash == 1))
+ {
+ *result_p = '/';
+ ++result_p;
+ }
+ }
+ *result_p = '\0';
+}
+
+/* Returns actual_to by calculating the relative path from -> to and
+ applying that to actual_from. An assumption that actual_from is a
+ dir is made, and it may or may not end with a '/' */
+char const *
+get_relocated_path (char const * from, char const * to, char const * actual_from)
+{
+ char const * relative_from_to = get_relative_path (from, to);
+ char * actual_to = (char *) malloc (strlen(actual_from) + 2 + strlen(relative_from_to));
+ return actual_to;
+}
+
+int
+get_executable_path(char const * argv0, char * result, ssize_t max_size)
+{
+ char * system_result = (char *) alloca (max_size);
+ ssize_t system_result_size = -1;
+ ssize_t result_size = -1;
+
+ if (system_result != NULL)
+ {
+#if defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH)
+#if defined(__linux__)
+ system_result_size = readlink("/proc/self/exe", system_result, max_size);
+#elif defined(__APPLE__)
+ uint32_t bufsize = (uint32_t)max_size;
+ if (_NSGetExecutablePath(system_result, &bufsize) == 0)
+ {
+ system_result_size = (ssize_t)bufsize;
+ }
+#elif defined(_WIN32)
+ unsigned long bufsize = (unsigned long)max_size;
+ system_result_size = GetModuleFileNameA(NULL, system_result, bufsize);
+ if (system_result_size == 0 || system_result_size == (ssize_t)bufsize)
+ {
+ /* Error, possibly not enough space. */
+ system_result_size = -1;
+ }
+ else
+ {
+ /* Early conversion to unix slashes instead of more changes
+ everywhere else .. */
+ char * winslash;
+ system_result[system_result_size] = '\0';
+ while ((winslash = strchr (system_result, '\\')) != NULL)
+ {
+ *winslash = '/';
+ }
+ }
+#else
+#warning "Don't know how to get executable path on this system"
+#endif
+#endif /* defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) */
+ }
+ /* Use argv0 as a default in-case of failure */
+ if (system_result_size != -1)
+ {
+ strncpy (result, system_result, system_result_size);
+ result[system_result_size] = '\0';
+ }
+ else
+ {
+ if (argv0 != NULL)
+ {
+ strncpy (result, argv0, max_size);
+ result[max_size-1] = '\0';
+ }
+ else
+ {
+ result[0] = '\0';
+ }
+ }
+ result_size = strlen (result);
+ return result_size;
+}
+
+char const *
+strip_n_prefix_folders(char const * path, size_t n)
+{
+ if (path == NULL)
+ {
+ return NULL;
+ }
+
+ if (path[0] != '/')
+ {
+ return path;
+ }
+
+ char const * last = path;
+ while (n-- && path != NULL)
+ {
+ last = path;
+ path = strchr (path + 1, '/');
+ }
+ return (path == NULL) ? last : path;
+}
+
+void
+strip_n_suffix_folders(char * path, size_t n)
+{
+ if (path == NULL)
+ {
+ return;
+ }
+ while (n--)
+ {
+ if (strrchr (path + 1, '/'))
+ {
+ *strrchr (path + 1, '/') = '\0';
+ }
+ else
+ {
+ return;
+ }
+ }
+ return;
+}
+
+size_t
+split_path_list(char const * path_list, char split_char, char *** arr)
+{
+ size_t path_count;
+ size_t path_list_size;
+ char const * path_list_p;
+
+ path_list_p = path_list;
+ if (path_list == NULL || path_list[0] == '\0')
+ {
+ return 0;
+ }
+ path_list_size = strlen (path_list);
+
+ path_count = 0;
+ do
+ {
+ ++path_count;
+ ++path_list_p;
+ }
+ while ((path_list_p = strchr (path_list_p, split_char)) != NULL);
+
+ /* allocate everything in one go. */
+ char * all_memory = (char *) malloc (sizeof (char *) * path_count + strlen(path_list) + 1);
+ if (all_memory == NULL)
+ return 0;
+ *arr = (char **)all_memory;
+ all_memory += sizeof (char *) * path_count;
+
+ path_count = 0;
+ path_list_p = path_list;
+ char const * next_path_list_p = 0;
+ do
+ {
+ next_path_list_p = strchr (path_list_p, split_char);
+ if (next_path_list_p != NULL)
+ {
+ ++next_path_list_p;
+ }
+ size_t this_size = (next_path_list_p != NULL)
+ ? next_path_list_p - path_list_p - 1
+ : &path_list[path_list_size] - path_list_p;
+ memcpy (all_memory, path_list_p, this_size);
+ all_memory[this_size] = '\0';
+ (*arr)[path_count++] = all_memory;
+ all_memory += this_size + 1;
+ } while ((path_list_p = next_path_list_p) != NULL);
+
+ return path_count;
+}
+
+char *
+get_relocated_path_list(char const * from, char const * to_path_list)
+{
+ char exe_path[32768];
+ char * temp;
+ get_executable_path (NULL, &exe_path[0], sizeof (exe_path) / sizeof (exe_path[0]));
+ if ((temp = strrchr (exe_path, '/')) != NULL)
+ {
+ temp[1] = '\0';
+ }
+
+ char **arr = NULL;
+ /* Ask Alexey why he added this. Are we not 100% sure
+ that we're dealing with unix paths here? */
+ char split_char = ':';
+ if (strchr (to_path_list, ';'))
+ {
+ split_char = ';';
+ }
+ size_t count = split_path_list (to_path_list, split_char, &arr);
+ int result_size = 1 + (count - 1); /* count - 1 is for ; delim. */
+ size_t exe_path_size = strlen (exe_path);
+ size_t i;
+ /* Space required is:
+ count * (exe_path_size + strlen (rel_to_datadir))
+ rel_to_datadir upper bound is:
+ (count * strlen (from)) + (3 * num_slashes (from))
+ + strlen(arr[i]) + 1.
+ .. pathalogically num_slashes (from) is strlen (from)
+ (from = ////////) */
+ size_t space_required = (count * (exe_path_size + 4 * strlen (from))) + count - 1;
+ for (i = 0; i < count; ++i)
+ {
+ space_required += strlen (arr[i]);
+ }
+ char * scratch = (char *) alloca (space_required);
+ if (scratch == NULL)
+ return NULL;
+ for (i = 0; i < count; ++i)
+ {
+ char * rel_to_datadir = get_relative_path (from, arr[i]);
+ scratch[0] = '\0';
+ arr[i] = scratch;
+ strcat (scratch, exe_path);
+ strcat (scratch, rel_to_datadir);
+ simplify_path (arr[i]);
+ size_t arr_i_size = strlen (arr[i]);
+ result_size += arr_i_size;
+ scratch = arr[i] + arr_i_size + 1;
+ }
+ char * result = (char *) malloc (result_size);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+ result[0] = '\0';
+ for (i = 0; i < count; ++i)
+ {
+ strcat (result, arr[i]);
+ if (i != count-1)
+ {
+#if defined(_WIN32)
+ strcat (result, ";");
+#else
+ strcat (result, ":");
+#endif
+ }
+ }
+ free ((void*)arr);
+ return result;
+}
+
+char *
+single_path_relocation(const char *from, const char *to)
+{
+ char exe_path[PATH_MAX];
+ get_executable_path (NULL, &exe_path[0], sizeof(exe_path)/sizeof(exe_path[0]));
+ if (strrchr (exe_path, '/') != NULL)
+ {
+ strrchr (exe_path, '/')[1] = '\0';
+ }
+ char * rel_to_datadir = get_relative_path (from, to);
+ strcat (exe_path, rel_to_datadir);
+ simplify_path (&exe_path[0]);
+ return malloc_copy_string(exe_path);
+}
+
+char *
+pathlist_relocation(const char *from_path, const char *to_path_list)
+{
+ static char stored_path[PATH_MAX];
+ static int stored = 0;
+ if (stored == 0)
+ {
+ char const * relocated = get_relocated_path_list(from_path, to_path_list);
+ strncpy (stored_path, relocated, PATH_MAX);
+ stored_path[PATH_MAX-1] = '\0';
+ free ((void *)relocated);
+ stored = 1;
+ }
+ return stored_path;
+}
--- /dev/null
+++ src/pathtools.h
@@ -0,0 +1,53 @@
+/*
+ .Some useful path tools.
+ .ASCII only for now.
+ .Written by Ray Donnelly in 2014.
+ .Licensed under CC0 (and anything.
+ .else you need to license it under).
+ .No warranties whatsoever.
+ .email: <mingw.android@gmail.com>.
+ */
+
+#ifndef PATHTOOLS_H
+#define PATHTOOLS_H
+
+#include <unistd.h>
+#if defined(__APPLE__)
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <stdio.h>
+
+char * malloc_copy_string(char const * original);
+
+/* In-place replaces any '\' with '/' and any '//' with '/' */
+void sanitise_path(char * path);
+
+/* Uses a host OS specific function to determine the path of the executable,
+ if IMPLEMENT_SYS_GET_EXECUTABLE_PATH is defined, otherwise uses argv0. */
+int get_executable_path(char const * argv0, char * result, ssize_t max_size);
+
+/* Where possible, in-place removes occourances of '.' and 'path/..' */
+void simplify_path(char * path);
+
+/* Allocates (via malloc) and returns the path to get from from to to. */
+char * get_relative_path(char const * from, char const * to);
+
+size_t split_path_list(char const * path_list, char split_char, char *** arr);
+
+/* Advances path along by the amount that removes n prefix folders. */
+char const *
+strip_n_prefix_folders(char const * path, size_t n);
+
+/* NULL terminates path to remove n suffix folders. */
+void
+strip_n_suffix_folders(char * path, size_t n);
+
+char const * get_relocated_path (char const * from, char const * to, char const * actual_from);
+char * get_relocated_path_list(char const * from, char const * to_path_list);
+
+char * single_path_relocation(const char *from, const char *to);
+char * pathlist_relocation(const char *from_path, const char *to_path_list);
+
+#endif /* PATHTOOLS_H */
--
2.21.1

View File

@@ -0,0 +1,38 @@
This avoid showing a `Assertion Failed Dialog Box` during configure and running bison with the assertion failur:
```
Expression: new_maximum >= _IOB_ENTRIES && new_maximum <= _NHANDLE_
```
msdn documentation of _setmaxstdio at
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setmaxstdio
Summary:
maximum of 8192 is a hard upper limit for the number of simultaneously open files accessed through the C run-time library.
Kudos to @SSE4 for finding the rootcause at
https://github.com/conan-io/conan-center-index/pull/2334#issuecomment-668171405
--- lib/getdtablesize.c
+++ lib/getdtablesize.c
@@ -79,12 +79,18 @@ getdtablesize (void)
freed when we call _setmaxstdio with the original value. */
int orig_max_stdio = _getmaxstdio ();
unsigned int bound;
- for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2)
+#ifdef _MSC_VER
+# define BOUND_START 0x2000
+#else
+# define BOUND_START 0x10000
+#endif
+ for (bound = BOUND_START; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2)
;
_setmaxstdio_nothrow (orig_max_stdio);
dtablesize = bound;
}
return dtablesize;
+#undef BOUND_START
}
#else

View File

@@ -0,0 +1,14 @@
build: don't link bison against libreadline
Reported by Paul Smith <psmith@gnu.org>.
https://lists.gnu.org/r/bug-bison/2020-10/msg00001.html
--- a/Makefile.in
+++ b/Makefile.in
@@ -3456,7 +3456,6 @@
$(LIB_SETLOCALE_NULL) \
$(LIBICONV) \
$(LIBINTL) \
- $(LIBREADLINE) \
$(LIBTEXTSTYLE)
@ENABLE_YACC_TRUE@nodist_bin_SCRIPTS = src/yacc

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES CXX)
find_package(BISON REQUIRED)
set(BISON_VARS
BISON_FOUND
BISON_EXECUTABLE
BISON_VERSION
)
foreach(BISON_VAR ${BISON_VARS})
message("${BISON_VAR}: ${${BISON_VAR}}")
if(NOT ${BISON_VAR})
message(FATAL_ERROR "${BISON_VAR} NOT FOUND")
endif()
endforeach()
bison_target(McParser mc_parser.yy "${CMAKE_CURRENT_BINARY_DIR}/mc_parser.cpp")
add_library(${PROJECT_NAME} STATIC ${BISON_McParser_OUTPUTS})

View File

@@ -0,0 +1,9 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,38 @@
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
from conan.tools.microsoft import unix_path
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv"
test_type = "explicit"
win_bash = True
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
def layout(self):
cmake_layout(self)
def build_requirements(self):
self.tool_requires(self.tested_reference_str)
if self._settings_build.os == "Windows":
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
@property
def _mc_parser_source(self):
return os.path.join(self.source_folder, "mc_parser.yy")
def test(self):
self.run("bison --version")
self.run("yacc --version")
self.run(f"bison -d {unix_path(self, self._mc_parser_source)}")

View File

@@ -0,0 +1,42 @@
%{
#include <iostream>
#include <string>
#include <map>
#include <cstdlib> //-- I need this for atoi
using namespace std;
int yylex();
int yyerror(const char *p) { cerr << "Error!" << endl; return 42; }
%}
%union {
int val;
char sym;
};
%token <val> NUM
%token <sym> OPA OPM LP RP STOP
%type <val> exp term sfactor factor res
%%
run: res run | res /* forces bison to process many stmts */
res: exp STOP { cout << $1 << endl; }
exp: exp OPA term { $$ = ($2 == '+' ? $1 + $3 : $1 - $3); }
| term { $$ = $1; }
term: term OPM factor { $$ = ($2 == '*' ? $1 * $3 : $1 / $3); }
| sfactor { $$ = $1; }
sfactor: OPA factor { $$ = ($1 == '+' ? $2 : -$2); }
| factor { $$ = $1; }
factor: NUM { $$ = $1; }
| LP exp RP { $$ = $2; }
%%
int main()
{
yyparse();
return 0;
}

9
recipes/bison/config.yml Normal file
View File

@@ -0,0 +1,9 @@
versions:
"3.8.2":
folder: all
"3.7.6":
folder: all
"3.7.1":
folder: all
"3.5.3":
folder: all

View File

@@ -0,0 +1,31 @@
sources:
"2.6.4":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_6_4/expat-2.6.4.tar.xz"
sha256: "a695629dae047055b37d50a0ff4776d1d45d0a4c842cf4ccee158441f55ff7ee"
"2.6.3":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_6_3/expat-2.6.3.tar.xz"
sha256: "274db254a6979bde5aad404763a704956940e465843f2a9bd9ed7af22e2c0efc"
"2.6.2":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_6_2/expat-2.6.2.tar.xz"
sha256: "ee14b4c5d8908b1bec37ad937607eab183d4d9806a08adee472c3c3121d27364"
"2.6.0":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_6_0/expat-2.6.0.tar.xz"
sha256: "cb5f5a8ea211e1cabd59be0a933a52e3c02cc326e86a4d387d8d218e7ee47a3e"
"2.5.0":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.xz"
sha256: "ef2420f0232c087801abf705e89ae65f6257df6b7931d37846a193ef2e8cdcbe"
"2.4.9":
sha256: "6e8c0728fe5c7cd3f93a6acce43046c5e4736c7b4b68e032e9350daa0efc0354"
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_4_9/expat-2.4.9.tar.xz"
"2.4.8":
sha256: "f79b8f904b749e3e0d20afeadecf8249c55b2e32d4ebb089ae378df479dcaf25"
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.xz"
"2.3.0":
sha256: "89df123c62f2c2e2b235692d9fe76def6a9ab03dbe95835345bf412726eb1987"
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_3_0/expat-2.3.0.tar.gz"
"2.2.10":
sha256: "bf42d1f52371d23684de36cc6d2f0f1acd02de264d1105bdc17792bbeb7e7ceb"
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/libexpat/libexpat/releases/download/R_2_2_10/expat-2.2.10.tar.gz"
patches:
"2.3.0":
- patch_file: "patches/0001-2.3.0-relax-vs-restriction.patch"

View File

@@ -0,0 +1,102 @@
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.files import apply_conandata_patches, collect_libs, copy, export_conandata_patches, get, rmdir
from conan.tools.microsoft import is_msvc, is_msvc_static_runtime
import os
required_conan_version = ">=1.53.0"
class ExpatConan(ConanFile):
name = "expat"
description = "Fast streaming XML parser written in C."
license = "MIT"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/libexpat/libexpat"
topics = ("xml", "parsing")
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"char_type": ["char", "wchar_t", "ushort"],
"large_size": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"char_type": "char",
"large_size": False,
}
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.cppstd")
self.settings.rm_safe("compiler.libcxx")
def layout(self):
cmake_layout(self, src_folder="src")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
tc = CMakeToolchain(self)
tc.variables["EXPAT_BUILD_DOCS"] = False
tc.variables["EXPAT_BUILD_EXAMPLES"] = False
tc.variables["EXPAT_SHARED_LIBS"] = self.options.shared
tc.variables["EXPAT_BUILD_TESTS"] = False
tc.variables["EXPAT_BUILD_TOOLS"] = False
tc.variables["EXPAT_CHAR_TYPE"] = self.options.char_type
if is_msvc(self):
tc.variables["EXPAT_MSVC_STATIC_CRT"] = is_msvc_static_runtime(self)
tc.variables["EXPAT_BUILD_PKGCONFIG"] = False
tc.variables["EXPAT_LARGE_SIZE"] = self.options.large_size
tc.generate()
def build(self):
apply_conandata_patches(self)
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
rmdir(self, os.path.join(self.package_folder, "share"))
def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_module_file_name", "EXPAT")
self.cpp_info.set_property("cmake_module_target_name", "EXPAT::EXPAT")
self.cpp_info.set_property("cmake_file_name", "expat")
self.cpp_info.set_property("cmake_target_name", "expat::expat")
self.cpp_info.set_property("pkg_config_name", "expat")
self.cpp_info.libs = collect_libs(self)
if not self.options.shared:
self.cpp_info.defines = ["XML_STATIC"]
if self.options.get_safe("char_type") in ("wchar_t", "ushort"):
self.cpp_info.defines.append("XML_UNICODE")
elif self.options.get_safe("char_type") == "wchar_t":
self.cpp_info.defines.append("XML_UNICODE_WCHAR_T")
if self.options.large_size:
self.cpp_info.defines.append("XML_LARGE_SIZE")
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.append("m")
# TODO: to remove in conan v2
self.cpp_info.names["cmake_find_package"] = "EXPAT"
self.cpp_info.names["cmake_find_package_multi"] = "expat"

View File

@@ -0,0 +1,13 @@
diff --git a/expat/CMakeLists.txt b/expat/CMakeLists.txt
index e3564691..0dc5cf80 100644
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -133,7 +133,7 @@ if(MSVC)
# Minimum supported MSVC version is 1910 = Visual Studio 15.0/2017
# See also https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html
if(MSVC_VERSION VERSION_LESS 1910)
- message(SEND_ERROR "MSVC_VERSION ${MSVC_VERSION} is not a supported Visual Studio compiler version. Please use Visual Studio 15.0/2017 or any later version.")
+ message(WARNING "MSVC_VERSION ${MSVC_VERSION} is not a supported Visual Studio compiler version. Please use Visual Studio 15.0/2017 or any later version.")
endif()
endif()

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES C)
find_package(expat REQUIRED CONFIG)
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE expat::expat)

View File

@@ -0,0 +1,10 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json",
"build/gcc-11.5-x86_64-17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")

View File

@@ -0,0 +1,64 @@
/* This is simple demonstration of how to use expat. This program
reads an XML document from standard input and writes a line with
the name of each element to standard output indenting child
elements by one tab stop more than their parent element.
It must be used with Expat compiled for UTF-8 output.
*/
#include <stdio.h>
#include "expat.h"
#ifdef XML_UNICODE_WCHAR_T
#include <wchar.h>
#endif
#ifdef XML_LARGE_SIZE
#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
#define XML_FMT_INT_MOD "I64"
#else
#define XML_FMT_INT_MOD "ll"
#endif
#else
#define XML_FMT_INT_MOD "l"
#endif
static void XMLCALL
startElement(void *userData, const XML_Char *name, const XML_Char **atts)
{
int i;
int *depthPtr = (int *)userData;
(void)atts;
for (i = 0; i < *depthPtr; i++)
putchar('\t');
#ifdef XML_UNICODE_WCHAR_T
fputws(name, stdout);
#else
puts(name);
#endif
*depthPtr += 1;
}
static void XMLCALL
endElement(void *userData, const XML_Char *name)
{
int *depthPtr = (int *)userData;
(void)name;
*depthPtr -= 1;
}
int
main(int argc, char *argv[])
{
XML_Parser parser = XML_ParserCreate(NULL);
int depth = 0;
(void)argc;
(void)argv;
XML_SetUserData(parser, &depth);
XML_SetElementHandler(parser, startElement, endElement);
XML_ParserFree(parser);
printf("Test application successfully ran!\n");
return 0;
}

View File

@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.10)
project(test_package LANGUAGES C)
find_package(EXPAT REQUIRED MODULE)
add_executable(${PROJECT_NAME} ../test_package/test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE EXPAT::EXPAT)
# Test whether variables from https://cmake.org/cmake/help/latest/module/FindEXPAT.html
# are properly defined in conan generators
set(_custom_vars
EXPAT_INCLUDE_DIRS
EXPAT_LIBRARIES
EXPAT_FOUND
)
foreach(_custom_var ${_custom_vars})
if(DEFINED ${_custom_var})
message(STATUS "${_custom_var}: ${${_custom_var}}")
else()
message(FATAL_ERROR "${_custom_var} not defined")
endif()
endforeach()

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES C)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/)

View File

@@ -0,0 +1,18 @@
from conans import ConanFile, CMake
from conan.tools.build import cross_building
import os
class TestPackageV1Conan(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 cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES C)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package_module/
${CMAKE_CURRENT_BINARY_DIR}/test_package_module/)

View File

@@ -0,0 +1,18 @@
from conans import ConanFile, CMake
from conan.tools.build import cross_building
import os
class TestPackageV1Conan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if not cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

19
recipes/expat/config.yml Normal file
View File

@@ -0,0 +1,19 @@
versions:
"2.6.4":
folder: all
"2.6.3":
folder: all
"2.6.2":
folder: all
"2.6.0":
folder: all
"2.5.0":
folder: all
"2.4.9":
folder: all
"2.4.8":
folder: all
"2.3.0":
folder: all
"2.2.10":
folder: all

View File

@@ -154,7 +154,7 @@ class FFMpegConan(ConanFile):
"with_coreimage": True,
"with_audiotoolbox": True,
"with_videotoolbox": True,
"with_programs": False,
"with_programs": True,
"with_libsvtav1": True,
"with_libaom": True,
"with_libdav1d": True,
@@ -367,15 +367,15 @@ class FFMpegConan(ConanFile):
def build_requirements(self):
if self.settings.arch in ("x86", "x86_64"):
#if Version(self.version) >= "7.0":
# if Version(self.version) >= "7.0":
# INFO: FFmpeg 7.0+ added avcodec vvc_mc.asm which fails to assemble with yasm 1.3.0
# src/libavcodec/x86/vvc/vvc_mc.asm:55: error: operand 1: expression is not simple or relocatable
# self.tool_requires("nasm/2.16.01")
#else:
#self.tool_requires("yasm/1.3.0")
self.tool_requires("nasm/[>=2.16.01]")
if not self.conf.get("tools.gnu:pkg_config", check_type=str):
self.tool_requires("pkgconf/[>=2.1.0]")
# else:
# self.tool_requires("yasm/1.3.0")
if self.settings.os != "Linux" and not self.conf.get("tools.gnu:pkg_config", check_type=str):
# See https://github.com/conan-io/conan-center-index/pull/26447#discussion_r1926682155
self.tool_requires("pkgconf/[>=2.1 <3]")
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
@@ -643,11 +643,12 @@ class FFMpegConan(ConanFile):
ranlib = buildenv_vars.get("RANLIB")
if ranlib:
args.append(f"--ranlib={unix_path(self, ranlib)}")
# for some reason pkgconf from conan can't find .pc files on Linux in the context of ffmpeg configure...
if self._settings_build.os != "Linux":
pkg_config = self.conf.get("tools.gnu:pkg_config", default=buildenv_vars.get("PKG_CONFIG"), check_type=str)
if pkg_config:
args.append(f"--pkg-config={unix_path(self, pkg_config)}")
pkg_config = self.conf.get("tools.gnu:pkg_config", default=buildenv_vars.get("PKG_CONFIG"), check_type=str)
if pkg_config:
# the ffmpeg configure script hardcodes the name of the executable,
# unlike other tools that use the PKG_CONFIG environment variable
# if we are aware the user has requested a specific pkg-config, we pass it to the configure script
args.append(f"--pkg-config={unix_path(self, pkg_config)}")
if is_msvc(self):
args.append("--toolchain=msvc")
if not check_min_vs(self, "190", raise_invalid=False):

View File

@@ -0,0 +1,16 @@
sources:
"2.15.0":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-freedesktop_org/software/fontconfig/release/fontconfig-2.15.0.tar.xz"
sha256: "63a0658d0e06e0fa886106452b58ef04f21f58202ea02a94c39de0d3335d7c0e"
"2.14.2":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-freedesktop_org/software/fontconfig/release/fontconfig-2.14.2.tar.xz"
sha256: "dba695b57bce15023d2ceedef82062c2b925e51f5d4cc4aef736cf13f60a468b"
"2.13.93":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-freedesktop_org/software/fontconfig/release/fontconfig-2.13.93.tar.gz"
sha256: "0f302a18ee52dde0793fe38b266bf269dfe6e0c0ae140e30d72c6cca5dc08db5"
patches:
"2.13.93":
- patch_file: "patches/0001-meson-win32.patch"
patch_type: "portability"
patch_source: "https://gitlab.freedesktop.org/fontconfig/fontconfig/-/commit/7bfbaecf819a8b1630dfc8f56126e31f985d5fb3"
patch_description: "Windows: Fix symlink privilege error detection"

View File

@@ -0,0 +1,132 @@
from conan import ConanFile
from conan.tools.apple import fix_apple_shared_install_name
from conan.tools.env import VirtualBuildEnv
from conan.tools.files import (
apply_conandata_patches, copy, export_conandata_patches, get,
rm, rmdir
)
from conan.tools.gnu import PkgConfigDeps
from conan.tools.layout import basic_layout
from conan.tools.meson import Meson, MesonToolchain
import os
required_conan_version = ">=1.64.0 <2 || >=2.2.0"
class FontconfigConan(ConanFile):
name = "fontconfig"
license = "MIT"
url = "https://github.com/conan-io/conan-center-index"
description = "Fontconfig is a library for configuring and customizing font access"
homepage = "https://gitlab.freedesktop.org/fontconfig/fontconfig"
topics = ("fonts", "freedesktop")
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
}
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")
def layout(self):
basic_layout(self, src_folder="src")
def requirements(self):
self.requires("freetype/2.13.2")
self.requires("expat/[>=2.6.2 <3]")
def build_requirements(self):
self.tool_requires("gperf/3.1")
# self.tool_requires("meson/1.4.0")
if not self.conf.get("tools.gnu:pkg_config", default=False, check_type=str):
self.tool_requires("pkgconf/[>=2.1.0]")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
deps = PkgConfigDeps(self)
deps.generate()
tc = MesonToolchain(self)
tc.project_options.update({
"doc": "disabled",
"nls": "disabled",
"tests": "disabled",
"tools": "disabled",
"sysconfdir": os.path.join("res", "etc"),
"datadir": os.path.join("res", "share"),
})
tc.generate()
def _patch_files(self):
apply_conandata_patches(self)
def build(self):
self._patch_files()
meson = Meson(self)
meson.configure()
meson.build()
def package(self):
copy(self, "COPYING", self.source_folder, os.path.join(self.package_folder, "licenses"))
meson = Meson(self)
meson.install()
rm(self, "*.pdb", self.package_folder, recursive=True)
rm(self, "*.conf", os.path.join(self.package_folder, "res", "etc", "fonts", "conf.d"))
rm(self, "*.def", os.path.join(self.package_folder, "lib"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
fix_apple_shared_install_name(self)
fix_msvc_libname(self)
def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "Fontconfig")
self.cpp_info.set_property("cmake_target_name", "Fontconfig::Fontconfig")
self.cpp_info.set_property("pkg_config_name", "fontconfig")
self.cpp_info.libs = ["fontconfig"]
if self.settings.os in ("Linux", "FreeBSD"):
self.cpp_info.system_libs.extend(["m", "pthread"])
fontconfig_path = os.path.join(self.package_folder, "res", "etc", "fonts")
self.runenv_info.append_path("FONTCONFIG_PATH", fontconfig_path)
# TODO: to remove in conan v2
self.cpp_info.names["cmake_find_package"] = "Fontconfig"
self.cpp_info.names["cmake_find_package_multi"] = "Fontconfig"
self.env_info.FONTCONFIG_PATH = fontconfig_path
def fix_msvc_libname(conanfile, remove_lib_prefix=True):
"""remove lib prefix & change extension to .lib in case of cl like compiler"""
if not conanfile.settings.get_safe("compiler.runtime"):
return
from conan.tools.files import rename
import glob
libdirs = getattr(conanfile.cpp.package, "libdirs")
for libdir in libdirs:
for ext in [".dll.a", ".dll.lib", ".a"]:
full_folder = os.path.join(conanfile.package_folder, libdir)
for filepath in glob.glob(os.path.join(full_folder, f"*{ext}")):
libname = os.path.basename(filepath)[0:-len(ext)]
if remove_lib_prefix and libname[0:3] == "lib":
libname = libname[3:]
rename(conanfile, filepath, os.path.join(os.path.dirname(filepath), f"{libname}.lib"))

View File

@@ -0,0 +1,19 @@
--- conf.d/link_confs.py
+++ conf.d/link_confs.py
@@ -3,6 +3,7 @@
import os
import sys
import argparse
+import platform
if __name__=='__main__':
parser = argparse.ArgumentParser()
@@ -26,7 +27,7 @@ if __name__=='__main__':
break
except OSError as e:
# Symlink privileges are not available
- if len(e.args) == 1 and 'privilege' in e.args[0]:
+ if platform.system().lower() == 'windows' and e.winerror == 1314:
break
raise
except FileExistsError:

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.14)
project(test_package LANGUAGES C)
find_package(Fontconfig REQUIRED)
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE Fontconfig::Fontconfig)
target_compile_features(${PROJECT_NAME} PRIVATE c_std_99)

View File

@@ -0,0 +1,10 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json",
"build/gcc-11.5-x86_64-17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
from conan.tools.build import can_run
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")

View File

@@ -0,0 +1,24 @@
#include <fontconfig/fontconfig.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
FcConfig* config = FcInitLoadConfigAndFonts();
FcPattern* pat = FcNameParse((const FcChar8*)"Arial");
FcConfigSubstitute(config, pat, FcMatchPattern);
FcDefaultSubstitute(pat);
char* fontFile;
FcResult result;
FcPattern* font = FcFontMatch(config, pat, &result);
if (font) {
FcChar8* file = NULL;
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
fontFile = (char*)file;
printf("%s\n",fontFile);
}
} else {
printf("Ops! I can't find any font!\n");
}
FcPatternDestroy(pat);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.1)
project(test_package C)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/
)

View File

@@ -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"
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)

View File

@@ -0,0 +1,7 @@
versions:
"2.15.0":
folder: all
"2.14.2":
folder: all
"2.13.93":
folder: all

View File

@@ -0,0 +1,7 @@
sources:
"3.1":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_gnu_org/pub/gnu/gperf/gperf-3.1.tar.gz"
sha256: "588546b945bba4b70b6a3a616e80b4ab466e3f33024a352fc2198112cdbb3ae2"
patches:
"3.1":
- patch_file: "patches/0001-remove-register-keyword.patch"

View File

@@ -0,0 +1,99 @@
from conan import ConanFile
from conan.tools.env import Environment, VirtualBuildEnv
from conan.tools.files import apply_conandata_patches, chdir, copy, export_conandata_patches, get, rmdir
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.layout import basic_layout
from conan.tools.microsoft import is_msvc, check_min_vs, unix_path
import os
required_conan_version = ">=1.57.0"
class GperfConan(ConanFile):
name = "gperf"
license = "GPL-3.0-or-later"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://www.gnu.org/software/gperf"
description = "GNU gperf is a perfect hash function generator"
topics = ("hash-generator", "hash")
settings = "os", "arch", "compiler", "build_type"
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
def export_sources(self):
export_conandata_patches(self)
def layout(self):
basic_layout(self, src_folder="src")
self.folders.build = self.folders.source
def package_id(self):
del self.info.settings.compiler
def build_requirements(self):
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
# gperf makefile relies on GNU Make behaviour
if self._settings_build.os == "FreeBSD":
self.tool_requires("make/4.4.1")
def source(self):
get(self, **self.conan_data["sources"][self.version],
destination=self.source_folder, strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
tc = AutotoolsToolchain(self)
if is_msvc(self) and check_min_vs(self, "180", raise_invalid=False):
tc.extra_cflags.append("-FS")
tc.extra_cxxflags.append("-FS")
tc.generate()
if is_msvc(self):
env = Environment()
compile_wrapper = unix_path(self, os.path.join(self.source_folder, "build-aux", "compile"))
ar_wrapper = unix_path(self, os.path.join(self.source_folder, "build-aux", "ar-lib"))
env.define("CC", f"{compile_wrapper} cl -nologo")
env.define("CXX", f"{compile_wrapper} cl -nologo")
env.append("CPPFLAGS", "-D_WIN32_WINNT=_WIN32_WINNT_WIN8")
env.define("LD", "link -nologo")
env.define("AR", f"{ar_wrapper} \"lib -nologo\"")
env.define("NM", "dumpbin -symbols")
env.define("OBJDUMP", ":")
env.define("RANLIB", ":")
env.define("STRIP", ":")
#Prevent msys2 from performing erroneous path conversions for C++ files
# when invoking cl.exe as this is already handled by the compile wrapper.
env.define("MSYS2_ARG_CONV_EXCL", "-Tp")
env.vars(self).save_script("conanbuild_gperf_msvc")
def build(self):
apply_conandata_patches(self)
autotools = Autotools(self)
with chdir(self, self.source_folder):
autotools.configure()
autotools.make()
def package(self):
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
autotools = Autotools(self)
with chdir(self, self.source_folder):
# TODO: replace by autotools.install() once https://github.com/conan-io/conan/issues/12153 fixed
autotools.install(args=[f"DESTDIR={unix_path(self, self.package_folder)}"])
rmdir(self, os.path.join(self.package_folder, "share"))
def package_info(self):
self.cpp_info.includedirs = []
self.cpp_info.libdirs = []
# TODO: to remove in conan v2
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))

View File

@@ -0,0 +1,13 @@
diff --git a/lib/getline.cc b/lib/getline.cc
index ecc3e85..2d97644 100644 (file)
--- a/lib/getline.cc
+++ b/lib/getline.cc
@@ -55,7 +55,7 @@ getstr (char **lineptr, size_t *n, FILE *stream, char terminator, size_t offset)
for (;;)
{
- register int c = getc (stream);
+ int c = getc (stream);
/* We always want at least one char left in the buffer, since we
always (unless we get an error while reading the first char)

View File

@@ -0,0 +1 @@
. "/home/aleksandr.vodyanov/Documents/Avroid/Conan/conan_recipes.git/recipes/gperf/all/test_package/conanbuildenv-release-x86_64.sh"

View File

@@ -0,0 +1,19 @@
script_folder="/home/aleksandr.vodyanov/Documents/Avroid/Conan/conan_recipes.git/recipes/gperf/all/test_package"
echo "echo Restoring environment" > "$script_folder/deactivate_conanbuildenv-release-x86_64.sh"
for v in CXX CC CONAN_V2_MODE PATH
do
is_defined="true"
value=$(printenv $v) || is_defined="" || true
if [ -n "$value" ] || [ -n "$is_defined" ]
then
echo export "$v='$value'" >> "$script_folder/deactivate_conanbuildenv-release-x86_64.sh"
else
echo unset $v >> "$script_folder/deactivate_conanbuildenv-release-x86_64.sh"
fi
done
export CXX="x86_64-linux-gnu-g++-12"
export CC="x86_64-linux-gnu-gcc-12"
export CONAN_V2_MODE="true"
export PATH="/home/aleksandr.vodyanov/.conan2/p/b/gperfac47c59da1cc9/p/bin:$PATH"

View File

@@ -0,0 +1,13 @@
from conan import ConanFile
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "VirtualBuildEnv"
test_type = "explicit"
def build_requirements(self):
self.tool_requires(self.tested_reference_str)
def test(self):
self.run("gperf --version")

View File

@@ -0,0 +1 @@
. "/home/aleksandr.vodyanov/Documents/Avroid/Conan/conan_recipes.git/recipes/gperf/all/test_package/conanrunenv-release-x86_64.sh"

View File

@@ -0,0 +1,14 @@
script_folder="/home/aleksandr.vodyanov/Documents/Avroid/Conan/conan_recipes.git/recipes/gperf/all/test_package"
echo "echo Restoring environment" > "$script_folder/deactivate_conanrunenv-release-x86_64.sh"
for v in
do
is_defined="true"
value=$(printenv $v) || is_defined="" || true
if [ -n "$value" ] || [ -n "$is_defined" ]
then
echo export "$v='$value'" >> "$script_folder/deactivate_conanrunenv-release-x86_64.sh"
else
echo unset $v >> "$script_folder/deactivate_conanrunenv-release-x86_64.sh"
fi
done

View File

@@ -0,0 +1 @@
. "/home/aleksandr.vodyanov/Documents/Avroid/Conan/conan_recipes.git/recipes/gperf/all/test_package/deactivate_conanbuildenv-release-x86_64.sh"

View File

@@ -0,0 +1,5 @@
echo Restoring environment
unset CXX
unset CC
unset CONAN_V2_MODE
export PATH='/home/aleksandr.vodyanov/Documents/Avroid/Conan/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/home/aleksandr.vodyanov/.fzf/bin'

View File

@@ -0,0 +1 @@
. "/home/aleksandr.vodyanov/Documents/Avroid/Conan/conan_recipes.git/recipes/gperf/all/test_package/deactivate_conanrunenv-release-x86_64.sh"

3
recipes/gperf/config.yml Normal file
View File

@@ -0,0 +1,3 @@
versions:
"3.1":
folder: "all"

View File

@@ -0,0 +1,49 @@
sources:
"76.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-76-1/icu4c-76_1-src.tgz"
sha256: "dfacb46bfe4747410472ce3e1144bf28a102feeaa4e3875bac9b4c6cf30f4f3e"
"75.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-75-1/icu4c-75_1-src.tgz"
sha256: "cb968df3e4d2e87e8b11c49a5d01c787bd13b9545280fc6642f826527618caef"
"74.2":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-74-2/icu4c-74_2-src.tgz"
sha256: "68db082212a96d6f53e35d60f47d38b962e9f9d207a74cfac78029ae8ff5e08c"
"74.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-74-1/icu4c-74_1-src.tgz"
sha256: "86ce8e60681972e60e4dcb2490c697463fcec60dd400a5f9bffba26d0b52b8d0"
"73.2":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-73-2/icu4c-73_2-src.tgz"
sha256: "818a80712ed3caacd9b652305e01afc7fa167e6f2e94996da44b90c2ab604ce1"
"73.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-73-1/icu4c-73_1-src.tgz"
sha256: "a457431de164b4aa7eca00ed134d00dfbf88a77c6986a10ae7774fc076bb8c45"
patches:
"76.1":
- patch_file: "patches/0001-76.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"75.1":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"74.2":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
- patch_file: "patches/0002-74.2-fix-emscripten.patch"
patch_description: "Add config file for wasm-emscripten platform"
patch_type: "portability"
patch_source: "https://gerrit.libreoffice.org/c/core/+/111130/9/external/icu/icu4c-emscripten-cross.patch.1"
"74.1":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"73.2":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"73.1":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"

View File

@@ -0,0 +1,374 @@
import glob
import hashlib
import os
import shutil
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.apple import is_apple_os
from conan.tools.build import cross_building, stdcpp_library, check_min_cppstd
from conan.tools.env import Environment, VirtualBuildEnv
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, mkdir, rename, replace_in_file, rm, rmdir, save
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.layout import basic_layout
from conan.tools.microsoft import check_min_vs, is_msvc, unix_path
from conan.tools.scm import Version
required_conan_version = ">=1.57.0"
class ICUConan(ConanFile):
name = "icu"
homepage = "http://site.icu-project.org"
license = "ICU"
description = "ICU is a mature, widely used set of C/C++ and Java libraries " \
"providing Unicode and Globalization support for software applications."
url = "https://github.com/conan-io/conan-center-index"
topics = ("icu4c", "i see you", "unicode")
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"data_packaging": ["files", "archive", "library", "static"],
"with_dyload": [True, False],
"dat_package_file": [None, "ANY"],
"with_icuio": [True, False],
"with_extras": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"data_packaging": "archive",
"with_dyload": True,
"dat_package_file": None,
"with_icuio": True,
"with_extras": False,
}
@property
def _min_cppstd(self):
return 17
@property
def _compilers_minimum_version(self):
return {
"gcc": "8",
"clang": "7",
"apple-clang": "12",
"Visual Studio": "16",
"msvc": "192",
}
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
@property
def _enable_icu_tools(self):
return self.settings.os not in ["iOS", "tvOS", "watchOS", "Emscripten"]
@property
def _with_unit_tests(self):
return not self.conf.get("tools.build:skip_test", default=True, check_type=bool)
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
del self.options.data_packaging
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
if Version(self.version) >= "74.1":
self.license = "Unicode-3.0"
def validate(self):
if self.options.dat_package_file:
if not os.path.exists(str(self.options.dat_package_file)):
raise ConanInvalidConfiguration("Non-existent dat_package_file specified")
if Version(self.version) >= "75.1":
if self.settings.compiler.cppstd:
check_min_cppstd(self, self._min_cppstd)
minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False)
if minimum_version and Version(self.settings.compiler.version) < minimum_version:
raise ConanInvalidConfiguration(
f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support."
)
def layout(self):
basic_layout(self, src_folder="src")
@staticmethod
def _sha256sum(file_path):
m = hashlib.sha256()
with open(file_path, "rb") as fh:
for data in iter(lambda: fh.read(8192), b""):
m.update(data)
return m.hexdigest()
def package_id(self):
if self.info.options.dat_package_file:
self.info.options.dat_package_file = self._sha256sum(str(self.info.options.dat_package_file))
def build_requirements(self):
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
if cross_building(self) and hasattr(self, "settings_build"):
self.tool_requires(str(self.ref))
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
tc = AutotoolsToolchain(self)
if check_min_vs(self, "180", raise_invalid=False):
tc.extra_cflags.append("-FS")
tc.extra_cxxflags.append("-FS")
if Version(self.version) >= "75.1" and not self.settings.compiler.cppstd and is_msvc(self):
tc.extra_cxxflags.append(f"-std:c++{self._min_cppstd}")
if not self.options.shared:
tc.extra_defines.append("U_STATIC_IMPLEMENTATION")
if is_apple_os(self):
tc.extra_defines.append("_DARWIN_C_SOURCE")
yes_no = lambda v: "yes" if v else "no"
tc.configure_args.extend([
"--datarootdir=${prefix}/lib", # do not use share
f"--enable-release={yes_no(self.settings.build_type != 'Debug')}",
f"--enable-debug={yes_no(self.settings.build_type == 'Debug')}",
f"--enable-dyload={yes_no(self.options.with_dyload)}",
f"--enable-extras={yes_no(self.options.with_extras)}",
f"--enable-icuio={yes_no(self.options.with_icuio)}",
"--disable-layoutex",
"--disable-layout",
f"--enable-tools={yes_no(self._enable_icu_tools)}",
f"--enable-tests={yes_no(self._with_unit_tests)}",
"--disable-samples",
])
if cross_building(self):
base_path = unix_path(self, self.dependencies.build["icu"].package_folder)
tc.configure_args.append(f"--with-cross-build={base_path}")
if self.settings.os in ["iOS", "tvOS", "watchOS"]:
# ICU build scripts interpret all Apple platforms as 'darwin'.
# Since this can coincide with the `build` triple, we need to tweak
# the build triple to avoid the collision and ensure the scripts
# know we are cross-building.
host_triplet = f"{str(self.settings.arch)}-apple-darwin"
build_triplet = f"{str(self._settings_build.arch)}-apple"
tc.update_configure_args({"--host": host_triplet,
"--build": build_triplet})
else:
arch64 = ["x86_64", "sparcv9", "ppc64", "ppc64le", "armv8", "armv8.3", "mips64"]
bits = "64" if self.settings.arch in arch64 else "32"
tc.configure_args.append(f"--with-library-bits={bits}")
if self.settings.os != "Windows":
# http://userguide.icu-project.org/icudata
# This is the only directly supported behavior on Windows builds.
tc.configure_args.append(f"--with-data-packaging={self.options.data_packaging}")
tc.generate()
if is_msvc(self):
env = Environment()
env.define("CC", "cl -nologo")
env.define("CXX", "cl -nologo")
if cross_building(self):
env.define("icu_cv_host_frag", "mh-msys-msvc")
env.vars(self).save_script("conanbuild_icu_msvc")
def _patch_sources(self):
apply_conandata_patches(self)
if not self._with_unit_tests:
# Prevent any call to python during configuration, it's only needed for unit tests
replace_in_file(
self,
os.path.join(self.source_folder, "source", "configure"),
"if test -z \"$PYTHON\"",
"if true",
)
if self._settings_build.os == "Windows":
# https://unicode-org.atlassian.net/projects/ICU/issues/ICU-20545
makeconv_cpp = os.path.join(self.source_folder, "source", "tools", "makeconv", "makeconv.cpp")
replace_in_file(self, makeconv_cpp,
"pathBuf.appendPathPart(arg, localError);",
"pathBuf.append(\"/\", localError); pathBuf.append(arg, localError);")
# relocatable shared libs on macOS
mh_darwin = os.path.join(self.source_folder, "source", "config", "mh-darwin")
replace_in_file(self, mh_darwin, "-install_name $(libdir)/$(notdir", "-install_name @rpath/$(notdir")
replace_in_file(self,
mh_darwin,
"-install_name $(notdir $(MIDDLE_SO_TARGET)) $(PKGDATA_TRAILING_SPACE)",
"-install_name @rpath/$(notdir $(MIDDLE_SO_TARGET))",
)
# workaround for https://unicode-org.atlassian.net/browse/ICU-20531
mkdir(self, os.path.join(self.build_folder, "data", "out", "tmp"))
# workaround for "No rule to make target 'out/tmp/dirs.timestamp'"
save(self, os.path.join(self.build_folder, "data", "out", "tmp", "dirs.timestamp"), "")
def build(self):
self._patch_sources()
if self.options.dat_package_file:
dat_package_file = glob.glob(os.path.join(self.source_folder, "source", "data", "in", "*.dat"))
if dat_package_file:
shutil.copy(str(self.options.dat_package_file), dat_package_file[0])
autotools = Autotools(self)
autotools.configure(build_script_folder=os.path.join(self.source_folder, "source"))
autotools.make()
if self._with_unit_tests:
autotools.make(target="check")
@property
def _data_filename(self):
vtag = Version(self.version).major
return f"icudt{vtag}l.dat"
@property
def _data_path(self):
data_dir_name = "icu"
if self.settings.os == "Windows" and self.settings.build_type == "Debug":
data_dir_name += "d"
data_dir = os.path.join(self.package_folder, "lib", data_dir_name, str(self.version))
return os.path.join(data_dir, self._data_filename)
def package(self):
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
autotools = Autotools(self)
autotools.install()
dll_files = glob.glob(os.path.join(self.package_folder, "lib", "*.dll"))
if dll_files:
bin_dir = os.path.join(self.package_folder, "bin")
mkdir(self, bin_dir)
for dll in dll_files:
dll_name = os.path.basename(dll)
rm(self, dll_name, bin_dir)
rename(self, src=dll, dst=os.path.join(bin_dir, dll_name))
if self.settings.os != "Windows" and self.options.data_packaging in ["files", "archive"]:
mkdir(self, os.path.join(self.package_folder, "res"))
rename(self, src=self._data_path, dst=os.path.join(self.package_folder, "res", self._data_filename))
# Copy some files required for cross-compiling
config_dir = os.path.join(self.package_folder, "config")
copy(self, "icucross.mk", src=os.path.join(self.build_folder, "config"), dst=config_dir)
copy(self, "icucross.inc", src=os.path.join(self.build_folder, "config"), dst=config_dir)
rmdir(self, os.path.join(self.package_folder, "lib", "icu"))
rmdir(self, os.path.join(self.package_folder, "lib", "man"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "share"))
def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "ICU")
prefix = "s" if self.settings.os == "Windows" and not self.options.shared else ""
suffix = "d" if self.settings.os == "Windows" and self.settings.build_type == "Debug" else ""
# icudata
self.cpp_info.components["icu-data"].set_property("cmake_target_name", "ICU::data")
icudata_libname = "icudt" if self.settings.os == "Windows" else "icudata"
self.cpp_info.components["icu-data"].libs = [f"{prefix}{icudata_libname}{suffix}"]
if not self.options.shared:
self.cpp_info.components["icu-data"].defines.append("U_STATIC_IMPLEMENTATION")
# icu uses c++, so add the c++ runtime
libcxx = stdcpp_library(self)
if libcxx:
self.cpp_info.components["icu-data"].system_libs.append(libcxx)
# Alias of data CMake component
self.cpp_info.components["icu-data-alias"].set_property("cmake_target_name", "ICU::dt")
self.cpp_info.components["icu-data-alias"].requires = ["icu-data"]
# icuuc
self.cpp_info.components["icu-uc"].set_property("cmake_target_name", "ICU::uc")
self.cpp_info.components["icu-uc"].set_property("pkg_config_name", "icu-uc")
self.cpp_info.components["icu-uc"].libs = [f"{prefix}icuuc{suffix}"]
self.cpp_info.components["icu-uc"].requires = ["icu-data"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["icu-uc"].system_libs = ["m", "pthread"]
if self.options.with_dyload:
self.cpp_info.components["icu-uc"].system_libs.append("dl")
elif self.settings.os == "Windows":
self.cpp_info.components["icu-uc"].system_libs = ["advapi32"]
# icui18n
self.cpp_info.components["icu-i18n"].set_property("cmake_target_name", "ICU::i18n")
self.cpp_info.components["icu-i18n"].set_property("pkg_config_name", "icu-i18n")
icui18n_libname = "icuin" if self.settings.os == "Windows" else "icui18n"
self.cpp_info.components["icu-i18n"].libs = [f"{prefix}{icui18n_libname}{suffix}"]
self.cpp_info.components["icu-i18n"].requires = ["icu-uc"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["icu-i18n"].system_libs = ["m"]
# Alias of i18n CMake component
self.cpp_info.components["icu-i18n-alias"].set_property("cmake_target_name", "ICU::in")
self.cpp_info.components["icu-i18n-alias"].requires = ["icu-i18n"]
# icuio
if self.options.with_icuio:
self.cpp_info.components["icu-io"].set_property("cmake_target_name", "ICU::io")
self.cpp_info.components["icu-io"].set_property("pkg_config_name", "icu-io")
self.cpp_info.components["icu-io"].libs = [f"{prefix}icuio{suffix}"]
self.cpp_info.components["icu-io"].requires = ["icu-i18n", "icu-uc"]
if self.settings.os != "Windows" and self.options.data_packaging in ["files", "archive"]:
self.cpp_info.components["icu-data"].resdirs = ["res"]
data_path = os.path.join(self.package_folder, "res", self._data_filename).replace("\\", "/")
self.runenv_info.prepend_path("ICU_DATA", data_path)
if self._enable_icu_tools or self.options.with_extras:
self.buildenv_info.prepend_path("ICU_DATA", data_path)
if self._enable_icu_tools:
# icutu
self.cpp_info.components["icu-tu"].set_property("cmake_target_name", "ICU::tu")
self.cpp_info.components["icu-tu"].libs = [f"{prefix}icutu{suffix}"]
self.cpp_info.components["icu-tu"].requires = ["icu-i18n", "icu-uc"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["icu-tu"].system_libs = ["pthread"]
# icutest
self.cpp_info.components["icu-test"].set_property("cmake_target_name", "ICU::test")
self.cpp_info.components["icu-test"].libs = [f"{prefix}icutest{suffix}"]
self.cpp_info.components["icu-test"].requires = ["icu-tu", "icu-uc"]
# TODO: to remove after conan v2
self.cpp_info.names["cmake_find_package"] = "ICU"
self.cpp_info.names["cmake_find_package_multi"] = "ICU"
self.cpp_info.components["icu-data"].names["cmake_find_package"] = "data"
self.cpp_info.components["icu-data"].names["cmake_find_package_multi"] = "data"
self.cpp_info.components["icu-data-alias"].names["cmake_find_package"] = "dt"
self.cpp_info.components["icu-data-alias"].names["cmake_find_package_multi"] = "dt"
self.cpp_info.components["icu-uc"].names["cmake_find_package"] = "uc"
self.cpp_info.components["icu-uc"].names["cmake_find_package_multi"] = "uc"
self.cpp_info.components["icu-i18n"].names["cmake_find_package"] = "i18n"
self.cpp_info.components["icu-i18n"].names["cmake_find_package_multi"] = "i18n"
self.cpp_info.components["icu-i18n-alias"].names["cmake_find_package"] = "in"
self.cpp_info.components["icu-i18n-alias"].names["cmake_find_package_multi"] = "in"
if self.options.with_icuio:
self.cpp_info.components["icu-io"].names["cmake_find_package"] = "io"
self.cpp_info.components["icu-io"].names["cmake_find_package_multi"] = "io"
if self.settings.os != "Windows" and self.options.data_packaging in ["files", "archive"]:
self.env_info.ICU_DATA.append(data_path)
if self._enable_icu_tools:
self.cpp_info.components["icu-tu"].names["cmake_find_package"] = "tu"
self.cpp_info.components["icu-tu"].names["cmake_find_package_multi"] = "tu"
self.cpp_info.components["icu-test"].names["cmake_find_package"] = "test"
self.cpp_info.components["icu-test"].names["cmake_find_package_multi"] = "test"
if self._enable_icu_tools or self.options.with_extras:
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))

View File

@@ -0,0 +1,43 @@
--- source/config/mh-mingw64
+++ source/config/mh-mingw64
@@ -94,7 +94,7 @@
# This is also for backwards compatibility.
DATA_STUBNAME = dt
I18N_STUBNAME = in
-LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
+#LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
#SH### copied from Makefile.inc
#SH## for icu-config to test with
@@ -102,13 +102,13 @@
#SH#ICULIBS_COMMON_LIB_NAME_A="${LIBICU}${COMMON_STUBNAME}${ICULIBSUFFIX}.${A}"
#SH#ICULIBS_DATA="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
+#ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)""
+#ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
#SH#
#SH## ICULIBS is the set of libraries your application should link
#SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well.
--- source/data/Makefile.in
+++ source/data/Makefile.in
@@ -207,7 +207,7 @@
ifneq ($(ICUDATA_SOURCE_IS_NATIVE_TARGET),YES)
# For MinGW, do we want the DLL to go in the bin location?
ifeq ($(MINGW_MOVEDLLSTOBINDIR),YES)
- $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(DESTDIR)$(bindir)
+ $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
else
$(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
endif

View File

@@ -0,0 +1,47 @@
diff --git a/source/config/mh-mingw64 b/source/config/mh-mingw64
index fb64c56..ff8922c 100644
--- a/source/config/mh-mingw64
+++ b/source/config/mh-mingw64
@@ -94,7 +94,7 @@ LIBPREFIX=
# This is also for backwards compatibility.
DATA_STUBNAME = dt
I18N_STUBNAME = in
-LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
+#LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
#SH### copied from Makefile.inc
#SH## for icu-config to test with
@@ -102,13 +102,13 @@ LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
#SH#ICULIBS_COMMON_LIB_NAME_A="${LIBICU}${COMMON_STUBNAME}${ICULIBSUFFIX}.${A}"
#SH#ICULIBS_DATA="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
+#ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
#SH#
#SH## ICULIBS is the set of libraries your application should link
#SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well.
diff --git a/source/data/Makefile.in b/source/data/Makefile.in
index 266ad7a..8e3be4f 100644
--- a/source/data/Makefile.in
+++ b/source/data/Makefile.in
@@ -193,7 +193,7 @@ endif
ifneq ($(ICUDATA_SOURCE_IS_NATIVE_TARGET),YES)
# For MinGW, do we want the DLL to go in the bin location?
ifeq ($(MINGW_MOVEDLLSTOBINDIR),YES)
- $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(DESTDIR)$(bindir)
+ $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
else
$(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
endif

View File

@@ -0,0 +1,109 @@
--- a/source/acinclude.m4
+++ b/source/acinclude.m4
@@ -85,6 +85,7 @@ powerpc*-apple-darwin*) icu_cv_host_frag=mh-darwin-ppc ;;
*-dec-osf*) icu_cv_host_frag=mh-alpha-osf ;;
*-*-nto*) icu_cv_host_frag=mh-qnx ;;
*-ncr-*) icu_cv_host_frag=mh-mpras ;;
+wasm*-*-emscripten*) icu_cv_host_frag=mh-emscripten ;;
*) icu_cv_host_frag=mh-unknown ;;
esac
]
--- /dev/null
+++ b/source/config/mh-emscripten
@@ -0,0 +1,86 @@
+## Emscripten-specific setup
+## Copyright (c) 1999-2013, International Business Machines Corporation and
+## others. All Rights Reserved.
+## Commands to generate dependency files
+GEN_DEPS.c= $(CC) -E -MM $(DEFS) $(CPPFLAGS)
+GEN_DEPS.cc= $(CXX) -E -MM $(DEFS) $(CPPFLAGS) $(CXXFLAGS)
+
+## Flags for position independent code
+SHAREDLIBCFLAGS = -fPIC
+SHAREDLIBCXXFLAGS = -fPIC
+SHAREDLIBCPPFLAGS = -DPIC
+
+## Additional flags when building libraries and with threads
+THREADSCPPFLAGS = -D_REENTRANT
+LIBCPPFLAGS =
+
+## Compiler switch to embed a runtime search path
+LD_RPATH= -Wl,-zorigin,-rpath,'$$'ORIGIN
+LD_RPATH_PRE = -Wl,-rpath,
+
+## Force RPATH=$ORIGIN to locate own dependencies w/o need for LD_LIBRARY_PATH:
+ENABLE_RPATH=YES
+RPATHLDFLAGS=${LD_RPATH_PRE}'$$ORIGIN'
+
+## These are the library specific LDFLAGS
+#LDFLAGSICUDT=-nodefaultlibs -nostdlib
+# Debian change: linking icudata as data only causes too many problems.
+LDFLAGSICUDT=
+
+## Compiler switch to embed a library name
+# The initial tab in the next line is to prevent icu-config from reading it.
+ LD_SONAME = -Wl,-soname -Wl,$(notdir $(MIDDLE_SO_TARGET))
+#SH# # We can't depend on MIDDLE_SO_TARGET being set.
+#SH# LD_SONAME=
+
+## Shared library options
+LD_SOOPTIONS= -Wl,-Bsymbolic-functions
+
+## Shared object suffix
+SO = so
+## Non-shared intermediate object suffix
+STATIC_O = o
+
+## Compilation rules
+# WASM needs -pthread for atomics support
+%.$(STATIC_O): $(srcdir)/%.c
+ $(call SILENT_COMPILE,$(strip $(COMPILE.c) $(STATICCPPFLAGS) $(STATICCFLAGS)) -pthread -o $@ $<)
+
+%.$(STATIC_O): $(srcdir)/%.cpp
+ $(call SILENT_COMPILE,$(strip $(COMPILE.cc) $(STATICCPPFLAGS) $(STATICCXXFLAGS)) -pthread -o $@ $<)
+
+
+## Dependency rules
+%.d: $(srcdir)/%.c
+ $(call ICU_MSG,(deps)) $<
+ @$(SHELL) -ec '$(GEN_DEPS.c) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+%.d: $(srcdir)/%.cpp
+ $(call ICU_MSG,(deps)) $<
+ @$(SHELL) -ec '$(GEN_DEPS.cc) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+## Versioned libraries rules
+
+%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
+ $(RM) $@ && ln -s ${<F} $@
+%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
+ $(RM) $@ && ln -s ${*F}.$(SO).$(SO_TARGET_VERSION) $@
+
+## Bind internal references
+
+# LDflags that pkgdata will use
+BIR_LDFLAGS= -Wl,-Bsymbolic
+
+# Dependencies [i.e. map files] for the final library
+BIR_DEPS=
+
+## Remove shared library 's'
+STATIC_PREFIX_WHEN_USED =
+STATIC_PREFIX =
+
+## without assembly
+PKGDATA_OPTS = -O $(top_builddir)/data/icupkg.inc -w
--- a/source/configure
+++ b/source/configure
@@ -5342,6 +5342,7 @@ powerpc*-apple-darwin*) icu_cv_host_frag=mh-darwin-ppc ;;
*-dec-osf*) icu_cv_host_frag=mh-alpha-osf ;;
*-*-nto*) icu_cv_host_frag=mh-qnx ;;
*-ncr-*) icu_cv_host_frag=mh-mpras ;;
+wasm*-*-emscripten*) icu_cv_host_frag=mh-emscripten ;;
*) icu_cv_host_frag=mh-unknown ;;
esac

View File

@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.8)
project(test_package LANGUAGES CXX)
find_package(ICU REQUIRED uc)
add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE ICU::uc)
if(ICU_VERSION VERSION_LESS "75.1")
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11)
else()
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
endif()

View File

@@ -0,0 +1,9 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")

View File

@@ -0,0 +1,623 @@
// This is taken from ICU samples: source/samples/ustring
/*
*******************************************************************************
*
* © 2016 and later: Unicode, Inc. and others.
* License & terms of use: http://www.unicode.org/copyright.html#License
*
*******************************************************************************
*******************************************************************************
*
* Copyright (C) 2000-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: ustring.c
* encoding: UTF-8
* tab size: 8 (not used)
* indentation:4
*
* created on: 2000aug15
* created by: Markus W. Scherer
*
* This file contains sample code that illustrates the use of Unicode strings
* with ICU.
*/
#include <stdio.h>
#define U_DEFINE_FALSE_AND_TRUE 1
#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/locid.h"
#include "unicode/ustring.h"
#include "unicode/ucnv.h"
#include "unicode/unistr.h"
#ifndef UPRV_LENGTHOF
#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
#endif
// helper functions -------------------------------------------------------- ***
// default converter for the platform encoding
static UConverter *cnv=NULL;
using namespace icu;
static void
printUString(const char *announce, const UChar *s, int32_t length) {
static char out[200];
UChar32 c;
int32_t i;
UErrorCode errorCode=U_ZERO_ERROR;
/*
* Convert to the "platform encoding". See notes in printUnicodeString().
* ucnv_fromUChars(), like most ICU APIs understands length==-1
* to mean that the string is NUL-terminated.
*/
ucnv_fromUChars(cnv, out, sizeof(out), s, length, &errorCode);
if(U_FAILURE(errorCode) || errorCode==U_STRING_NOT_TERMINATED_WARNING) {
printf("%sproblem converting string from Unicode: %s\n", announce, u_errorName(errorCode));
return;
}
printf("%s%s {", announce, out);
/* output the code points (not code units) */
if(length>=0) {
/* s is not NUL-terminated */
for(i=0; i<length; /* U16_NEXT post-increments */) {
U16_NEXT(s, i, length, c);
printf(" %04x", c);
}
} else {
/* s is NUL-terminated */
for(i=0; /* condition in loop body */; /* U16_NEXT post-increments */) {
U16_NEXT(s, i, length, c);
if(c==0) {
break;
}
printf(" %04x", c);
}
}
printf(" }\n");
}
static void
printUnicodeString(const char *announce, const UnicodeString &s) {
static char out[200];
int32_t i, length;
// output the string, converted to the platform encoding
// Note for Windows: The "platform encoding" defaults to the "ANSI codepage",
// which is different from the "OEM codepage" in the console window.
// However, if you pipe the output into a file and look at it with Notepad
// or similar, then "ANSI" characters will show correctly.
// Production code should be aware of what encoding is required,
// and use a UConverter or at least a charset name explicitly.
out[s.extract(0, 99, out)]=0;
printf("%s%s {", announce, out);
// output the code units (not code points)
length=s.length();
for(i=0; i<length; ++i) {
printf(" %04x", s.charAt(i));
}
printf(" }\n");
}
// sample code for utf.h macros -------------------------------------------- ***
static void
demo_utf_h_macros() {
static UChar input[]={ 0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062 };
UChar32 c;
int32_t i;
UBool isError;
printf("\n* demo_utf_h_macros() -------------- ***\n\n");
printUString("iterate forward through: ", input, UPRV_LENGTHOF(input));
for(i=0; i<UPRV_LENGTHOF(input); /* U16_NEXT post-increments */) {
/* Iterating forwards
Codepoint at offset 0: U+0061
Codepoint at offset 1: U+10000
Codepoint at offset 3: U+10ffff
Codepoint at offset 5: U+0062
*/
printf("Codepoint at offset %d: U+", i);
U16_NEXT(input, i, UPRV_LENGTHOF(input), c);
printf("%04x\n", c);
}
puts("");
isError=FALSE;
i=1; /* write position, gets post-incremented so needs to be in an l-value */
U16_APPEND(input, i, UPRV_LENGTHOF(input), 0x0062, isError);
printUString("iterate backward through: ", input, UPRV_LENGTHOF(input));
for(i=UPRV_LENGTHOF(input); i>0; /* U16_PREV pre-decrements */) {
U16_PREV(input, 0, i, c);
/* Iterating backwards
Codepoint at offset 5: U+0062
Codepoint at offset 3: U+10ffff
Codepoint at offset 2: U+dc00 -- unpaired surrogate because lead surr. overwritten
Codepoint at offset 1: U+0062 -- by this BMP code point
Codepoint at offset 0: U+0061
*/
printf("Codepoint at offset %d: U+%04x\n", i, c);
}
}
// sample code for Unicode strings in C ------------------------------------ ***
static void demo_C_Unicode_strings() {
printf("\n* demo_C_Unicode_strings() --------- ***\n\n");
static const UChar text[]={ 0x41, 0x42, 0x43, 0 }; /* "ABC" */
static const UChar appendText[]={ 0x61, 0x62, 0x63, 0 }; /* "abc" */
static const UChar cmpText[]={ 0x61, 0x53, 0x73, 0x43, 0 }; /* "aSsC" */
UChar buffer[32];
int32_t compare;
int32_t length=u_strlen(text); /* length=3 */
/* simple ANSI C-style functions */
buffer[0]=0; /* empty, NUL-terminated string */
u_strncat(buffer, text, 1); /* append just n=1 character ('A') */
u_strcat(buffer, appendText); /* buffer=="Aabc" */
length=u_strlen(buffer); /* length=4 */
printUString("should be \"Aabc\": ", buffer, -1);
/* bitwise comparing buffer with text */
compare=u_strcmp(buffer, text);
if(compare<=0) {
printf("String comparison error, expected \"Aabc\" > \"ABC\"\n");
}
/* Build "A<sharp s>C" in the buffer... */
u_strcpy(buffer, text);
buffer[1]=0xdf; /* sharp s, case-compares equal to "ss" */
printUString("should be \"A<sharp s>C\": ", buffer, -1);
/* Compare two strings case-insensitively using full case folding */
compare=u_strcasecmp(buffer, cmpText, U_FOLD_CASE_DEFAULT);
if(compare!=0) {
printf("String case insensitive comparison error, expected \"AbC\" to be equal to \"ABC\"\n");
}
}
// sample code for case mappings with C APIs -------------------------------- ***
static void demoCaseMapInC() {
/*
* input=
* "aB<capital sigma>"
* "iI<small dotless i><capital dotted I> "
* "<sharp s> <small lig. ffi>"
* "<small final sigma><small sigma><capital sigma>"
*/
static const UChar input[]={
0x61, 0x42, 0x3a3,
0x69, 0x49, 0x131, 0x130, 0x20,
0xdf, 0x20, 0xfb03,
0x3c2, 0x3c3, 0x3a3, 0
};
UChar buffer[32];
UErrorCode errorCode;
UChar32 c;
int32_t i, j, length;
UBool isError;
printf("\n* demoCaseMapInC() ----------------- ***\n\n");
/*
* First, use simple case mapping functions which provide
* 1:1 code point mappings without context/locale ID.
*
* Note that some mappings will not be "right" because some "real"
* case mappings require context, depend on the locale ID,
* and/or result in a change in the number of code points.
*/
printUString("input string: ", input, -1);
/* uppercase */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_toupper(c);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-uppercased: ", buffer, j);
/* lowercase */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_tolower(c);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-lowercased: ", buffer, j);
/* titlecase */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_totitle(c);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-titlecased: ", buffer, j);
/* case-fold/default */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_foldCase(c, U_FOLD_CASE_DEFAULT);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-case-folded/default: ", buffer, j);
/* case-fold/Turkic */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_foldCase(c, U_FOLD_CASE_EXCLUDE_SPECIAL_I);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-case-folded/Turkic: ", buffer, j);
/*
* Second, use full case mapping functions which provide
* 1:n code point mappings (n can be 0!) and are sensitive to context and locale ID.
*
* Note that lower/upper/titlecasing take a locale ID while case-folding
* has bit flag options instead, by design of the Unicode SpecialCasing.txt UCD file.
*
* Also, string titlecasing requires a BreakIterator to find starts of words.
* The sample code here passes in a NULL pointer; u_strToTitle() will open and close a default
* titlecasing BreakIterator automatically.
* For production code where many strings are titlecased it would be more efficient
* to open a BreakIterator externally and pass it in.
*/
printUString("\ninput string: ", input, -1);
/* lowercase/English */
errorCode=U_ZERO_ERROR;
length=u_strToLower(buffer, UPRV_LENGTHOF(buffer), input, -1, "en", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-lowercased/en: ", buffer, length);
} else {
printf("error in u_strToLower(en)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* lowercase/Turkish */
errorCode=U_ZERO_ERROR;
length=u_strToLower(buffer, UPRV_LENGTHOF(buffer), input, -1, "tr", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-lowercased/tr: ", buffer, length);
} else {
printf("error in u_strToLower(tr)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* uppercase/English */
errorCode=U_ZERO_ERROR;
length=u_strToUpper(buffer, UPRV_LENGTHOF(buffer), input, -1, "en", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-uppercased/en: ", buffer, length);
} else {
printf("error in u_strToUpper(en)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* uppercase/Turkish */
errorCode=U_ZERO_ERROR;
length=u_strToUpper(buffer, UPRV_LENGTHOF(buffer), input, -1, "tr", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-uppercased/tr: ", buffer, length);
} else {
printf("error in u_strToUpper(tr)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* titlecase/English */
errorCode=U_ZERO_ERROR;
length=u_strToTitle(buffer, UPRV_LENGTHOF(buffer), input, -1, NULL, "en", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-titlecased/en: ", buffer, length);
} else {
printf("error in u_strToTitle(en)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* titlecase/Turkish */
errorCode=U_ZERO_ERROR;
length=u_strToTitle(buffer, UPRV_LENGTHOF(buffer), input, -1, NULL, "tr", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-titlecased/tr: ", buffer, length);
} else {
printf("error in u_strToTitle(tr)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* case-fold/default */
errorCode=U_ZERO_ERROR;
length=u_strFoldCase(buffer, UPRV_LENGTHOF(buffer), input, -1, U_FOLD_CASE_DEFAULT, &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-case-folded/default: ", buffer, length);
} else {
printf("error in u_strFoldCase(default)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* case-fold/Turkic */
errorCode=U_ZERO_ERROR;
length=u_strFoldCase(buffer, UPRV_LENGTHOF(buffer), input, -1, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-case-folded/Turkic: ", buffer, length);
} else {
printf("error in u_strFoldCase(Turkic)=%ld error=%s\n", length, u_errorName(errorCode));
}
}
// sample code for case mappings with C++ APIs ------------------------------ ***
static void demoCaseMapInCPlusPlus() {
/*
* input=
* "aB<capital sigma>"
* "iI<small dotless i><capital dotted I> "
* "<sharp s> <small lig. ffi>"
* "<small final sigma><small sigma><capital sigma>"
*/
static const UChar input[]={
0x61, 0x42, 0x3a3,
0x69, 0x49, 0x131, 0x130, 0x20,
0xdf, 0x20, 0xfb03,
0x3c2, 0x3c3, 0x3a3, 0
};
printf("\n* demoCaseMapInCPlusPlus() --------- ***\n\n");
UnicodeString s(input), t;
const Locale &en=Locale::getEnglish();
Locale tr("tr");
/*
* Full case mappings as in demoCaseMapInC(), using UnicodeString functions.
* These functions modify the string object itself.
* Since we want to keep the input string around, we copy it each time
* and case-map the copy.
*/
printUnicodeString("input string: ", s);
/* lowercase/English */
printUnicodeString("full-lowercased/en: ", (t=s).toLower(en));
/* lowercase/Turkish */
printUnicodeString("full-lowercased/tr: ", (t=s).toLower(tr));
/* uppercase/English */
printUnicodeString("full-uppercased/en: ", (t=s).toUpper(en));
/* uppercase/Turkish */
printUnicodeString("full-uppercased/tr: ", (t=s).toUpper(tr));
/* titlecase/English */
printUnicodeString("full-titlecased/en: ", (t=s).toTitle(NULL, en));
/* titlecase/Turkish */
printUnicodeString("full-titlecased/tr: ", (t=s).toTitle(NULL, tr));
/* case-folde/default */
printUnicodeString("full-case-folded/default: ", (t=s).foldCase(U_FOLD_CASE_DEFAULT));
/* case-folde/Turkic */
printUnicodeString("full-case-folded/Turkic: ", (t=s).foldCase(U_FOLD_CASE_EXCLUDE_SPECIAL_I));
}
// sample code for UnicodeString storage models ----------------------------- ***
static const UChar readonly[]={
0x61, 0x31, 0x20ac
};
static UChar writeable[]={
0x62, 0x32, 0xdbc0, 0xdc01 // includes a surrogate pair for a supplementary code point
};
static char out[100];
static void
demoUnicodeStringStorage() {
// These sample code lines illustrate how to use UnicodeString, and the
// comments tell what happens internally. There are no APIs to observe
// most of this programmatically, except for stepping into the code
// with a debugger.
// This is by design to hide such details from the user.
int32_t i;
printf("\n* demoUnicodeStringStorage() ------- ***\n\n");
// * UnicodeString with internally stored contents
// instantiate a UnicodeString from a single code point
// the few (2) UChars will be stored in the object itself
UnicodeString one((UChar32)0x24001);
// this copies the few UChars into the "two" object
UnicodeString two=one;
printf("length of short string copy: %d\n", two.length());
// set "one" to contain the 3 UChars from readonly
// this setTo() variant copies the characters
one.setTo(readonly, UPRV_LENGTHOF(readonly));
// * UnicodeString with allocated contents
// build a longer string that will not fit into the object's buffer
one+=UnicodeString(writeable, UPRV_LENGTHOF(writeable));
one+=one;
one+=one;
printf("length of longer string: %d\n", one.length());
// copying will use the same allocated buffer and increment the reference
// counter
two=one;
printf("length of longer string copy: %d\n", two.length());
// * UnicodeString using readonly-alias to a const UChar array
// construct a string that aliases a readonly buffer
UnicodeString three(FALSE, readonly, UPRV_LENGTHOF(readonly));
printUnicodeString("readonly-alias string: ", three);
// copy-on-write: any modification to the string results in
// a copy to either the internal buffer or to a newly allocated one
three.setCharAt(1, 0x39);
printUnicodeString("readonly-aliasing string after modification: ", three);
// the aliased array is not modified
for(i=0; i<three.length(); ++i) {
printf("readonly buffer[%d] after modifying its string: 0x%lx\n",
i, readonly[i]);
}
// setTo() readonly alias
one.setTo(FALSE, writeable, UPRV_LENGTHOF(writeable));
// copying the readonly-alias object with fastCopyFrom() (new in ICU 2.4)
// will readonly-alias the same buffer
two.fastCopyFrom(one);
printUnicodeString("fastCopyFrom(readonly alias of \"writeable\" array): ", two);
printf("verify that a fastCopyFrom(readonly alias) uses the same buffer pointer: %d (should be 1)\n",
one.getBuffer()==two.getBuffer());
// a normal assignment will clone the contents (new in ICU 2.4)
two=one;
printf("verify that a regular copy of a readonly alias uses a different buffer pointer: %d (should be 0)\n",
one.getBuffer()==two.getBuffer());
// * UnicodeString using writeable-alias to a non-const UChar array
UnicodeString four(writeable, UPRV_LENGTHOF(writeable), UPRV_LENGTHOF(writeable));
printUnicodeString("writeable-alias string: ", four);
// a modification writes through to the buffer
four.setCharAt(1, 0x39);
for(i=0; i<four.length(); ++i) {
printf("writeable-alias backing buffer[%d]=0x%lx "
"after modification\n", i, writeable[i]);
}
// a copy will not alias any more;
// instead, it will get a copy of the contents into allocated memory
two=four;
two.setCharAt(1, 0x21);
for(i=0; i<two.length(); ++i) {
printf("writeable-alias backing buffer[%d]=0x%lx after "
"modification of string copy\n", i, writeable[i]);
}
// setTo() writeable alias, capacity==length
one.setTo(writeable, UPRV_LENGTHOF(writeable), UPRV_LENGTHOF(writeable));
// grow the string - it will not fit into the backing buffer any more
// and will get copied before modification
one.append((UChar)0x40);
// shrink it back so it would fit
one.truncate(one.length()-1);
// we still operate on the copy
one.setCharAt(1, 0x25);
printf("string after growing too much and then shrinking[1]=0x%lx\n"
" backing store for this[1]=0x%lx\n",
one.charAt(1), writeable[1]);
// if we need it in the original buffer, then extract() to it
// extract() does not do anything if the string aliases that same buffer
// i=min(one.length(), length of array)
if(one.length()<UPRV_LENGTHOF(writeable)) {
i=one.length();
} else {
i=UPRV_LENGTHOF(writeable);
}
one.extract(0, i, writeable);
for(i=0; i<UPRV_LENGTHOF(writeable); ++i) {
printf("writeable-alias backing buffer[%d]=0x%lx after re-extract\n",
i, writeable[i]);
}
}
// sample code for UnicodeString instantiations ----------------------------- ***
static void
demoUnicodeStringInit() {
// *** Make sure to read about invariant characters in utypes.h! ***
// Initialization of Unicode strings from C literals works _only_ for
// invariant characters!
printf("\n* demoUnicodeStringInit() ---------- ***\n\n");
// the string literal is 32 chars long - this must be counted for the macro
UnicodeString invariantOnly=UNICODE_STRING("such characters are safe 123 %-.", 32);
/*
* In C, we need two macros: one to declare the UChar[] array, and
* one to populate it; the second one is a noop on platforms where
* wchar_t is compatible with UChar and ASCII-based.
* The length of the string literal must be counted for both macros.
*/
/* declare the invString array for the string */
U_STRING_DECL(invString, "such characters are safe 123 %-.", 32);
/* populate it with the characters */
U_STRING_INIT(invString, "such characters are safe 123 %-.", 32);
// compare the C and C++ strings
printf("C and C++ Unicode strings are equal: %d\n", invariantOnly==UnicodeString(TRUE, invString, 32));
/*
* convert between char * and UChar * strings that
* contain only invariant characters
*/
static const char *cs1="such characters are safe 123 %-.";
static UChar us1[40];
static char cs2[40];
u_charsToUChars(cs1, us1, 33); /* include the terminating NUL */
u_UCharsToChars(us1, cs2, 33);
printf("char * -> UChar * -> char * with only "
"invariant characters: \"%s\"\n",
cs2);
// initialize a UnicodeString from a string literal that contains
// escape sequences written with invariant characters
// do not forget to duplicate the backslashes for ICU to see them
// then, count each double backslash only once!
UnicodeString german=UNICODE_STRING(
"Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\n", 64).
unescape();
printUnicodeString("german UnicodeString from unescaping:\n ", german);
/*
* C: convert and unescape a char * string with only invariant
* characters to fill a UChar * string
*/
UChar buffer[200];
int32_t length;
length=u_unescape(
"Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\n",
buffer, UPRV_LENGTHOF(buffer));
printf("german C Unicode string from char * unescaping: (length %d)\n ", length);
printUnicodeString("", UnicodeString(buffer));
}
extern int
main(int argc, const char *argv[]) {
UErrorCode errorCode=U_ZERO_ERROR;
// Note: Using a global variable for any object is not exactly thread-safe...
// You can change this call to e.g. ucnv_open("UTF-8", &errorCode) if you pipe
// the output to a file and look at it with a Unicode-capable editor.
// This will currently affect only the printUString() function, see the code above.
// printUnicodeString() could use this, too, by changing to an extract() overload
// that takes a UConverter argument.
cnv=ucnv_open(NULL, &errorCode);
if(U_FAILURE(errorCode)) {
fprintf(stderr, "error %s opening the default converter\n", u_errorName(errorCode));
return errorCode;
}
ucnv_setFromUCallBack(cnv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_C, NULL, NULL, &errorCode);
if(U_FAILURE(errorCode)) {
fprintf(stderr, "error %s setting the escape callback in the default converter\n", u_errorName(errorCode));
ucnv_close(cnv);
return errorCode;
}
demo_utf_h_macros();
demo_C_Unicode_strings();
demoCaseMapInC();
demoCaseMapInCPlusPlus();
demoUnicodeStringStorage();
demoUnicodeStringInit();
ucnv_close(cnv);
return 0;
}

13
recipes/icu/config.yml Normal file
View File

@@ -0,0 +1,13 @@
versions:
"76.1":
folder: all
"75.1":
folder: all
"74.2":
folder: all
"74.1":
folder: all
"73.2":
folder: all
"73.1":
folder: all

View File

@@ -0,0 +1,40 @@
sources:
"8.1.0":
url: "https://dev.mysql.com/get/Downloads/MySQL-8.1/mysql-8.1.0.tar.gz"
sha256: "3dd017a940734aa90796a4c65e125e6712f64bbbbe3388d36469deaa87b599eb"
"8.0.34":
url: "https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.34.tar.gz"
sha256: "e65d03a3c42618b5fbf99042aed33209402e9b27aa62c7c8743ffd4788d8db1d"
"8.0.31":
url: "https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.31.tar.gz"
sha256: "67bb8cba75b28e95c7f7948563f01fb84528fcbb1a35dba839d4ce44fe019baa"
"8.0.30":
url: "https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.30.tar.gz"
sha256: "c988d5c6ba9a56692a6cd6e9813465b5fc9368ed4b461df97059a2fc160c8b84"
"8.0.25":
url: "https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.25.tar.gz"
sha256: "c16aa9cf621bc028efba2bb11f3c36a323b125fa0d108ff92fab60e46309206e"
patches:
"8.1.0":
- patch_file: "patches/0006-fix-cpp20-build-8.1.0.patch"
patch_description: "Fix C++20 compilation"
patch_type: "portability"
"8.0.34":
- patch_file: "patches/0006-fix-cpp20-build-8.0.29.patch"
patch_description: "Fix C++20 compilation"
patch_type: "portability"
"8.0.31":
- patch_file: "patches/0006-fix-cpp20-build-8.0.29.patch"
patch_description: "Fix C++20 compilation"
patch_type: "portability"
"8.0.30":
- patch_file: "patches/0006-fix-cpp20-build-8.0.29.patch"
patch_description: "Fix C++20 compilation"
patch_type: "portability"
"8.0.25":
- patch_file: "patches/0004-fix-805-cpp17-build.patch"
patch_description: "Fix C++17 compilation"
patch_type: "portability"
- patch_file: "patches/0005-fix-macos-12.0.x-version-detection.patch"
patch_description: "Fix macOS 12.0 version detection"
patch_type: "bugfix"

View File

@@ -0,0 +1,287 @@
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.apple import is_apple_os
from conan.tools.build import check_min_cppstd, cross_building, stdcpp_library
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
from conan.tools.env import VirtualRunEnv, VirtualBuildEnv
from conan.tools.files import rename, get, apply_conandata_patches, replace_in_file, rmdir, rm, export_conandata_patches, mkdir
from conan.tools.gnu import PkgConfigDeps
from conan.tools.microsoft import is_msvc, is_msvc_static_runtime
from conan.tools.scm import Version
import os
required_conan_version = ">=1.55.0"
class LibMysqlClientCConan(ConanFile):
name = "libmysqlclient"
description = "A MySQL client library for C development."
license = "GPL-2.0"
url = "https://github.com/conan-io/conan-center-index"
topics = ("mysql", "sql", "connector", "database")
homepage = "https://dev.mysql.com/downloads/mysql/"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
}
package_type = "library"
short_paths = True
@property
def _min_cppstd(self):
return "17" if Version(self.version) >= "8.0.27" else "11"
@property
def _compilers_minimum_version(self):
return {
"Visual Studio": "16",
"msvc": "192",
"gcc": "7" if Version(self.version) >= "8.0.27" else "5.3",
"clang": "6",
}
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
def layout(self):
cmake_layout(self, src_folder="src")
def requirements(self):
if Version(self.version) < "8.0.30":
self.requires("openssl/1.1.1w")
else:
self.requires("openssl/[>=1.1 <4]")
self.requires("zlib/[>=1.2.11 <2]")
self.requires("zstd/1.5.5")
self.requires("lz4/1.9.4")
if self.settings.os == "FreeBSD":
self.requires("libunwind/1.7.2")
def validate_build(self):
if self.settings.compiler.get_safe("cppstd"):
check_min_cppstd(self, self._min_cppstd)
if hasattr(self, "settings_build") and cross_building(self, skip_x64_x86=True):
raise ConanInvalidConfiguration("Cross compilation not yet supported by the recipe. Contributions are welcomed.")
def validate(self):
def loose_lt_semver(v1, v2):
lv1 = [int(v) for v in v1.split(".")]
lv2 = [int(v) for v in v2.split(".")]
min_length = min(len(lv1), len(lv2))
return lv1[:min_length] < lv2[:min_length]
minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False)
if minimum_version and loose_lt_semver(str(self.settings.compiler.version), minimum_version):
raise ConanInvalidConfiguration(f"{self.ref} requires {self.settings.compiler} {minimum_version} or newer")
# mysql < 8.0.29 uses `requires` in source code. It is the reserved keyword in C++20.
# https://github.com/mysql/mysql-server/blob/mysql-8.0.0/include/mysql/components/services/dynamic_loader.h#L270
if self.settings.compiler.get_safe("cppstd") == "20" and Version(self.version) < "8.0.29":
raise ConanInvalidConfiguration(f"{self.ref} doesn't support C++20")
def build_requirements(self):
if is_apple_os(self):
self.tool_requires("cmake/[>=3.18 <4]")
if self.settings.os == "FreeBSD" and not self.conf.get("tools.gnu:pkg_config", check_type=str):
self.tool_requires("pkgconf/2.0.3")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def _patch_sources(self):
apply_conandata_patches(self)
libs_to_remove = ["icu", "libevent", "re2", "rapidjson", "protobuf", "libedit"]
for lib in libs_to_remove:
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
f"MYSQL_CHECK_{lib.upper()}()\n",
"",
strict=False)
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
f"INCLUDE({lib})\n",
"",
strict=False)
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
f"WARN_MISSING_SYSTEM_{lib.upper()}({lib.upper()}_WARN_GIVEN)",
f"# WARN_MISSING_SYSTEM_{lib.upper()}({lib.upper()}_WARN_GIVEN)",
strict=False)
if lib != "libevent" or Version(self.version) < "8.0.34":
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
f"SET({lib.upper()}_WARN_GIVEN)",
f"# SET({lib.upper()}_WARN_GIVEN)",
strict=False)
for folder in ["client", "man", "mysql-test", "libbinlogstandalone"]:
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
f"ADD_SUBDIRECTORY({folder})\n",
"",
strict=False)
rmdir(self, os.path.join(self.source_folder, "storage", "ndb"))
for t in ["INCLUDE(cmake/boost.cmake)\n", "MYSQL_CHECK_EDITLINE()\n"]:
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
t,
"",
strict=False)
# Upstream does not actually load lz4 directories for system, force it to
if Version(self.version) < "8.0.34":
replace_in_file(self, os.path.join(self.source_folder, "libbinlogevents", "CMakeLists.txt"),
"INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/libbinlogevents/include)",
"MY_INCLUDE_SYSTEM_DIRECTORIES(LZ4)\nINCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/libbinlogevents/include)")
replace_in_file(self, os.path.join(self.source_folder, "cmake", "zstd.cmake"),
"NAMES zstd",
f"NAMES zstd {self.dependencies['zstd'].cpp_info.aggregated_components().libs[0]}")
# Fix discovery & link to OpenSSL
ssl_cmake = os.path.join(self.source_folder, "cmake", "ssl.cmake")
replace_in_file(self, ssl_cmake,
"NAMES ssl",
f"NAMES ssl {self.dependencies['openssl'].cpp_info.components['ssl'].libs[0]}")
replace_in_file(self, ssl_cmake,
"NAMES crypto",
f"NAMES crypto {self.dependencies['openssl'].cpp_info.components['crypto'].libs[0]}")
replace_in_file(self, ssl_cmake,
"IF(NOT OPENSSL_APPLINK_C)\n",
"IF(FALSE AND NOT OPENSSL_APPLINK_C)\n",
strict=False)
replace_in_file(self, ssl_cmake,
"SET(SSL_LIBRARIES ${MY_OPENSSL_LIBRARY} ${MY_CRYPTO_LIBRARY})",
"find_package(OpenSSL REQUIRED MODULE)\nset(SSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)")
# And do not merge OpenSSL libs into mysqlclient lib
replace_in_file(self, os.path.join(self.source_folder, "cmake", "libutils.cmake"),
'IF(WIN32 AND ${TARGET} STREQUAL "mysqlclient")',
"if(0)")
# Do not copy shared libs of dependencies to package folder
deps_shared = ["SSL", "KERBEROS", "SASL", "LDAP", "PROTOBUF"]
if Version(self.version) < "8.0.34":
deps_shared.append("CURL")
for dep in deps_shared:
replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"),
f"MYSQL_CHECK_{dep}_DLLS()",
"")
if self.settings.os == "Macos":
replace_in_file(self, os.path.join(self.source_folder, "libmysql", "CMakeLists.txt"),
f"COMMAND {'libmysql_api_test'}",
f"COMMAND DYLD_LIBRARY_PATH={os.path.join(self.build_folder, 'library_output_directory')} {os.path.join(self.build_folder, 'runtime_output_directory', 'libmysql_api_test')}")
replace_in_file(self, os.path.join(self.source_folder, "cmake", "install_macros.cmake"),
" INSTALL_DEBUG_SYMBOLS(",
" # INSTALL_DEBUG_SYMBOLS(")
def generate(self):
vbenv = VirtualBuildEnv(self)
vbenv.generate()
if not cross_building(self):
vrenv = VirtualRunEnv(self)
vrenv.generate(scope="build")
tc = CMakeToolchain(self)
# Not used anywhere in the CMakeLists
tc.cache_variables["DISABLE_SHARED"] = not self.options.shared
tc.cache_variables["STACK_DIRECTION"] = "-1" # stack grows downwards, on very few platforms stack grows upwards
tc.cache_variables["WITHOUT_SERVER"] = True
tc.cache_variables["WITH_UNIT_TESTS"] = False
tc.cache_variables["ENABLED_PROFILING"] = False
tc.cache_variables["MYSQL_MAINTAINER_MODE"] = False
tc.cache_variables["WIX_DIR"] = False
# Disable additional Linux distro-specific compiler checks.
# The recipe already checks for minimum versions of supported
# compilers.
tc.cache_variables["FORCE_UNSUPPORTED_COMPILER"] = True
tc.cache_variables["WITH_LZ4"] = "system"
tc.cache_variables["WITH_ZSTD"] = "system"
tc.cache_variables["ZSTD_INCLUDE_DIR"] = self.dependencies["zstd"].cpp_info.aggregated_components().includedirs[0].replace("\\", "/")
if is_msvc(self):
tc.cache_variables["WINDOWS_RUNTIME_MD"] = not is_msvc_static_runtime(self)
tc.cache_variables["WITH_SSL"] = self.dependencies["openssl"].package_folder.replace("\\", "/")
tc.cache_variables["WITH_ZLIB"] = "system"
# Remove to ensure reproducible build, this only affects docs generation
tc.cache_variables["CMAKE_DISABLE_FIND_PACKAGE_Doxygen"] = True
tc.generate()
deps = CMakeDeps(self)
deps.generate()
if self.settings.os == "FreeBSD":
deps = PkgConfigDeps(self)
deps.generate()
def build(self):
self._patch_sources()
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
cmake = CMake(self)
cmake.install()
mkdir(self, os.path.join(self.package_folder, "licenses"))
rename(self, os.path.join(self.package_folder, "LICENSE"), os.path.join(self.package_folder, "licenses", "LICENSE"))
rm(self, "README", self.package_folder)
rm(self, "*.pdb", self.package_folder, recursive=True)
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "lib", "plugin"))
rmdir(self, os.path.join(self.package_folder, "docs"))
rmdir(self, os.path.join(self.package_folder, "share"))
if self.settings.os == "Windows":
if self.options.shared:
rename(self, os.path.join(self.package_folder, "lib", "libmysql.dll"),
os.path.join(self.package_folder, "bin", "libmysql.dll"))
rm(self, "*mysqlclient.*", os.path.join(self.package_folder, "lib"))
else:
rm(self, "*.dll", os.path.join(self.package_folder, "lib"))
rm(self, "*libmysql.*", os.path.join(self.package_folder, "lib"))
else:
if self.options.shared:
rm(self, "*.a", os.path.join(self.package_folder, "lib"))
else:
rm(self, "*.dylib", os.path.join(self.package_folder, "lib"))
rm(self, "*.so*", os.path.join(self.package_folder, "lib"))
def package_info(self):
self.cpp_info.set_property("pkg_config_name", "mysqlclient")
self.cpp_info.libs = ["libmysql" if self.settings.os == "Windows" and self.options.shared else "mysqlclient"]
self.cpp_info.includedirs.append(os.path.join("include", "mysql"))
if not self.options.shared:
stdcpplib = stdcpp_library(self)
if stdcpplib:
self.cpp_info.system_libs.append(stdcpplib)
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.extend(["m", "resolv"])
if self.settings.os == "Windows":
self.cpp_info.system_libs.extend(["dnsapi", "secur32"])
# TODO: There is no official FindMySQL.cmake, but it's a common Find files in many projects
# do we want to support it in CMakeDeps?
self.cpp_info.names["cmake_find_package"] = "MySQL"
self.cpp_info.names["cmake_find_package_multi"] = "MySQL"

View File

@@ -0,0 +1,13 @@
diff --git a/mysys/my_default.cc b/mysys/my_default.cc
--- a/mysys/my_default.cc
+++ b/mysys/my_default.cc
@@ -1180,7 +1180,7 @@ static mysql_file_getline_ret mysql_file_getline(char *buff, int size,
/* If the supplied buff/size is enough to store the line, then we return the
* buff itself. In this case, we use this noop deleter */
- static auto noop_free = [](void *) {};
+ static auto noop_free = [](void *) noexcept {};
if (is_login_file) {
if (mysql_file_ftell(file) == 0) {

View File

@@ -0,0 +1,13 @@
diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake
index 192035dd..dedc59c6 100644
--- a/cmake/package_name.cmake
+++ b/cmake/package_name.cmake
@@ -94,7 +94,7 @@ MACRO(GET_PACKAGE_FILE_NAME Var)
STRING(REGEX MATCH
"ProductVersion:[\n\t ]*([0-9]+)\\.([0-9]+)" UNUSED ${SW_VERS_PRODUCTVERSION})
- IF(NOT CMAKE_MATCH_1 OR NOT CMAKE_MATCH_2)
+ IF(CMAKE_MATCH_1 STREQUAL "" OR CMAKE_MATCH_2 STREQUAL "")
MESSAGE(FATAL_ERROR "Could not run sw_vers")
ENDIF()

View File

@@ -0,0 +1,17 @@
diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h
index a03d754..381216d 100644
--- a/sql/sql_bitmap.h
+++ b/sql/sql_bitmap.h
@@ -138,10 +138,10 @@ class Bitmap<64> {
ulonglong map;
public:
- Bitmap<64>() { init(); }
+ Bitmap() { init(); }
enum { ALL_BITS = 64 };
- explicit Bitmap<64>(uint prefix_to_set) { set_prefix(prefix_to_set); }
+ explicit Bitmap(uint prefix_to_set) { set_prefix(prefix_to_set); }
void init() { clear_all(); }
void init(uint prefix_to_set) { set_prefix(prefix_to_set); }
uint length() const { return 64; }

View File

@@ -0,0 +1,17 @@
diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h
index 0f4a540..bd81a40 100644
--- a/sql/sql_bitmap.h
+++ b/sql/sql_bitmap.h
@@ -145,10 +145,10 @@ class Bitmap<64> {
ulonglong map;
public:
- Bitmap<64>() { init(); }
+ Bitmap() { init(); }
enum { ALL_BITS = 64 };
- explicit Bitmap<64>(uint prefix_to_set) { set_prefix(prefix_to_set); }
+ explicit Bitmap(uint prefix_to_set) { set_prefix(prefix_to_set); }
void init() { clear_all(); }
void init(uint prefix_to_set) { set_prefix(prefix_to_set); }
uint length() const { return 64; }

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES C)
find_package(libmysqlclient REQUIRED CONFIG)
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE libmysqlclient::libmysqlclient)

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")

View File

@@ -0,0 +1,8 @@
#include <mysql.h>
#include <stdio.h>
int main(int argc, char **argv)
{
printf("MySQL client version: %s\n", mysql_get_client_info());
return 0;
}

View File

@@ -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(MySQL REQUIRED CONFIG)
add_executable(${PROJECT_NAME} ../test_package/test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE MySQL::MySQL)

View File

@@ -0,0 +1,18 @@
from conans import ConanFile, CMake
from conan.tools.build import cross_building
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 cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

View File

@@ -0,0 +1,11 @@
versions:
"8.1.0":
folder: all
"8.0.34":
folder: all
"8.0.31":
folder: all
"8.0.30":
folder: all
"8.0.25":
folder: all

View File

@@ -0,0 +1,39 @@
sources:
"15.5":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v15.5/postgresql-15.5.tar.bz2"
sha256: "8f53aa95d78eb8e82536ea46b68187793b42bba3b4f65aa342f540b23c9b10a6"
"15.4":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v15.4/postgresql-15.4.tar.bz2"
sha256: "baec5a4bdc4437336653b6cb5d9ed89be5bd5c0c58b94e0becee0a999e63c8f9"
"15.3":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v15.3/postgresql-15.3.tar.bz2"
sha256: "ffc7d4891f00ffbf5c3f4eab7fbbced8460b8c0ee63c5a5167133b9e6599d932"
"14.9":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v14.9/postgresql-14.9.tar.bz2"
sha256: "b1fe3ba9b1a7f3a9637dd1656dfdad2889016073fd4d35f13b50143cbbb6a8ef"
patches:
"15.5":
- patch_file: "patches/15/001-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"
- patch_file: "patches/15.5/0001-Use-BIO_-get-set-_app_data-instead-of-BIO_-get-se.patch"
patch_description: "Fix libpq w/ openssl >=3.2.x"
patch_type: "backport"
"15.4":
- patch_file: "patches/15/001-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"
- patch_file: "patches/15/0001-Use-BIO_-get-set-_app_data-instead-of-BIO_-get-se.patch"
patch_description: "Fix libpq w/ openssl >=3.2.x"
patch_type: "backport"
"15.3":
- patch_file: "patches/15/001-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"
- patch_file: "patches/15/0001-Use-BIO_-get-set-_app_data-instead-of-BIO_-get-se.patch"
patch_description: "Fix libpq w/ openssl >=3.2.x"
patch_type: "backport"
"14.9":
- patch_file: "patches/14/002-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"

View File

@@ -0,0 +1,288 @@
from conan import ConanFile
from conan.tools.apple import fix_apple_shared_install_name
from conan.tools.build import cross_building
from conan.tools.env import Environment, VirtualBuildEnv, VirtualRunEnv
from conan.tools.files import apply_conandata_patches, chdir, copy, export_conandata_patches, get, replace_in_file, rm, rmdir
from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps
from conan.tools.layout import basic_layout
from conan.tools.microsoft import is_msvc, msvc_runtime_flag, unix_path, VCVars
from conan.tools.scm import Version
import glob
import os
required_conan_version = ">=1.54.0"
class LibpqConan(ConanFile):
name = "libpq"
description = "The library used by all the standard PostgreSQL tools."
topics = ("postgresql", "database", "db")
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://www.postgresql.org/docs/current/static/libpq.html"
license = "PostgreSQL"
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"with_openssl": [True, False],
"disable_rpath": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"with_openssl": False,
"disable_rpath": False,
}
@property
def _is_clang8_x86(self):
return self.settings.os == "Linux" and \
self.settings.compiler == "clang" and \
self.settings.compiler.version == "8" and \
self.settings.arch == "x86"
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
self.options.rm_safe("fPIC")
self.options.rm_safe("disable_rpath")
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")
def layout(self):
basic_layout(self, src_folder="src")
def requirements(self):
if self.options.with_openssl:
self.requires("openssl/[>=1.1 <4]")
def build_requirements(self):
if is_msvc(self):
self.tool_requires("strawberryperl/5.32.1.1")
elif self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
if is_msvc(self):
vcvars = VCVars(self)
vcvars.generate()
config = "DEBUG" if self.settings.build_type == "Debug" else "RELEASE"
env = Environment()
env.define("CONFIG", config)
env.vars(self).save_script("conanbuild_msvc")
else:
if not cross_building(self):
env = VirtualRunEnv(self)
env.generate(scope="build")
tc = AutotoolsToolchain(self)
tc.configure_args.append('--without-readline')
tc.configure_args.append('--without-zlib')
tc.configure_args.append('--with-openssl' if self.options.with_openssl else '--without-openssl')
if cross_building(self) and not self.options.with_openssl:
tc.configure_args.append("--disable-strong-random")
if cross_building(self, skip_x64_x86=True):
tc.configure_args.append("USE_DEV_URANDOM=1")
if self.settings.os != "Windows" and self.options.disable_rpath:
tc.configure_args.append('--disable-rpath')
if self._is_clang8_x86:
tc.extra_cflags.append("-msse2")
tc.make_args.append(f"DESTDIR={unix_path(self, self.package_folder)}")
if self.settings.os == "Windows":
tc.make_args.append("MAKE_DLL={}".format(str(self.options.shared).lower()))
tc.generate()
AutotoolsDeps(self).generate()
def _patch_sources(self):
if is_msvc(self):
# https://www.postgresql.org/docs/8.3/install-win32-libpq.html
# https://github.com/postgres/postgres/blob/master/src/tools/msvc/README
if not self.options.shared:
replace_in_file(self,os.path.join(self.source_folder, "src", "tools", "msvc", "MKvcbuild.pm"),
"$libpq = $solution->AddProject('libpq', 'dll', 'interfaces',",
"$libpq = $solution->AddProject('libpq', 'lib', 'interfaces',")
host_deps = [dep for _, dep in self.dependencies.host.items()]
system_libs = []
for dep in host_deps:
system_libs.extend(dep.cpp_info.aggregated_components().system_libs)
linked_system_libs = ", ".join(["'{}.lib'".format(lib) for lib in system_libs])
replace_in_file(self,os.path.join(self.source_folder, "src", "tools", "msvc", "Project.pm"),
"libraries => [],",
"libraries => [{}],".format(linked_system_libs))
runtime = {
"MT": "MultiThreaded",
"MTd": "MultiThreadedDebug",
"MD": "MultiThreadedDLL",
"MDd": "MultiThreadedDebugDLL",
}.get(msvc_runtime_flag(self))
msbuild_project_pm = os.path.join(self.source_folder, "src", "tools", "msvc", "MSBuildProject.pm")
replace_in_file(self,msbuild_project_pm, "</Link>", """</Link>
<Lib>
<TargetMachine>$targetmachine</TargetMachine>
</Lib>""")
replace_in_file(self,msbuild_project_pm, "'MultiThreadedDebugDLL'", "'%s'" % runtime)
replace_in_file(self,msbuild_project_pm, "'MultiThreadedDLL'", "'%s'" % runtime)
config_default_pl = os.path.join(self.source_folder, "src", "tools", "msvc", "config_default.pl")
solution_pm = os.path.join(self.source_folder, "src", "tools", "msvc", "Solution.pm")
if self.options.with_openssl:
openssl = self.dependencies["openssl"]
for ssl in ["VC\\libssl32", "VC\\libssl64", "libssl"]:
replace_in_file(self,solution_pm,
"%s.lib" % ssl,
"%s.lib" % openssl.cpp_info.components["ssl"].libs[0])
for crypto in ["VC\\libcrypto32", "VC\\libcrypto64", "libcrypto"]:
replace_in_file(self,solution_pm,
"%s.lib" % crypto,
"%s.lib" % openssl.cpp_info.components["crypto"].libs[0])
replace_in_file(self,config_default_pl,
"openssl => undef",
"openssl => '%s'" % openssl.package_folder.replace("\\", "/"))
elif self.settings.os == "Windows":
if self.settings.get_safe("compiler.threads") == "posix":
# Use MinGW pthread library
replace_in_file(self, os.path.join(self.source_folder, "src", "interfaces", "libpq", "Makefile"),
"ifeq ($(enable_thread_safety), yes)\nOBJS += pthread-win32.o\nendif",
"")
# When linking to static openssl, it comes with static pthread library too, failing with:
# libpq.so.5.15: U pthread_exit@GLIBC_2.2.5: libpq must not be calling any function which invokes exit
# https://www.postgresql.org/message-id/20210703001639.GB2374652%40rfd.leadboat.com
if Version(self.version) >= "15":
replace_in_file(self, os.path.join(self.source_folder, "src", "interfaces", "libpq", "Makefile"),
"-v __cxa_atexit",
"-v __cxa_atexit -e pthread_exit")
def build(self):
apply_conandata_patches(self)
self._patch_sources()
if is_msvc(self):
with chdir(self, os.path.join(self.source_folder, "src", "tools", "msvc")):
self.run("perl build.pl libpq")
if not self.options.shared:
self.run("perl build.pl libpgport")
else:
autotools = Autotools(self)
with chdir(self, os.path.join(self.build_folder)):
autotools.configure()
with chdir(self, os.path.join(self.build_folder, "src", "backend")):
autotools.make(target="generated-headers")
with chdir(self, os.path.join(self.build_folder, "src", "common")):
autotools.make()
with chdir(self, os.path.join(self.build_folder, "src", "include")):
autotools.make()
with chdir(self, os.path.join(self.build_folder, "src", "interfaces", "libpq")):
autotools.make()
if Version(self.version) >= 12:
with chdir(self, os.path.join(self.build_folder, "src", "port")):
autotools.make()
with chdir(self, os.path.join(self.build_folder, "src", "bin", "pg_config")):
autotools.make()
def _remove_unused_libraries_from_package(self):
bin_folder = os.path.join(self.package_folder, "bin")
lib_folder = os.path.join(self.package_folder, "lib")
rm(self, "*.dll", lib_folder)
if self.options.shared:
for lib in glob.glob(os.path.join(lib_folder, "*.a")):
if not (self.settings.os == "Windows" and os.path.basename(lib) == "libpq.dll.a"):
os.remove(lib)
else:
rm(self, "*.dll", bin_folder)
rm(self, "*.dll.a", lib_folder)
rm(self, "*.so*", lib_folder)
rm(self, "*.dylib", lib_folder)
def package(self):
copy(self, "COPYRIGHT", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
if is_msvc(self):
copy(self, pattern="*postgres_ext.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*pg_config.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*pg_config_ext.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*libpq-fe.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*libpq-events.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*.h", src=os.path.join(self.source_folder, "src", "include", "libpq"),
dst=os.path.join(self.package_folder, "include", "libpq"),
keep_path=False)
copy(self, pattern="*genbki.h", src=self.source_folder, dst=os.path.join(self.package_folder, "include", "catalog"), keep_path=False)
copy(self, pattern="*pg_type.h", src=self.source_folder, dst=os.path.join(self.package_folder, "include", "catalog"), keep_path=False)
if self.options.shared:
copy(self, pattern="**/libpq.dll", dst=os.path.join(self.package_folder, "bin"), src=self.source_folder, keep_path=False)
copy(self, pattern="**/libpq.lib", dst=os.path.join(self.package_folder, "lib"), src=self.source_folder, keep_path=False)
else:
copy(self, pattern="*.lib", dst=os.path.join(self.package_folder, "lib"), src=self.source_folder, keep_path=False)
else:
autotools = Autotools(self)
with chdir(self, os.path.join(self.build_folder, "src", "common")):
autotools.install()
with chdir(self, os.path.join(self.build_folder, "src", "include")):
autotools.install()
with chdir(self, os.path.join(self.build_folder, "src", "interfaces", "libpq")):
autotools.install()
if Version(self.version) >= 12:
with chdir(self, os.path.join(self.build_folder, "src", "port")):
autotools.install()
with chdir(self, os.path.join(self.build_folder, "src", "bin", "pg_config")):
autotools.install()
copy(self, "*.h", src=os.path.join(self.source_folder, "src", "include", "catalog"),
dst=os.path.join(self.package_folder, "include", "catalog"))
rmdir(self, os.path.join(self.package_folder, "share"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "include", "postgresql", "server"))
self._remove_unused_libraries_from_package()
fix_apple_shared_install_name(self)
copy(self, "*.h", src=os.path.join(self.source_folder, "src", "backend", "catalog"),
dst=os.path.join(self.package_folder, "include", "catalog"))
def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "PostgreSQL")
self.cpp_info.set_property("cmake_target_name", "PostgreSQL::PostgreSQL")
self.cpp_info.set_property("pkg_config_name", "libpq")
self.env_info.PostgreSQL_ROOT = self.package_folder
self.cpp_info.components["pq"].libs = [f"{'lib' if is_msvc(self) else ''}pq"]
if self.options.with_openssl:
self.cpp_info.components["pq"].requires.append("openssl::openssl")
if not self.options.shared:
if is_msvc(self):
self.cpp_info.components["pgport"].libs = ["libpgport"]
self.cpp_info.components["pq"].requires.append("pgport")
self.cpp_info.components["pgcommon"].libs = ["libpgcommon"]
self.cpp_info.components["pq"].requires.append("pgcommon")
else:
self.cpp_info.components["pgcommon"].libs = ["pgcommon"]
self.cpp_info.components["pq"].requires.append("pgcommon")
self.cpp_info.components["pgcommon"].libs.append("pgcommon_shlib")
self.cpp_info.components["pgport"].libs = ["pgport", "pgport_shlib"]
if self.settings.os == "Windows":
self.cpp_info.components["pgport"].system_libs = ["ws2_32"]
self.cpp_info.components["pgcommon"].requires.append("pgport")
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["pq"].system_libs = ["pthread"]
elif self.settings.os == "Windows":
self.cpp_info.components["pq"].system_libs = ["ws2_32", "secur32", "advapi32", "shell32", "crypt32", "wldap32"]
self.cpp_info.names["cmake_find_package"] = "PostgreSQL"
self.cpp_info.names["cmake_find_package_multi"] = "PostgreSQL"

View File

@@ -0,0 +1,39 @@
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -358,7 +358,10 @@ else
# Win32 case
# See notes in src/backend/parser/Makefile about the following two rules
-$(stlib): $(shlib)
+$(stlib): $(OBJS) | $(SHLIB_PREREQS)
+ rm -f $@
+ $(LINK.static) $@ $^
+ $(RANLIB) $@
touch $@
# XXX A backend that loads a module linked with libgcc_s_dw2-1.dll will exit
@@ -371,12 +374,12 @@ $(stlib): $(shlib)
# Else we just use --export-all-symbols.
ifeq (,$(SHLIB_EXPORTS))
$(shlib): $(OBJS) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=lib$(NAME).dll.a
else
DLL_DEFFILE = lib$(NAME)dll.def
$(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=lib$(NAME).dll.a
UC_NAME = $(shell echo $(NAME) | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
@@ -452,6 +455,9 @@ endif # not aix
ifneq (,$(findstring $(PORTNAME),win32 cygwin))
$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
endif
+ifneq (,$(findstring $(PORTNAME),win32))
+ $(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/lib$(NAME).dll.a'
+endif
else # no soname
$(INSTALL_SHLIB) $< '$(DESTDIR)$(pkglibdir)/$(shlib)'
endif

View File

@@ -0,0 +1,193 @@
From 672103a67aaf0dae5be6c5adcc5ce19e5b6d7676 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@neon.tech>
Date: Mon, 27 Nov 2023 11:49:52 -0600
Subject: [PATCH v1] Use BIO_{get,set}_app_data() instead of
BIO_{get,set}_data()
Compiling Postgres against OpenSSL 3.2 exposed a regression:
$ psql "postgresql://$DB?sslmode=require"
psql: error: connection to server at "redacted" (redacted), port 5432 failed: ERROR: Parameter 'user' is missing in startup packet.
double free or corruption (out)
Aborted (core dumped)
Analyzing the backtrace, openssl was overwriting heap-allocated data in
our PGconn struct because it thought BIO::ptr was a struct bss_sock_st
*. OpenSSL then called a memset() on a member of that struct, and we
zeroed out data in our PGconn struct.
BIO_get_data(3) says the following:
> These functions are mainly useful when implementing a custom BIO.
>
> The BIO_set_data() function associates the custom data pointed to by ptr
> with the BIO a. This data can subsequently be retrieved via a call to
> BIO_get_data(). This can be used by custom BIOs for storing
> implementation specific information.
If you take a look at my_BIO_s_socket(), we create a partially custom
BIO, but for the most part are defaulting to the methods defined by
BIO_s_socket(). We need to set application-specific data and not BIO
private data, so that the BIO implementation we rely on, can properly
assert that its private data is what it expects.
Rebased against libpq15
Co-authored-by: Bo Andreson <mail@boanderson.me>
---
src/backend/libpq/be-secure-openssl.c | 11 +++--------
src/include/pg_config.h.in | 3 ---
src/interfaces/libpq/fe-secure-openssl.c | 20 +++-----------------
src/tools/msvc/Solution.pm | 2 --
4 files changed, 6 insertions(+), 30 deletions(-)
diff --git a/configure b/configure
index d83a402ea1..d55440cd6a 100755
--- a/configure
+++ b/configure
@@ -13239,7 +13239,7 @@ done
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+ for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index 570daced81..2bc752ca1a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1347,7 +1347,7 @@ if test "$with_ssl" = openssl ; then
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
# OpenSSL versions before 1.1.0 required setting callback functions, for
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
# function was removed.
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index f5c5ed210e..aed8a75345 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -839,11 +839,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods = NULL;
static int
@@ -853,7 +848,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL)
{
- res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -873,7 +868,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res = 0;
- res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -949,7 +944,7 @@ my_SSL_set_fd(Port *port, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, port);
+ BIO_set_app_data(bio, port);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(port->ssl, bio, bio);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index d09e9f9a1c..768e3d719c 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -77,9 +77,6 @@
/* Define to 1 if you have the `backtrace_symbols' function. */
#undef HAVE_BACKTRACE_SYMBOLS
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
/* Define to 1 if you have the `BIO_meth_new' function. */
#undef HAVE_BIO_METH_NEW
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index af59ff49f7..8d68d023e9 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1800,11 +1800,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods;
static int
@@ -1812,7 +1807,7 @@ my_sock_read(BIO *h, char *buf, int size)
{
int res;
- res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_read((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1842,7 +1837,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res;
- res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1933,7 +1928,7 @@ my_SSL_set_fd(PGconn *conn, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, conn);
+ BIO_set_app_data(bio, conn);
SSL_set_bio(conn->ssl, bio, bio);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 790f03b05e..a53239fa28 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -226,7 +226,6 @@ sub GenerateFiles
HAVE_ATOMICS => 1,
HAVE_ATOMIC_H => undef,
HAVE_BACKTRACE_SYMBOLS => undef,
- HAVE_BIO_GET_DATA => undef,
HAVE_BIO_METH_NEW => undef,
HAVE_CLOCK_GETTIME => undef,
HAVE_COMPUTED_GOTO => undef,
@@ -566,7 +565,6 @@ sub GenerateFiles
|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
{
$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
- $define{HAVE_BIO_GET_DATA} = 1;
$define{HAVE_BIO_METH_NEW} = 1;
$define{HAVE_HMAC_CTX_FREE} = 1;
$define{HAVE_HMAC_CTX_NEW} = 1;
--
Tristan Partin
Neon (https://neon.tech)

View File

@@ -0,0 +1,193 @@
From 672103a67aaf0dae5be6c5adcc5ce19e5b6d7676 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@neon.tech>
Date: Mon, 27 Nov 2023 11:49:52 -0600
Subject: [PATCH v1] Use BIO_{get,set}_app_data() instead of
BIO_{get,set}_data()
Compiling Postgres against OpenSSL 3.2 exposed a regression:
$ psql "postgresql://$DB?sslmode=require"
psql: error: connection to server at "redacted" (redacted), port 5432 failed: ERROR: Parameter 'user' is missing in startup packet.
double free or corruption (out)
Aborted (core dumped)
Analyzing the backtrace, openssl was overwriting heap-allocated data in
our PGconn struct because it thought BIO::ptr was a struct bss_sock_st
*. OpenSSL then called a memset() on a member of that struct, and we
zeroed out data in our PGconn struct.
BIO_get_data(3) says the following:
> These functions are mainly useful when implementing a custom BIO.
>
> The BIO_set_data() function associates the custom data pointed to by ptr
> with the BIO a. This data can subsequently be retrieved via a call to
> BIO_get_data(). This can be used by custom BIOs for storing
> implementation specific information.
If you take a look at my_BIO_s_socket(), we create a partially custom
BIO, but for the most part are defaulting to the methods defined by
BIO_s_socket(). We need to set application-specific data and not BIO
private data, so that the BIO implementation we rely on, can properly
assert that its private data is what it expects.
Rebased against libpq15
Co-authored-by: Bo Andreson <mail@boanderson.me>
---
src/backend/libpq/be-secure-openssl.c | 11 +++--------
src/include/pg_config.h.in | 3 ---
src/interfaces/libpq/fe-secure-openssl.c | 20 +++-----------------
src/tools/msvc/Solution.pm | 2 --
4 files changed, 6 insertions(+), 30 deletions(-)
diff --git a/configure b/configure
index d733a59..c13ad3d 100755
--- a/configure
+++ b/configure
@@ -13237,7 +13237,7 @@ done
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+ for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index 44868ba..77e59a2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1347,7 +1347,7 @@ if test "$with_ssl" = openssl ; then
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
# OpenSSL versions before 1.1.0 required setting callback functions, for
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
# function was removed.
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 8f9b81c..9abee50 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -830,11 +830,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods = NULL;
static int
@@ -844,7 +839,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL)
{
- res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -864,7 +859,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res = 0;
- res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -940,7 +935,7 @@ my_SSL_set_fd(Port *port, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, port);
+ BIO_set_app_data(bio, port);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(port->ssl, bio, bio);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index d09e9f9..768e3d7 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -77,9 +77,6 @@
/* Define to 1 if you have the `backtrace_symbols' function. */
#undef HAVE_BACKTRACE_SYMBOLS
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
/* Define to 1 if you have the `BIO_meth_new' function. */
#undef HAVE_BIO_METH_NEW
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index af59ff4..8d68d02 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1800,11 +1800,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods;
static int
@@ -1812,7 +1807,7 @@ my_sock_read(BIO *h, char *buf, int size)
{
int res;
- res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_read((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1842,7 +1837,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res;
- res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1933,7 +1928,7 @@ my_SSL_set_fd(PGconn *conn, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, conn);
+ BIO_set_app_data(bio, conn);
SSL_set_bio(conn->ssl, bio, bio);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 790f03b..a53239f 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -226,7 +226,6 @@ sub GenerateFiles
HAVE_ATOMICS => 1,
HAVE_ATOMIC_H => undef,
HAVE_BACKTRACE_SYMBOLS => undef,
- HAVE_BIO_GET_DATA => undef,
HAVE_BIO_METH_NEW => undef,
HAVE_CLOCK_GETTIME => undef,
HAVE_COMPUTED_GOTO => undef,
@@ -566,7 +565,6 @@ sub GenerateFiles
|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
{
$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
- $define{HAVE_BIO_GET_DATA} = 1;
$define{HAVE_BIO_METH_NEW} = 1;
$define{HAVE_HMAC_CTX_FREE} = 1;
$define{HAVE_HMAC_CTX_NEW} = 1;
--
Tristan Partin
Neon (https://neon.tech)

View File

@@ -0,0 +1,39 @@
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -322,7 +322,10 @@ else # PORTNAME == aix
# AIX case
# See notes in src/backend/parser/Makefile about the following two rules
-$(stlib): $(shlib)
+$(stlib): $(OBJS) | $(SHLIB_PREREQS)
+ rm -f $@
+ $(LINK.static) $@ $^
+ $(RANLIB) $@
touch $@
$(shlib): $(OBJS) | $(SHLIB_PREREQS)
@@ -371,12 +374,12 @@ $(stlib): $(shlib)
# Else we just use --export-all-symbols.
ifeq (,$(SHLIB_EXPORTS))
$(shlib): $(OBJS) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=lib$(NAME).dll.a
else
DLL_DEFFILE = lib$(NAME)dll.def
$(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=lib$(NAME).dll.a
UC_NAME = $(shell echo $(NAME) | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
@@ -457,6 +460,9 @@ endif # not aix
ifneq (,$(findstring $(PORTNAME),win32 cygwin))
$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
endif
+ifneq (,$(findstring $(PORTNAME),win32))
+ $(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/lib$(NAME).dll.a'
+endif
else # no soname
$(INSTALL_SHLIB) $< '$(DESTDIR)$(pkglibdir)/$(shlib)'
endif

View File

@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES C)
find_package(PostgreSQL REQUIRED)
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE PostgreSQL::PostgreSQL)

View File

@@ -0,0 +1,10 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json",
"build/gcc-11.5-x86_64-17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")

View File

@@ -0,0 +1,17 @@
#include "libpq-fe.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
PGconn *conn = NULL;
const int version = PQlibVersion();
printf("PQlibVersion: %d\n", version);
conn = PQconnectdb("dbname = postgres");
PQstatus(conn);
PQfinish(conn);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES C)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/)

View File

@@ -0,0 +1,18 @@
from conans import ConanFile, CMake
from conan.tools.build import cross_building
import os
class TestPackageV1Conan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if not cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

9
recipes/libpq/config.yml Normal file
View File

@@ -0,0 +1,9 @@
versions:
"15.5":
folder: all
"15.4":
folder: all
"15.3":
folder: all
"14.9":
folder: all

View File

@@ -0,0 +1,37 @@
sources:
"2.13.4":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.13/libxml2-2.13.4.tar.xz"
sha256: "65d042e1c8010243e617efb02afda20b85c2160acdbfbcb5b26b80cec6515650"
"2.12.9":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.12/libxml2-2.12.9.tar.xz"
sha256: "59912db536ab56a3996489ea0299768c7bcffe57169f0235e7f962a91f483590"
"2.12.4":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.12/libxml2-2.12.4.tar.xz"
sha256: "497360e423cf0bd99eacdb7c6215dea92e6d6e89ee940393c2bae0e77cb9b7d0"
"2.12.3":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.12/libxml2-2.12.3.tar.xz"
sha256: "8c8f1092340a89ff32bc44ad5c9693aff9bc8a7a3e161bb239666e5d15ac9aaa"
"2.11.9":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.11/libxml2-2.11.9.tar.xz"
sha256: "780157a1efdb57188ec474dca87acaee67a3a839c2525b2214d318228451809f"
"2.11.6":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.11/libxml2-2.11.6.tar.xz"
sha256: "c90eee7506764abbe07bb616b82da452529609815aefef423d66ef080eb0c300"
"2.11.4":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.11/libxml2-2.11.4.tar.xz"
sha256: "737e1d7f8ab3f139729ca13a2494fd17bf30ddb4b7a427cf336252cab57f57f7"
"2.10.4":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.10/libxml2-2.10.4.tar.xz"
sha256: "ed0c91c5845008f1936739e4eee2035531c1c94742c6541f44ee66d885948d45"
"2.10.3":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.10/libxml2-2.10.3.tar.xz"
sha256: "5d2cc3d78bec3dbe212a9d7fa629ada25a7da928af432c93060ff5c17ee28a9c"
"2.9.14":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.9/libxml2-2.9.14.tar.xz"
sha256: "60d74a257d1ccec0475e749cba2f21559e48139efba6ff28224357c7c798dfee"
"2.9.12":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.9/libxml2-2.9.12.tar.xz"
sha256: "28a92f6ab1f311acf5e478564c49088ef0ac77090d9c719bbc5d518f1fe62eb9"
"2.9.10":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-download_gnome_org/sources/libxml2/2.9/libxml2-2.9.10.tar.xz"
sha256: "593b7b751dd18c2d6abcd0c4bcb29efc203d0b4373a6df98e3a455ea74ae2813"

View File

@@ -0,0 +1,414 @@
from conan import ConanFile
from conan.tools.apple import fix_apple_shared_install_name
from conan.tools.build import cross_building, build_jobs
from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
from conan.tools.files import copy, get, rename, rm, rmdir, replace_in_file, save, chdir, mkdir
from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps, PkgConfigDeps
from conan.tools.layout import basic_layout
from conan.tools.microsoft import is_msvc, msvc_runtime_flag, unix_path, NMakeDeps, NMakeToolchain
from conan.tools.scm import Version
import os
import itertools
import textwrap
required_conan_version = ">=1.55.0"
class Libxml2Conan(ConanFile):
name = "libxml2"
package_type = "library"
url = "https://github.com/conan-io/conan-center-index"
description = "libxml2 is a software library for parsing XML documents"
topics = "xml", "parser", "validation"
homepage = "https://gitlab.gnome.org/GNOME/libxml2/-/wikis/"
license = "MIT"
settings = "os", "arch", "compiler", "build_type"
# from ./configure and ./win32/configure.js
default_options = {
"shared": False,
"fPIC": True,
"include_utils": True,
"c14n": True,
"catalog": True,
"docbook": True, # dropped after 2.10.3
"ftp": True,
"http": True,
"html": True,
"iconv": True,
"icu": False,
"iso8859x": True,
"legacy": True,
"mem-debug": False,
"output": True,
"pattern": True,
"push": True,
"python": False,
"reader": True,
"regexps": True,
"run-debug": False,
"sax1": True,
"schemas": True,
"schematron": True,
"threads": True,
"tree": True,
"valid": True,
"writer": True,
"xinclude": True,
"xpath": True,
"xptr": True,
"zlib": True,
"lzma": False,
}
options = {name: [True, False] for name in default_options.keys()}
@property
def _configure_option_names(self):
return [name for name in self.default_options.keys() if (name in self.options)
and (name not in ["shared", "fPIC", "include_utils"])]
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
@property
def _is_mingw_windows(self):
return self.settings.compiler == "gcc" and self.settings.os == "Windows" and self._settings_build.os == "Windows"
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
if Version(self.version) >= "2.10.3":
del self.options.docbook
if Version(self.version) >= "2.11.0":
self.options.rm_safe("run-debug")
if Version(self.version) >= "2.13.0":
self.options.rm_safe("mem-debug")
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")
def layout(self):
basic_layout(self, src_folder="src")
def requirements(self):
if self.options.zlib:
self.requires("zlib/[>=1.2.11 <2]")
if self.options.lzma:
self.requires("xz_utils/5.4.5")
if self.options.iconv:
self.requires("libiconv/1.17", transitive_headers=True, transitive_libs=True)
if self.options.icu:
self.requires("icu/73.2")
def build_requirements(self):
if not (is_msvc(self) or self._is_mingw_windows):
if self.options.zlib or self.options.lzma or self.options.icu:
if not self.conf.get("tools.gnu:pkg_config", check_type=str):
self.tool_requires("pkgconf/[>=2.1.0]")
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
if is_msvc(self):
tc = NMakeToolchain(self)
tc.generate()
deps = NMakeDeps(self)
deps.generate()
elif self._is_mingw_windows:
pass # nothing to do for mingw? it calls mingw-make directly
else:
env = VirtualBuildEnv(self)
env.generate()
if not cross_building(self):
env = VirtualRunEnv(self)
env.generate(scope="build")
tc = AutotoolsToolchain(self)
yes_no = lambda v: "yes" if v else "no"
tc.configure_args.extend([
f"--enable-shared={yes_no(self.options.shared)}",
f"--enable-static={yes_no(not self.options.shared)}",
])
for option_name in self._configure_option_names:
option_value = getattr(self.options, option_name)
tc.configure_args.append(f"--with-{option_name}={yes_no(option_value)}")
tc.generate()
tc = PkgConfigDeps(self)
tc.generate()
tc = AutotoolsDeps(self)
tc.generate()
def _build_msvc(self):
with chdir(self, os.path.join(self.source_folder, 'win32')):
debug = "yes" if self.settings.build_type == "Debug" else "no"
static = "no" if self.options.shared else "yes"
args = [
"cscript",
"configure.js",
"compiler=msvc",
f"prefix={self.package_folder}",
f"cruntime=/{msvc_runtime_flag(self)}",
f"debug={debug}",
f"static={static}",
]
incdirs = [incdir for dep in self.dependencies.values() for incdir in dep.cpp_info.includedirs]
libdirs = [libdir for dep in self.dependencies.values() for libdir in dep.cpp_info.libdirs]
args.append(f"include=\"{';'.join(incdirs)}\"")
args.append(f"lib=\"{';'.join(libdirs)}\"")
for name in self._configure_option_names:
cname = {"mem-debug": "mem_debug",
"run-debug": "run_debug",
"docbook": "docb"}.get(name, name)
value = getattr(self.options, name)
value = "yes" if value else "no"
args.append(f"{cname}={value}")
configure_command = ' '.join(args)
self.output.info(configure_command)
self.run(configure_command)
# Fix library names because they can be not just zlib.lib
def fix_library(option, package, old_libname):
if option:
libs = []
aggregated_cpp_info = self.dependencies[package].cpp_info.aggregated_components()
for lib in itertools.chain(aggregated_cpp_info.libs, aggregated_cpp_info.system_libs):
libname = lib
if not libname.endswith('.lib'):
libname += '.lib'
libs.append(libname)
replace_in_file(self, "Makefile.msvc",
f"LIBS = $(LIBS) {old_libname}",
f"LIBS = $(LIBS) {' '.join(libs)}")
fix_library(self.options.zlib, 'zlib', 'zlib.lib')
fix_library(self.options.lzma, "xz_utils", "liblzma.lib")
fix_library(self.options.iconv, 'libiconv', 'iconv.lib')
fix_library(self.options.icu, 'icu', 'advapi32.lib sicuuc.lib sicuin.lib sicudt.lib')
fix_library(self.options.icu, 'icu', 'icuuc.lib icuin.lib icudt.lib')
self.run("nmake /f Makefile.msvc libxml libxmla libxmladll")
if self.options.include_utils:
self.run("nmake /f Makefile.msvc utils")
def _package_msvc(self):
with chdir(self, os.path.join(self.source_folder, 'win32')):
self.run("nmake /f Makefile.msvc install-libs")
if self.options.include_utils:
self.run("nmake /f Makefile.msvc install-dist")
def _build_mingw(self):
with chdir(self, os.path.join(self.source_folder, "win32")):
# configuration
yes_no = lambda v: "yes" if v else "no"
args = [
"cscript",
"configure.js",
"compiler=mingw",
f"prefix={self.package_folder}",
f"debug={yes_no(self.settings.build_type == 'Debug')}",
f"static={yes_no(not self.options.shared)}",
]
incdirs = [incdir for dep in self.dependencies.values() for incdir in dep.cpp_info.includedirs]
libdirs = [libdir for dep in self.dependencies.values() for libdir in dep.cpp_info.libdirs]
args.append(f"include=\"{' -I'.join(incdirs)}\"")
args.append(f"lib=\"{' -L'.join(libdirs)}\"")
for name in self._configure_option_names:
cname = {
"mem-debug": "mem_debug",
"run-debug": "run_debug",
"docbook": "docb",
}.get(name, name)
args.append(f"{cname}={yes_no(getattr(self.options, name))}")
configure_command = " ".join(args)
self.output.info(configure_command)
self.run(configure_command)
# build
def fix_library(option, package, old_libname):
if option:
aggregated_cpp_info = self.dependencies[package].cpp_info.aggregated_components()
replace_in_file(self,
"Makefile.mingw",
f"LIBS += -l{old_libname}",
f"LIBS += -l{' -l'.join(aggregated_cpp_info.libs)}",
)
fix_library(self.options.iconv, "libiconv", "iconv")
fix_library(self.options.zlib, "zlib", "z")
fix_library(self.options.lzma, "xz_utils", "lzma")
self.run(f"mingw32-make -j{build_jobs(self)} -f Makefile.mingw libxml libxmla")
if self.options.include_utils:
self.run(f"mingw32-make -j{build_jobs(self)} -f Makefile.mingw utils")
def _package_mingw(self):
with chdir(self, os.path.join(self.source_folder, "win32")):
mkdir(self, os.path.join(self.package_folder, "include", "libxml2"))
self.run("mingw32-make -f Makefile.mingw install-libs")
if self.options.include_utils:
self.run("mingw32-make -f Makefile.mingw install-dist")
def _patch_sources(self):
# Break dependency of install on build
for makefile in ("Makefile.mingw", "Makefile.msvc"):
replace_in_file(self, os.path.join(self.source_folder, "win32", makefile),
"install-libs : all",
"install-libs :")
def build(self):
self._patch_sources()
if is_msvc(self):
self._build_msvc()
elif self._is_mingw_windows:
self._build_mingw()
else:
autotools = Autotools(self)
autotools.configure()
autotools.make("libxml2.la")
if self.options.include_utils:
for target in ["xmllint", "xmlcatalog", "xml2-config"]:
autotools.make(target)
def package(self):
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"), ignore_case=True, keep_path=False)
copy(self, "Copyright", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"), ignore_case=True, keep_path=False)
if is_msvc(self):
self._package_msvc()
# remove redundant libraries to avoid confusion
if not self.options.shared:
rm(self, "libxml2.dll", os.path.join(self.package_folder, "bin"))
rm(self, "libxml2_a_dll.lib", os.path.join(self.package_folder, "lib"))
rm(self, "libxml2_a.lib" if self.options.shared else "libxml2.lib", os.path.join(self.package_folder, "lib"))
rm(self, "*.pdb", os.path.join(self.package_folder, "bin"))
elif self._is_mingw_windows:
self._package_mingw()
if self.options.shared:
rm(self, "libxml2.a", os.path.join(self.package_folder, "lib"))
rename(self, os.path.join(self.package_folder, "lib", "libxml2.lib"),
os.path.join(self.package_folder, "lib", "libxml2.dll.a"))
else:
rm(self, "libxml2.dll", os.path.join(self.package_folder, "bin"))
rm(self, "libxml2.lib", os.path.join(self.package_folder, "lib"))
else:
autotools = Autotools(self)
for target in ["install-libLTLIBRARIES", "install-data"]:
autotools.make(target=target, args=[f"DESTDIR={unix_path(self, self.package_folder)}"])
if self.options.include_utils:
autotools.install()
rm(self, "*.la", os.path.join(self.package_folder, "lib"))
rm(self, "*.sh", os.path.join(self.package_folder, "lib"))
rm(self, "run*", os.path.join(self.package_folder, "bin"))
rm(self, "test*", os.path.join(self.package_folder, "bin"))
rmdir(self, os.path.join(self.package_folder, "share"))
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
fix_apple_shared_install_name(self)
for header in ["win32config.h", "wsockcompat.h"]:
copy(self, pattern=header, src=os.path.join(self.source_folder, "include"),
dst=os.path.join(self.package_folder, "include", "libxml2"), keep_path=False)
self._create_cmake_module_variables(
os.path.join(self.package_folder, self._module_file_rel_path)
)
def _create_cmake_module_variables(self, module_file):
# FIXME: also define LIBXML2_XMLLINT_EXECUTABLE variable
content = textwrap.dedent(f"""\
set(LibXml2_FOUND TRUE)
set(LIBXML2_FOUND TRUE)
if(DEFINED LibXml2_INCLUDE_DIRS)
set(LIBXML2_INCLUDE_DIR ${{LibXml2_INCLUDE_DIRS}})
set(LIBXML2_INCLUDE_DIRS ${{LibXml2_INCLUDE_DIRS}})
elseif(DEFINED libxml2_INCLUDE_DIRS)
set(LIBXML2_INCLUDE_DIR ${{libxml2_INCLUDE_DIRS}})
set(LIBXML2_INCLUDE_DIRS ${{libxml2_INCLUDE_DIRS}})
endif()
if(DEFINED LibXml2_LIBRARIES)
set(LIBXML2_LIBRARIES ${{LibXml2_LIBRARIES}})
set(LIBXML2_LIBRARY ${{LibXml2_LIBRARIES}})
elseif(DEFINED libxml2_LIBRARIES)
set(LIBXML2_LIBRARIES ${{libxml2_LIBRARIES}})
set(LIBXML2_LIBRARY ${{libxml2_LIBRARIES}})
endif()
if(DEFINED LibXml2_DEFINITIONS)
set(LIBXML2_DEFINITIONS ${{LibXml2_DEFINITIONS}})
elseif(DEFINED libxml2_DEFINITIONS)
set(LIBXML2_DEFINITIONS ${{libxml2_DEFINITIONS}})
else()
set(LIBXML2_DEFINITIONS "")
endif()
set(LIBXML2_VERSION_STRING "{self.version}")
""")
save(self, module_file, content)
@property
def _module_file_rel_path(self):
return os.path.join("lib", "cmake", f"conan-official-{self.name}-variables.cmake")
def package_info(self):
# FIXME: Provide LibXml2::xmllint & LibXml2::xmlcatalog imported target for executables
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_module_file_name", "LibXml2")
self.cpp_info.set_property("cmake_file_name", "libxml2")
self.cpp_info.set_property("cmake_target_name", "LibXml2::LibXml2")
self.cpp_info.set_property("cmake_build_modules", [self._module_file_rel_path])
self.cpp_info.set_property("pkg_config_name", "libxml-2.0")
prefix = "lib" if is_msvc(self) else ""
suffix = "_a" if is_msvc(self) and not self.options.shared else ""
self.cpp_info.libs = [f"{prefix}xml2{suffix}"]
self.cpp_info.includedirs.append(os.path.join("include", "libxml2"))
if not self.options.shared:
self.cpp_info.defines = ["LIBXML_STATIC"]
if self.options.include_utils:
bindir = os.path.join(self.package_folder, "bin")
self.output.info(f"Appending PATH environment variable: {bindir}")
self.env_info.PATH.append(bindir)
if self.settings.os in ["Linux", "FreeBSD", "Android"]:
self.cpp_info.system_libs.append("m")
if self.options.threads and self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.append("pthread")
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.append("dl")
elif self.settings.os == "Windows":
if self.options.ftp or self.options.http:
self.cpp_info.system_libs.extend(["ws2_32", "wsock32"])
if Version(self.version) >= "2.13.4":
# https://gitlab.gnome.org/GNOME/libxml2/-/issues/791
# https://gitlab.gnome.org/GNOME/libxml2/-/blob/2.13/win32/Makefile.msvc?ref_type=heads#L84
self.cpp_info.system_libs.append("bcrypt")
# TODO: to remove in conan v2 once cmake_find_package* & pkg_config generators removed
self.cpp_info.filenames["cmake_find_package"] = "LibXml2"
self.cpp_info.filenames["cmake_find_package_multi"] = "libxml2"
self.cpp_info.names["cmake_find_package"] = "LibXml2"
self.cpp_info.names["cmake_find_package_multi"] = "LibXml2"
self.cpp_info.build_modules["cmake_find_package"] = [self._module_file_rel_path]
self.cpp_info.names["pkg_config"] = "libxml-2.0"

View File

@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.12)
project(test_package LANGUAGES C)
find_package(LibXml2 REQUIRED MODULE)
add_executable(${PROJECT_NAME} ../test_package/test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2)
# Test whether variables from https://cmake.org/cmake/help/latest/module/FindLibXml2.html
# are properly defined in conan generators
set(_custom_vars
LibXml2_FOUND # since CMake 3.14
LIBXML2_FOUND # until CMake 3.14
LIBXML2_INCLUDE_DIR
LIBXML2_INCLUDE_DIRS
LIBXML2_LIBRARIES
LIBXML2_DEFINITIONS
LIBXML2_VERSION_STRING
)
foreach(_custom_var ${_custom_vars})
if(DEFINED ${_custom_var})
message(STATUS "${_custom_var}: ${${_custom_var}}")
else()
message(FATAL_ERROR "${_custom_var} not defined")
endif()
endforeach()

View File

@@ -0,0 +1,27 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")
xml_path = os.path.join(self.source_folder, os.pardir, "test_package", "books.xml")
self.run(f"{bin_path} {xml_path}", env="conanrun")

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_package LANGUAGES C)
find_package(libxml2 REQUIRED CONFIG)
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2)

View File

@@ -0,0 +1,9 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
<book id="bk103">
<author>Corets, Eva</author>
<title>Maeve Ascendant</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-11-17</publish_date>
<description>After the collapse of a nanotechnology
society in England, the young survivors lay the
foundation for a new society.</description>
</book>
<book id="bk104">
<author>Corets, Eva</author>
<title>Oberon's Legacy</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2001-03-10</publish_date>
<description>In post-apocalypse England, the mysterious
agent known only as Oberon helps to create a new life
for the inhabitants of London. Sequel to Maeve
Ascendant.</description>
</book>
<book id="bk105">
<author>Corets, Eva</author>
<title>The Sundered Grail</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2001-09-10</publish_date>
<description>The two daughters of Maeve, half-sisters,
battle one another for control of England. Sequel to
Oberon's Legacy.</description>
</book>
<book id="bk106">
<author>Randall, Cynthia</author>
<title>Lover Birds</title>
<genre>Romance</genre>
<price>4.95</price>
<publish_date>2000-09-02</publish_date>
<description>When Carla meets Paul at an ornithology
conference, tempers fly as feathers get ruffled.</description>
</book>
<book id="bk107">
<author>Thurman, Paula</author>
<title>Splish Splash</title>
<genre>Romance</genre>
<price>4.95</price>
<publish_date>2000-11-02</publish_date>
<description>A deep sea diver finds true love twenty
thousand leagues beneath the sea.</description>
</book>
<book id="bk108">
<author>Knorr, Stefan</author>
<title>Creepy Crawlies</title>
<genre>Horror</genre>
<price>4.95</price>
<publish_date>2000-12-06</publish_date>
<description>An anthology of horror stories about roaches,
centipedes, scorpions and other insects.</description>
</book>
<book id="bk109">
<author>Kress, Peter</author>
<title>Paradox Lost</title>
<genre>Science Fiction</genre>
<price>6.95</price>
<publish_date>2000-11-02</publish_date>
<description>After an inadvertant trip through a Heisenberg
Uncertainty Device, James Salway discovers the problems
of being quantum.</description>
</book>
<book id="bk110">
<author>O'Brien, Tim</author>
<title>Microsoft .NET: The Programming Bible</title>
<genre>Computer</genre>
<price>36.95</price>
<publish_date>2000-12-09</publish_date>
<description>Microsoft's .NET initiative is explored in
detail in this deep programmer's reference.</description>
</book>
<book id="bk111">
<author>O'Brien, Tim</author>
<title>MSXML3: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>36.95</price>
<publish_date>2000-12-01</publish_date>
<description>The Microsoft MSXML3 parser is covered in
detail, with attention to XML DOM interfaces, XSLT processing,
SAX and more.</description>
</book>
<book id="bk112">
<author>Galos, Mike</author>
<title>Visual Studio 7: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>49.95</price>
<publish_date>2001-04-16</publish_date>
<description>Microsoft Visual Studio 7 is explored in depth,
looking at how Visual Basic, Visual C++, C#, and ASP+ are
integrated into a comprehensive development
environment.</description>
</book>
</catalog>

View File

@@ -0,0 +1,27 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
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")
xml_path = os.path.join(self.source_folder, "books.xml")
self.run(f"{bin_path} {xml_path}", env="conanrun")

View File

@@ -0,0 +1,45 @@
#include <stdio.h>
#include <stdlib.h>
#include <libxml/xmlversion.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
static void print_element_names(xmlNode *a_node)
{
xmlNode *cur_node = NULL;
for (cur_node = a_node; cur_node; cur_node = cur_node->next)
{
if (cur_node->type == XML_ELEMENT_NODE)
{
printf("node type: Element, name: %s\n", cur_node->name);
}
print_element_names(cur_node->children);
}
}
int main(int argc, char **argv)
{
xmlDoc *doc = NULL;
xmlNode *root_element = NULL;
if (argc != 2)
return (1);
LIBXML_TEST_VERSION
/*parse the file and get the DOM */
doc = xmlReadFile(argv[1], NULL, 0);
if (doc == NULL)
{
printf("error: could not parse file %s\n", argv[1]);
exit(-1);
}
/*Get the root element node */
root_element = xmlDocGetRootElement(doc);
print_element_names(root_element);
xmlFreeDoc(doc); // free document
xmlCleanupParser(); // Free globals
return 0;
}

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_cmake_module_package
${CMAKE_CURRENT_BINARY_DIR}/test_cmake_module_package)

View File

@@ -0,0 +1,18 @@
from conans import ConanFile, CMake, tools
import os
class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake", "cmake_find_package"
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")
xml_path = os.path.join(self.source_folder, os.pardir, "test_package", "books.xml")
self.run(f"{bin_path} {xml_path}", run_environment=True)

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.1)
project(test_package)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package
${CMAKE_CURRENT_BINARY_DIR}/test_package)

Some files were not shown because too many files have changed in this diff Show More