Skip to content

Commit f4350bd

Browse files
committed
adding meson build option for header only mode
1 parent 4ef7024 commit f4350bd

3 files changed

Lines changed: 170 additions & 119 deletions

File tree

meson.build

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,58 @@ project(
88
default_options: ['cpp_std=c++17,c++11', 'warning_level=3'],
99
)
1010

11-
inc = include_directories('.')
11+
# Option to build as header-only library
12+
header_only = get_option('header_only')
1213

13-
srcs = files('pystring.cpp')
14+
inc = include_directories('.')
1415
hdrs = files('pystring.h')
1516

16-
pystring_lib = library(
17-
'pystring',
18-
srcs,
19-
implicit_include_directories: false,
20-
include_directories: inc,
21-
version: meson.project_version(),
22-
install: true,
23-
)
24-
pystring_dep = declare_dependency(
25-
link_with: pystring_lib,
26-
include_directories: inc,
27-
)
17+
if header_only
18+
# Header-only mode: create a header-only dependency
19+
message('Building pystring as header-only library')
20+
21+
pystring_dep = declare_dependency(
22+
include_directories: inc,
23+
compile_args: ['-DPYSTRING_HEADER_ONLY'],
24+
)
25+
26+
# Install headers for header-only mode
27+
install_headers(hdrs, files('pystring_impl.h'), subdir: 'pystring')
28+
29+
else
30+
# Compiled mode: build as normal library
31+
message('Building pystring as compiled library')
32+
33+
srcs = files('pystring.cpp')
34+
35+
pystring_lib = library(
36+
'pystring',
37+
srcs,
38+
implicit_include_directories: false,
39+
include_directories: inc,
40+
version: meson.project_version(),
41+
install: true,
42+
)
43+
44+
pystring_dep = declare_dependency(
45+
link_with: pystring_lib,
46+
include_directories: inc,
47+
)
48+
49+
# Install headers for compiled mode
50+
install_headers(hdrs, subdir: 'pystring')
51+
52+
# Generate pkg-config file
53+
pkgconfig = import('pkgconfig')
54+
pkgconfig.generate(
55+
pystring_lib,
56+
description: 'C++ functions matching the interface and behavior of python string methods with std::string',
57+
)
58+
endif
59+
2860
meson.override_dependency('pystring', pystring_dep)
2961

62+
# Build and run tests
3063
test(
3164
'PyStringTest',
3265
executable(
@@ -36,11 +69,3 @@ test(
3669
build_by_default: false,
3770
),
3871
)
39-
40-
install_headers(hdrs, subdir: 'pystring')
41-
42-
pkgconfig = import('pkgconfig')
43-
pkgconfig.generate(
44-
pystring_lib,
45-
description: 'C++ functions matching the interface and behavior of python string methods with std::string',
46-
)

meson_options.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
option('header_only', type: 'boolean', value: false, description: 'Build as header-only library')

unittest.h

Lines changed: 122 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#ifndef INCLUDED_PYSTRING_UNITTEST_H
66
#define INCLUDED_PYSTRING_UNITTEST_H
77

8-
#include <iostream>
98
#include <cmath>
9+
#include <iostream>
1010
#include <vector>
1111

1212
extern int unit_test_failures;
@@ -15,111 +15,136 @@ void unittest_fail();
1515

1616
typedef void (*PYSTRINGTestFunc)();
1717

18-
struct PYSTRINGTest
19-
{
20-
PYSTRINGTest(std::string testgroup, std::string testname, PYSTRINGTestFunc test) :
21-
group(testgroup), name(testname), function(test) { };
22-
std::string group, name;
23-
PYSTRINGTestFunc function;
18+
struct PYSTRINGTest {
19+
PYSTRINGTest(std::string testgroup, std::string testname,
20+
PYSTRINGTestFunc test)
21+
: group(testgroup), name(testname), function(test){};
22+
std::string group, name;
23+
PYSTRINGTestFunc function;
2424
};
2525

2626
typedef std::vector<PYSTRINGTest> UnitTests;
2727

28-
UnitTests& GetUnitTests();
28+
UnitTests &GetUnitTests();
2929

30-
struct AddTest { AddTest(PYSTRINGTest&& test); };
30+
struct AddTest {
31+
AddTest(PYSTRINGTest &&test);
32+
};
3133

3234
/// PYSTRING_CHECK_* macros checks if the conditions is met, and if not,
3335
/// prints an error message indicating the module and line where the
3436
/// error occurred, but does NOT abort. This is helpful for unit tests
3537
/// where we do not want one failure.
36-
#define PYSTRING_CHECK_ASSERT(x) \
37-
((x) ? ((void)0) \
38-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
39-
<< "FAILED: " << #x << "\n"), \
40-
(void)++unit_test_failures))
41-
42-
#define PYSTRING_CHECK_EQUAL(x,y) \
43-
(((x) == (y)) ? ((void)0) \
44-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
45-
<< "FAILED: " << #x << " == " << #y << "\n" \
46-
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
47-
(void)++unit_test_failures))
48-
49-
#define PYSTRING_CHECK_NE(x,y) \
50-
(((x) != (y)) ? ((void)0) \
51-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
52-
<< "FAILED: " << #x << " != " << #y << "\n" \
53-
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
54-
(void)++unit_test_failures))
55-
56-
#define PYSTRING_CHECK_LT(x,y) \
57-
(((x) < (y)) ? ((void)0) \
58-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
59-
<< "FAILED: " << #x << " < " << #y << "\n" \
60-
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
61-
(void)++unit_test_failures))
62-
63-
#define PYSTRING_CHECK_GT(x,y) \
64-
(((x) > (y)) ? ((void)0) \
65-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
66-
<< "FAILED: " << #x << " > " << #y << "\n" \
67-
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
68-
(void)++unit_test_failures))
69-
70-
#define PYSTRING_CHECK_LE(x,y) \
71-
(((x) <= (y)) ? ((void)0) \
72-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
73-
<< "FAILED: " << #x << " <= " << #y << "\n" \
74-
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
75-
(void)++unit_test_failures))
76-
77-
#define PYSTRING_CHECK_GE(x,y) \
78-
(((x) >= (y)) ? ((void)0) \
79-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
80-
<< "FAILED: " << #x << " >= " << #y << "\n" \
81-
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
82-
(void)++unit_test_failures))
83-
84-
#define PYSTRING_CHECK_CLOSE(x,y,tol) \
85-
((std::abs((x) - (y)) < tol) ? ((void)0) \
86-
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
87-
<< "FAILED: abs(" << #x << " - " << #y << ") < " << #tol << "\n" \
88-
<< "\tvalues were '" << (x) << "', '" << (y) << "' and '" << (tol) << "'\n"), \
89-
(void)++unit_test_failures))
90-
91-
#define PYSTRING_CHECK_THOW(S, E) \
92-
try { S; throw "throwanything"; } catch( E const& ex ) { } catch (...) { \
93-
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
94-
<< "FAILED: " << #E << " is expected to be thrown\n"; \
95-
++unit_test_failures; }
96-
97-
#define PYSTRING_CHECK_NO_THOW(S) \
98-
try { S; } catch (...) { \
99-
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
100-
<< "FAILED: exception thrown from " << #S <<"\n"; \
101-
++unit_test_failures; }
102-
103-
#define PYSTRING_ADD_TEST(group, name) \
104-
static void pystringtest_##group##_##name(); \
105-
AddTest pystringaddtest_##group##_##name(PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \
106-
static void pystringtest_##group##_##name()
107-
108-
#define PYSTRING_TEST_SETUP() \
109-
int unit_test_failures = 0
110-
111-
#define PYSTRING_TEST_APP(app) \
112-
std::vector<PYSTRINGTest>& GetUnitTests() { \
113-
static std::vector<PYSTRINGTest> pystring_unit_tests; \
114-
return pystring_unit_tests; } \
115-
AddTest::AddTest(PYSTRINGTest&& test){GetUnitTests().emplace_back(test);}; \
116-
PYSTRING_TEST_SETUP(); \
117-
int main(int, char **) { std::cerr << "\n" << #app <<"\n\n"; \
118-
for(size_t i = 0; i < GetUnitTests().size(); ++i) { \
119-
int _tmp = unit_test_failures; GetUnitTests()[i].function(); \
120-
std::cerr << "Test [" << GetUnitTests()[i].group << "] [" << GetUnitTests()[i].name << "] - "; \
121-
std::cerr << (_tmp == unit_test_failures ? "PASSED" : "FAILED") << "\n"; } \
122-
std::cerr << "\n" << unit_test_failures << " tests failed\n\n"; \
123-
return unit_test_failures; }
38+
#define PYSTRING_CHECK_ASSERT(x) \
39+
((x) ? ((void)0) \
40+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
41+
<< "FAILED: " << #x << "\n"), \
42+
(void)++unit_test_failures))
43+
44+
#define PYSTRING_CHECK_EQUAL(x, y) \
45+
(((x) == (y)) ? ((void)0) \
46+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
47+
<< "FAILED: " << #x << " == " << #y << "\n" \
48+
<< "\tvalues were '" << (x) << "' and '" << (y) \
49+
<< "'\n"), \
50+
(void)++unit_test_failures))
51+
52+
#define PYSTRING_CHECK_NE(x, y) \
53+
(((x) != (y)) ? ((void)0) \
54+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
55+
<< "FAILED: " << #x << " != " << #y << "\n" \
56+
<< "\tvalues were '" << (x) << "' and '" << (y) \
57+
<< "'\n"), \
58+
(void)++unit_test_failures))
59+
60+
#define PYSTRING_CHECK_LT(x, y) \
61+
(((x) < (y)) ? ((void)0) \
62+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
63+
<< "FAILED: " << #x << " < " << #y << "\n" \
64+
<< "\tvalues were '" << (x) << "' and '" << (y) \
65+
<< "'\n"), \
66+
(void)++unit_test_failures))
67+
68+
#define PYSTRING_CHECK_GT(x, y) \
69+
(((x) > (y)) ? ((void)0) \
70+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
71+
<< "FAILED: " << #x << " > " << #y << "\n" \
72+
<< "\tvalues were '" << (x) << "' and '" << (y) \
73+
<< "'\n"), \
74+
(void)++unit_test_failures))
75+
76+
#define PYSTRING_CHECK_LE(x, y) \
77+
(((x) <= (y)) ? ((void)0) \
78+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
79+
<< "FAILED: " << #x << " <= " << #y << "\n" \
80+
<< "\tvalues were '" << (x) << "' and '" << (y) \
81+
<< "'\n"), \
82+
(void)++unit_test_failures))
83+
84+
#define PYSTRING_CHECK_GE(x, y) \
85+
(((x) >= (y)) ? ((void)0) \
86+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
87+
<< "FAILED: " << #x << " >= " << #y << "\n" \
88+
<< "\tvalues were '" << (x) << "' and '" << (y) \
89+
<< "'\n"), \
90+
(void)++unit_test_failures))
91+
92+
#define PYSTRING_CHECK_CLOSE(x, y, tol) \
93+
((std::abs((x) - (y)) < tol) \
94+
? ((void)0) \
95+
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
96+
<< "FAILED: abs(" << #x << " - " << #y << ") < " << #tol \
97+
<< "\n" \
98+
<< "\tvalues were '" << (x) << "', '" << (y) << "' and '" \
99+
<< (tol) << "'\n"), \
100+
(void)++unit_test_failures))
101+
102+
#define PYSTRING_CHECK_THOW(S, E) \
103+
try { \
104+
S; \
105+
throw "throwanything"; \
106+
} catch (E const &ex) { \
107+
} catch (...) { \
108+
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
109+
<< "FAILED: " << #E << " is expected to be thrown\n"; \
110+
++unit_test_failures; \
111+
}
112+
113+
#define PYSTRING_CHECK_NO_THOW(S) \
114+
try { \
115+
S; \
116+
} catch (...) { \
117+
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
118+
<< "FAILED: exception thrown from " << #S << "\n"; \
119+
++unit_test_failures; \
120+
}
121+
122+
#define PYSTRING_ADD_TEST(group, name) \
123+
static void pystringtest_##group##_##name(); \
124+
AddTest pystringaddtest_##group##_##name( \
125+
PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \
126+
static void pystringtest_##group##_##name()
127+
128+
#define PYSTRING_TEST_SETUP() int unit_test_failures = 0
129+
130+
#define PYSTRING_TEST_APP(app) \
131+
std::vector<PYSTRINGTest> &GetUnitTests() { \
132+
static std::vector<PYSTRINGTest> pystring_unit_tests; \
133+
return pystring_unit_tests; \
134+
} \
135+
AddTest::AddTest(PYSTRINGTest &&test) { GetUnitTests().emplace_back(test); } \
136+
PYSTRING_TEST_SETUP(); \
137+
int main(int, char **) { \
138+
std::cerr << "\n" << #app << "\n\n"; \
139+
for (size_t i = 0; i < GetUnitTests().size(); ++i) { \
140+
int _tmp = unit_test_failures; \
141+
GetUnitTests()[i].function(); \
142+
std::cerr << "Test [" << GetUnitTests()[i].group << "] [" \
143+
<< GetUnitTests()[i].name << "] - "; \
144+
std::cerr << (_tmp == unit_test_failures ? "PASSED" : "FAILED") << "\n"; \
145+
} \
146+
std::cerr << "\n" << unit_test_failures << " tests failed\n\n"; \
147+
return unit_test_failures; \
148+
}
124149

125150
#endif

0 commit comments

Comments
 (0)