diff options
39 files changed, 267 insertions, 154 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index d8a4b12..ac69dd4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -49,17 +49,15 @@ branches: only: - master -skip_commits: - files: - - docs/**/* - install: - cmd: set "ORIG_PATH=%PATH%" # Boost 1.56.0: https://www.appveyor.com/docs/build-environment/#boost #- cmd: set "BOOST_ROOT=C:\Libraries\boost" + # Use a Ninja with QuLogic's patch: https://github.com/ninja-build/ninja/issues/1219 + - cmd: set "MESON_FIXED_NINJA=1" + - ps: (new-object net.webclient).DownloadFile('http://nirbheek.in/files/binaries/ninja/win32/ninja.exe', 'C:\projects\meson\ninja.exe') # Use the x86 python only when building for x86 for the cpython tests. # For all other archs (including, say, arm), use the x64 python. - - ps: (new-object net.webclient).DownloadFile('https://www.dropbox.com/s/bbzvepq85hv47x1/ninja.exe?dl=1', 'C:\projects\meson\ninja.exe') - cmd: if %arch%==x86 (set MESON_PYTHON_PATH=C:\python34) else (set MESON_PYTHON_PATH=C:\python34-x64) # Set paths and config for each build type. diff --git a/.travis.yml b/.travis.yml index 5b6e022..559b39c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,9 @@ matrix: before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja python3; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python3; fi + # Use a Ninja with QuLogic's patch: https://github.com/ninja-build/ninja/issues/1219 + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir -p $HOME/tools; curl -L http://nirbheek.in/files/binaries/ninja/macos/ninja -o $HOME/tools/ninja; chmod +x $HOME/tools/ninja; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:zesty; fi # We need to copy the current checkout inside the Docker container, @@ -45,6 +47,6 @@ script: ci_env=`bash <(curl -s https://codecov.io/env)` docker run $ci_env -v ${PWD}/.coverage:/root/.coverage \ withgit \ - /bin/sh -c "cd /root && CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX ./run_tests.py -- $MESON_ARGS && chmod -R a+rwX .coverage" + /bin/sh -c "cd /root && mkdir -p tools; wget -c http://nirbheek.in/files/binaries/ninja/linux-amd64/ninja -O /root/tools/ninja; chmod +x /root/tools/ninja; CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX PATH=/root/tools:$PATH MESON_FIXED_NINJA=1 ./run_tests.py -- $MESON_ARGS && chmod -R a+rwX .coverage" fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) OBJC=$CC OBJCXX=$CXX ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) OBJC=$CC OBJCXX=$CXX PATH=$HOME/tools:$PATH MESON_FIXED_NINJA=1 ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi diff --git a/ci/appveyor-install.bat b/ci/appveyor-install.bat index becc80a..9eddeac 100644 --- a/ci/appveyor-install.bat +++ b/ci/appveyor-install.bat @@ -1,5 +1,7 @@ set CACHE=C:\cache set CYGWIN_MIRROR="http://cygwin.mirror.constant.com" +set CYGWIN_ADDITIONAL_REPO="http://www.dronecode.org.uk/cygwin/" +set CYGWIN_ADDITIONAL_REPO_KEY="http://www.dronecode.org.uk/cygwin/dronecode.gpg" if _%arch%_ == _x64_ set SETUP=setup-x86_64.exe && set CYGWIN_ROOT=C:\cygwin64 if _%arch%_ == _x86_ set SETUP=setup-x86.exe && set CYGWIN_ROOT=C:\cygwin @@ -7,5 +9,5 @@ if _%arch%_ == _x86_ set SETUP=setup-x86.exe && set CYGWIN_ROOT=C:\cygwin if not exist %CACHE% mkdir %CACHE% echo Updating Cygwin and installing ninja and test prerequisites -%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -l "%CACHE%" -g -P "ninja,gcc-objc,gcc-objc++,libglib2.0-devel,zlib-devel,python3-pip" +%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -s "%CYGWIN_ADDITIONAL_REPO%" -K "%CYGWIN_ADDITIONAL_REPO_KEY%" -l "%CACHE%" -g -P "ninja,gcc-objc,gcc-objc++,libglib2.0-devel,zlib-devel,python3-pip" echo Install done diff --git a/contributing.txt b/contributing.txt index c4809ec..094c5e6 100644 --- a/contributing.txt +++ b/contributing.txt @@ -58,7 +58,7 @@ These are bad because they would make Meson's DSL Turing complete. The second feature is a Make backend. The FAQ has specific information why these two features will not be -added to Meson: https://github.com/mesonbuild/meson/wiki/FAQ +added to Meson: http://mesonbuild.com/FAQ.html Merge requests adding either of these two features will be automatically rejected. Please save everyone's time (especially your own) and don't start diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md index 5978b5d..06efff3 100644 --- a/docs/markdown/Compiler-properties.md +++ b/docs/markdown/Compiler-properties.md @@ -29,26 +29,9 @@ Compiler id == The compiler object has a method called `get_id`, which returns a -lower case string describing the "family" of the compiler. It has one -of the following values. - -| Value | Compiler family | -| ----- | ---------------- | -| gcc | The GNU Compiler Collection | -| clang | The Clang compiler | -| msvc | Microsoft Visual Studio | -| intel | Intel compiler | -| llvm | LLVM-based compiler (Swift, D) | -| mono | Xamarin C# compiler | -| dmd | D lang reference compiler | -| rustc | Rust compiler | -| valac | Vala compiler | -| pathscale | The Pathscale Fortran compiler | -| pgi | The Portland Fortran compiler | -| sun | Sun Fortran compiler | -| g95 | The G95 Fortran compiler | -| open64 | The Open64 Fortran Compiler | -| nagfor | The NAG Fortran compiler | +lower case string describing the "family" of the compiler. See +[reference tables](Reference-tables.md) for a list of supported +compiler ids. Does code compile? == diff --git a/docs/markdown/Getting-meson.md b/docs/markdown/Getting-meson.md index d654ff3..8664d61 100644 --- a/docs/markdown/Getting-meson.md +++ b/docs/markdown/Getting-meson.md @@ -5,7 +5,7 @@ Meson releases can be downloaded from the [GitHub release page]. Meson is also available in the [Python Package Index] and can be -installed with <tt>pip3 install meson</tt>. +installed with `pip3 install meson`. The newest development code can be obtained directly from [Git] diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md index 3672761..99a9c8e 100644 --- a/docs/markdown/Gnome-module.md +++ b/docs/markdown/Gnome-module.md @@ -226,6 +226,7 @@ files and the second specifies the XML file name. * `namespace`: namespace of the interface * `object_manager`: *(Added 0.40.0)* if true generates object manager code * `annotations`: *(Added 0.43.0)* list of lists of 3 strings for the annotation for `'ELEMENT', 'KEY', 'VALUE'` +* `docbook`: *(Added 0.43.0)* prefix to generate `'PREFIX'-NAME.xml` docbooks Returns an opaque object containing the source files. Add it to a top level target's source list. @@ -241,7 +242,8 @@ gdbus_src = gnome.gdbus_codegen('example-interface', 'com.example.Sample.xml', namespace : 'Sample', annotations : [ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'] - ] + ], + docbook : 'example-interface-doc' ) ``` diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 7c26d7c..2025ab5 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1180,11 +1180,13 @@ the following methods. Python](https://docs.python.org/3/library/os.path.html#os.path.join) special-case absolute paths. - `MESONINTROSPECT` contains the path to the `mesonintrospect` - executable that corresponds to the `meson` executable that was used - to configure the build. (This might be a different path then the - first `mesonintrospect` executable found in `PATH`.) It can be used - to query build configuration. + `MESONINTROSPECT` contains the path to the introspect command that + corresponds to the `meson` executable that was used to configure the + build. (This might be a different path then the first executable + found in `PATH`.) It can be used to query build configuration. Note + that the value may contain many parts, i.e. it may be `python3 + /path/to/meson.py introspect`. The user is responsible for splitting + the string to an array if needed. - `source_root()` returns a string with the absolute path to the source root directory. Note: you should use the `files()` function diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md new file mode 100644 index 0000000..b604fb6 --- /dev/null +++ b/docs/markdown/Reference-tables.md @@ -0,0 +1,60 @@ +# Reference tables + +## Compiler ids + +These are return values of the `get_id` method in a compiler object. + +| Value | Compiler family | +| ----- | ---------------- | +| gcc | The GNU Compiler Collection | +| clang | The Clang compiler | +| msvc | Microsoft Visual Studio | +| intel | Intel compiler | +| llvm | LLVM-based compiler (Swift, D) | +| mono | Xamarin C# compiler | +| dmd | D lang reference compiler | +| rustc | Rust compiler | +| valac | Vala compiler | +| pathscale | The Pathscale Fortran compiler | +| pgi | The Portland Fortran compiler | +| sun | Sun Fortran compiler | +| g95 | The G95 Fortran compiler | +| open64 | The Open64 Fortran Compiler | +| nagfor | The NAG Fortran compiler | + +## Script environment variables + +| Value | Comment | +| ----- | ------- | +| MESON_SOURCE_ROOT | Absolute path to the source dir | +| MESON_BUILD_ROOT | Absolute path to the build dir | +| MESONINTROSPECT | Command to run to run the introspection command, may be of the form `python /path/to/meson introspect`, user is responsible for splitting the path if necessary. | +| MESON_SUBDIR | Current subdirectory, only set for `run_command` | + +## CPU families + +These are returned by the `cpu_family` method of `build_machine`, +`host_machine` and `target_machine`. For cross compilation they are +set in the cross file. + +| Value | Comment | +| ----- | ------- | +| x86 | 32 bit x86 processor | +| x86_64 | 64 bit x86 processor | +| arm | 32 bit ARM processor | + +Any cpu family not listed in the above list is not guaranteed to +remain stable in future releases. + +## Operating system names + +These are provided by the `.system()` method call. + +| Value | Comment | +| ----- | ------- | +| linux | | +| darwin | Either OSX or iOS | +| windows | Any version of Windows | + +Any string not listed above is not guaranteed to remain stable in +future releases.
\ No newline at end of file diff --git a/docs/markdown/Videos.md b/docs/markdown/Videos.md index ab128c6..5abfbe4 100644 --- a/docs/markdown/Videos.md +++ b/docs/markdown/Videos.md @@ -9,7 +9,7 @@ short-description: Videos about Meson (from Linux.conf.au 2015 -- Auckland, New Zealand) <div class="video-container"> -<iframe width="854" height="480" src="https://www.youtube.com/embed/KPi0AuVpxLI" frameborder="0" allowfullscreen></iframe> +<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/KPi0AuVpxLI" allowfullscreen></iframe> </div> ## Talks about design, goals behind Meson's multiplatform dependency system was held @@ -17,7 +17,7 @@ short-description: Videos about Meson (From Linux.conf.au 2016 -- Geelong, Australia) <div class="video-container"> -<iframe width="854" height="480" src="https://www.youtube.com/embed/CTJtKtQ8R5k" frameborder="0" allowfullscreen></iframe> +<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/CTJtKtQ8R5k" allowfullscreen></iframe> </div> ## Features and benefits of Meson's multiplatform support for building and dependencies] @@ -25,7 +25,7 @@ short-description: Videos about Meson (Libre Application Summit 2016 talk _New world, new tools_ explored further) <div class="video-container"> -<iframe width="854" height="480" src="https://www.youtube.com/embed/0-gx1qU2pPo" frameborder="0" allowfullscreen></iframe> +<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/0-gx1qU2pPo" allowfullscreen></iframe> </div> ## The first ever public presentation on Meson @@ -33,5 +33,5 @@ short-description: Videos about Meson (lightning talk at FOSDEM 2014) <video width="854" height="480" controls> - < <source src=http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm> + <source src=http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm> </video> diff --git a/docs/markdown/index.md b/docs/markdown/index.md index 2aba0d7..81c17ff 100644 --- a/docs/markdown/index.md +++ b/docs/markdown/index.md @@ -24,10 +24,10 @@ The main design point of Meson is that every moment a developer spends writing o There are two main methods of connecting with other Meson developers. The first one is the mailing list, which is hosted at [Google Groups](https://groups.google.com/forum/#!forum/mesonbuild). -The second way is via IRC. The channel to use is <tt>#mesonbuild</tt> at [Freenode](https://freenode.net/). +The second way is via IRC. The channel to use is `#mesonbuild` at [Freenode](https://freenode.net/). ## Development -All development on Meson is done on [GitHub project](https://github.com/mesonbuild/meson). For further info look into the <tt>contributing.txt</tt> file that comes with Meson's source checkout. +All development on Meson is done on [GitHub project](https://github.com/mesonbuild/meson). For further info look into the `contributing.txt` file that comes with Meson's source checkout. You do not need to sign a CLA to contribute to Meson. diff --git a/docs/sitemap.txt b/docs/sitemap.txt index cb1570a..89dfdbd 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -48,6 +48,7 @@ index.md Creating-OSX-packages.md Creating-Linux-binaries.md Reference-manual.md + Reference-tables.md FAQ.md Reproducible-builds.md howtox.md diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 4dbf41c..97959b6 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -65,12 +65,12 @@ class ExecutableSerialisation: self.capture = capture class TestSerialisation: - def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env, + def __init__(self, name, suite, fname, is_cross_built, exe_wrapper, is_parallel, cmd_args, env, should_fail, timeout, workdir, extra_paths): self.name = name self.suite = suite self.fname = fname - self.is_cross = is_cross + self.is_cross_built = is_cross_built self.exe_runner = exe_wrapper self.is_parallel = is_parallel self.cmd_args = cmd_args @@ -180,8 +180,9 @@ class Backend: # target that the GeneratedList is used in return os.path.join(self.get_target_private_dir(target), src) - def get_unity_source_filename(self, target, suffix): - return target.name + '-unity.' + suffix + def get_unity_source_file(self, target, suffix): + osrc = target.name + '-unity.' + suffix + return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc) def generate_unity_files(self, target, unity_src): abs_files = [] @@ -189,18 +190,15 @@ class Backend: compsrcs = classify_unity_sources(target.compilers.values(), unity_src) def init_language_file(suffix): - unity_src_name = self.get_unity_source_filename(target, suffix) - unity_src_subdir = self.get_target_private_dir_abs(target) - outfilename = os.path.join(unity_src_subdir, - unity_src_name) - outfileabs = os.path.join(self.environment.get_build_dir(), - outfilename) + unity_src = self.get_unity_source_file(target, suffix) + outfileabs = unity_src.absolute_path(self.environment.get_source_dir(), + self.environment.get_build_dir()) outfileabs_tmp = outfileabs + '.tmp' abs_files.append(outfileabs) outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp) if not os.path.exists(outfileabs_tmp_dir): os.makedirs(outfileabs_tmp_dir) - result.append(mesonlib.File(True, unity_src_subdir, unity_src_name)) + result.append(unity_src) return open(outfileabs_tmp, 'w') # For each language, generate a unity source file and return the list @@ -257,11 +255,11 @@ class Backend: else: exe_cmd = [exe] exe_needs_wrapper = False - is_cross = exe_needs_wrapper and \ + is_cross_built = exe_needs_wrapper and \ self.environment.is_cross_build() and \ self.environment.cross_info.need_cross_compiler() and \ self.environment.cross_info.need_exe_wrapper() - if is_cross: + if is_cross_built: exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: exe_wrapper = None @@ -270,7 +268,7 @@ class Backend: else: extra_paths = [] es = ExecutableSerialisation(basename, exe_cmd, cmd_args, env, - is_cross, exe_wrapper, workdir, + is_cross_built, exe_wrapper, workdir, extra_paths, capture) pickle.dump(es, f) return exe_data @@ -310,13 +308,35 @@ class Backend: return result def object_filename_from_source(self, target, source, is_unity): - if isinstance(source, mesonlib.File): - source = source.fname + assert isinstance(source, mesonlib.File) + build_dir = self.environment.get_build_dir() + rel_src = source.rel_to_builddir(self.build_to_src) # foo.vala files compile down to foo.c and then foo.c.o, not foo.vala.o - if source.endswith(('.vala', '.gs')): + if rel_src.endswith(('.vala', '.gs')): + # See description in generate_vala_compile for this logic. + if source.is_built: + if os.path.isabs(rel_src): + rel_src = rel_src[len(build_dir) + 1:] + rel_src = os.path.relpath(rel_src, self.get_target_private_dir(target)) + else: + rel_src = os.path.basename(rel_src) if is_unity: - return source[:-5] + '.c.' + self.environment.get_object_suffix() - source = os.path.join(self.get_target_private_dir(target), source[:-5] + '.c') + return 'meson-generated_' + rel_src[:-5] + '.c.' + self.environment.get_object_suffix() + # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. + source = 'meson-generated_' + rel_src[:-5] + '.c' + elif source.is_built: + if os.path.isabs(rel_src): + rel_src = rel_src[len(build_dir) + 1:] + targetdir = self.get_target_private_dir(target) + # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. + source = 'meson-generated_' + os.path.relpath(rel_src, targetdir) + else: + if os.path.isabs(rel_src): + # Not from the source directory; hopefully this doesn't conflict with user's source files. + source = os.path.basename(rel_src) + else: + source = os.path.relpath(os.path.join(build_dir, rel_src), + os.path.join(self.environment.get_source_dir(), target.get_subdir())) return source.replace('/', '_').replace('\\', '_') + '.' + self.environment.get_object_suffix() def determine_ext_objs(self, target, extobj, proj_dir_to_build_root): @@ -330,9 +350,8 @@ class Backend: extobj.srclist[0]) # There is a potential conflict here, but it is unlikely that # anyone both enables unity builds and has a file called foo-unity.cpp. - osrc = self.get_unity_source_filename(extobj.target, - comp.get_default_suffix()) - osrc = os.path.join(self.get_target_private_dir(extobj.target), osrc) + osrc = self.get_unity_source_file(extobj.target, + comp.get_default_suffix()) objname = self.object_filename_from_source(extobj.target, osrc, True) objname = objname.replace('/', '_').replace('\\', '_') objpath = os.path.join(proj_dir_to_build_root, targetdir, objname) @@ -515,6 +534,10 @@ class Backend: self.environment.cross_info.need_exe_wrapper() if isinstance(exe, build.BuildTarget): is_cross = is_cross and exe.is_cross + if isinstance(exe, dependencies.ExternalProgram): + # E.g. an external verificator or simulator program run on a generated executable. + # Can always be run. + is_cross = False if is_cross: exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index bff173a..cd92972 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -192,6 +192,9 @@ int dummy; def generate(self, interp): self.interpreter = interp + self.ninja_command = environment.detect_ninja(log=True) + if self.ninja_command is None: + raise MesonException('Could not detect Ninja v1.5 or newer') outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename) tempfilename = outfilename + '~' with open(tempfilename, 'w') as outfile: @@ -225,11 +228,10 @@ int dummy; # http://clang.llvm.org/docs/JSONCompilationDatabase.html def generate_compdb(self): - ninja_exe = environment.detect_ninja() pch_compilers = ['%s_PCH' % i for i in self.build.compilers] native_compilers = ['%s_COMPILER' % i for i in self.build.compilers] cross_compilers = ['%s_CROSS_COMPILER' % i for i in self.build.cross_compilers] - ninja_compdb = [ninja_exe, '-t', 'compdb'] + pch_compilers + native_compilers + cross_compilers + ninja_compdb = [self.ninja_command, '-t', 'compdb'] + pch_compilers + native_compilers + cross_compilers builddir = self.environment.get_build_dir() try: jsondb = subprocess.check_output(ninja_compdb, cwd=builddir) @@ -2116,39 +2118,21 @@ rule FORTRAN_DEP_HACK self.target_arg_cache[key] = commands commands = CompilerArgs(commands.compiler, commands) - if isinstance(src, mesonlib.File) and src.is_built: - rel_src = os.path.join(src.subdir, src.fname) - if os.path.isabs(rel_src): - assert(rel_src.startswith(self.environment.get_build_dir())) - rel_src = rel_src[len(self.environment.get_build_dir()) + 1:] - abs_src = os.path.join(self.environment.get_build_dir(), rel_src) - elif isinstance(src, mesonlib.File): + build_dir = self.environment.get_build_dir() + if isinstance(src, File): rel_src = src.rel_to_builddir(self.build_to_src) - abs_src = src.absolute_path(self.environment.get_source_dir(), - self.environment.get_build_dir()) + if os.path.isabs(rel_src): + # Source files may not be from the source directory if they originate in source-only libraries, + # so we can't assert that the absolute path is anywhere in particular. + if src.is_built: + assert rel_src.startswith(build_dir) + rel_src = rel_src[len(build_dir) + 1:] elif is_generated: raise AssertionError('BUG: broken generated source file handling for {!r}'.format(src)) else: - if isinstance(src, File): - rel_src = src.rel_to_builddir(self.build_to_src) - else: - raise InvalidArguments('Invalid source type: {!r}'.format(src)) - abs_src = os.path.join(self.environment.get_build_dir(), rel_src) - if isinstance(src, File): - if src.is_built: - src_filename = os.path.join(src.subdir, src.fname) - if os.path.isabs(src_filename): - assert(src_filename.startswith(self.environment.get_build_dir())) - src_filename = src_filename[len(self.environment.get_build_dir()) + 1:] - else: - src_filename = src.fname - elif os.path.isabs(src): - src_filename = os.path.basename(src) - else: - src_filename = src - obj_basename = src_filename.replace('/', '_').replace('\\', '_') + raise InvalidArguments('Invalid source type: {!r}'.format(src)) + obj_basename = self.object_filename_from_source(target, src, self.is_unity(target)) rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) - rel_obj += '.' + self.environment.get_object_suffix() dep_file = compiler.depfile_for_object(rel_obj) # Add MSVC debug file generation compile flags: /Fd /FS @@ -2181,6 +2165,7 @@ rule FORTRAN_DEP_HACK # outdir argument instead. # https://github.com/mesonbuild/meson/issues/1348 if not is_generated: + abs_src = os.path.join(build_dir, rel_src) extra_deps += self.get_fortran_deps(compiler, abs_src, target) # Dependency hack. Remove once multiple outputs in Ninja is fixed: # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 @@ -2583,11 +2568,8 @@ rule FORTRAN_DEP_HACK default = 'default all\n\n' outfile.write(default) - ninja_command = environment.detect_ninja() - if ninja_command is None: - raise MesonException('Could not detect Ninja v1.6 or newer') elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY') - elem.add_item('COMMAND', [ninja_command, '-t', 'clean']) + elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean']) elem.add_item('description', 'Cleaning.') # Alias that runs the above-defined meson-clean target self.create_target_alias('meson-clean', outfile) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index ec5ad7d..0bbc17c 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -80,39 +80,10 @@ class Vs2010Backend(backends.Backend): super().__init__(build) self.name = 'vs2010' self.project_file_version = '10.0.30319.1' - self.sources_conflicts = {} self.platform_toolset = None self.vs_version = '2010' self.windows_target_platform_version = None - def object_filename_from_source(self, target, source, is_unity=False): - basename = os.path.basename(source.fname) - filename_without_extension = '.'.join(basename.split('.')[:-1]) - if basename in self.sources_conflicts[target.get_id()]: - # If there are multiple source files with the same basename, we must resolve the conflict - # by giving each a unique object output file. - filename_without_extension = '.'.join(source.fname.split('.')[:-1]).replace('/', '_').replace('\\', '_') - return filename_without_extension + '.' + self.environment.get_object_suffix() - - def resolve_source_conflicts(self): - for name, target in self.build.targets.items(): - if not isinstance(target, BuildTarget): - continue - conflicts = {} - for s in target.get_sources(): - if hasattr(s, 'held_object'): - s = s.held_object - if not isinstance(s, File): - continue - basename = os.path.basename(s.fname) - conflicting_sources = conflicts.get(basename, None) - if conflicting_sources is None: - conflicting_sources = [] - conflicts[basename] = conflicting_sources - conflicting_sources.append(s) - self.sources_conflicts[target.get_id()] = {name: src_conflicts for name, src_conflicts in conflicts.items() - if len(src_conflicts) > 1} - def generate_custom_generator_commands(self, target, parent_node): generator_output_files = [] custom_target_include_dirs = [] @@ -164,7 +135,6 @@ class Vs2010Backend(backends.Backend): return generator_output_files, custom_target_output_files, custom_target_include_dirs def generate(self, interp): - self.resolve_source_conflicts() self.interpreter = interp target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None) if target_machine.endswith('64'): @@ -1004,9 +974,7 @@ class Vs2010Backend(backends.Backend): self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) - basename = os.path.basename(s.fname) - if basename in self.sources_conflicts[target.get_id()]: - ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s) + ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s, False) for s in gen_src: inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s) lang = Vs2010Backend.lang_from_source_file(s) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 0b2a159..2f33a03 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -90,16 +90,19 @@ def find_coverage_tools(): genhtml_exe = None return gcovr_exe, lcov_exe, genhtml_exe -def detect_ninja(version='1.5'): +def detect_ninja(version='1.5', log=False): for n in ['ninja', 'ninja-build']: try: p, found = Popen_safe([n, '--version'])[0:2] except (FileNotFoundError, PermissionError): # Doesn't exist in PATH or isn't executable continue + found = found.strip() # Perhaps we should add a way for the caller to know the failure mode # (not found or too old) if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version): + if log: + mlog.log('Found ninja-{} at {}'.format(found, shlex.quote(shutil.which(n)))) return n def detect_native_windows_arch(): diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 4862e23..d03e5a2 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -215,6 +215,9 @@ def is_osx(): def is_linux(): return platform.system().lower() == 'linux' +def is_haiku(): + return platform.system().lower() == 'haiku' + def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index ec2bc58..1657ddd 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -121,13 +121,12 @@ class MesonApp: priv_dir = os.path.join(build_dir, 'meson-private/coredata.dat') if os.path.exists(priv_dir): if not handshake: - print('''Trying to run Meson on a build directory that has already been configured. -If you want to build it, just run your build command (e.g. ninja) inside the -build directory. Meson will autodetect any changes in your setup and regenerate -itself as required. Though it shouldn't be necessary, running ninja reconfigure -will force Meson to regenerate the build files. - -If you want to change option values, use meson configure instead.''') + print('Directory already configured, exiting Meson. Just run your build command\n' + '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n' + 'reconfigure to force Meson to regenerate.\n' + '\nIf build failures persist, manually wipe your build directory to clear any\n' + 'stored system data.\n' + '\nTo change option values, run meson configure instead.') sys.exit(0) else: if handshake: @@ -341,7 +340,7 @@ def run(args, mainfile=None): dir2 = '.' try: if mainfile is None: - sys.exit('I iz broken. Sorry.') + raise AssertionError('I iz broken. Sorry.') app = MesonApp(dir1, dir2, mainfile, handshake, options, sys.argv) except Exception as e: # Log directory does not exist, so just print @@ -357,7 +356,11 @@ def run(args, mainfile=None): mlog.log(mlog.red('\nMeson encountered an error in file %s, line %d, column %d:' % (e.file, e.lineno, e.colno))) else: mlog.log(mlog.red('\nMeson encountered an error:')) + # Error message mlog.log(e) + # Path to log file + logfile = os.path.join(app.build_dir, environment.Environment.log_dir, mlog.log_fname) + mlog.log("\nA full log can be found at", mlog.bold(logfile)) if os.environ.get('MESON_FORCE_BACKTRACE'): raise else: diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index 659c8f5..18c1e6a 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -22,11 +22,12 @@ colorize_console = platform.system().lower() != 'windows' and os.isatty(sys.stdo os.environ.get('TERM') != 'dumb' log_dir = None log_file = None +log_fname = 'meson-log.txt' def initialize(logdir): global log_dir, log_file log_dir = logdir - log_file = open(os.path.join(logdir, 'meson-log.txt'), 'w', encoding='utf8') + log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8') def shutdown(): global log_file diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index cb8f560..fcdd193 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -680,6 +680,11 @@ class GnomeModule(ExtensionModule): source_str = '@@'.join(sources) langs = mesonlib.stringlistify(kwargs.pop('languages', [])) + if langs: + mlog.log(mlog.red('DEPRECATION:'), '''The "languages" argument of gnome.yelp() is deprecated. +Use a LINGUAS file in the sources directory instead. +This will become a hard error in the future.''') + media = mesonlib.stringlistify(kwargs.pop('media', [])) symlinks = kwargs.pop('symlink_media', True) @@ -850,7 +855,8 @@ class GnomeModule(ExtensionModule): return [] - @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default', 'annotations'}) + @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default', + 'annotations', 'docbook'}) def gdbus_codegen(self, state, args, kwargs): if len(args) != 2: raise MesonException('Gdbus_codegen takes two arguments, name and xml file.') @@ -864,6 +870,8 @@ class GnomeModule(ExtensionModule): cmd += ['--c-namespace', kwargs.pop('namespace')] if kwargs.get('object_manager', False): cmd += ['--c-generate-object-manager'] + if 'docbook' in kwargs: + cmd += ['--generate-docbook', kwargs.pop('docbook')] # Annotations are a bit ugly in that they are a list of lists of strings... annotations = kwargs.pop('annotations', []) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 2520ae8..4e049a8 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -195,10 +195,10 @@ class TestHarness: def run_single_test(self, wrap, test): if test.fname[0].endswith('.jar'): cmd = ['java', '-jar'] + test.fname - elif not test.is_cross and run_with_mono(test.fname[0]): + elif not test.is_cross_built and run_with_mono(test.fname[0]): cmd = ['mono'] + test.fname else: - if test.is_cross: + if test.is_cross_built: if test.exe_runner is None: # Can not run test on cross compiled executable # because there is no execute wrapper. @@ -224,7 +224,7 @@ class TestHarness: child_env.update(test.env) if len(test.extra_paths) > 0: - child_env['PATH'] += os.pathsep.join([''] + test.extra_paths) + child_env['PATH'] = os.pathsep.join(test.extra_paths + ['']) + child_env['PATH'] # If MALLOC_PERTURB_ is not set, or if it is set to an empty value, # (i.e., the test or the environment don't explicitly set it), set diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py index 978a870..ab99267 100644 --- a/mesonbuild/scripts/yelphelper.py +++ b/mesonbuild/scripts/yelphelper.py @@ -18,6 +18,7 @@ import shutil import argparse from .. import mlog from . import destdir_join +from .gettext import read_linguas parser = argparse.ArgumentParser() parser.add_argument('command') @@ -108,6 +109,9 @@ def run(args): build_subdir = os.path.join(os.environ['MESON_BUILD_ROOT'], options.subdir) abs_sources = [os.path.join(src_subdir, 'C', source) for source in sources] + if not langs: + langs = read_linguas(src_subdir) + if options.command == 'pot': build_pot(src_subdir, options.project_id, sources) elif options.command == 'update-po': diff --git a/msi/createmsi.py b/msi/createmsi.py index 921e2ac..13b4081 100755 --- a/msi/createmsi.py +++ b/msi/createmsi.py @@ -77,8 +77,16 @@ class PackageGenerator: modules = [os.path.splitext(os.path.split(x)[1])[0] for x in glob(os.path.join('mesonbuild/modules/*'))] modules = ['mesonbuild.modules.' + x for x in modules if not x.startswith('_')] modulestr = ','.join(modules) - subprocess.check_call(['c:\\Python\python.exe', - 'c:\\Python\Scripts\\cxfreeze', + python = 'c:\\Python\python.exe' + if sys.executable: + python = sys.executable + cxfreeze = os.path.join(os.path.dirname(python), "Scripts", "cxfreeze") + if not os.path.isfile(cxfreeze): + print("ERROR: This script requires cx_freeze module") + sys.exit(1) + + subprocess.check_call([python, + cxfreeze, '--target-dir', main_stage, '--include-modules', @@ -214,6 +222,9 @@ class PackageGenerator: wixdir = 'c:\\Program Files\\Wix Toolset v3.11\\bin' if not os.path.isdir(wixdir): wixdir = 'c:\\Program Files (x86)\\Wix Toolset v3.11\\bin' + if not os.path.isdir(wixdir): + print("ERROR: This script requires WIX") + sys.exit(1) subprocess.check_call([os.path.join(wixdir, 'candle'), self.main_xml]) subprocess.check_call([os.path.join(wixdir, 'light'), '-ext', 'WixUIExtension', diff --git a/run_tests.py b/run_tests.py index efbdaaa..f74ff13 100755 --- a/run_tests.py +++ b/run_tests.py @@ -104,6 +104,12 @@ def get_backend_commands(backend, debug=False): return cmd, clean_cmd, test_cmd, install_cmd, uninstall_cmd def ensure_backend_detects_changes(backend): + # We're using a ninja with QuLogic's patch for sub-1s resolution timestamps + # and not running on HFS+ which only stores dates in seconds: + # https://developer.apple.com/legacy/library/technotes/tn/tn1150.html#HFSPlusDates + # FIXME: Upgrade Travis image to Apple FS when that becomes available + if 'MESON_FIXED_NINJA' in os.environ and not mesonlib.is_osx(): + return # This is needed to increase the difference between build.ninja's # timestamp and the timestamp of whatever you changed due to a Ninja # bug: https://github.com/ninja-build/ninja/issues/371 @@ -171,7 +177,7 @@ if __name__ == '__main__': backend = Backend.xcode break # Running on a developer machine? Be nice! - if not mesonlib.is_windows() and 'TRAVIS' not in os.environ: + if not mesonlib.is_windows() and not mesonlib.is_haiku() and 'TRAVIS' not in os.environ: os.nice(20) # Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. diff --git a/test cases/common/159 reserved targets/meson.build b/test cases/common/159 reserved targets/meson.build index 26572c0..24fd937 100644 --- a/test cases/common/159 reserved targets/meson.build +++ b/test cases/common/159 reserved targets/meson.build @@ -26,6 +26,9 @@ subdir('uninstall') subdir('runtarget') +py3 = import('python3').find_python() + custom_target('ctlist-test', output : 'out.txt', - command : ['echo'], capture : true, + command : [py3, '-c', 'print("")'], + capture : true, build_by_default : true) diff --git a/test cases/common/160 duplicate source names/dir1/file.c b/test cases/common/160 duplicate source names/dir1/file.c new file mode 100644 index 0000000..094e187 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir1/file.c @@ -0,0 +1,16 @@ +extern int dir2; +extern int dir2_dir1; +extern int dir3; +extern int dir3_dir1; + +int main() { + if (dir2 != 20) + return 1; + if (dir2_dir1 != 21) + return 1; + if (dir3 != 30) + return 1; + if (dir3_dir1 != 31) + return 1; + return 0; +} diff --git a/test cases/common/160 duplicate source names/dir1/meson.build b/test cases/common/160 duplicate source names/dir1/meson.build new file mode 100644 index 0000000..00bc85d --- /dev/null +++ b/test cases/common/160 duplicate source names/dir1/meson.build @@ -0,0 +1 @@ +sources += files('file.c') diff --git a/test cases/common/160 duplicate source names/dir2/dir1/file.c b/test cases/common/160 duplicate source names/dir2/dir1/file.c new file mode 100644 index 0000000..5aac8e5 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir2/dir1/file.c @@ -0,0 +1 @@ +int dir2_dir1 = 21; diff --git a/test cases/common/160 duplicate source names/dir2/file.c b/test cases/common/160 duplicate source names/dir2/file.c new file mode 100644 index 0000000..6cf8d66 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir2/file.c @@ -0,0 +1 @@ +int dir2 = 20; diff --git a/test cases/common/160 duplicate source names/dir2/meson.build b/test cases/common/160 duplicate source names/dir2/meson.build new file mode 100644 index 0000000..f116a02 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir2/meson.build @@ -0,0 +1 @@ +sources += files('file.c', 'dir1/file.c') diff --git a/test cases/common/160 duplicate source names/dir3/dir1/file.c b/test cases/common/160 duplicate source names/dir3/dir1/file.c new file mode 100644 index 0000000..04667c2 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir3/dir1/file.c @@ -0,0 +1 @@ +int dir3_dir1 = 31; diff --git a/test cases/common/160 duplicate source names/dir3/file.c b/test cases/common/160 duplicate source names/dir3/file.c new file mode 100644 index 0000000..d16d0a8 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir3/file.c @@ -0,0 +1 @@ +int dir3 = 30; diff --git a/test cases/common/160 duplicate source names/dir3/meson.build b/test cases/common/160 duplicate source names/dir3/meson.build new file mode 100644 index 0000000..70ddbf2 --- /dev/null +++ b/test cases/common/160 duplicate source names/dir3/meson.build @@ -0,0 +1 @@ +lib = static_library('lib', 'file.c', 'dir1/file.c') diff --git a/test cases/common/160 duplicate source names/meson.build b/test cases/common/160 duplicate source names/meson.build new file mode 100644 index 0000000..cac5194 --- /dev/null +++ b/test cases/common/160 duplicate source names/meson.build @@ -0,0 +1,7 @@ +project('proj', 'c') + +sources = [] +subdir('dir1') +subdir('dir2') +subdir('dir3') +executable('a.out', sources : sources, objects : lib.extract_all_objects()) diff --git a/test cases/frameworks/13 yelp/help/LINGUAS b/test cases/frameworks/13 yelp/help/LINGUAS new file mode 100644 index 0000000..173f978 --- /dev/null +++ b/test cases/frameworks/13 yelp/help/LINGUAS @@ -0,0 +1,2 @@ +de +es diff --git a/test cases/frameworks/13 yelp/help/meson.build b/test cases/frameworks/13 yelp/help/meson.build index 85bc980..c8edd61 100644 --- a/test cases/frameworks/13 yelp/help/meson.build +++ b/test cases/frameworks/13 yelp/help/meson.build @@ -13,3 +13,9 @@ gnome.yelp('meson-symlink', symlink_media: true, languages: ['de', 'es'], ) + +gnome.yelp('meson-linguas', + sources: 'index.page', + media: 'media/test.txt', + symlink_media: false, +) diff --git a/test cases/frameworks/13 yelp/installed_files.txt b/test cases/frameworks/13 yelp/installed_files.txt index 9fc097d..1f6522f 100644 --- a/test cases/frameworks/13 yelp/installed_files.txt +++ b/test cases/frameworks/13 yelp/installed_files.txt @@ -10,3 +10,9 @@ usr/share/help/es/meson-symlink/media/test.txt usr/share/help/es/meson-symlink/index.page usr/share/help/de/meson-symlink/index.page usr/share/help/de/meson-symlink/media/test.txt +usr/share/help/C/meson-linguas/index.page +usr/share/help/C/meson-linguas/media/test.txt +usr/share/help/es/meson-linguas/media/test.txt +usr/share/help/es/meson-linguas/index.page +usr/share/help/de/meson-linguas/index.page +usr/share/help/de/meson-linguas/media/test.txt diff --git a/test cases/frameworks/7 gnome/gdbus/meson.build b/test cases/frameworks/7 gnome/gdbus/meson.build index f8a8eba..ea91caa 100644 --- a/test cases/frameworks/7 gnome/gdbus/meson.build +++ b/test cases/frameworks/7 gnome/gdbus/meson.build @@ -3,7 +3,8 @@ gdbus_src = gnome.gdbus_codegen('generated-gdbus', 'com.example.Sample.xml', namespace : 'Sample', annotations : [ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'] - ] + ], + docbook : 'generated-gdbus-doc' ) gdbus_exe = executable('gdbus-test', 'gdbusprog.c', diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py index 0789a0c..5fe433c 100755 --- a/tools/cmake2meson.py +++ b/tools/cmake2meson.py @@ -26,7 +26,7 @@ class Token: class Statement: def __init__(self, name, args): - self.name = name + self.name = name.lower() self.args = args class Lexer: @@ -120,7 +120,10 @@ class Parser: args.append(self.arguments()) self.expect('rparen') arg = self.current - if self.accept('string') \ + if self.accept('comment'): + rest = self.arguments() + args += rest + elif self.accept('string') \ or self.accept('varexp') \ or self.accept('id'): args.append(arg) @@ -155,7 +158,7 @@ class Converter: if i.tid == 'id': res.append("'%s'" % i.value) elif i.tid == 'varexp': - res.append('%s' % i.value) + res.append('%s' % i.value.lower()) elif i.tid == 'string': res.append("'%s'" % i.value) else: |