1# Copyright 2019 The Meson development team
2
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6
7#     http://www.apache.org/licenses/LICENSE-2.0
8
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14from mesonbuild.templates.sampleimpl import SampleImpl
15import re
16
17
18lib_h_template = '''#pragma once
19#if defined _WIN32 || defined __CYGWIN__
20  #ifdef BUILDING_{utoken}
21    #define {utoken}_PUBLIC __declspec(dllexport)
22  #else
23    #define {utoken}_PUBLIC __declspec(dllimport)
24  #endif
25#else
26  #ifdef BUILDING_{utoken}
27      #define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
28  #else
29      #define {utoken}_PUBLIC
30  #endif
31#endif
32
33int {utoken}_PUBLIC {function_name}();
34
35'''
36
37lib_c_template = '''#include <{header_file}>
38
39/* This function will not be exported and is not
40 * directly callable by users of this library.
41 */
42int internal_function() {{
43    return 0;
44}}
45
46int {function_name}() {{
47    return internal_function();
48}}
49'''
50
51lib_c_test_template = '''#include <{header_file}>
52#include <stdio.h>
53
54int main(int argc, char **argv) {{
55    if(argc != 1) {{
56        printf("%s takes no arguments.\\n", argv[0]);
57        return 1;
58    }}
59    return {function_name}();
60}}
61'''
62
63lib_c_meson_template = '''project('{project_name}', 'c',
64  version : '{version}',
65  default_options : ['warning_level=3'])
66
67# These arguments are only used to build the shared library
68# not the executables that use the library.
69lib_args = ['-DBUILDING_{utoken}']
70
71shlib = shared_library('{lib_name}', '{source_file}',
72  install : true,
73  c_args : lib_args,
74  gnu_symbol_visibility : 'hidden',
75)
76
77test_exe = executable('{test_exe_name}', '{test_source_file}',
78  link_with : shlib)
79test('{test_name}', test_exe)
80
81# Make this library usable as a Meson subproject.
82{ltoken}_dep = declare_dependency(
83  include_directories: include_directories('.'),
84  link_with : shlib)
85
86# Make this library usable from the system's
87# package manager.
88install_headers('{header_file}', subdir : '{header_dir}')
89
90pkg_mod = import('pkgconfig')
91pkg_mod.generate(
92  name : '{project_name}',
93  filebase : '{ltoken}',
94  description : 'Meson sample project.',
95  subdirs : '{header_dir}',
96  libraries : shlib,
97  version : '{version}',
98)
99'''
100
101hello_c_template = '''#include <stdio.h>
102
103#define PROJECT_NAME "{project_name}"
104
105int main(int argc, char **argv) {{
106    if(argc != 1) {{
107        printf("%s takes no arguments.\\n", argv[0]);
108        return 1;
109    }}
110    printf("This is project %s.\\n", PROJECT_NAME);
111    return 0;
112}}
113'''
114
115hello_c_meson_template = '''project('{project_name}', 'c',
116  version : '{version}',
117  default_options : ['warning_level=3'])
118
119exe = executable('{exe_name}', '{source_name}',
120  install : true)
121
122test('basic', exe)
123'''
124
125
126class CProject(SampleImpl):
127    def __init__(self, options):
128        super().__init__()
129        self.name = options.name
130        self.version = options.version
131
132    def create_executable(self) -> None:
133        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
134        source_name = lowercase_token + '.c'
135        open(source_name, 'w', encoding='utf-8').write(hello_c_template.format(project_name=self.name))
136        open('meson.build', 'w', encoding='utf-8').write(
137            hello_c_meson_template.format(project_name=self.name,
138                                          exe_name=lowercase_token,
139                                          source_name=source_name,
140                                          version=self.version))
141
142    def create_library(self) -> None:
143        lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower())
144        uppercase_token = lowercase_token.upper()
145        function_name = lowercase_token[0:3] + '_func'
146        test_exe_name = lowercase_token + '_test'
147        lib_h_name = lowercase_token + '.h'
148        lib_c_name = lowercase_token + '.c'
149        test_c_name = lowercase_token + '_test.c'
150        kwargs = {'utoken': uppercase_token,
151                  'ltoken': lowercase_token,
152                  'header_dir': lowercase_token,
153                  'function_name': function_name,
154                  'header_file': lib_h_name,
155                  'source_file': lib_c_name,
156                  'test_source_file': test_c_name,
157                  'test_exe_name': test_exe_name,
158                  'project_name': self.name,
159                  'lib_name': lowercase_token,
160                  'test_name': lowercase_token,
161                  'version': self.version,
162                  }
163        open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs))
164        open(lib_c_name, 'w', encoding='utf-8').write(lib_c_template.format(**kwargs))
165        open(test_c_name, 'w', encoding='utf-8').write(lib_c_test_template.format(**kwargs))
166        open('meson.build', 'w', encoding='utf-8').write(lib_c_meson_template.format(**kwargs))
167