Minit templates modularization

pull/4973/head
Michael Hirsch, Ph.D 5 years ago committed by Jussi Pakkanen
parent b3fe4a0a18
commit bbe6db08e3
  1. 5
      docs/markdown/snippets/new_meson_project_templates.md
  2. 406
      mesonbuild/minit.py
  3. 0
      mesonbuild/templates/__init__.py
  4. 177
      mesonbuild/templates/cpptemplates.py
  5. 156
      mesonbuild/templates/ctemplates.py
  6. 132
      mesonbuild/templates/dlangtemplates.py
  7. 130
      mesonbuild/templates/fortrantemplates.py
  8. 156
      mesonbuild/templates/objctemplates.py
  9. 103
      mesonbuild/templates/rusttemplates.py
  10. 37
      run_unittests.py
  11. 1
      setup.py

@ -0,0 +1,5 @@
## Added new Meson templates for `Dlang`, `Rust`, `Objective-C`
Meson now ships with predefined project templates for `Dlang`,
`Fortran`, `Rust`, `Objective-C`, and by passing the associated flags `d`,
`fortran`, `rust`, `objc` to `meson init --language`.

@ -14,241 +14,20 @@
"""Code that creates simple startup projects."""
import os, sys, re, shutil, subprocess
from pathlib import Path
import re, shutil, subprocess
from glob import glob
from mesonbuild import mesonlib
from mesonbuild.environment import detect_ninja
lib_h_template = '''#pragma once
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __declspec(dllexport)
#else
#define {utoken}_PUBLIC __declspec(dllimport)
#endif
#else
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
#else
#define {utoken}_PUBLIC
#endif
#endif
from mesonbuild.templates.ctemplates import (create_exe_c_sample, create_lib_c_sample)
from mesonbuild.templates.cpptemplates import (create_exe_cpp_sample, create_lib_cpp_sample)
from mesonbuild.templates.objctemplates import (create_exe_objc_sample, create_lib_objc_sample)
from mesonbuild.templates.dlangtemplates import (create_exe_d_sample, create_lib_d_sample)
from mesonbuild.templates.fortrantemplates import (create_exe_fortran_sample, create_lib_fortran_sample)
from mesonbuild.templates.rusttemplates import (create_exe_rust_sample, create_lib_rust_sample)
int {utoken}_PUBLIC {function_name}();
'''
lib_c_template = '''#include <{header_file}>
/* This function will not be exported and is not
* directly callable by users of this library.
*/
int internal_function() {{
return 0;
}}
int {function_name}() {{
return internal_function();
}}
'''
lib_c_test_template = '''#include <{header_file}>
#include <stdio.h>
int main(int argc, char **argv) {{
if(argc != 1) {{
printf("%s takes no arguments.\\n", argv[0]);
return 1;
}}
return {function_name}();
}}
'''
lib_c_meson_template = '''project('{project_name}', 'c',
version : '{version}',
default_options : ['warning_level=3'])
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_{utoken}']
shlib = shared_library('{lib_name}', '{source_file}',
install : true,
c_args : lib_args,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
# Make this library usable from the system's
# package manager.
install_headers('{header_file}', subdir : '{header_dir}')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : '{project_name}',
filebase : '{ltoken}',
description : 'Meson sample project.',
subdirs : '{header_dir}',
libraries : shlib,
version : '{version}',
)
'''
hello_c_template = '''#include <stdio.h>
#define PROJECT_NAME "{project_name}"
int main(int argc, char **argv) {{
if(argc != 1) {{
printf("%s takes no arguments.\\n", argv[0]);
return 1;
}}
printf("This is project %s.\\n", PROJECT_NAME);
return 0;
}}
'''
hello_c_meson_template = '''project('{project_name}', 'c',
version : '{version}',
default_options : ['warning_level=3'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
hello_cpp_template = '''#include <iostream>
#define PROJECT_NAME "{project_name}"
int main(int argc, char **argv) {{
if(argc != 1) {{
std::cout << argv[0] << "takes no arguments.\\n";
return 1;
}}
std::cout << "This is project " << PROJECT_NAME << ".\\n";
return 0;
}}
'''
hello_cpp_meson_template = '''project('{project_name}', 'cpp',
version : '{version}',
default_options : ['warning_level=3',
'cpp_std=c++14'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
lib_hpp_template = '''#pragma once
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __declspec(dllexport)
#else
#define {utoken}_PUBLIC __declspec(dllimport)
#endif
#else
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
#else
#define {utoken}_PUBLIC
#endif
#endif
namespace {namespace} {{
class {utoken}_PUBLIC {class_name} {{
public:
{class_name}();
int get_number() const;
private:
int number;
}};
}}
'''
lib_cpp_template = '''#include <{header_file}>
namespace {namespace} {{
{class_name}::{class_name}() {{
number = 6;
}}
int {class_name}::get_number() const {{
return number;
}}
}}
'''
lib_cpp_test_template = '''#include <{header_file}>
#include <iostream>
int main(int argc, char **argv) {{
if(argc != 1) {{
std::cout << argv[0] << " takes no arguments.\\n";
return 1;
}}
{namespace}::{class_name} c;
return c.get_number() != 6;
}}
'''
lib_cpp_meson_template = '''project('{project_name}', 'cpp',
version : '{version}',
default_options : ['warning_level=3', 'cpp_std=c++14'])
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_{utoken}']
shlib = shared_library('{lib_name}', '{source_file}',
install : true,
cpp_args : lib_args,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
# Make this library usable from the system's
# package manager.
install_headers('{header_file}', subdir : '{header_dir}')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : '{project_name}',
filebase : '{ltoken}',
description : 'Meson sample project.',
subdirs : '{header_dir}',
libraries : shlib,
version : '{version}',
)
'''
FORTRAN_SUFFIXES = ['.f', '.for', '.F', '.f90', '.F90']
info_message = '''Sample project created. To build it run the
following commands:
@ -257,76 +36,6 @@ meson builddir
ninja -C builddir
'''
def create_exe_c_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.c'
open(source_name, 'w').write(hello_c_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_c_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_c_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
function_name = lowercase_token[0:3] + '_func'
lib_h_name = lowercase_token + '.h'
lib_c_name = lowercase_token + '.c'
test_c_name = lowercase_token + '_test.c'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'function_name': function_name,
'header_file': lib_h_name,
'source_file': lib_c_name,
'test_source_file': test_c_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_h_name, 'w').write(lib_h_template.format(**kwargs))
open(lib_c_name, 'w').write(lib_c_template.format(**kwargs))
open(test_c_name, 'w').write(lib_c_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_c_meson_template.format(**kwargs))
def create_exe_cpp_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.cpp'
open(source_name, 'w').write(hello_cpp_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_cpp_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_cpp_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
class_name = uppercase_token[0] + lowercase_token[1:]
namespace = lowercase_token
lib_h_name = lowercase_token + '.hpp'
lib_c_name = lowercase_token + '.cpp'
test_c_name = lowercase_token + '_test.cpp'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'class_name': class_name,
'namespace': namespace,
'header_file': lib_h_name,
'source_file': lib_c_name,
'test_source_file': test_c_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_h_name, 'w').write(lib_hpp_template.format(**kwargs))
open(lib_c_name, 'w').write(lib_cpp_template.format(**kwargs))
open(test_c_name, 'w').write(lib_cpp_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_cpp_meson_template.format(**kwargs))
def create_sample(options):
if options.language == 'c':
if options.type == 'executable':
@ -342,17 +51,44 @@ def create_sample(options):
create_lib_cpp_sample(options.name, options.version)
else:
raise RuntimeError('Unreachable code')
elif options.language == 'd':
if options.type == 'executable':
create_exe_d_sample(options.name, options.version)
elif options.type == 'library':
create_lib_d_sample(options.name, options.version)
else:
raise RuntimeError('Unreachable code')
elif options.language == 'fortran':
if options.type == 'executable':
create_exe_fortran_sample(options.name, options.version)
elif options.type == 'library':
create_lib_fortran_sample(options.name, options.version)
else:
raise RuntimeError('Unreachable code')
elif options.language == 'rust':
if options.type == 'executable':
create_exe_rust_sample(options.name, options.version)
elif options.type == 'library':
create_lib_rust_sample(options.name, options.version)
else:
raise RuntimeError('Unreachable code')
elif options.language == 'objc':
if options.type == 'executable':
create_exe_objc_sample(options.name, options.version)
elif options.type == 'library':
create_lib_objc_sample(options.name, options.version)
else:
raise RuntimeError('Unreachable code')
else:
raise RuntimeError('Unreachable code')
print(info_message)
def autodetect_options(options, sample=False):
if not options.name:
options.name = os.path.basename(os.getcwd())
options.name = Path().resolve().stem
if not re.match('[a-zA-Z_][a-zA-Z0-9]*', options.name) and sample:
print('Name of current directory "{}" is not usable as a sample project name.\n'
'Specify a project name with --name.'.format(options.name))
sys.exit(1)
raise SystemExit('Name of current directory "{}" is not usable as a sample project name.\n'
'Specify a project name with --name.'.format(options.name))
print('Using "{}" (name of current directory) as project name.'
.format(options.name))
if not options.executable:
@ -364,28 +100,40 @@ def autodetect_options(options, sample=False):
return
if not options.srcfiles:
srcfiles = []
for f in os.listdir():
if f.endswith('.cc') or f.endswith('.cpp') or f.endswith('.c'):
for f in (f for f in Path().iterdir() if f.is_file()):
if f.suffix in (['.cc', '.cpp', '.c', '.d', '.m', '.rs'] + FORTRAN_SUFFIXES):
srcfiles.append(f)
if not srcfiles:
print("No recognizable source files found.\n"
"Run me in an empty directory to create a sample project.")
sys.exit(1)
raise SystemExit('No recognizable source files found.\n'
'Run meson init in an empty directory to create a sample project.')
options.srcfiles = srcfiles
print("Detected source files: " + ' '.join(srcfiles))
print("Detected source files: " + ' '.join(map(str, srcfiles)))
options.srcfiles = [Path(f) for f in options.srcfiles]
if not options.language:
for f in options.srcfiles:
if f.endswith('.cc') or f.endswith('.cpp'):
if f.suffix in ('.cc', '.cpp'):
options.language = 'cpp'
break
if f.endswith('.c'):
if f.suffix == '.c':
options.language = 'c'
break
if f.suffix == '.d':
options.language = 'd'
break
if f.suffix in FORTRAN_SUFFIXES:
options.language = 'fortran'
break
if f.suffix == '.rs':
options.language = 'rust'
break
if f.suffix == '.m':
options.language = 'objc'
break
if not options.language:
print("Can't autodetect language, please specify it with -l.")
sys.exit(1)
raise SystemExit("Can't autodetect language, please specify it with -l.")
print("Detected language: " + options.language)
meson_executable_template = '''project('{project_name}', '{language}',
version : '{version}',
default_options : [{default_options}])
@ -397,10 +145,9 @@ executable('{executable}',
def create_meson_build(options):
if options.type != 'executable':
print('\nGenerating a meson.build file from existing sources is\n'
'supported only for project type "executable".\n'
'Run me in an empty directory to create a sample project.')
sys.exit(1)
raise SystemExit('\nGenerating a meson.build file from existing sources is\n'
'supported only for project type "executable".\n'
'Run meson init in an empty directory to create a sample project.')
default_options = ['warning_level=3']
if options.language == 'cpp':
# This shows how to set this very common option.
@ -431,7 +178,7 @@ def add_arguments(parser):
parser.add_argument("-n", "--name", help="project name. default: name of current directory")
parser.add_argument("-e", "--executable", help="executable name. default: project name")
parser.add_argument("-d", "--deps", help="dependencies, comma-separated")
parser.add_argument("-l", "--language", choices=['c', 'cpp'],
parser.add_argument("-l", "--language", choices=['c', 'cpp', 'd', 'fortran', 'rust', 'objc'],
help="project language. default: autodetected based on source files")
parser.add_argument("-b", "--build", help="build after generation", action='store_true')
parser.add_argument("--builddir", help="directory for build", default='build')
@ -441,7 +188,7 @@ def add_arguments(parser):
choices=['executable', 'library'])
parser.add_argument('--version', default='0.1')
def run(options):
def run(options) -> int:
if not glob('*'):
autodetect_options(options, sample=True)
if not options.language:
@ -450,21 +197,20 @@ def run(options):
create_sample(options)
else:
autodetect_options(options)
if os.path.isfile('meson.build') and not options.force:
print('meson.build already exists. Use --force to overwrite.')
sys.exit(1)
if Path('meson.build').is_file() and not options.force:
raise SystemExit('meson.build already exists. Use --force to overwrite.')
create_meson_build(options)
if options.build:
if os.path.isdir(options.builddir) and options.force:
if Path(options.builddir).is_dir() and options.force:
print('Build directory already exists, deleting it.')
shutil.rmtree(options.builddir)
print('Building...')
cmd = mesonlib.meson_command + [options.builddir]
err = subprocess.call(cmd)
if err:
sys.exit(1)
ret = subprocess.run(cmd)
if ret.returncode:
raise SystemExit
cmd = [detect_ninja(), '-C', options.builddir]
err = subprocess.call(cmd)
if err:
sys.exit(1)
ret = subprocess.run(cmd)
if ret.returncode:
raise SystemExit
return 0

@ -0,0 +1,177 @@
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
hello_cpp_template = '''#include <iostream>
#define PROJECT_NAME "{project_name}"
int main(int argc, char **argv) {{
if(argc != 1) {{
std::cout << argv[0] << "takes no arguments.\\n";
return 1;
}}
std::cout << "This is project " << PROJECT_NAME << ".\\n";
return 0;
}}
'''
hello_cpp_meson_template = '''project('{project_name}', 'cpp',
version : '{version}',
default_options : ['warning_level=3',
'cpp_std=c++14'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
lib_hpp_template = '''#pragma once
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __declspec(dllexport)
#else
#define {utoken}_PUBLIC __declspec(dllimport)
#endif
#else
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
#else
#define {utoken}_PUBLIC
#endif
#endif
namespace {namespace} {{
class {utoken}_PUBLIC {class_name} {{
public:
{class_name}();
int get_number() const;
private:
int number;
}};
}}
'''
lib_cpp_template = '''#include <{header_file}>
namespace {namespace} {{
{class_name}::{class_name}() {{
number = 6;
}}
int {class_name}::get_number() const {{
return number;
}}
}}
'''
lib_cpp_test_template = '''#include <{header_file}>
#include <iostream>
int main(int argc, char **argv) {{
if(argc != 1) {{
std::cout << argv[0] << " takes no arguments.\\n";
return 1;
}}
{namespace}::{class_name} c;
return c.get_number() != 6;
}}
'''
lib_cpp_meson_template = '''project('{project_name}', 'cpp',
version : '{version}',
default_options : ['warning_level=3', 'cpp_std=c++14'])
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_{utoken}']
shlib = shared_library('{lib_name}', '{source_file}',
install : true,
cpp_args : lib_args,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
# Make this library usable from the system's
# package manager.
install_headers('{header_file}', subdir : '{header_dir}')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : '{project_name}',
filebase : '{ltoken}',
description : 'Meson sample project.',
subdirs : '{header_dir}',
libraries : shlib,
version : '{version}',
)
'''
def create_exe_cpp_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.cpp'
open(source_name, 'w').write(hello_cpp_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_cpp_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_cpp_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
class_name = uppercase_token[0] + lowercase_token[1:]
namespace = lowercase_token
lib_hpp_name = lowercase_token + '.hpp'
lib_cpp_name = lowercase_token + '.cpp'
test_cpp_name = lowercase_token + '_test.cpp'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'class_name': class_name,
'namespace': namespace,
'header_file': lib_hpp_name,
'source_file': lib_cpp_name,
'test_source_file': test_cpp_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_hpp_name, 'w').write(lib_hpp_template.format(**kwargs))
open(lib_cpp_name, 'w').write(lib_cpp_template.format(**kwargs))
open(test_cpp_name, 'w').write(lib_cpp_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_cpp_meson_template.format(**kwargs))

@ -0,0 +1,156 @@
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
lib_h_template = '''#pragma once
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __declspec(dllexport)
#else
#define {utoken}_PUBLIC __declspec(dllimport)
#endif
#else
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
#else
#define {utoken}_PUBLIC
#endif
#endif
int {utoken}_PUBLIC {function_name}();
'''
lib_c_template = '''#include <{header_file}>
/* This function will not be exported and is not
* directly callable by users of this library.
*/
int internal_function() {{
return 0;
}}
int {function_name}() {{
return internal_function();
}}
'''
lib_c_test_template = '''#include <{header_file}>
#include <stdio.h>
int main(int argc, char **argv) {{
if(argc != 1) {{
printf("%s takes no arguments.\\n", argv[0]);
return 1;
}}
return {function_name}();
}}
'''
lib_c_meson_template = '''project('{project_name}', 'c',
version : '{version}',
default_options : ['warning_level=3'])
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_{utoken}']
shlib = shared_library('{lib_name}', '{source_file}',
install : true,
c_args : lib_args,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
# Make this library usable from the system's
# package manager.
install_headers('{header_file}', subdir : '{header_dir}')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : '{project_name}',
filebase : '{ltoken}',
description : 'Meson sample project.',
subdirs : '{header_dir}',
libraries : shlib,
version : '{version}',
)
'''
hello_c_template = '''#include <stdio.h>
#define PROJECT_NAME "{project_name}"
int main(int argc, char **argv) {{
if(argc != 1) {{
printf("%s takes no arguments.\\n", argv[0]);
return 1;
}}
printf("This is project %s.\\n", PROJECT_NAME);
return 0;
}}
'''
hello_c_meson_template = '''project('{project_name}', 'c',
version : '{version}',
default_options : ['warning_level=3'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
def create_exe_c_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.c'
open(source_name, 'w').write(hello_c_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_c_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_c_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
function_name = lowercase_token[0:3] + '_func'
lib_h_name = lowercase_token + '.h'
lib_c_name = lowercase_token + '.c'
test_c_name = lowercase_token + '_test.c'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'function_name': function_name,
'header_file': lib_h_name,
'source_file': lib_c_name,
'test_source_file': test_c_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_h_name, 'w').write(lib_h_template.format(**kwargs))
open(lib_c_name, 'w').write(lib_c_template.format(**kwargs))
open(test_c_name, 'w').write(lib_c_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_c_meson_template.format(**kwargs))

@ -0,0 +1,132 @@
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
hello_d_template = '''module main;
import std.stdio;
enum PROJECT_NAME = "{project_name}";
int main(string[] args) {{
if (args.length != 1){{
writefln("%s takes no arguments.\\n", args[0]);
return 1;
}}
writefln("This is project %s.\\n", PROJECT_NAME);
return 0;
}}
'''
hello_d_meson_template = '''project('{project_name}', 'd',
version : '{version}',
default_options: ['warning_level=3'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
lib_d_template = '''module {module_file};
/* This function will not be exported and is not
* directly callable by users of this library.
*/
int internal_function() {{
return 0;
}}
int {function_name}() {{
return internal_function();
}}
'''
lib_d_test_template = '''module {module_file}_test;
import std.stdio;
import {module_file};
int main(string[] args) {{
if (args.length != 1){{
writefln("%s takes no arguments.\\n", args[0]);
return 1;
}}
return {function_name}();
}}
'''
lib_d_meson_template = '''project('{project_name}', 'd',
version : '{version}',
default_options : ['warning_level=3'])
stlib = static_library('{lib_name}', '{source_file}',
install : true,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : stlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : stlib)
# Make this library usable from the Dlang
# build system.
dlang_mod = import('dlang')
dlang_mod.generate_dub_file(meson.project_name().to_lower(), meson.source_root(),
name : meson.project_name(),
license: meson.project_license(),
sourceFiles : '{source_file}',
description : 'Meson sample project.',
version : '{version}',
)
'''
def create_exe_d_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.d'
open(source_name, 'w').write(hello_d_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_d_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_d_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
function_name = lowercase_token[0:3] + '_func'
lib_m_name = lowercase_token
lib_d_name = lowercase_token + '.d'
test_d_name = lowercase_token + '_test.d'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'function_name': function_name,
'module_file': lib_m_name,
'source_file': lib_d_name,
'test_source_file': test_d_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_d_name, 'w').write(lib_d_template.format(**kwargs))
open(test_d_name, 'w').write(lib_d_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_d_meson_template.format(**kwargs))

@ -0,0 +1,130 @@
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
lib_fortran_template = '''
! This procedure will not be exported and is not
! directly callable by users of this library.
module modfoo
implicit none
private
public :: {function_name}
contains
integer function internal_function()
internal_function = 0
end function internal_function
integer function {function_name}()
{function_name} = internal_function()
end function {function_name}
end module modfoo
'''
lib_fortran_test_template = '''
use modfoo
print *,{function_name}()
end program
'''
lib_fortran_meson_template = '''project('{project_name}', 'fortran',
version : '{version}',
default_options : ['warning_level=3'])
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_{utoken}']
shlib = shared_library('{lib_name}', '{source_file}',
install : true,
fortran_args : lib_args,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : '{project_name}',
filebase : '{ltoken}',
description : 'Meson sample project.',
subdirs : '{header_dir}',
libraries : shlib,
version : '{version}',
)
'''
hello_fortran_template = '''
implicit none
character(len=*), parameter :: PROJECT_NAME = "{project_name}"
print *,"This is project ", PROJECT_NAME
end program
'''
hello_fortran_meson_template = '''project('{project_name}', 'fortran',
version : '{version}',
default_options : ['warning_level=3'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
def create_exe_fortran_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.f90'
open(source_name, 'w').write(hello_fortran_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_fortran_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_fortran_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
function_name = lowercase_token[0:3] + '_func'
lib_fortran_name = lowercase_token + '.f90'
test_fortran_name = lowercase_token + '_test.f90'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'function_name': function_name,
'source_file': lib_fortran_name,
'test_source_file': test_fortran_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_fortran_name, 'w').write(lib_fortran_template.format(**kwargs))
open(test_fortran_name, 'w').write(lib_fortran_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_fortran_meson_template.format(**kwargs))

@ -0,0 +1,156 @@
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
lib_h_template = '''#pragma once
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __declspec(dllexport)
#else
#define {utoken}_PUBLIC __declspec(dllimport)
#endif
#else
#ifdef BUILDING_{utoken}
#define {utoken}_PUBLIC __attribute__ ((visibility ("default")))
#else
#define {utoken}_PUBLIC
#endif
#endif
int {utoken}_PUBLIC {function_name}();
'''
lib_objc_template = '''#import <{header_file}>
/* This function will not be exported and is not
* directly callable by users of this library.
*/
int internal_function() {{
return 0;
}}
int {function_name}() {{
return internal_function();
}}
'''
lib_objc_test_template = '''#import <{header_file}>
#import <stdio.h>
int main(int argc, char **argv) {{
if(argc != 1) {{
printf("%s takes no arguments.\\n", argv[0]);
return 1;
}}
return {function_name}();
}}
'''
lib_objc_meson_template = '''project('{project_name}', 'objc',
version : '{version}',
default_options : ['warning_level=3'])
# These arguments are only used to build the shared library
# not the executables that use the library.
lib_args = ['-DBUILDING_{utoken}']
shlib = shared_library('{lib_name}', '{source_file}',
install : true,
objc_args : lib_args,
gnu_symbol_visibility : 'hidden',
)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
# Make this library usable from the system's
# package manager.
install_headers('{header_file}', subdir : '{header_dir}')
pkg_mod = import('pkgconfig')
pkg_mod.generate(
name : '{project_name}',
filebase : '{ltoken}',
description : 'Meson sample project.',
subdirs : '{header_dir}',
libraries : shlib,
version : '{version}',
)
'''
hello_objc_template = '''#import <stdio.h>
#define PROJECT_NAME "{project_name}"
int main(int argc, char **argv) {{
if(argc != 1) {{
printf("%s takes no arguments.\\n", argv[0]);
return 1;
}}
printf("This is project %s.\\n", PROJECT_NAME);
return 0;
}}
'''
hello_objc_meson_template = '''project('{project_name}', 'objc',
version : '{version}',
default_options : ['warning_level=3'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
def create_exe_objc_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.m'
open(source_name, 'w').write(hello_objc_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_objc_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_objc_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
function_name = lowercase_token[0:3] + '_func'
lib_h_name = lowercase_token + '.h'
lib_objc_name = lowercase_token + '.m'
test_objc_name = lowercase_token + '_test.m'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'function_name': function_name,
'header_file': lib_h_name,
'source_file': lib_objc_name,
'test_source_file': test_objc_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_h_name, 'w').write(lib_h_template.format(**kwargs))
open(lib_objc_name, 'w').write(lib_objc_template.format(**kwargs))
open(test_objc_name, 'w').write(lib_objc_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_objc_meson_template.format(**kwargs))

@ -0,0 +1,103 @@
# Copyright 2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
lib_rust_template = '''#![crate_name = "{crate_file}"]
/* This function will not be exported and is not
* directly callable by users of this library.
*/
fn internal_function() -> i32 {{
return 0;
}}
pub fn {function_name}() -> i32 {{
return internal_function();
}}
'''
lib_rust_test_template = '''extern crate {crate_file};
fn main() {{
println!("printing: {{}}", {crate_file}::{function_name}());
}}
'''
lib_rust_meson_template = '''project('{project_name}', 'rust',
version : '{version}',
default_options : ['warning_level=3'])
shlib = static_library('{lib_name}', '{source_file}', install : true)
test_exe = executable('{test_exe_name}', '{test_source_file}',
link_with : shlib)
test('{test_name}', test_exe)
# Make this library usable as a Meson subproject.
{ltoken}_dep = declare_dependency(
include_directories: include_directories('.'),
link_with : shlib)
'''
hello_rust_template = '''
fn main() {{
let project_name = "{project_name}";
println!("This is project {{}}.\\n", project_name);
}}
'''
hello_rust_meson_template = '''project('{project_name}', 'rust',
version : '{version}',
default_options : ['warning_level=3'])
exe = executable('{exe_name}', '{source_name}',
install : true)
test('basic', exe)
'''
def create_exe_rust_sample(project_name, project_version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
source_name = lowercase_token + '.rs'
open(source_name, 'w').write(hello_rust_template.format(project_name=project_name))
open('meson.build', 'w').write(hello_rust_meson_template.format(project_name=project_name,
exe_name=lowercase_token,
source_name=source_name,
version=project_version))
def create_lib_rust_sample(project_name, version):
lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower())
uppercase_token = lowercase_token.upper()
function_name = lowercase_token[0:3] + '_func'
lib_crate_name = lowercase_token
lib_rs_name = lowercase_token + '.rs'
test_rs_name = lowercase_token + '_test.rs'
kwargs = {'utoken': uppercase_token,
'ltoken': lowercase_token,
'header_dir': lowercase_token,
'function_name': function_name,
'crate_file': lib_crate_name,
'source_file': lib_rs_name,
'test_source_file': test_rs_name,
'test_exe_name': lowercase_token,
'project_name': project_name,
'lib_name': lowercase_token,
'test_name': lowercase_token,
'version': version,
}
open(lib_rs_name, 'w').write(lib_rust_template.format(**kwargs))
open(test_rs_name, 'w').write(lib_rust_test_template.format(**kwargs))
open('meson.build', 'w').write(lib_rust_meson_template.format(**kwargs))

@ -3009,8 +3009,33 @@ int main(int argc, char **argv) {
ninja = detect_ninja()
if ninja is None:
raise unittest.SkipTest('This test currently requires ninja. Fix this once "meson build" works.')
for lang in ('c', 'cpp'):
langs = ['c']
env = get_fake_env()
try:
env.detect_cpp_compiler(MachineChoice.HOST)
langs.append('cpp')
except EnvironmentException:
pass
try:
env.detect_d_compiler(MachineChoice.HOST)
langs.append('d')
except EnvironmentException:
pass
try:
env.detect_fortran_compiler(MachineChoice.HOST)
langs.append('fortran')
except EnvironmentException:
pass
try:
env.detect_objc_compiler(MachineChoice.HOST)
langs.append('objc')
except EnvironmentException:
pass
# FIXME: omitting rust as Windows AppVeyor CI finds Rust but doesn't link correctly
for lang in langs:
for target_type in ('executable', 'library'):
# test empty directory
with tempfile.TemporaryDirectory() as tmpdir:
self._run(self.meson_command + ['init', '--language', lang, '--type', target_type],
workdir=tmpdir)
@ -3018,10 +3043,12 @@ int main(int argc, char **argv) {
workdir=tmpdir)
self._run(ninja,
workdir=os.path.join(tmpdir, 'builddir'))
with tempfile.TemporaryDirectory() as tmpdir:
with open(os.path.join(tmpdir, 'foo.' + lang), 'w') as f:
f.write('int main() {}')
self._run(self.meson_command + ['init', '-b'], workdir=tmpdir)
# test directory with existing code file
if lang in ('c', 'cpp'):
with tempfile.TemporaryDirectory() as tmpdir:
with open(os.path.join(tmpdir, 'foo.' + lang), 'w') as f:
f.write('int main() {}')
self._run(self.meson_command + ['init', '-b'], workdir=tmpdir)
# The test uses mocking and thus requires that
# the current process is the one to run the Meson steps.

@ -35,6 +35,7 @@ packages = ['mesonbuild',
'mesonbuild.dependencies',
'mesonbuild.modules',
'mesonbuild.scripts',
'mesonbuild.templates',
'mesonbuild.wrap']
package_data = {
'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakeListsLLVM.txt', 'data/CMakePathInfo.txt'],

Loading…
Cancel
Save