diff options
-rw-r--r-- | docs/markdown/Generating-sources.md | 2 | ||||
-rw-r--r-- | docs/markdown/Release-notes-for-0.45.0.md | 31 | ||||
-rw-r--r-- | docs/markdown/snippets/improved-meson-init.md | 19 | ||||
-rw-r--r-- | mesonbuild/minit.py | 130 | ||||
-rwxr-xr-x | run_unittests.py | 3 |
5 files changed, 162 insertions, 23 deletions
diff --git a/docs/markdown/Generating-sources.md b/docs/markdown/Generating-sources.md index 1c3225b..cbe6c0d 100644 --- a/docs/markdown/Generating-sources.md +++ b/docs/markdown/Generating-sources.md @@ -127,7 +127,7 @@ argument list as separate elements. gen3 = generator(genprog, output : '@BASENAME@.cc', arguments : ['@INPUT@', '@EXTRA_ARGS@', '@OUTPUT@']) -gen3_src1 = gen3.process('input1.y) +gen3_src1 = gen3.process('input1.y') gen3_src2 = gen3.process('input2.y', extra_args: '--foo') gen3_src3 = gen3.process('input3.y', extra_args: ['--foo', '--bar']) ``` diff --git a/docs/markdown/Release-notes-for-0.45.0.md b/docs/markdown/Release-notes-for-0.45.0.md index 23bff93..6b24183 100644 --- a/docs/markdown/Release-notes-for-0.45.0.md +++ b/docs/markdown/Release-notes-for-0.45.0.md @@ -5,13 +5,18 @@ short-description: Release notes for 0.45 # New features +## Python minimum version is now 3.5 + +Meson will from this version on require Python version 3.5 or newer. + ## Config-Tool based dependencies can be specified in a cross file -Tools like LLVM and pcap use a config tool for dependencies, this is a script -or binary that is run to get configuration information (cflags, ldflags, etc) -from. +Tools like LLVM and pcap use a config tool for dependencies, this is a +script or binary that is run to get configuration information (cflags, +ldflags, etc) from. -These binaries may now be specified in the `binaries` section of a cross file. +These binaries may now be specified in the `binaries` section of a +cross file. ```dosini [binaries] @@ -109,8 +114,8 @@ values. It can be specified like this in the `meson_options.txt` file: ## New method meson.project_license() -The `meson` builtin object now has a `project_license()` method that returns a -list of all licenses for the project. +The `meson` builtin object now has a `project_license()` method that +returns a list of all licenses for the project. ## Rust cross-compilation @@ -147,10 +152,10 @@ meson init --name=myproject --type=executable --language=c ## Improve test setup selection -Test setups are now identified (also) by the project they belong to and it -is possible to select the used test setup from a specific project. E.g. -to use a test setup `some_setup` from project `some_project` for all -executed tests one can use +Test setups are now identified (also) by the project they belong to +and it is possible to select the used test setup from a specific +project. E.g. to use a test setup `some_setup` from project +`some_project` for all executed tests one can use meson test --setup some_project:some_setup @@ -171,9 +176,11 @@ The `promote` command makes it easy to copy nested dependencies to the top level meson wrap promote scommon -This will search the project tree for a subproject called `scommon` and copy it to the top level. +This will search the project tree for a subproject called `scommon` +and copy it to the top level. -If there are many embedded subprojects with the same name, you have to specify which one to promote manually like this: +If there are many embedded subprojects with the same name, you have to +specify which one to promote manually like this: meson wrap promote subprojects/s1/subprojects/scommon diff --git a/docs/markdown/snippets/improved-meson-init.md b/docs/markdown/snippets/improved-meson-init.md new file mode 100644 index 0000000..ec17bc4 --- /dev/null +++ b/docs/markdown/snippets/improved-meson-init.md @@ -0,0 +1,19 @@ +## Autogeneration of simple meson.build files + +A feature to generate a meson.build file compiling given C/C++ source +files into a single executable has been added to "meson init". By +default, it will take all recognizable source files in the current +directory. You can also specify a list of dependencies with the -d +flag and automatically invoke a build with the -b flag to check if the +code builds with those dependencies. + +For example, + +```meson +meson init -fbd sdl2,gl +``` + +will look for C or C++ files in the current directory, generate a +meson.build for them with the dependencies of sdl2 and gl and +immediately try to build it, overwriting any previous meson.build and +build directory. diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 4459a05..0461cd9 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -14,8 +14,10 @@ """Code that creates simple startup projects.""" -import sys, argparse, re +import os, sys, argparse, re, shutil from glob import glob +from mesonbuild import mesonlib +from mesonbuild.environment import detect_ninja lib_h_template = '''#pragma once #if defined _WIN32 || defined __CYGWIN__ @@ -122,8 +124,7 @@ int main(int argc, char **argv) {{ hello_c_meson_template = '''project('{project_name}', 'c', version : '{version}', - default_options : ['warning_level=3', - 'cpp_std=c++14']) + default_options : ['warning_level=3']) exe = executable('{exe_name}', '{source_name}', install : true) @@ -147,7 +148,8 @@ int main(int argc, char **argv) {{ hello_cpp_meson_template = '''project('{project_name}', 'cpp', version : '{version}', - default_options : ['warning_level=3']) + default_options : ['warning_level=3', + 'cpp_std=c++14']) exe = executable('{exe_name}', '{source_name}', install : true) @@ -356,15 +358,123 @@ def create_sample(options): raise RuntimeError('Unreachable code') print(info_message) +def autodetect_options(options, sample=False): + if not options.name: + options.name = os.path.basename(os.getcwd()) + 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) + print('Using "{}" (name of current directory) as project name.' + .format(options.name)) + if not options.executable: + options.executable = options.name + print('Using "{}" (project name) as name of executable to build.' + .format(options.executable)) + if sample: + # The rest of the autodetection is not applicable to generating sample projects. + return + if not options.srcfiles: + srcfiles = [] + for f in os.listdir(): + if f.endswith('.cc') or f.endswith('.cpp') or f.endswith('.c'): + 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) + options.srcfiles = srcfiles + print("Detected source files: " + ' '.join(srcfiles)) + if not options.language: + for f in options.srcfiles: + if f.endswith('.cc') or f.endswith('.cpp'): + options.language = 'cpp' + break + if f.endswith('.c'): + options.language = 'c' + break + if not options.language: + print("Can't autodetect language, please specify it with -l.") + sys.exit(1) + print("Detected language: " + options.language) + +meson_executable_template = '''project('{project_name}', '{language}', + version : '{version}', + default_options : [{default_options}]) + +executable('{executable}', + {sourcespec},{depspec} + install : true) +''' + +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) + default_options = ['warning_level=3'] + if options.language == 'cpp': + # This shows how to set this very common option. + default_options += ['cpp_std=c++14'] + # If we get a meson.build autoformatter one day, this code could + # be simplified quite a bit. + formatted_default_options = ', '.join("'{}'".format(x) for x in default_options) + sourcespec = ',\n '.join("'{}'".format(x) for x in options.srcfiles) + depspec = '' + if options.deps: + depspec = '\n dependencies : [\n ' + depspec += ',\n '.join("dependency('{}')".format(x) + for x in options.deps.split(',')) + depspec += '],' + content = meson_executable_template.format(project_name=options.name, + language=options.language, + version=options.version, + executable=options.executable, + sourcespec=sourcespec, + depspec=depspec, + default_options=formatted_default_options) + open('meson.build', 'w').write(content) + print('Generated meson.build file:\n\n' + content) + def run(args): parser = argparse.ArgumentParser(prog='meson') - parser.add_argument('--name', default = 'mesonsample') + parser.add_argument("srcfiles", metavar="sourcefile", nargs="*", + help="source files. default: all recognized files in current directory") + 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'], + 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') + parser.add_argument("-f", "--force", action="store_true", + help="force overwrite of existing files and directories.") parser.add_argument('--type', default='executable', choices=['executable', 'library']) - parser.add_argument('--language', default='c', choices=['c', 'cpp']) - parser.add_argument('--version', default='1.0') + parser.add_argument('--version', default='0.1') options = parser.parse_args(args) - if len(glob('*')) != 0: - sys.exit('This command must be run in an empty directory.') - create_sample(options) + if len(glob('*')) == 0: + autodetect_options(options, sample=True) + if not options.language: + print('Defaulting to generating a C language project.') + options.language = 'c' + 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) + create_meson_build(options) + if options.build: + if os.path.isdir(options.builddir) and options.force: + print('Build directory already exists, deleting it.') + shutil.rmtree(options.builddir) + print('Building...') + err = os.system('{} "{}"'.format(' '.join(mesonlib.meson_command), options.builddir)) + if err: + sys.exit(1) + err = os.system('{} -C "{}"'.format(detect_ninja(), options.builddir)) + if err: + sys.exit(1) return 0 diff --git a/run_unittests.py b/run_unittests.py index 0a55ac1..8f69077 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1780,6 +1780,9 @@ int main(int argc, char **argv) { workdir=tmpdir) self._run(ninja, workdir=os.path.join(tmpdir, 'builddir')) + with tempfile.TemporaryDirectory() as tmpdir: + open(os.path.join(tmpdir, 'foo.' + lang), 'w').write('int main() {}') + self._run(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. |