diff -Nru gyp-0.1~svn1729/AUTHORS gyp-0.1+20150913git1f374df9/AUTHORS --- gyp-0.1~svn1729/AUTHORS 2013-06-26 18:03:45.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/AUTHORS 2015-09-13 13:41:20.000000000 +0000 @@ -7,3 +7,5 @@ Steven Knight Ryan Norton +David J. Sankel +Eric N. Vander Weele diff -Nru gyp-0.1~svn1729/buildbot/buildbot_run.py gyp-0.1+20150913git1f374df9/buildbot/buildbot_run.py --- gyp-0.1~svn1729/buildbot/buildbot_run.py 2013-06-14 17:20:04.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/buildbot/buildbot_run.py 2015-09-13 13:41:20.000000000 +0000 @@ -3,72 +3,65 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. - """Argument-less script to select what to run on the buildbots.""" - import os import shutil import subprocess import sys -if sys.platform in ['win32', 'cygwin']: - EXE_SUFFIX = '.exe' -else: - EXE_SUFFIX = '' - - BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__)) TRUNK_DIR = os.path.dirname(BUILDBOT_DIR) ROOT_DIR = os.path.dirname(TRUNK_DIR) -ANDROID_DIR = os.path.join(ROOT_DIR, 'android') +CMAKE_DIR = os.path.join(ROOT_DIR, 'cmake') +CMAKE_BIN_DIR = os.path.join(CMAKE_DIR, 'bin') OUT_DIR = os.path.join(TRUNK_DIR, 'out') def CallSubProcess(*args, **kwargs): """Wrapper around subprocess.call which treats errors as build exceptions.""" - retcode = subprocess.call(*args, **kwargs) + with open(os.devnull) as devnull_fd: + retcode = subprocess.call(stdin=devnull_fd, *args, **kwargs) if retcode != 0: print '@@@STEP_EXCEPTION@@@' sys.exit(1) -def PrepareAndroidTree(): - """Prepare an Android tree to run 'android' format tests.""" +def PrepareCmake(): + """Build CMake 2.8.8 since the version in Precise is 2.8.7.""" if os.environ['BUILDBOT_CLOBBER'] == '1': - print '@@@BUILD_STEP Clobber Android checkout@@@' - shutil.rmtree(ANDROID_DIR) + print '@@@BUILD_STEP Clobber CMake checkout@@@' + shutil.rmtree(CMAKE_DIR) - # The release of Android we use is static, so there's no need to do anything + # We always build CMake 2.8.8, so no need to do anything # if the directory already exists. - if os.path.isdir(ANDROID_DIR): + if os.path.isdir(CMAKE_DIR): return - print '@@@BUILD_STEP Initialize Android checkout@@@' - os.mkdir(ANDROID_DIR) - CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot']) - CallSubProcess(['git', 'config', '--global', - 'user.email', 'chrome-bot@google.com']) - CallSubProcess(['git', 'config', '--global', 'color.ui', 'false']) - CallSubProcess( - ['repo', 'init', - '-u', 'https://android.googlesource.com/platform/manifest', - '-b', 'android-4.2.1_r1', - '-g', 'all,-notdefault,-device,-darwin,-mips,-x86'], - cwd=ANDROID_DIR) + print '@@@BUILD_STEP Initialize CMake checkout@@@' + os.mkdir(CMAKE_DIR) - print '@@@BUILD_STEP Sync Android@@@' - CallSubProcess(['repo', 'sync', '-j4'], cwd=ANDROID_DIR) + print '@@@BUILD_STEP Sync CMake@@@' + CallSubProcess( + ['git', 'clone', + '--depth', '1', + '--single-branch', + '--branch', 'v2.8.8', + '--', + 'git://cmake.org/cmake.git', + CMAKE_DIR], + cwd=CMAKE_DIR) - print '@@@BUILD_STEP Build Android@@@' + print '@@@BUILD_STEP Build CMake@@@' CallSubProcess( - ['/bin/bash', - '-c', 'source build/envsetup.sh && lunch full-eng && make -j4'], - cwd=ANDROID_DIR) + ['/bin/bash', 'bootstrap', '--prefix=%s' % CMAKE_DIR], + cwd=CMAKE_DIR) + CallSubProcess( ['make', 'cmake'], cwd=CMAKE_DIR) -def GypTestFormat(title, format=None, msvs_version=None): + +def GypTestFormat(title, format=None, msvs_version=None, tests=[]): """Run the gyp tests for a given format, emitting annotator tags. See annotator docs at: @@ -87,21 +80,13 @@ if msvs_version: env['GYP_MSVS_VERSION'] = msvs_version command = ' '.join( - [sys.executable, 'trunk/gyptest.py', + [sys.executable, 'gyp/gyptest.py', '--all', '--passed', '--format', format, - '--chdir', 'trunk']) - if format == 'android': - # gyptest needs the environment setup from envsetup/lunch in order to build - # using the 'android' backend, so this is done in a single shell. - retcode = subprocess.call( - ['/bin/bash', - '-c', 'source build/envsetup.sh && lunch full-eng && cd %s && %s' - % (ROOT_DIR, command)], - cwd=ANDROID_DIR, env=env) - else: - retcode = subprocess.call(command, cwd=ROOT_DIR, env=env, shell=True) + '--path', CMAKE_BIN_DIR, + '--chdir', 'gyp'] + tests) + retcode = subprocess.call(command, cwd=ROOT_DIR, env=env, shell=True) if retcode: # Emit failure tag, and keep going. print '@@@STEP_FAILURE@@@' @@ -117,13 +102,11 @@ print 'Done.' retcode = 0 - # The Android gyp bot runs on linux so this must be tested first. - if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-android': - PrepareAndroidTree() - retcode += GypTestFormat('android') - elif sys.platform.startswith('linux'): + if sys.platform.startswith('linux'): retcode += GypTestFormat('ninja') retcode += GypTestFormat('make') + PrepareCmake() + retcode += GypTestFormat('cmake') elif sys.platform == 'darwin': retcode += GypTestFormat('ninja') retcode += GypTestFormat('xcode') @@ -131,8 +114,13 @@ elif sys.platform == 'win32': retcode += GypTestFormat('ninja') if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64': - retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010') - retcode += GypTestFormat('msvs-2012', format='msvs', msvs_version='2012') + retcode += GypTestFormat('msvs-ninja-2013', format='msvs-ninja', + msvs_version='2013', + tests=[ + r'test\generator-output\gyptest-actions.py', + r'test\generator-output\gyptest-relocate.py', + r'test\generator-output\gyptest-rules.py']) + retcode += GypTestFormat('msvs-2013', format='msvs', msvs_version='2013') else: raise Exception('Unknown platform') if retcode: diff -Nru gyp-0.1~svn1729/buildbot/commit_queue/cq_config.json gyp-0.1+20150913git1f374df9/buildbot/commit_queue/cq_config.json --- gyp-0.1~svn1729/buildbot/commit_queue/cq_config.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/buildbot/commit_queue/cq_config.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "trybots": { + "launched": { + "tryserver.nacl": { + "gyp-presubmit": ["defaulttests"], + "gyp-linux": ["defaulttests"], + "gyp-mac": ["defaulttests"], + "gyp-win32": ["defaulttests"], + "gyp-win64": ["defaulttests"] + } + }, + "triggered": { + } + } +} diff -Nru gyp-0.1~svn1729/buildbot/commit_queue/OWNERS gyp-0.1+20150913git1f374df9/buildbot/commit_queue/OWNERS --- gyp-0.1~svn1729/buildbot/commit_queue/OWNERS 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/buildbot/commit_queue/OWNERS 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +set noparent +bradnelson@chromium.org +bradnelson@google.com +iannucci@chromium.org +scottmg@chromium.org +thakis@chromium.org diff -Nru gyp-0.1~svn1729/buildbot/commit_queue/README gyp-0.1+20150913git1f374df9/buildbot/commit_queue/README --- gyp-0.1~svn1729/buildbot/commit_queue/README 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/buildbot/commit_queue/README 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,3 @@ +cq_config.json describes the trybots that must pass in order +to land a change through the commit queue. +Comments are here as the file is strictly JSON. diff -Nru gyp-0.1~svn1729/codereview.settings gyp-0.1+20150913git1f374df9/codereview.settings --- gyp-0.1~svn1729/codereview.settings 2010-04-27 23:47:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/codereview.settings 2015-09-13 13:41:20.000000000 +0000 @@ -1,10 +1,10 @@ # This file is used by gcl to get repository specific information. CODE_REVIEW_SERVER: codereview.chromium.org CC_LIST: gyp-developer@googlegroups.com -VIEW_VC: http://code.google.com/p/gyp/source/detail?r= -TRY_ON_UPLOAD: True +VIEW_VC: https://chromium.googlesource.com/external/gyp/+/ +TRY_ON_UPLOAD: False TRYSERVER_PROJECT: gyp -TRYSERVER_PATCHLEVEL: 0 -TRYSERVER_ROOT: trunk +TRYSERVER_PATCHLEVEL: 1 +TRYSERVER_ROOT: gyp TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl - +PROJECT: gyp diff -Nru gyp-0.1~svn1729/debian/changelog gyp-0.1+20150913git1f374df9/debian/changelog --- gyp-0.1~svn1729/debian/changelog 2014-03-18 15:40:03.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/changelog 2015-11-04 15:49:38.000000000 +0000 @@ -1,3 +1,26 @@ +gyp (0.1+20150913git1f374df9-1ubuntu1) xenial; urgency=medium + + * Merge from Debian unstable. (LP: #1511949) Remaining changes: + debian/preinst: + - help dpkg when /usr/lib/python2.7/dist-packages/gyp-0.1.egg-info + is changed from a symlink to a directory (LP: #1246730) + + -- Hans Joachim Desserud Sat, 31 Oct 2015 12:42:33 +0100 + +gyp (0.1+20150913git1f374df9-1) unstable; urgency=medium + + * Upstream update to git 1f374df9 (Closes: #798516) + * Preprend date to upstream version + * Update get-orig-source target + * Update Homepage + * Update copyright years + * Update copyright Source + * Install docs + * Standards-Version 3.9.6 + * Set Section to devel instead of python + + -- Jérémy Lal Sun, 13 Sep 2015 21:19:18 +0200 + gyp (0.1~svn1729-3ubuntu1) trusty; urgency=low * debian/preinst: @@ -8,7 +31,7 @@ gyp (0.1~svn1729-3) unstable; urgency=low - * Build-Depends on python-setuptools. (Closes: #724516) + * Build-Depends on python-setuptools. (Closes: #724516) -- Jérémy Lal Tue, 24 Sep 2013 18:30:37 +0200 @@ -124,7 +147,7 @@ -- Fabien Tassin Sat, 27 Mar 2010 04:00:02 +0100 gyp (0.1~svn785-0ubuntu1) lucid; urgency=low - + * New upstream snapshot, needed to support --no-circular-check -- Fabien Tassin Wed, 17 Feb 2010 22:00:38 +0100 diff -Nru gyp-0.1~svn1729/debian/control gyp-0.1+20150913git1f374df9/debian/control --- gyp-0.1~svn1729/debian/control 2013-09-24 16:28:53.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/control 2015-11-04 15:47:11.000000000 +0000 @@ -1,12 +1,13 @@ Source: gyp -Section: python +Section: devel Priority: optional -Maintainer: Debian Chromium Maintainers +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Chromium Maintainers Uploaders: Giuseppe Iuculano , Jérémy Lal Build-Depends: debhelper (>= 7.0.50~), python (>= 2.6.6-3~), python-setuptools, asciidoc, xsltproc, docbook-xsl, docbook-xml -Standards-Version: 3.9.4 -Homepage: http://code.google.com/p/gyp/ +Standards-Version: 3.9.6 +Homepage: https://chromium.googlesource.com/external/gyp/ Package: gyp Architecture: all diff -Nru gyp-0.1~svn1729/debian/copyright gyp-0.1+20150913git1f374df9/debian/copyright --- gyp-0.1~svn1729/debian/copyright 2013-09-04 08:03:51.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/copyright 2015-09-13 19:16:07.000000000 +0000 @@ -1,9 +1,9 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Source: http://gyp.googlecode.com/svn/trunk +Source: https://chromium.googlesource.com/external/gyp/ Files: * -Copyright: 2009-2013 Google Inc. All rights reserved. - 2011-2013 The Chromium Authors. All rights reserved. +Copyright: 2009-2015 Google Inc. All rights reserved. + 2011-2014 The Chromium Authors. All rights reserved. 2013 Yandex LLC License: BSD-3-clause~Google diff -Nru gyp-0.1~svn1729/debian/docs gyp-0.1+20150913git1f374df9/debian/docs --- gyp-0.1~svn1729/debian/docs 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/docs 2015-09-13 19:16:07.000000000 +0000 @@ -0,0 +1 @@ +docs/* diff -Nru gyp-0.1~svn1729/debian/patches/1001_append_cppflags_to_cxxflags.patch gyp-0.1+20150913git1f374df9/debian/patches/1001_append_cppflags_to_cxxflags.patch --- gyp-0.1~svn1729/debian/patches/1001_append_cppflags_to_cxxflags.patch 2013-09-13 21:33:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/patches/1001_append_cppflags_to_cxxflags.patch 2015-09-13 19:16:07.000000000 +0000 @@ -6,7 +6,7 @@ Last-Update: 2013-05-03 --- a/pylib/gyp/generator/make.py +++ b/pylib/gyp/generator/make.py -@@ -249,7 +249,7 @@ +@@ -275,7 +275,7 @@ CC.target ?= %(CC.target)s CFLAGS.target ?= $(CFLAGS) CXX.target ?= %(CXX.target)s diff -Nru gyp-0.1~svn1729/debian/patches/1002_no_ez_setup.patch gyp-0.1+20150913git1f374df9/debian/patches/1002_no_ez_setup.patch --- gyp-0.1~svn1729/debian/patches/1002_no_ez_setup.patch 2013-09-13 20:49:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/patches/1002_no_ez_setup.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ ---- a/setup.py -+++ b/setup.py -@@ -4,8 +4,6 @@ - # Use of this source code is governed by a BSD-style license that can be - # found in the LICENSE file. - --from ez_setup import use_setuptools --use_setuptools() - from setuptools import setup - - setup( diff -Nru gyp-0.1~svn1729/debian/patches/2001_kfreebsd_flock.patch gyp-0.1+20150913git1f374df9/debian/patches/2001_kfreebsd_flock.patch --- gyp-0.1~svn1729/debian/patches/2001_kfreebsd_flock.patch 2013-09-13 21:33:32.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/patches/2001_kfreebsd_flock.patch 2015-09-13 19:16:07.000000000 +0000 @@ -4,9 +4,9 @@ Last-Update: 2013-07-20 --- a/pylib/gyp/generator/make.py +++ b/pylib/gyp/generator/make.py -@@ -1990,11 +1990,11 @@ +@@ -2045,11 +2045,11 @@ + 'flock': './gyp-flock-tool flock', 'flock_index': 2, - 'extra_commands': SHARED_HEADER_SUN_COMMANDS, }) - elif flavor == 'freebsd': + # elif flavor == 'freebsd': @@ -17,6 +17,6 @@ + # header_params.update({ + # 'flock': 'lockf', + # }) - - header_params.update({ - 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), + elif flavor == 'aix': + header_params.update({ + 'link_commands': LINK_COMMANDS_AIX, diff -Nru gyp-0.1~svn1729/debian/patches/series gyp-0.1+20150913git1f374df9/debian/patches/series --- gyp-0.1~svn1729/debian/patches/series 2013-09-13 20:49:23.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/patches/series 2015-09-13 19:16:07.000000000 +0000 @@ -1,3 +1,2 @@ 1001_append_cppflags_to_cxxflags.patch 2001_kfreebsd_flock.patch -1002_no_ez_setup.patch diff -Nru gyp-0.1~svn1729/debian/rules gyp-0.1+20150913git1f374df9/debian/rules --- gyp-0.1~svn1729/debian/rules 2013-09-16 23:54:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/debian/rules 2015-09-13 19:16:07.000000000 +0000 @@ -1,37 +1,12 @@ #!/usr/bin/make -f -### Tarball (get-orig-source & get-current-source) - -PACKAGE := gyp -PACKAGE_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(\([0-9]\+\):\)\?\(.*\)-.*/\3/p') -PACKAGE_VERSION_ROOT := $(shell echo '$(PACKAGE_VERSION)' | cut -d~ -f1) -PACKAGE_VERSION_SVN := $(shell echo '$(PACKAGE_VERSION)' | cut -d~ -f2 | sed 's/svn//') -SVN_URL := http://gyp.googlecode.com/svn/trunk - -TMP_DIR := get-orig-source-$(shell echo $$$$) - -.PHONY: get-orig-source get-current-source - -pack-source: - rm -rf $(TMP_DIR) $(TARBALL) - mkdir $(TMP_DIR) - svn export -r $(SVN_REV) $(SVN_URL) $(TMP_DIR)/$(PACKAGE)-$(SRC_VERSION).orig - GZIP='--best --no-name' tar czf $(TARBALL) -C $(TMP_DIR) $(PACKAGE)-$(SRC_VERSION).orig - rm -rf $(TMP_DIR) - echo " "$(TARBALL)" created; move it to the right destination to build the package" - -get-orig-source: SVN_REV = $(shell LANG=C svn info $(SVN_URL) | grep ^Revision: | cut -d' ' -f2) -get-orig-source: SRC_VERSION = $(PACKAGE_VERSION_ROOT)~svn$(SVN_REV) -get-orig-source: TARBALL = $(PACKAGE)_$(SRC_VERSION).orig.tar.gz -get-orig-source: pack-source - -get-current-source: SVN_REV = $(PACKAGE_VERSION_SVN) -get-current-source: SRC_VERSION = $(PACKAGE_VERSION_ROOT)~svn$(SVN_REV) -get-current-source: TARBALL = $(PACKAGE)_$(SRC_VERSION).orig.tar.gz -get-current-source: pack-source - -### +upstreamVersion := $(shell dpkg-parsechangelog -SVersion | cut -d- -f1) +upstreamHash := $(shell echo $(upstreamVersion) | grep -oP '(?<=git)\w+') +upstreamUrl := $(shell grep -oP "(?<=Homepage: )(.+)" $(CURDIR)/debian/control) +upstreamName := $(shell dpkg-parsechangelog -SSource) +get-orig-source: + wget -O - $(upstreamUrl)+archive/$(upstreamHash).tar.gz > ../$(upstreamName)_$(upstreamVersion).orig.tar.gz %: dh $@ --with python2 diff -Nru gyp-0.1~svn1729/docs/Buildbot.md gyp-0.1+20150913git1f374df9/docs/Buildbot.md --- gyp-0.1~svn1729/docs/Buildbot.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/Buildbot.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +# Buildbot + +Gyp's Buildbot status page can be found here: +http://build.chromium.org/f/client/gyp/ + +The code that implements Gyp's test waterfall is called "parasite" and is an +experimental replacement for Buildbot's build master that uses trybots to run +tests. The code can be found here: +http://src.chromium.org/viewvc/chrome/trunk/tools/parasite/ diff -Nru gyp-0.1~svn1729/docs/GypVsCMake.md gyp-0.1+20150913git1f374df9/docs/GypVsCMake.md --- gyp-0.1~svn1729/docs/GypVsCMake.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/GypVsCMake.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,118 @@ +# GYP vs. CMake # + +GYP was originally created to generate native IDE project files (Visual Studio, Xcode) for building [Chromium](http://www.chromim.org). + +The functionality of GYP is very similar to the [CMake](http://www.cmake.org) +build tool. Bradley Nelson wrote up the following description of why the team +created GYP instead of using CMake. The text below is copied from +http://www.mail-archive.com/webkit-dev@lists.webkit.org/msg11029.html + +``` + +Re: [webkit-dev] CMake as a build system? +Bradley Nelson +Mon, 19 Apr 2010 22:38:30 -0700 + +Here's the innards of an email with a laundry list of stuff I came up with a +while back on the gyp-developers list in response to Mike Craddick regarding +what motivated gyp's development, since we were aware of cmake at the time +(we'd even started a speculative port): + + +I did an exploratory port of portions of Chromium to cmake (I think I got as +far as net, base, sandbox, and part of webkit). +There were a number of motivations, not all of which would apply to other +projects. Also, some of the design of gyp was informed by experience at +Google with large projects built wholly from source, leading to features +absent from cmake, but not strictly required for Chromium. + +1. Ability to incrementally transition on Windows. It took us about 6 months +to switch fully to gyp. Previous attempts to move to scons had taken a long +time and failed, due to the requirement to transition while in flight. For a +substantial period of time, we had a hybrid of checked in vcproj and +gyp generated +vcproj. To this day we still have a good number of GUIDs pinned in the +gyp files, +because different parts of our release pipeline have leftover assumptions +regarding manipulating the raw sln/vcprojs. This transition occurred from +the bottom up, largely because modules like base were easier to convert, and +had a lower churn rate. During early stages of the transition, the majority +of the team wasn't even aware they were using gyp, as it integrated into +their existing workflow, and only affected modules that had been converted. + +2. Generation of a more 'normal' vcproj file. Gyp attempts, particularly on +Windows, to generate vcprojs which resemble hand generated projects. It +doesn't generate any Makefile type projects, but instead produces msvs +Custom Build Steps and Custom Build Rules. This makes the resulting projects +easier to understand from the IDE and avoids parts of the IDE that simply +don't function correctly if you use Makefile projects. Our early hope with +gyp was to support the least common denominator of features present in each +of the platform specific project file formats, rather than falling back on +generated Makefiles/shell scripts to emulate some common abstraction. CMake by +comparison makes a good faith attempt to use native project features, but +falls back on generated scripts in order to preserve the same semantics on +each platforms. + +3. Abstraction on the level of project settings, rather than command line +flags. In gyp's syntax you can add nearly any option present in a hand +generated xcode/vcproj file. This allows you to use abstractions built into +the IDEs rather than reverse engineering them possibly incorrectly for +things like: manifest generation, precompiled headers, bundle generation. +When somebody wants to use a particular menu option from msvs, I'm able to +do a web search on the name of the setting from the IDE and provide them +with a gyp stanza that does the equivalent. In many cases, not all project +file constructs correspond to command line flags. + +4. Strong notion of module public/private interface. Gyp allows targets to +publish a set of direct_dependent_settings, specifying things like +include_dirs, defines, platforms specific settings, etc. This means that +when module A depends on module B, it automatically acquires the right build +settings without module A being filled with assumptions/knowledge of exactly +how module B is built. Additionally, all of the transitive dependencies of +module B are pulled in. This avoids their being a single top level view of +the project, rather each gyp file expresses knowledge about its immediate +neighbors. This keep local knowledge local. CMake effectively has a large +shared global namespace. + +5. Cross platform generation. CMake is not able to generate all project +files on all platforms. For example xcode projects cannot be generated from +windows (cmake uses mac specific libraries to do project generation). This +means that for instance generating a tarball containing pregenerated +projects for all platforms is hard with Cmake (requires distribution to +several machine types). + +6. Gyp has rudimentary cross compile support. Currently we've added enough +functionality to gyp to support x86 -> arm cross compiles. Last I checked +this functionality wasn't present in cmake. (This occurred later). + + +That being said there are a number of drawbacks currently to gyp: + +1. Because platform specific settings are expressed at the project file +level (rather than the command line level). Settings which might otherwise +be shared in common between platforms (flags to gcc on mac/linux), end up +being repeated twice. Though in fairness there is actually less sharing here +than you'd think. include_dirs and defines actually represent 90% of what +can be typically shared. + +2. CMake may be more mature, having been applied to a broader range of +projects. There a number of 'tool modules' for cmake, which are shared in a +common community. + +3. gyp currently makes some nasty assumptions about the availability of +chromium's hermetic copy of cygwin on windows. This causes you to either +have to special case a number of rules, or swallow this copy of cygwin as a +build time dependency. + +4. CMake includes a fairly readable imperative language. Currently Gyp has a +somewhat poorly specified declarative language (variable expansion happens +in sometimes weird and counter-intuitive ways). In fairness though, gyp assumes +that external python scripts can be used as an escape hatch. Also gyp avoids +a lot of the things you'd need imperative code for, by having a nice target +settings publication mechanism. + +5. (Feature/drawback depending on personal preference). Gyp's syntax is +DEEPLY nested. It suffers from all of Lisp's advantages and drawbacks. + +-BradN +``` diff -Nru gyp-0.1~svn1729/docs/Hacking.md gyp-0.1+20150913git1f374df9/docs/Hacking.md --- gyp-0.1~svn1729/docs/Hacking.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/Hacking.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,77 @@ +# GYP Hacking + +Note that the instructions below assume that you have the Chromium +[depot tools](http://dev.chromium.org/developers/how-tos/depottools) +installed and configured. +If you don't, you do not pass go, and you cannot collect your $200. + +## Getting the sources + +Best is to use git to hack on anything, you can set up a git clone of GYP +as follows: + +``` +git clone https://chromium.googlesource.com/external/gyp.git +cd gyp +``` + +## Testing your change + +GYP has a suite of tests which you can run with the provided test driver +to make sure your changes aren't breaking anything important. + +You run the test driver with e.g. + +``` +python gyptest.py +python gyptest.py test/win # Only run Windows-related tests. +python gyptest.py -a -f ninja # Only run ninja-related tests. +``` + +See [Testing](Testing) for more details on the test framework. + +Note that it can be handy to look at the project files output by the tests +to diagnose problems. The easiest way to do that is by kindly asking the +test driver to leave the temporary directories it creates in-place. +This is done by setting the enviroment variable "PRESERVE", e.g. + +``` +set PRESERVE=all # On Windows +export PRESERVE=all # On saner platforms. +``` + +## Reviewing your change + +All changes to GYP must be code reviewed before submission, GYP uses rietveld. + +Upload your change with: + +``` +git cl upload +``` + +## Submitting + +Once you're ready to submit, you can use the GYP try bots to test your change +with e.g. + +``` +git try +``` + +Once the change has been approved (LGTMed) and passes trybots, you can submit +it with: + +``` +git cl land +``` + +To be allowed to submit, you will need committer rights in the project. You +need to do the new password dance at +https://chromium.googlesource.com/new-password . + +## Migrating from an old with-svn checkout + +Remove the [svn] entry from .git/config, and the .git/svn subdirs to avoid +having `git cl land` complain that it looks like the repo is a SVN one. It might +be easier to just repull instead. diff -Nru gyp-0.1~svn1729/docs/InputFormatReference.md gyp-0.1+20150913git1f374df9/docs/InputFormatReference.md --- gyp-0.1~svn1729/docs/InputFormatReference.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/InputFormatReference.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,1082 @@ +# Input Format Reference + +[TOC] + +## Primitive Types + +The following primitive types are found within input files: + + * String values, which may be represented by enclosing them in + `'single quotes'` or `"double quotes"`. By convention, single + quotes are used. + * Integer values, which are represented in decimal without any special + decoration. Integers are fairly rare in input files, but have a few + applications in boolean contexts, where the convention is to + represent true values with `1` and false with `0`. + * Lists, which are represented as a sequence of items separated by + commas (`,`) within square brackets (`[` and `]`). A list may + contain any other primitive types, including other lists. + Generally, each item of a list must be of the same type as all other + items in the list, but in some cases (such as within `conditions` + sections), the list structure is more tightly specified. A trailing + comma is permitted. + + This example list contains three string values. + + ``` + [ 'Generate', 'Your', 'Projects', ] + ``` + + * Dictionaries, which map keys to values. All keys are strings. + Values may be of any other primitive type, including other + dictionaries. A dictionary is enclosed within curly braces (`{` and + `}`). Keys precede values, separated by a colon (`:`). Successive + dictionary entries are separated by commas (`,`). A trailing comma + is permitted. It is an error for keys to be duplicated within a + single dictionary as written in an input file, although keys may + replace other keys during [merging](#Merging). + + This example dictionary maps each of three keys to different values. + + ``` + { + 'inputs': ['version.c.in'], + 'outputs': ['version.c'], + 'process_outputs_as_sources': 1, + } + ``` + +## Overall Structure + +A GYP input file is organized as structured data. At the root scope of +each `.gyp` or `.gypi` (include) file is a dictionary. The keys and +values of this dictionary, along with any descendants contained within +the values, provide the data contained within the file. This data is +given meaning by interpreting specific key names and their associated +values in specific ways (see [Settings Keys](#Settings_Keys)). + +### Comments (#) + +Within an input file, a comment is introduced by a pound sign (`#`) not +within a string. Any text following the pound sign, up until the end of +the line, is treated as a comment. + +#### Example + +``` +{ + 'school_supplies': [ + 'Marble composition book', + 'Sharp #2 pencil', + 'Safety scissors', # You still shouldn't run with these + ], +} +``` + +In this example, the # in `'Sharp #2 pencil'` is not taken as +introducing a comment because it occurs within a string, but the text +after `'Safety scissors'` is treated as a comment having no impact on +the data within the file. + +## Merging + +### Merge Basics (=, ?, +) + +Many operations on GYP input files occurs by merging dictionary and list +items together. During merge operations, it is important to recognize +the distinction between source and destination values. Items from the +source value are merged into the destination, which leaves the source +unchanged and the destination modified by the source. A dictionary may +only be merged into another dictionary, and a list may only be merged +into another list. + + * When merging a dictionary, for each key in the source: + * If the key does not exist in the destination dictionary, insert it + and copy the associated value directly. + * If the key does exist: + * If the associated value is a dictionary, perform the dictionary + merging procedure using the source's and destination's value + dictionaries. + * If the associated value is a list, perform the list merging + procedure using the source's and destination's value lists. + * If the associated value is a string or integer, the destination + value is replaced by the source value. + * When merging a list, merge according to the suffix appended to the + key name, if the list is a value within a dictionary. + * If the key ends with an equals sign (`=`), the policy is for the + source list to completely replace the destination list if it + exists. _Mnemonic: `=` for assignment._ + * If the key ends with a question mark (`?`), the policy is for the + source list to be set as the destination list only if the key is + not already present in the destination. _Mnemonic: `?` for + conditional assignment_. + * If the key ends with a plus sign (`+`), the policy is for the + source list contents to be prepended to the destination list. + _Mnemonic: `+` for addition or concatenation._ + * If the list key is undecorated, the policy is for the source list + contents to be appended to the destination list. This is the + default list merge policy. + +#### Example + +Source dictionary: + +``` +{ + 'include_dirs+': [ + 'shared_stuff/public', + ], + 'link_settings': { + 'libraries': [ + '-lshared_stuff', + ], + }, + 'test': 1, +} +``` + +Destination dictionary: + +``` +{ + 'target_name': 'hello', + 'sources': [ + 'kitty.cc', + ], + 'include_dirs': [ + 'headers', + ], + 'link_settings': { + 'libraries': [ + '-lm', + ], + 'library_dirs': [ + '/usr/lib', + ], + }, + 'test': 0, +} +``` + +Merged dictionary: + +``` +{ + 'target_name': 'hello', + 'sources': [ + 'kitty.cc', + ], + 'include_dirs': [ + 'shared_stuff/public', # Merged, list item prepended due to include_dirs+ + 'headers', + ], + 'link_settings': { + 'libraries': [ + '-lm', + '-lshared_stuff', # Merged, list item appended + ], + 'library_dirs': [ + '/usr/lib', + ], + }, + 'test': 1, # Merged, int value replaced +} +``` + +## Pathname Relativization + +In a `.gyp` or `.gypi` file, many string values are treated as pathnames +relative to the file in which they are defined. + +String values associated with the following keys, or contained within +lists associated with the following keys, are treated as pathnames: + + * destination + * files + * include\_dirs + * inputs + * libraries + * outputs + * sources + * mac\_bundle\_resources + * mac\_framework\_dirs + * msvs\_cygwin\_dirs + * msvs\_props + +Additionally, string values associated with keys ending in the following +suffixes, or contained within lists associated with keys ending in the +following suffixes, are treated as pathnames: + + * `_dir` + * `_dirs` + * `_file` + * `_files` + * `_path` + * `_paths` + +However, any string value beginning with any of these characters is +excluded from pathname relativization: + + * `/` for identifying absolute paths. + * `$` for introducing build system variable expansions. + * `-` to support specifying such items as `-llib`, meaning “library + `lib` in the library search path.” + * `<`, `>`, and `!` for GYP expansions. + +When merging such relative pathnames, they are adjusted so that they can +remain valid relative pathnames, despite being relative to a new home. + +#### Example + +Source dictionary from `../build/common.gypi`: + +``` +{ + 'include_dirs': ['include'], # Treated as relative to ../build + 'libraries': ['-lz'], # Not treated as a pathname, begins with a dash + 'defines': ['NDEBUG'], # defines does not contain pathnames +} +``` + +Target dictionary, from `base.gyp`: + +``` +{ + 'sources': ['string_util.cc'], +} +``` + +Merged dictionary: + +``` +{ + 'sources': ['string_util.cc'], + 'include_dirs': ['../build/include'], + 'libraries': ['-lz'], + 'defines': ['NDEBUG'], +} +``` + +Because of pathname relativization, after the merge is complete, all of +the pathnames in the merged dictionary are valid relative to the +directory containing `base.gyp`. + +## List Singletons + +Some list items are treated as singletons, and the list merge process +will enforce special rules when merging them. At present, any string +item in a list that does not begin with a dash (`-`) is treated as a +singleton, although **this is subject to change.** When appending or +prepending a singleton to a list, if the item is already in the list, +only the earlier instance is retained in the merged list. + +#### Example + +Source dictionary: + +``` +{ + 'defines': [ + 'EXPERIMENT=1', + 'NDEBUG', + ], +} +``` + +Destination dictionary: + +``` +{ + 'defines': [ + 'NDEBUG', + 'USE_THREADS', + ], +} +``` + +Merged dictionary: + +``` +{ + 'defines': [ + 'NDEBUG', + 'USE_THREADS', + 'EXPERIMENT=1', # Note that NDEBUG is not appended after this. + ], +} +``` + +## Including Other Files + +If the `-I` (`--include`) argument was used to invoke GYP, any files +specified will be implicitly merged into the root dictionary of all +`.gyp` files. + +An [includes](#includes) section may be placed anywhere within a +`.gyp` or `.gypi` (include) file. `includes` sections contain lists of +other files to include. They are processed sequentially and merged into +the enclosing dictionary at the point that the `includes` section was +found. `includes` sections at the root of a `.gyp` file dictionary are +merged after any `-I` includes from the command line. + +[includes](#includes) sections are processed immediately after a file is +loaded, even before [variable and conditional +processing](#Variables_and_Conditionals), so it is not possible to +include a file based on a [variable reference](#Variable_Expansions). +While it would be useful to be able to include files based on variable +expansions, it is most likely more useful to allow included files access +to variables set by the files that included them. + +An [includes](#includes) section may, however, be placed within a +[conditional](#Conditionals) section. The included file itself will +be loaded unconditionally, but its dictionary will be discarded if the +associated condition is not true. + +## Variables and Conditionals + +### Variables + +There are three main types of variables within GYP. + + * Predefined variables. By convention, these are named with + `CAPITAL_LETTERS`. Predefined variables are set automatically by + GYP. They may be overridden, but it is not advisable to do so. See + [Predefined Variables](#Predefined_Variables) for a list of + variables that GYP provides. + * User-defined variables. Within any dictionary, a key named + `variables` can be provided, containing a mapping between variable + names (keys) and their contents (values), which may be strings, + integers, or lists of strings. By convention, user-defined + variables are named with `lowercase_letters`. + * Automatic variables. Within any dictionary, any key with a string + value has a corresponding automatic variable whose name is the same + as the key name with an underscore (`_`) prefixed. For example, if + your dictionary contains `type: 'static_library'`, an automatic + variable named `_type` will be provided, and its value will be a + string, `'static_library'`. + +Variables are inherited from enclosing scopes. + +### Providing Default Values for Variables (%) + +Within a `variables` section, keys named with percent sign (`%`) +suffixes mean that the variable should be set only if it is undefined at +the time it is processed. This can be used to provide defaults for +variables that would otherwise be undefined, so that they may reliably +be used in [variable expansion or conditional +processing](#Variables_and_Conditionals). + +### Predefined Variables + +Each GYP generator module provides defaults for the following variables: + + * `OS`: The name of the operating system that the generator produces + output for. Common values for values for `OS` are: + + * `'linux'` + * `'mac'` + * `'win'` + + But other values may be encountered and this list should not be + considered exhaustive. The `gypd` (debug) generator module does not + provide a predefined value for `OS`. When invoking GYP with the + `gypd` module, if a value for `OS` is needed, it must be provided on + the command line, such as `gyp -f gypd -DOS=mac`. + + GYP generators also provide defaults for these variables. They may + be expressed in terms of variables used by the build system that + they generate for, often in `$(VARIABLE)` format. For example, the + GYP `PRODUCT_DIR` variable maps to the Xcode `BUILT_PRODUCTS_DIR` + variable, so `PRODUCT_DIR` is defined by the Xcode generator as + `$(BUILT_PRODUCTS_DIR)`. + * `EXECUTABLE_PREFIX`: A prefix, if any, applied to executable names. + Usually this will be an empty string. + * `EXECUTABLE_SUFFIX`: A suffix, if any, applied to executable names. + On Windows, this will be `.exe`, elsewhere, it will usually be an + empty string. + * `INTERMEDIATE_DIR`: A directory that can be used to place + intermediate build results in. `INTERMEDIATE_DIR` is only + guaranteed to be accessible within a single target (See targets). + This variable is most useful within the context of rules and actions + (See rules, See actions). Compare with `SHARED_INTERMEDIATE_DIR`. + * `PRODUCT_DIR`: The directory in which the primary output of each + target, such as executables and libraries, is placed. + * `RULE_INPUT_ROOT`: The base name for the input file (e.g. "`foo`"). + See Rules. + * `RULE_INPUT_EXT`: The file extension for the input file (e.g. + "`.cc`"). See Rules. + * `RULE_INPUT_NAME`: Full name of the input file (e.g. "`foo.cc`"). + See Rules. + * `RULE_INPUT_PATH`: Full path to the input file (e.g. + "`/bar/foo.cc`"). See Rules. + * `SHARED_INTERMEDIATE_DIR`: A directory that can be used to place + intermediate build results in, and have them be accessible to other + targets. Unlike `INTERMEDIATE_DIR`, each target in a project, + possibly spanning multiple `.gyp` files, shares the same + `SHARED_INTERMEDIATE_DIR`. + +The following additional predefined variables may be available under +certain circumstances: + + * `DEPTH`. When GYP is invoked with a `--depth` argument, when + processing any `.gyp` file, `DEPTH` will be a relative path from the + `.gyp` file to the directory specified by the `--depth` argument. + +### User-Defined Variables + +A user-defined variable may be defined in terms of other variables, but +not other variables that have definitions provided in the same scope. + +### Variable Expansions (<, >, <@, >@) + +GYP provides two forms of variable expansions, “early” or “pre” +expansions, and “late,” “post,” or “target” expansions. They have +similar syntax, differing only in the character used to introduce them. + + * Early expansions are introduced by a less-than (`<`) character. + _Mnemonic: the arrow points to the left, earlier on a timeline._ + * Late expansions are introduced by a less-than (`>`) character. + _Mnemonic: the arrow points to the right, later on a timeline._ + +The difference the two phases of expansion is described in [Early and +Late Phases](#Early_and_Late_Phases). + +These characters were chosen based upon the requirement that they not +conflict with the variable format used natively by build systems. While +the dollar sign (`$`) is the most natural fit for variable expansions, +its use was ruled out because most build systems already use that +character for their own variable expansions. Using different characters +means that no escaping mechanism was needed to differentiate between GYP +variables and build system variables, and writing build system variables +into GYP files is not cumbersome. + +Variables may contain lists or strings, and variable expansions may +occur in list or string context. There are variant forms of variable +expansions that may be used to determine how each type of variable is to +be expanded in each context. + + * When a variable is referenced by `<(VAR)` or `>(VAR)`: + * If `VAR` is a string, the variable reference within the string is + replaced by variable's string value. + * If `VAR` is a list, the variable reference within the string is + replaced by a string containing the concatenation of all of the + variable’s list items. Generally, the items are joined with + spaces between each, but the specific behavior is + generator-specific. The precise encoding used by any generator + should be one that would allow each list item to be treated as a + separate argument when used as program arguments on the system + that the generator produces output for. + * When a variable is referenced by `<@(VAR)` or `>@(VAR)`: + * The expansion must occur in list context. + * The list item must be `'<@(VAR)'` or `'>@(VAR)'` exactly. + * If `VAR` is a list, each of its elements are inserted into the + list in which expansion is taking place, replacing the list item + containing the variable reference. + * If `VAR` is a string, the string is converted to a list which is + inserted into the list in which expansion is taking place as + above. The conversion into a list is generator-specific, but + generally, spaces in the string are taken as separators between + list items. The specific method of converting the string to a + list should be the inverse of the encoding method used to expand + list variables in string context, above. + +GYP treats references to undefined variables as errors. + +### Command Expansions (` form + of [variable expansions](#Variable_Expansions), + and on the `!` form of [command + expansions](#Command_Expansions_(!,_!@)). + +These two phases are provided because there are some circumstances in +which each is desirable. + +The “early” phase is appropriate for most expansions and evaluations. +“Early” expansions and evaluations may be performed anywhere within any +`.gyp` or `.gypi` file. + +The “late” phase is appropriate when expansion or evaluation must be +deferred until a specific section has been merged into target context. +“Late” expansions and evaluations only occur within `targets` sections +and their descendants. The typical use case for a late-phase expansion +is to provide, in some globally-included `.gypi` file, distinct +behaviors depending on the specifics of a target. + +#### Example + +Given this input: + +``` +{ + 'target_defaults': { + 'target_conditions': [ + ['_type=="shared_library"', {'cflags': ['-fPIC']}], + ], + }, + 'targets': [ + { + 'target_name': 'sharing_is_caring', + 'type': 'shared_library', + }, + { + 'target_name': 'static_in_the_attic', + 'type': 'static_library', + }, + ] +} +``` + +The conditional needs to be evaluated only in target context; it is +nonsense outside of target context because no `_type` variable is +defined. [target\_conditions](#target_conditions) allows evaluation +to be deferred until after the [targets](#targets) sections are +merged into their copies of [target\_defaults](#target_defaults). +The resulting targets, after “late” phase processing: + +``` +{ + 'targets': [ + { + 'target_name': 'sharing_is_caring', + 'type': 'shared_library', + 'cflags': ['-fPIC'], + }, + { + 'target_name': 'static_in_the_attic', + 'type': 'static_library', + }, + ] +} +``` + +### Expansion and Evaluation Performed Simultaneously + +During any expansion and evaluation phase, both expansion and evaluation +are performed simultaneously. The process for handling variable +expansions and conditional evaluation within a dictionary is: + + * Load [automatic variables](#Variables) (those with leading + underscores). + * If a [variables](#variables) section is present, recurse into its + dictionary. This allows [conditionals](#Conditionals) to be + present within the `variables` dictionary. + * Load [Variables user-defined variables](#User-Defined) from the + [variables](#variables) section. + * For each string value in the dictionary, perform [variable + expansion](#Variable_Expansions) and, if operating + during the “late” phase, [command + expansions](#Command_Expansions). + * Reload [automatic variables](#Variables) and [Variables + user-defined variables](#User-Defined) because the variable + expansion step may have resulted in changes to the automatic + variables. + * If a [conditions](#conditions) or + [target\_conditions](#target_conditions) section (depending on + phase) is present, recurse into its dictionary. This is done after + variable expansion so that conditionals may take advantage of + expanded automatic variables. + * Evaluate [conditionals](#Conditionals). + * Reload [automatic variables](#Variables) and [Variables + user-defined variables](#User-Defined) because the conditional + evaluation step may have resulted in changes to the automatic + variables. + * Recurse into child dictionaries or lists that have not yet been + processed. + +One quirk of this ordering is that you cannot expect a +[variables](#variables) section within a dictionary’s +[conditional](#Conditionals) to be effective in the dictionary +itself, but the added variables will be effective in any child +dictionaries or lists. It is thought to be far more worthwhile to +provide resolved [automatic variables](#Variables) to +[conditional](#Conditionals) sections, though. As a workaround, to +conditionalize variable values, place a [conditions](#conditions) or +[target\_conditions](#target_conditions) section within the +[variables](#variables) section. + +## Dependencies and Dependents + +In GYP, “dependents” are targets that rely on other targets, called +“dependencies.” Dependents declare their reliance with a special +section within their target dictionary, +[dependencies](#dependencies). + +### Dependent Settings + +It is useful for targets to “advertise” settings to their dependents. +For example, a target might require that all of its dependents add +certain directories to their include paths, link against special +libraries, or define certain preprocessor macros. GYP allows these +cases to be handled gracefully with “dependent settings” sections. +There are three types of such sections: + + * [direct\_dependent\_settings](#direct_dependent_settings), which + advertises settings to a target's direct dependents only. + * [all\_dependent\_settings](#all_dependnet_settings), which + advertises settings to all of a target's dependents, both direct and + indirect. + * [link\_settings](#link_settings), which contains settings that + should be applied when a target’s object files are used as linker + input. + +Furthermore, in some cases, a target needs to pass its dependencies’ +settings on to its own dependents. This might happen when a target’s +own public header files include header files provided by its dependency. +[export\_dependent\_settings](#export_dependent_settings) allows a +target to declare dependencies for which +[direct\_dependent\_settings](#direct_dependent_settings) should be +passed through to its own dependents. + +Dependent settings processing merges a copy of the relevant dependent +settings dictionary from a dependency into its relevant dependent +targets. + +In most instances, +[direct\_dependent\_settings](#direct_dependent_settings) will be +used. There are very few cases where +[all\_dependent\_settings](#all_dependent_settings) is actually +correct; in most of the cases where it is tempting to use, it would be +preferable to declare +[export\_dependent\_settings](#export_dependent_settings). Most +[libraries](#libraries) and [library\_dirs](#library_dirs) +sections should be placed within [link\_settings](#link_settings) +sections. + +#### Example + +Given: + +``` +{ + 'targets': [ + { + 'target_name': 'cruncher', + 'type': 'static_library', + 'sources': ['cruncher.cc'], + 'direct_dependent_settings': { + 'include_dirs': ['.'], # dependents need to find cruncher.h. + }, + 'link_settings': { + 'libraries': ['-lm'], # cruncher.cc does math. + }, + }, + { + 'target_name': 'cruncher_test', + 'type': 'executable', + 'dependencies': ['cruncher'], + 'sources': ['cruncher_test.cc'], + }, + ], +} +``` + +After dependent settings processing, the dictionary for `cruncher_test` +will be: + +``` +{ + 'target_name': 'cruncher_test', + 'type': 'executable', + 'dependencies': ['cruncher'], # implies linking against cruncher + 'sources': ['cruncher_test.cc'], + 'include_dirs': ['.'] + 'libraries': ['-lm'], +}, +``` + +If `cruncher` was declared as a `shared_library` instead of a +`static_library`, the `cruncher_test` target would not contain `-lm`, +but instead, `cruncher` itself would link against `-lm`. + +## Linking Dependencies + +The precise meaning of a dependency relationship varies with the +[types](#type) of the [targets](#targets) at either end of the +relationship. In GYP, a dependency relationship can indicate two things +about how targets relate to each other: + + * Whether the dependent target needs to link against the dependency. + * Whether the dependency target needs to be built prior to the + dependent. If the former case is true, this case must be true as + well. + +The analysis of the first item is complicated by the differences between +static and shared libraries. + + * Static libraries are simply collections of object files (`.o` or + `.obj`) that are used as inputs to a linker (`ld` or `link.exe`). + Static libraries don't link against other libraries, they’re + collected together and used when eventually linking a shared library + or executable. + * Shared libraries are linker output and must undergo symbol + resolution. They must link against other libraries (static or + shared) in order to facilitate symbol resolution. They may be used + as libraries in subsequent link steps. + * Executables are also linker output, and also undergo symbol + resolution. Like shared libraries, they must link against static + and shared libraries to facilitate symbol resolution. They may not + be reused as linker inputs in subsequent link steps. + +Accordingly, GYP performs an operation referred to as “static library +dependency adjustment,” in which it makes each linker output target +(shared libraries and executables) link against the static libraries it +depends on, either directly or indirectly. Because the linkable targets +link against these static libraries, they are also made direct +dependents of the static libraries. + +As part of this process, GYP is also able to remove the direct +dependency relationships between two static library targets, as a +dependent static library does not actually need to link against a +dependency static library. This removal facilitates speedier builds +under some build systems, as they are now free to build the two targets +in parallel. The removal of this dependency is incorrect in some cases, +such as when the dependency target contains [rules](#rules) or +[actions](#actions) that generate header files required by the +dependent target. In such cases, the dependency target, the one +providing the side-effect files, must declare itself as a +[hard\_dependency](#hard_dependency). This setting instructs GYP to +not remove the dependency link between two static library targets in its +generated output. + +## Loading Files to Resolve Dependencies + +When GYP runs, it loads all `.gyp` files needed to resolve dependencies +found in [dependencies](#dependencies) sections. These files are not +merged into the files that reference them, but they may contain special +sections that are merged into dependent target dictionaries. + +## Build Configurations + +Explain this. + +## List Filters + +GYP allows list items to be filtered by “exclusions” and “patterns.” +Any list containing string values in a dictionary may have this +filtering applied. For the purposes of this section, a list modified by +exclusions or patterns is referred to as a “base list”, in contrast to +the “exclusion list” and “pattern list” that operates on it. + + * For a base list identified by key name `key`, the `key!` list + provides exclusions. + * For a base list identified by key name `key`, the `key/` list + provides regular expression pattern-based filtering. + +Both `key!` and `key/` may be present. The `key!` exclusion list will +be processed first, followed by the `key/` pattern list. + +Exclusion lists are most powerful when used in conjunction with +[conditionals](#Conditionals). + +## Exclusion Lists (!) + +An exclusion list provides a way to remove items from the related list +based on exact matching. Any item found in an exclusion list will be +removed from the corresponding base list. + +#### Example + +This example excludes files from the `sources` based on the setting of +the `OS` variable. + +``` +{ + 'sources:' [ + 'mac_util.mm', + 'win_util.cc', + ], + 'conditions': [ + ['OS=="mac"', {'sources!': ['win_util.cc']}], + ['OS=="win"', {'sources!': ['mac_util.cc']}], + ], +} +``` + +## Pattern Lists (/) + +Pattern lists are similar to, but more powerful than, [exclusion +lists](#Exclusion_Lists_(!)). Each item in a pattern list is itself +a two-element list. The first item is a string, either `'include'` or +`'exclude'`, specifying the action to take. The second item is a string +specifying a regular expression. Any item in the base list matching the +regular expression pattern will either be included or excluded, based on +the action specified. + +Items in a pattern list are processed in sequence, and an excluded item +that is later included will not be removed from the list (unless it is +subsequently excluded again.) + +Pattern lists are processed after [exclusion +lists](#Exclusion_Lists_(!)), so it is possible for a pattern list to +re-include items previously excluded by an exclusion list. + +Nothing is actually removed from a base list until all items in an +[exclusion list](#Exclusion_Lists_(!)) and pattern list have been +evaluated. This allows items to retain their correct position relative +to one another even after being excluded and subsequently included. + +#### Example + +In this example, a uniform naming scheme is adopted for +platform-specific files. + +``` +{ + 'sources': [ + 'io_posix.cc', + 'io_win.cc', + 'launcher_mac.cc', + 'main.cc', + 'platform_util_linux.cc', + 'platform_util_mac.mm', + ], + 'sources/': [ + ['exclude', '_win\\.cc$'], + ], + 'conditions': [ + ['OS!="linux"', {'sources/': [['exclude', '_linux\\.cc$']]}], + ['OS!="mac"', {'sources/': [['exclude', '_mac\\.cc|mm?$']]}], + ['OS=="win"', {'sources/': [ + ['include', '_win\\.cc$'], + ['exclude', '_posix\\.cc$'], + ]}], + ], +} +``` + +After the pattern list is applied, `sources` will have the following +values, depending on the setting of `OS`: + + * When `OS` is `linux`: `['io_posix.cc', 'main.cc', + 'platform_util_linux.cc']` + * When `OS` is `mac`: `['io_posix.cc', 'launcher_mac.cc', 'main.cc', + 'platform_util_mac.mm']` + * When `OS` is `win`: `['io_win.cc', 'main.cc', + 'platform_util_win.cc']` + +Note that when `OS` is `win`, the `include` for `_win.cc` files is +processed after the `exclude` matching the same pattern, because the +`sources/` list participates in [merging](#Merging) during +[conditional evaluation](#Conditonals) just like any other list +would. This guarantees that the `_win.cc` files, previously +unconditionally excluded, will be re-included when `OS` is `win`. + +## Locating Excluded Items + +In some cases, a GYP generator needs to access to items that were +excluded by an [exclusion list](#Exclusion_Lists_(!)) or [pattern +list](#Pattern_Lists_(/)). When GYP excludes items during processing +of either of these list types, it places the results in an `_excluded` +list. In the example above, when `OS` is `mac`, `sources_excluded` +would be set to `['io_win.cc', 'platform_util_linux.cc']`. Some GYP +generators use this feature to display excluded files in the project +files they generate for the convenience of users, who may wish to refer +to other implementations. + +## Processing Order + +GYP uses a defined and predictable order to execute the various steps +performed between loading files and generating output. + + * Load files. + * Load `.gyp` files. Merge any [command-line + includes](#Including_Other_Files) into each `.gyp` file’s root + dictionary. As [includes](#Including_Other_Files) are found, + load them as well and [merge](#Merging) them into the scope in + which the [includes](#includes) section was found. + * Perform [“early” or “pre”](#Early_and_Late_Phases) [variable + expansion and conditional + evaluation](#Variables_and_Conditionals). + * [Merge](#Merging) each [target’s](#targets) dictionary into + the `.gyp` file’s root [target\_defaults](#target_defaults) + dictionary. + * Scan each [target](#targets) for + [dependencies](#dependencies), and repeat the above steps for + any newly-referenced `.gyp` files not yet loaded. + * Scan each [target](#targets) for wildcard + [dependencies](#dependencies), expanding the wildcards. + * Process [dependent settings](#Dependent_Settings). These + sections are processed, in order: + * [all\_dependent\_settings](#all_dependent_settings) + * [direct\_dependent\_settings](#direct_dependent_settings) + * [link\_dependent\_settings](#link_dependent_settings) + * Perform [static library dependency + adjustment](#Linking_Dependencies). + * Perform [“late,” “post,” or “target”](#Early_and_Late_Phases) + [variable expansion and conditional + evaluation](#Variables_and_Conditionals) on [target](#targets) + dictionaries. + * Merge [target](#targets) settings into + [configurations](#configurations) as appropriate. + * Process [exclusion and pattern + lists](#List_Exclusions_and_Patterns). + +## Settings Keys + +### Settings that may appear anywhere + +#### conditions + +_List of `condition` items_ + +A `conditions` section introduces a subdictionary that is only merged +into the enclosing scope based on the evaluation of a conditional +expression. Each `condition` within a `conditions` list is itself a +list of at least two items: + + 1. A string containing the conditional expression itself. Conditional + expressions may take the following forms: + * For string values, `var=="value"` and `var!="value"` to test + equality and inequality. For example, `'OS=="linux"'` is true + when the `OS` variable is set to `"linux"`. + * For integer values, `var==value`, `var!=value`, `var=value`, and `var>value`, to test equality and + several common forms of inequality. For example, + `'chromium_code==0'` is true when the `chromium_code` variable is + set to `0`. + * It is an error for a conditional expression to reference any + undefined variable. + 1. A dictionary containing the subdictionary to be merged into the + enclosing scope if the conditional expression evaluates to true. + +These two items can be followed by any number of similar two items that +will be evaluated if the previous conditional expression does not +evaluate to true. + +An additional optional dictionary can be appended to this sequence of +two items. This optional dictionary will be merged into the enclosing +scope if none of the conditional expressions evaluate to true. + +Within a `conditions` section, each item is processed sequentially, so +it is possible to predict the order in which operations will occur. + +There is no restriction on nesting `conditions` sections. + +`conditions` sections are very similar to `target_conditions` sections. +See target\_conditions. + +#### Example + +``` +{ + 'sources': [ + 'common.cc', + ], + 'conditions': [ + ['OS=="mac"', {'sources': ['mac_util.mm']}], + ['OS=="win"', {'sources': ['win_main.cc']}, {'sources': ['posix_main.cc']}], + ['OS=="mac"', {'sources': ['mac_impl.mm']}, + 'OS=="win"', {'sources': ['win_impl.cc']}, + {'sources': ['default_impl.cc']} + ], + ], +} +``` + +Given this input, the `sources` list will take on different values based +on the `OS` variable. + + * If `OS` is `"mac"`, `sources` will contain `['common.cc', + 'mac_util.mm', 'posix_main.cc', 'mac_impl.mm']`. + * If `OS` is `"win"`, `sources` will contain `['common.cc', + 'win_main.cc', 'win_impl.cc']`. + * If `OS` is any other value such as `"linux"`, `sources` will contain + `['common.cc', 'posix_main.cc', 'default_impl.cc']`. diff -Nru gyp-0.1~svn1729/docs/LanguageSpecification.md gyp-0.1+20150913git1f374df9/docs/LanguageSpecification.md --- gyp-0.1~svn1729/docs/LanguageSpecification.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/LanguageSpecification.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,475 @@ +# GYP (Generate Your Projects) Language Specification + +Status: Draft (as of 2009-01-30) + +Mark Mentovai _et al._ + +Modified: 2009-02-10 + +[TOC] + +## Objective + +Create a tool for the Chromium project that generates native Visual Studio, +Xcode and SCons and/or make build files from a platform-independent input +format. Make the input format as reasonably general as possible without +spending extra time trying to "get everything right," except where not doing so +would likely lead Chromium to an eventual dead end. When in doubt, do what +Chromium needs and don't worry about generalizing the solution. + +## Background + +Numerous other projects, both inside and outside Google, have tried to +create a simple, universal cross-platform build representation that +still allows sufficient per-platform flexibility to accommodate +irreconcilable differences. The fact that no obvious working candidate +exists that meets Chromium's requirements indicates this is probably a +tougher problem than it appears at first glance. We aim to succeed by +creating a tool that is highly specific to Chromium's specific use case, +not to the general case of design a completely platform-independent tool +for expressing any possible build. + +The Mac has the most sophisticated model for application development +through an IDE. Consequently, we will use the Xcode model as the +starting point (the input file format must handle Chromium's use of +Xcode seamlessly) and adapt the design as necessary for the other +platforms. + +## Overview + +The overall design has the following characteristics: + + * Input configurations are specified in files with the suffix `.gyp`. + * Each `.gyp` file specifies how to build the targets for the + "component" defined by that file. + * Each `.gyp` file generates one or more output files appropriate to + the platform: + * On Mac, a `.gyp` file generates one Xcode .xcodeproj bundle with + information about how its targets are built. + * On Windows, a `.gyp` file generates one Visual Studio .sln file, + and one Visual Studio .vcproj file per target. + * On Linux, a `.gyp` file generates one SCons file and/or one + Makefile per target + * The `.gyp` file syntax is a Python data structure. + * Use of arbitrary Python in `.gyp` files is forbidden. + * Use of eval() with restricted globals and locals on `.gyp` file + contents restricts the input to an evaluated expression, not + arbitrary Python statements. + * All input is expected to comply with JSON, with two exceptions: + the # character (not inside strings) begins a comment that lasts + until the end of the line, and trailing commas are permitted at + the end of list and dict contents. + * Input data is a dictionary of keywords and values. + * "Invalid" keywords on any given data structure are not illegal, + they're just ignored. + * TODO: providing warnings on use of illegal keywords would help + users catch typos. Figure out something nice to do with this. + +## Detailed Design + +Some up-front design principles/thoughts/TODOs: + + * Re-use keywords consistently. + * Keywords that allow configuration of a platform-specific concept get + prefixed appropriately: + * Examples: `msvs_disabled_warnings`, `xcode_framework_dirs` + * The input syntax is declarative and data-driven. + * This gets enforced by using Python `eval()` (which only evaluates + an expression) instead of `exec` (which executes arbitrary python) + * Semantic meanings of specific keyword values get deferred until all + are read and the configuration is being evaluated to spit out the + appropriate file(s) + * Source file lists: + * Are flat lists. Any imposed ordering within the `.gyp` file (e.g. + alphabetically) is purely by convention and for developer + convenience. When source files are linked or archived together, + it is expected that this will occur in the order that files are + listed in the `.gyp` file. + * Source file lists contain no mechanism for by-hand folder + configuration (`Filter` tags in Visual Studio, `Groups` in Xcode) + * A folder hierarchy is created automatically that mirrors the file + system + +### Example + +``` +{ + 'target_defaults': { + 'defines': [ + 'U_STATIC_IMPLEMENTATION', + ['LOGFILE', 'foo.log',], + ], + 'include_dirs': [ + '..', + ], + }, + 'targets': [ + { + 'target_name': 'foo', + 'type': 'static_library', + 'sources': [ + 'foo/src/foo.cc', + 'foo/src/foo_main.cc', + ], + 'include_dirs': [ + 'foo', + 'foo/include', + ], + 'conditions': [ + [ 'OS==mac', { 'sources': [ 'platform_test_mac.mm' ] } ] + ], + 'direct_dependent_settings': { + 'defines': [ + 'UNIT_TEST', + ], + 'include_dirs': [ + 'foo', + 'foo/include', + ], + }, + }, + ], +} +``` + +### Structural Elements + +### Top-level Dictionary + +This is the single dictionary in the `.gyp` file that defines the +targets and how they're to be built. + +The following keywords are meaningful within the top-level dictionary +definition: + +|:------------- |:------------------| +| `conditions` | A conditional section that may contain other items that can be present in a top-level dictionary, on a conditional basis. See the "Conditionals" section below. | +| `includes` | A list of `.gypi` files to be included in the top-level dictionary. | +| `target_defaults` | A dictionary of default settings to be inherited by all targets in the top-level dictionary. See the "Settings keywords" section below. | +| `targets` | A list of target specifications. See the "targets" below. | +| `variables` | A dictionary containing variable definitions. Each key in this dictionary is the name of a variable, and each value must be a string value that the variable is to be set to. | + +### targets + +A list of dictionaries defining targets to be built by the files +generated from this `.gyp` file. + +Targets may contain `includes`, `conditions`, and `variables` sections +as permitted in the root dictionary. The following additional keywords +have structural meaning for target definitions: + +|:---------- |:------------------------------------------| +| `actions` | A list of special custom actions to perform on a specific input file, or files, to produce output files. See the "Actions" section below. | +| `all_dependent_settings` | A dictionary of settings to be applied to all dependents of the target, transitively. This includes direct dependents and the entire set of their dependents, and so on. This section may contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare `direct_dependent_settings` and `link_settings`. | +| `configurations` | A list of dictionaries defining build configurations for the target. See the "Configurations" section below. | +| `copies` | A list of copy actions to perform. See the "Copies" section below. | +| `defines` | A list of preprocesor definitions to be passed on the command line to the C/C++ compiler (via `-D` or `/D` options). | +| `dependencies` | A list of targets on which this target depends. Targets in other `.gyp` files are specified as `../path/to/other.gyp:target_we_want`. | +| `direct_dependent_settings` | A dictionary of settings to be applied to other targets that depend on this target. These settings will only be applied to direct dependents. This section may contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare with `all_dependent_settings` and `link_settings`. | +| `include_dirs` | A list of include directories to be passed on the command line to the C/C++ compiler (via `-I` or `/I` options). | +| `libraries` | A list of list of libraries (and/or frameworks) on which this target depends. | +| `link_settings` | A dictionary of settings to be applied to targets in which this target's contents are linked. `executable` and `shared_library` targets are linkable, so if they depend on a non-linkable target such as a `static_library`, they will adopt its `link_settings`. This section can contain anything found within a `target` dictionary, except `configurations`, `target_name`, and `type` sections. Compare `all_dependent_settings` and `direct_dependent_settings`. | +| `rules` | A special custom action to perform on a list of input files, to produce output files. See the "Rules" section below. | +| `sources` | A list of source files that are used to build this target or which should otherwise show up in the IDE for this target. In practice, we expect this list to be a union of all files necessary to build the target on all platforms, as well as other related files that aren't actually used for building, like README files. | +| `target_conditions` | Like `conditions`, but evaluation is delayed until the settings have been merged into an actual target. `target_conditions` may be used to place conditionals into a `target_defaults` section but have them still depend on specific target settings. | +| `target_name` | The name of a target being defined. | +| `type` | The type of target being defined. This field currently supports `executable`, `static_library`, `shared_library`, and `none`. The `none` target type is useful when producing output which is not linked. For example, converting raw translation files into resources or documentation into platform specific help files. | +| `msvs_props` | A list of Visual Studio property sheets (`.vsprops` files) to be used to build the target. | +| `xcode_config_file` | An Xcode configuration (`.xcconfig` file) to be used to build the target. | +| `xcode_framework_dirs` | A list of framework directories be used to build the target. | + +You can affect the way that lists/dictionaries are merged together (for +example the way a list in target\_defaults interacts with the same named +list in the target itself) with a couple of special characters, which +are covered in [Merge +Basics](InputFormatReference#Merge_Basics_(=,_?,_+).md) and [List +Filters](InputFormatReference#List_Filters.md) on the +InputFormatReference page. + +### configurations + +`configurations` sections may be found within `targets` or +`target_defaults` sections. The `configurations` section is a list of +dictionaries specifying different build configurations. Because +configurations are implemented as lists, it is not currently possible to +override aspects of configurations that are imported into a target from +a `target_defaults` section. + +NOTE: It is extremely important that each target within a project define +the same set of configurations. This continues to apply even when a +project spans across multiple `.gyp` files. + +A configuration dictionary may contain anything that can be found within +a target dictionary, except for `actions`, `all_dependent_settings`, +`configurations`, `dependencies`, `direct_dependent_settings`, +`libraries`, `link_settings`, `sources`, `target_name`, and `type`. + +Configuration dictionaries may also contain these elements: + +|:---------------------|:----------------------------------------------------| +| `configuration_name` | Required attribute. The name of the configuration. | + +### Conditionals + +Conditionals may appear within any dictionary in a `.gyp` file. There +are two tpes of conditionals, which differ only in the timing of their +processing. `conditons` sections are processed shortly after loading +`.gyp` files, and `target_conditons` sections are processed after all +dependencies have been computed. + +A conditional section is introduced with a `conditions` or +`target_conditions` dictionary keyword, and is composed of a list. Each +list contains two or three elements. The first two elements, which are +always required, are the conditional expression to evaluate and a +dictionary containing settings to merge into the dictionary containing +the `conditions` or `target_conditions` section if the expression +evaluates to true. The third, optional, list element is a dictionary to +merge if the expression evaluates to false. + +The `eval()` of the expression string takes place in the context of +global and/or local dictionaries that constructed from the `.gyp` input +data, and overrides the `__builtin__` dictionary, to prevent the +execution of arbitrary Python code. + +### Actions + +An `actions` section provides a list of custom build actions to perform +on inputs, producing outputs. The `actions` section is organized as a +list. Each item in the list is a dictionary having the following form: + +|:--------------|:-------|:-----------------------------| +| `action_name` | string | The name of the action. Depending on how actions are implemented in the various generators, some may desire or require this property to be set to a unique name; others may ignore this property entirely. | +| `inputs` | list | A list of pathnames treated as inputs to the custom action. | +| `outputs` | list | A list of pathnames that the custom action produces. | +| `action` | list | A command line invocation used to produce `outputs` from `inputs`. For maximum cross-platform compatibility, invocations that require a Python interpreter should be specified with a first element `"python"`. This will enable generators for environments with specialized Python installations to be able to perform the action in an appropriate Python environment. | +| `message` | string | A message to be displayed to the user by the build system when the action is run. | + +Build environments will compare `inputs` and `outputs`. If any `output` +is missing or is outdated relative to any `input`, the custom action +will be invoked. If all `outputs` are present and newer than all +`inputs`, the `outputs` are considered up-to-date and the action need +not be invoked. + +Actions are implemented in Xcode as shell script build phases performed +prior to the compilation phase. In the Visual Studio generator, actions +appear files with a `FileConfiguration` containing a custom +`VCCustomBuildTool` specifying the remainder of the inputs, the outputs, +and the action. + +Combined with variable expansions, actions can be quite powerful. Here +is an example action that leverages variable expansions to minimize +duplication of pathnames: + +``` + 'sources': [ + # libraries.cc is generated by the js2c action below. + '<(INTERMEDIATE_DIR)/libraries.cc', + ], + 'actions': [ + { + 'variables': { + 'core_library_files': [ + 'src/runtime.js', + 'src/v8natives.js', + 'src/macros.py', + ], + }, + 'action_name': 'js2c', + 'inputs': [ + 'tools/js2c.py', + '<@(core_library_files)', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/libraries.cc', + '<(INTERMEDIATE_DIR)/libraries-empty.cc', + ], + 'action': ['python', 'tools/js2c.py', '<@(_outputs)', 'CORE', '<@(core_library_files)'], + }, + ], +``` + +### Rules + +A `rules` section provides custom build action to perform on inputs, producing +outputs. The `rules` section is organized as a list. Each item in the list is +a dictionary having the following form: + +|:------------|:-------|:-----------------------------------------| +| `rule_name` | string | The name of the rule. Depending on how Rules are implemented in the various generators, some may desire or require this property to be set to a unique name; others may ignore this property entirely. | +| `extension` | string | All source files of the current target with the given extension will be treated successively as inputs to the rule. | +| `inputs` | list | Additional dependencies of the rule. | +| `outputs` | list | A list of pathnames that the rule produces. Has access to `RULE_INPUT_` variables (see below). | +| `action` | list | A command line invocation used to produce `outputs` from `inputs`. For maximum cross-platform compatibility, invocations that require a Python interpreter should be specified with a first element `"python"`. This will enable generators for environments with specialized Python installations to be able to perform the action in an appropriate Python environment. Has access to `RULE_INPUT_` variables (see below). | +| `message` | string | A message to be displayed to the user by the build system when the action is run. Has access to `RULE_INPUT_` variables (see below). | + +There are several variables available to `outputs`, `action`, and `message`. + +|:---------------------|:------------------------------------| +| `RULE_INPUT_PATH` | The full path to the current input. | +| `RULE_INPUT_DIRNAME` | The directory of the current input. | +| `RULE_INPUT_NAME` | The file name of the current input. | +| `RULE_INPUT_ROOT` | The file name of the current input without extension. | +| `RULE_INPUT_EXT` | The file name extension of the current input. | + +Rules can be thought of as Action generators. For each source selected +by `extension` an special action is created. This action starts out with +the same `inputs`, `outputs`, `action`, and `message` as the rule. The +source is added to the action's `inputs`. The `outputs`, `action`, and +`message` are then handled the same but with the additional variables. +If the `_output` variable is used in the `action` or `message` the +`RULE_INPUT_` variables in `output` will be expanded for the current +source. + +### Copies + +A `copies` section provides a simple means of copying files. The +`copies` section is organized as a list. Each item in the list is a +dictionary having the following form: + +|:--------------|:-------|:------------------------------| +| `destination` | string | The directory into which the `files` will be copied. | +| `files` | list | A list of files to be copied. | + +The copies will be created in `destination` and have the same file name +as the file they are copied from. Even if the `files` are from multiple +directories they will all be copied into the `destination` directory. +Each `destination` file has an implicit build dependency on the file it +is copied from. + +### Generated Xcode .pbxproj Files + +We derive the following things in a `project.pbxproj` plist file within +an `.xcodeproj` bundle from the above input file formats as follows: + + * `Group hierarchy`: This is generated in a fixed format with contents + derived from the input files. There is no provision for the user to + specify additional groups or create a custom hierarchy. + * `Configuration group`: This will be used with the + `xcode_config_file` property above, if needed. + * `Source group`: The union of the `sources` lists of all `targets` + after applying appropriate `conditions`. The resulting list is + sorted and put into a group hierarchy that matches the layout of + the directory tree on disk, with a root of // (the top of the + hierarchy). + * `Frameworks group`: Taken directly from `libraries` value for the + target, after applying appropriate conditions. + * `Projects group`: References to other `.xcodeproj` bundles that + are needed by the `.xcodeproj` in which the group is contained. + * `Products group`: Output from the various targets. + * `Project References`: + * `Project Configurations`: + * Per-`.xcodeproj` file settings are not supported, all settings are + applied at the target level. + * `Targets`: + * `Phases`: Copy sources, link with libraries/frameworks, ... + * `Target Configurations`: Specified by input. + * `Dependencies`: (local and remote) + +### Generated Visual Studio .vcproj Files + +We derive the following sections in a `.vcproj` file from the above +input file formats as follows: + + * `VisualStudioProject`: + * `Platforms`: + * `ToolFiles`: + * `Configurations`: + * `Configuration`: + * `References`: + * `Files`: + * `Filter`: + * `File`: + * `FileConfiguration`: + * `Tool`: + * `Globals`: + +### Generated Visual Studio .sln Files + +We derive the following sections in a `.sln` file from the above input +file formats as follows: + + * `Projects`: + * `WebsiteProperties`: + * `ProjectDependencies`: + * `Global`: + * `SolutionConfigurationPlatforms`: + * `ProjectConfigurationPlatforms`: + * `SolutionProperties`: + * `NestedProjects`: + +## Code Location + +Here! http://gyp.googlecode.com/ + +## Group Members + +|:-----------------|:---------------------------------| +| Darin Fisher | Overall approval of final design | +| Elliot Glaysher | Approval of Linux build functionality. | +| Alex Harper | | +| Steven Knight | Language specification.
Code for generating Scons files from `.gyp` files. | +| Mark Mentovai | Input language design and implementation.
Code for generating Xcode files from `.gyp` files.
Approval of Mac (Xcode) build functionality. | +| Bradley Nelson | Code for generating Visual Studio files from `.gyp` files. | +| Randall Spangler | | +| Nicolas Sylvain | Approval of Windows build functionality. | + +## Caveats + +TODO(sgk): Notes/Question from very first prototype draft of the language. +Make sure these issues are addressed somewhere before deleting. + + * Libraries are easy, application abstraction is harder + * Applications involves resource compilation + * Applications involve many inputs + * Applications include transitive closure of dependencies + * Specific use cases like cc\_library + * Mac compiles more than just .c/.cpp files (specifically, .m and .mm + files) + * Compiler options vary by: + * File type + * Target type + * Individual file + * Files may have custom settings per file per platform, but we probably + don't care or need to support this in gyp. + * Will all linked non-Chromium projects always use the same versions of every + subsystem? + * Variants are difficult. We've identified the following variants (some + specific to Chromium, some typical of other projects in the same ballpark): + * Target platform + * V8 vs. JSC + * Debug vs. Release + * Toolchain (VS version, gcc, version) + * Host platform + * L10N + * Vendor + * Purify / Valgrind + * Will everyone upgrade VS at once? + * What does a dylib dependency mean? + +## Testing Plan + +_What are the sub-units of your system that will be independently testable? +Tests must be approved by the code reviewer, and must follow the guidelines in +the unittesting document as far as possible. See What Is A Design Document for +criteria for whole system tests on servers. If there are changes envisaged in +your future work, would your tests verify the base functionality? If some of +your tests cannot be easily automated (e.g. UI tests), how will you document +the needed special procedures?_ + +## Documentation Plan + +Documentation via this wiki: http://code.google.com/p/gyp + +## Work Estimates + +_Estimates of how long each phase will take (please be detailed; subtask +granularity should be roughly one week)_ + +## Launch Plans + +_What are the launch plans for your project? This includes, but is not limited +to: + * What visible changes your project will cause on the site. + * What will be the impact on production and/or search partners. + * What new servers will be introduced. + * Rough timeline for releasing your project._ diff -Nru gyp-0.1~svn1729/docs/Source.md gyp-0.1+20150913git1f374df9/docs/Source.md --- gyp-0.1~svn1729/docs/Source.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/Source.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,3 @@ +# Source code + +https://chromium.googlesource.com/external/gyp diff -Nru gyp-0.1~svn1729/docs/Testing.md gyp-0.1+20150913git1f374df9/docs/Testing.md --- gyp-0.1~svn1729/docs/Testing.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/Testing.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,459 @@ +# GYP (Generate Your Projects) Tests + +-- + +Status: Draft (as of 2009-08-18) + +Steven Knight +_et al._ + +Modified: 2009-08-18 + +[TOC] + +## Introduction + +This document describes the GYP testing infrastructure, +as provided by the `TestGyp.py` module. + +These tests emphasize testing the _behavior_ of the +various GYP-generated build configurations: +Visual Studio, Xcode, SCons, Make, etc. +The goal is _not_ to test the output of the GYP generators by, +for example, comparing a GYP-generated Makefile +against a set of known "golden" Makefiles +(although the testing infrastructure could +be used to write those kinds of tests). +The idea is that the generated build configuration files +could be completely written to add a feature or fix a bug +so long as they continue to support the functional behaviors +defined by the tests: building programs, shared libraries, etc. + +## "Hello, world!" GYP test configuration + +Here is an actual test configuration, +a simple build of a C program to print `"Hello, world!"`. + +``` + $ ls -l test/hello + total 20 + -rw-r--r-- 1 knight knight 312 Jul 30 20:22 gyptest-all.py + -rw-r--r-- 1 knight knight 307 Jul 30 20:22 gyptest-default.py + -rwxr-xr-x 1 knight knight 326 Jul 30 20:22 gyptest-target.py + -rw-r--r-- 1 knight knight 98 Jul 30 20:22 hello.c + -rw-r--r-- 1 knight knight 142 Jul 30 20:22 hello.gyp + $ +``` + +The `gyptest-*.py` files are three separate tests (test scripts) +that use this configuration. The first one, `gyptest-all.py`, +looks like this: + +``` + #!/usr/bin/env python + + """ + Verifies simplest-possible build of a "Hello, world!" program + using an explicit build target of 'all'. + """ + + import TestGyp + + test = TestGyp.TestGyp() + + test.run_gyp('hello.gyp') + + test.build_all('hello.gyp') + + test.run_built_executable('hello', stdout="Hello, world!\n") + + test.pass_test() +``` + +The test script above runs GYP against the specified input file +(`hello.gyp`) to generate a build configuration. +It then tries to build the `'all'` target +(or its equivalent) using the generated build configuration. +Last, it verifies that the build worked as expected +by running the executable program (`hello`) +that was just presumably built by the generated configuration, +and verifies that the output from the program +matches the expected `stdout` string (`"Hello, world!\n"`). + +Which configuration is generated +(i.e., which build tool to test) +is specified when the test is run; +see the next section. + +Surrounding the functional parts of the test +described above are the header, +which should be basically the same for each test +(modulo a different description in the docstring): + +``` + #!/usr/bin/env python + + """ + Verifies simplest-possible build of a "Hello, world!" program + using an explicit build target of 'all'. + """ + + import TestGyp + + test = TestGyp.TestGyp() +``` + +Similarly, the footer should be the same in every test: + +``` + test.pass_test() +``` + +## Running tests + +Test scripts are run by the `gyptest.py` script. +You can specify (an) explicit test script(s) to run: + +``` + $ python gyptest.py test/hello/gyptest-all.py + PYTHONPATH=/home/knight/src/gyp/trunk/test/lib + TESTGYP_FORMAT=scons + /usr/bin/python test/hello/gyptest-all.py + PASSED + $ +``` + +If you specify a directory, all test scripts +(scripts prefixed with `gyptest-`) underneath +the directory will be run: + +``` + $ python gyptest.py test/hello + PYTHONPATH=/home/knight/src/gyp/trunk/test/lib + TESTGYP_FORMAT=scons + /usr/bin/python test/hello/gyptest-all.py + PASSED + /usr/bin/python test/hello/gyptest-default.py + PASSED + /usr/bin/python test/hello/gyptest-target.py + PASSED + $ +``` + +Or you can specify the `-a` option to run all scripts +in the tree: + +``` + $ python gyptest.py -a + PYTHONPATH=/home/knight/src/gyp/trunk/test/lib + TESTGYP_FORMAT=scons + /usr/bin/python test/configurations/gyptest-configurations.py + PASSED + /usr/bin/python test/defines/gyptest-defines.py + PASSED + . + . + . + . + /usr/bin/python test/variables/gyptest-commands.py + PASSED + $ +``` + +If any tests fail during the run, +the `gyptest.py` script will report them in a +summary at the end. + +## Debugging tests + +Tests that create intermediate output do so under the gyp/out/testworkarea +directory. On test completion, intermediate output is cleaned up. To preserve +this output, set the environment variable PRESERVE=1. This can be handy to +inspect intermediate data when debugging a test. + +You can also set PRESERVE\_PASS=1, PRESERVE\_FAIL=1 or PRESERVE\_NO\_RESULT=1 +to preserve output for tests that fall into one of those categories. + +# Specifying the format (build tool) to use + +By default, the `gyptest.py` script will generate configurations for +the "primary" supported build tool for the platform you're on: +Visual Studio on Windows, +Xcode on Mac, +and (currently) SCons on Linux. +An alternate format (build tool) may be specified +using the `-f` option: + +``` + $ python gyptest.py -f make test/hello/gyptest-all.py + PYTHONPATH=/home/knight/src/gyp/trunk/test/lib + TESTGYP_FORMAT=make + /usr/bin/python test/hello/gyptest-all.py + PASSED + $ +``` + +Multiple tools may be specified in a single pass as +a comma-separated list: + +``` + $ python gyptest.py -f make,scons test/hello/gyptest-all.py + PYTHONPATH=/home/knight/src/gyp/trunk/test/lib + TESTGYP_FORMAT=make + /usr/bin/python test/hello/gyptest-all.py + PASSED + TESTGYP_FORMAT=scons + /usr/bin/python test/hello/gyptest-all.py + PASSED + $ +``` + +## Test script functions and methods + +The `TestGyp` class contains a lot of functionality +intended to make it easy to write tests. +This section describes the most useful pieces for GYP testing. + +(The `TestGyp` class is actually a subclass of more generic +`TestCommon` and `TestCmd` base classes +that contain even more functionality than is +described here.) + +### Initialization + +The standard initialization formula is: + +``` + import TestGyp + test = TestGyp.TestGyp() +``` + +This copies the contents of the directory tree in which +the test script lives to a temporary directory for execution, +and arranges for the temporary directory's removal on exit. + +By default, any comparisons of output or file contents +must be exact matches for the test to pass. +If you need to use regular expressions for matches, +a useful alternative initialization is: + +``` + import TestGyp + test = TestGyp.TestGyp(match = TestGyp.match_re, + diff = TestGyp.diff_re)` +``` + +### Running GYP + +The canonical invocation is to simply specify the `.gyp` file to be executed: + +``` + test.run_gyp('file.gyp') +``` + +Additional GYP arguments may be specified: + +``` + test.run_gyp('file.gyp', arguments=['arg1', 'arg2', ...]) +``` + +To execute GYP from a subdirectory (where, presumably, the specified file +lives): + +``` + test.run_gyp('file.gyp', chdir='subdir') +``` + +### Running the build tool + +Running the build tool requires passing in a `.gyp` file, which may be used to +calculate the name of a specific build configuration file (such as a MSVS +solution file corresponding to the `.gyp` file). + +There are several different `.build_*()` methods for invoking different types +of builds. + +To invoke a build tool with an explicit `all` target (or equivalent): + +``` + test.build_all('file.gyp') +``` + +To invoke a build tool with its default behavior (for example, executing `make` +with no targets specified): + +``` + test.build_default('file.gyp') +``` + +To invoke a build tool with an explicit specified target: + +``` + test.build_target('file.gyp', 'target') +``` + +### Running executables + +The most useful method executes a program built by the GYP-generated +configuration: + +``` + test.run_built_executable('program') +``` + +The `.run_built_executable()` method will account for the actual built target +output location for the build tool being tested, as well as tack on any +necessary executable file suffix for the platform (for example `.exe` on +Windows). + +`stdout=` and `stderr=` keyword arguments specify expected standard output and +error output, respectively. Failure to match these (if specified) will cause +the test to fail. An explicit `None` value will suppress that verification: + +``` + test.run_built_executable('program', + stdout="expect this output\n", + stderr=None) +``` + +Note that the default values are `stdout=None` and `stderr=''` (that is, no +check for standard output, and error output must be empty). + +Arbitrary executables (not necessarily those built by GYP) can be executed with +the lower-level `.run()` method: + +``` + test.run('program') +``` + +The program must be in the local directory (that is, the temporary directory +for test execution) or be an absolute path name. + +### Fetching command output + +``` + test.stdout() +``` + +Returns the standard output from the most recent executed command (including +`.run_gyp()`, `.build_*()`, or `.run*()` methods). + +``` + test.stderr() +``` + +Returns the error output from the most recent executed command (including +`.run_gyp()`, `.build_*()`, or `.run*()` methods). + +### Verifying existence or non-existence of files or directories + +``` + test.must_exist('file_or_dir') +``` + +Verifies that the specified file or directory exists, and fails the test if it +doesn't. + +``` + test.must_not_exist('file_or_dir') +``` + +Verifies that the specified file or directory does not exist, and fails the +test if it does. + +### Verifying file contents + +``` + test.must_match('file', 'expected content\n') +``` + +Verifies that the content of the specified file match the expected string, and +fails the test if it does not. By default, the match must be exact, but +line-by-line regular expressions may be used if the `TestGyp` object was +initialized with `TestGyp.match_re`. + +``` + test.must_not_match('file', 'expected content\n') +``` + +Verifies that the content of the specified file does _not_ match the expected +string, and fails the test if it does. By default, the match must be exact, +but line-by-line regular expressions may be used if the `TestGyp` object was +initialized with `TestGyp.match_re`. + +``` + test.must_contain('file', 'substring') +``` + +Verifies that the specified file contains the specified substring, and fails +the test if it does not. + +``` + test.must_not_contain('file', 'substring') +``` + +Verifies that the specified file does not contain the specified substring, and +fails the test if it does. + +``` + test.must_contain_all_lines(output, lines) +``` + +Verifies that the output string contains all of the "lines" in the specified +list of lines. In practice, the lines can be any substring and need not be +`\n`-terminaed lines per se. If any line is missing, the test fails. + +``` + test.must_not_contain_any_lines(output, lines) +``` + +Verifies that the output string does _not_ contain any of the "lines" in the +specified list of lines. In practice, the lines can be any substring and need +not be `\n`-terminaed lines per se. If any line exists in the output string, +the test fails. + +``` + test.must_contain_any_line(output, lines) +``` + +Verifies that the output string contains at least one of the "lines" in the +specified list of lines. In practice, the lines can be any substring and need +not be `\n`-terminaed lines per se. If none of the specified lines is present, +the test fails. + +### Reading file contents + +``` + test.read('file') +``` + +Returns the contents of the specified file. Directory elements contained in a +list will be joined: + +``` + test.read(['subdir', 'file']) +``` + +### Test success or failure + +``` + test.fail_test() +``` + +Fails the test, reporting `FAILED` on standard output and exiting with an exit +status of `1`. + +``` + test.pass_test() +``` + +Passes the test, reporting `PASSED` on standard output and exiting with an exit +status of `0`. + +``` + test.no_result() +``` + +Indicates the test had no valid result (i.e., the conditions could not be +tested because of an external factor like a full file system). Reports `NO +RESULT` on standard output and exits with a status of `2`. diff -Nru gyp-0.1~svn1729/docs/UserDocumentation.md gyp-0.1+20150913git1f374df9/docs/UserDocumentation.md --- gyp-0.1~svn1729/docs/UserDocumentation.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/docs/UserDocumentation.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,975 @@ +# GYP (Generate Your Projects) User Documentation + +Status: Draft (as of 2009-05-19) + +Mark Mentovai , +Steven Knight +_et al._ + +Modified: 2009-05-19 + +[TOC] + +## Introduction + +This document is intended to provide a user-level guide to GYP. The +emphasis here is on how to use GYP to accomplish specific tasks, not on +the complete technical language specification. (For that, see the +[LanguageSpecification](LanguageSpecification).) + +The document below starts with some overviews to provide context: an +overview of the structure of a `.gyp` file itself, an overview of a +typical executable-program target in a `.gyp` file, an an overview of a +typical library target in a `.gyp` file. + +After the overviews, there are examples of `gyp` patterns for different +common use cases. + +## Skeleton of a typical Chromium .gyp file + +Here is the skeleton of a typical `.gyp` file in the Chromium tree: + +``` + { + 'variables': { + . + . + . + }, + 'includes': [ + '../build/common.gypi', + ], + 'target_defaults': { + . + . + . + }, + 'targets': [ + { + 'target_name': 'target_1', + . + . + . + }, + { + 'target_name': 'target_2', + . + . + . + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'targets': [ + { + 'target_name': 'linux_target_3', + . + . + . + }, + ], + }], + ['OS=="win"', { + 'targets': [ + { + 'target_name': 'windows_target_4', + . + . + . + }, + ], + }, { # OS != "win" + 'targets': [ + { + 'target_name': 'non_windows_target_5', + . + . + . + }, + }], + ], + } +``` + +The entire file just contains a Python dictionary. (It's actually JSON, +with two small Pythonic deviations: comments are introduced with `#`, +and a `,` (comma)) is legal after the last element in a list or +dictionary.) + +The top-level pieces in the `.gyp` file are as follows: + +`'variables'`: Definitions of variables that can be interpolated and +used in various other parts of the file. + +`'includes'`: A list of of other files that will be included in this +file. By convention, included files have the suffix `.gypi` (gyp +include). + +`'target_defaults'`: Settings that will apply to _all_ of the targets +defined in this `.gyp` file. + +`'targets'`: The list of targets for which this `.gyp` file can +generate builds. Each target is a dictionary that contains settings +describing all the information necessary to build the target. + +`'conditions'`: A list of condition specifications that can modify the +contents of the items in the global dictionary defined by this `.gyp` +file based on the values of different variablwes. As implied by the +above example, the most common use of a `conditions` section in the +top-level dictionary is to add platform-specific targets to the +`targets` list. + +## Skeleton of a typical executable target in a .gyp file + +The most straightforward target is probably a simple executable program. +Here is an example `executable` target that demonstrates the features +that should cover most simple uses of gyp: + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'msvs_guid': '5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65', + 'dependencies': [ + 'xyzzy', + '../bar/bar.gyp:bar', + ], + 'defines': [ + 'DEFINE_FOO', + 'DEFINE_A_VALUE=value', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'file1.cc', + 'file2.cc', + ], + 'conditions': [ + ['OS=="linux"', { + 'defines': [ + 'LINUX_DEFINE', + ], + 'include_dirs': [ + 'include/linux', + ], + }], + ['OS=="win"', { + 'defines': [ + 'WINDOWS_SPECIFIC_DEFINE', + ], + }, { # OS != "win", + 'defines': [ + 'NON_WINDOWS_DEFINE', + ], + }] + ], + }, + ], + } +``` + +The top-level settings in the target include: + +`'target_name'`: The name by which the target should be known, which +should be unique across all `.gyp` files. This name will be used as the +project name in the generated Visual Studio solution, as the target name +in the generated XCode configuration, and as the alias for building this +target from the command line of the generated SCons configuration. + +`'type'`: Set to `executable`, logically enough. + +`'msvs_guid'`: THIS IS ONLY TRANSITIONAL. This is a hard-coded GUID +values that will be used in the generated Visual Studio solution +file(s). This allows us to check in a `chrome.sln` file that +interoperates with gyp-generated project files. Once everything in +Chromium is being generated by gyp, it will no longer be important that +the GUIDs stay constant across invocations, and we'll likely get rid of +these settings, + +`'dependencies'`: This lists other targets that this target depends on. +The gyp-generated files will guarantee that the other targets are built +before this target. Any library targets in the `dependencies` list will +be linked with this target. The various settings (`defines`, +`include_dirs`, etc.) listed in the `direct_dependent_settings` sections +of the targets in this list will be applied to how _this_ target is +built and linked. See the more complete discussion of +`direct_dependent_settings`, below. + +`'defines'`: The C preprocessor definitions that will be passed in on +compilation command lines (using `-D` or `/D` options). + +`'include_dirs'`: The directories in which included header files live. +These will be passed in on compilation command lines (using `-I` or `/I` +options). + +`'sources'`: The source files for this target. + +`'conditions'`: A block of conditions that will be evaluated to update +the different settings in the target dictionary. + +## Skeleton of a typical library target in a .gyp file + +The vast majority of targets are libraries. Here is an example of a +library target including the additional features that should cover most +needs of libraries: + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': '<(library)' + 'msvs_guid': '5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65', + 'dependencies': [ + 'xyzzy', + '../bar/bar.gyp:bar', + ], + 'defines': [ + 'DEFINE_FOO', + 'DEFINE_A_VALUE=value', + ], + 'include_dirs': [ + '..', + ], + 'direct_dependent_settings': { + 'defines': [ + 'DEFINE_FOO', + 'DEFINE_ADDITIONAL', + ], + 'linkflags': [ + ], + }, + 'export_dependent_settings': [ + '../bar/bar.gyp:bar', + ], + 'sources': [ + 'file1.cc', + 'file2.cc', + ], + 'conditions': [ + ['OS=="linux"', { + 'defines': [ + 'LINUX_DEFINE', + ], + 'include_dirs': [ + 'include/linux', + ], + ], + ['OS=="win"', { + 'defines': [ + 'WINDOWS_SPECIFIC_DEFINE', + ], + }, { # OS != "win", + 'defines': [ + 'NON_WINDOWS_DEFINE', + ], + }] + ], + ], + } +``` + +The possible entries in a library target are largely the same as those +that can be specified for an executable target (`defines`, +`include_dirs`, etc.). The differences include: + +`'type'`: This should almost always be set to '<(library)', which allows +the user to define at gyp time whether libraries are to be built static +or shared. (On Linux, at least, linking with shared libraries saves +significant link time.) If it's necessary to pin down the type of +library to be built, the `type` can be set explicitly to +`static_library` or `shared_library`. + +`'direct_dependent_settings'`: This defines the settings that will be +applied to other targets that _directly depend_ on this target--that is, +that list _this_ target in their `'dependencies'` setting. This is +where you list the `defines`, `include_dirs`, `cflags` and `linkflags` +that other targets that compile or link against this target need to +build consistently. + +`'export_dependent_settings'`: This lists the targets whose +`direct_dependent_settings` should be "passed on" to other targets that +use (depend on) this target. `TODO: expand on this description.` + +## Use Cases + +These use cases are intended to cover the most common actions performed +by developers using GYP. + +Note that these examples are _not_ fully-functioning, self-contained +examples (or else they'd be way too long). Each example mostly contains +just the keywords and settings relevant to the example, with perhaps a +few extra keywords for context. The intent is to try to show the +specific pieces you need to pay attention to when doing something. +[NOTE: if practical use shows that these examples are confusing without +additional context, please add what's necessary to clarify things.] + +### Add new source files + +There are similar but slightly different patterns for adding a +platform-independent source file vs. adding a source file that only +builds on some of the supported platforms. + +#### Add a source file that builds on all platforms + +**Simplest possible case**: You are adding a file(s) that builds on all +platforms. + +Just add the file(s) to the `sources` list of the appropriate dictionary +in the `targets` list: + +``` + { + 'targets': [ + { + 'target_name': 'my_target', + 'type': 'executable', + 'sources': [ + '../other/file_1.cc', + 'new_file.cc', + 'subdir/file3.cc', + ], + }, + ], + }, +``` + +File path names are relative to the directory in which the `.gyp` file lives. + +Keep the list sorted alphabetically (unless there's a really, really, +_really_ good reason not to). + +#### Add a platform-specific source file + +##### Your platform-specific file is named `*_linux.{ext}`, `*_mac.{ext}`, `*_posix.{ext}` or `*_win.{ext}` + +The simplest way to add a platform-specific source file, assuming you're +adding a completely new file and get to name it, is to use one of the +following standard suffixes: + + * `_linux` (e.g. `foo_linux.cc`) + * `_mac` (e.g. `foo_mac.cc`) + * `_posix` (e.g. `foo_posix.cc`) + * `_win` (e.g. `foo_win.cc`) + +Simply add the file to the `sources` list of the appropriate dict within +the `targets` list, like you would any other source file. + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'sources': [ + 'independent.cc', + 'specific_win.cc', + ], + }, + ], + }, +``` + +The Chromium `.gyp` files all have appropriate `conditions` entries to +filter out the files that aren't appropriate for the current platform. +In the above example, the `specific_win.cc` file will be removed +automatically from the source-list on non-Windows builds. + +##### Your platform-specific file does not use an already-defined pattern + +If your platform-specific file does not contain a +`*_{linux,mac,posix,win}` substring (or some other pattern that's +already in the `conditions` for the target), and you can't change the +file name, there are two patterns that can be used. + +**Prefererred**: Add the file to the `sources` list of the appropriate +dictionary within the `targets` list. Add an appropriate `conditions` +section to exclude the specific files name: + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'sources': [ + 'linux_specific.cc', + ], + 'conditions': [ + ['OS != "linux"', { + 'sources!': [ + # Linux-only; exclude on other platforms. + 'linux_specific.cc', + ] + }[, + ], + }, + ], + }, +``` + +Despite the duplicate listing, the above is generally preferred because +the `sources` list contains a useful global list of all sources on all +platforms with consistent sorting on all platforms. + +**Non-preferred**: In some situations, however, it might make sense to +list a platform-specific file only in a `conditions` section that +specifically _includes_ it in the `sources` list: + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'sources': [], + ['OS == "linux"', { + 'sources': [ + # Only add to sources list on Linux. + 'linux_specific.cc', + ] + }], + }, + ], + }, +``` + +The above two examples end up generating equivalent builds, with the +small exception that the `sources` lists will list the files in +different orders. (The first example defines explicitly where +`linux_specific.cc` appears in the list--perhaps in in the +middle--whereas the second example will always tack it on to the end of +the list.) + +**Including or excluding files using patterns**: There are more +complicated ways to construct a `sources` list based on patterns. See +`TODO(sgk)` below. + +### Add a new executable + +An executable program is probably the most straightforward type of +target, since all it typically needs is a list of source files, some +compiler/linker settings (probably varied by platform), and some library +targets on which it depends and which must be used in the final link. + +#### Add an executable that builds on all platforms + +Add a dictionary defining the new executable target to the `targets` +list in the appropriate `.gyp` file. Example: + +``` + { + 'targets': [ + { + 'target_name': 'new_unit_tests', + 'type': 'executable', + 'defines': [ + 'FOO', + ], + 'include_dirs': [ + '..', + ], + 'dependencies': [ + 'other_target_in_this_file', + 'other_gyp2:target_in_other_gyp2', + ], + 'sources': [ + 'new_additional_source.cc', + 'new_unit_tests.cc', + ], + }, + ], + } +``` + +#### Add a platform-specific executable + +Add a dictionary defining the new executable target to the `targets` +list within an appropriate `conditions` block for the platform. The +`conditions` block should be a sibling to the top-level `targets` list: + +``` + { + 'targets': [ + ], + 'conditions': [ + ['OS=="win"', { + 'targets': [ + { + 'target_name': 'new_unit_tests', + 'type': 'executable', + 'defines': [ + 'FOO', + ], + 'include_dirs': [ + '..', + ], + 'dependencies': [ + 'other_target_in_this_file', + 'other_gyp2:target_in_other_gyp2', + ], + 'sources': [ + 'new_additional_source.cc', + 'new_unit_tests.cc', + ], + }, + ], + }], + ], + } +``` + +### Add settings to a target + +There are several different types of settings that can be defined for +any given target. + +#### Add new preprocessor definitions (`-D` or `/D` flags) + +New preprocessor definitions are added by the `defines` setting: + +``` + { + 'targets': [ + { + 'target_name': 'existing_target', + 'defines': [ + 'FOO', + 'BAR=some_value', + ], + }, + ], + }, +``` + +These may be specified directly in a target's settings, as in the above +example, or in a `conditions` section. + +#### Add a new include directory (`-I` or `/I` flags) + +New include directories are added by the `include_dirs` setting: + +``` + { + 'targets': [ + { + 'target_name': 'existing_target', + 'include_dirs': [ + '..', + 'include', + ], + }, + ], + }, +``` + +These may be specified directly in a target's settings, as in the above +example, or in a `conditions` section. + +#### Add new compiler flags + +Specific compiler flags can be added with the `cflags` setting: + +``` + { + 'targets': [ + { + 'target_name': 'existing_target', + 'conditions': [ + ['OS=="win"', { + 'cflags': [ + '/WX', + ], + }, { # OS != "win" + 'cflags': [ + '-Werror', + ], + }], + ], + }, + ], + }, +``` + +Because these flags will be specific to the actual compiler involved, +they will almost always be only set within a `conditions` section. + +#### Add new linker flags + +Setting linker flags is OS-specific. On linux and most non-mac posix +systems, they can be added with the `ldflags` setting: + +``` + { + 'targets': [ + { + 'target_name': 'existing_target', + 'conditions': [ + ['OS=="linux"', { + 'ldflags': [ + '-pthread', + ], + }], + ], + }, + ], + }, +``` + +Because these flags will be specific to the actual linker involved, +they will almost always be only set within a `conditions` section. + +On OS X, linker settings are set via `xcode_settings`, on Windows via +`msvs_settings`. + +#### Exclude settings on a platform + +Any given settings keyword (`defines`, `include_dirs`, etc.) has a +corresponding form with a trailing `!` (exclamation point) to remove +values from a setting. One useful example of this is to remove the +Linux `-Werror` flag from the global settings defined in +`build/common.gypi`: + +``` + { + 'targets': [ + { + 'target_name': 'third_party_target', + 'conditions': [ + ['OS=="linux"', { + 'cflags!': [ + '-Werror', + ], + }], + ], + }, + ], + }, +``` + +### Cross-compiling + +GYP has some (relatively limited) support for cross-compiling. + +If the variable `GYP_CROSSCOMPILE` or one of the toolchain-related +variables (like `CC_host` or `CC_target`) is set, GYP will think that +you wish to do a cross-compile. + +When cross-compiling, each target can be part of a "host" build, a +"target" build, or both. By default, the target is assumed to be (only) +part of the "target" build. The 'toolsets' property can be set on a +target to change the default. + +A target's dependencies are assumed to match the build type (so, if A +depends on B, by default that means that a target build of A depends on +a target build of B). You can explicitly depend on targets across +toolchains by specifying "#host" or "#target" in the dependencies list. +If GYP is not doing a cross-compile, the "#host" and "#target" will be +stripped as needed, so nothing breaks. + +### Add a new library + +TODO: write intro + +#### Add a library that builds on all platforms + +Add the a dictionary defining the new library target to the `targets` +list in the appropriate `.gyp` file. Example: + +``` + { + 'targets': [ + { + 'target_name': 'new_library', + 'type': '<(library)', + 'defines': [ + 'FOO', + 'BAR=some_value', + ], + 'include_dirs': [ + '..', + ], + 'dependencies': [ + 'other_target_in_this_file', + 'other_gyp2:target_in_other_gyp2', + ], + 'direct_dependent_settings': { + 'include_dirs': '.', + }, + 'export_dependent_settings': [ + 'other_target_in_this_file', + ], + 'sources': [ + 'new_additional_source.cc', + 'new_library.cc', + ], + }, + ], + } +``` + +The use of the `<(library)` variable above should be the default `type` +setting for most library targets, as it allows the developer to choose, +at `gyp` time, whether to build with static or shared libraries. +(Building with shared libraries saves a _lot_ of link time on Linux.) + +It may be necessary to build a specific library as a fixed type. Is so, +the `type` field can be hard-wired appropriately. For a static library: + +``` + 'type': 'static_library', +``` + +For a shared library: + +``` + 'type': 'shared_library', +``` + +#### Add a platform-specific library + +Add a dictionary defining the new library target to the `targets` list +within a `conditions` block that's a sibling to the top-level `targets` +list: + +``` + { + 'targets': [ + ], + 'conditions': [ + ['OS=="win"', { + 'targets': [ + { + 'target_name': 'new_library', + 'type': '<(library)', + 'defines': [ + 'FOO', + 'BAR=some_value', + ], + 'include_dirs': [ + '..', + ], + 'dependencies': [ + 'other_target_in_this_file', + 'other_gyp2:target_in_other_gyp2', + ], + 'direct_dependent_settings': { + 'include_dirs': '.', + }, + 'export_dependent_settings': [ + 'other_target_in_this_file', + ], + 'sources': [ + 'new_additional_source.cc', + 'new_library.cc', + ], + }, + ], + }], + ], + } +``` + +### Dependencies between targets + +GYP provides useful primitives for establishing dependencies between +targets, which need to be configured in the following situations. + +#### Linking with another library target + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'dependencies': [ + 'libbar', + ], + }, + { + 'target_name': 'libbar', + 'type': '<(library)', + 'sources': [ + ], + }, + ], + } +``` + +Note that if the library target is in a different `.gyp` file, you have +to specify the path to other `.gyp` file, relative to this `.gyp` file's +directory: + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'dependencies': [ + '../bar/bar.gyp:libbar', + ], + }, + ], + } +``` + +Adding a library often involves updating multiple `.gyp` files, adding +the target to the approprate `.gyp` file (possibly a newly-added `.gyp` +file), and updating targets in the other `.gyp` files that depend on +(link with) the new library. + +#### Compiling with necessary flags for a library target dependency + +We need to build a library (often a third-party library) with specific +preprocessor definitions or command-line flags, and need to ensure that +targets that depend on the library build with the same settings. This +situation is handled by a `direct_dependent_settings` block: + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'dependencies': [ + 'libbar', + ], + }, + { + 'target_name': 'libbar', + 'type': '<(library)', + 'defines': [ + 'LOCAL_DEFINE_FOR_LIBBAR', + 'DEFINE_TO_USE_LIBBAR', + ], + 'include_dirs': [ + '..', + 'include/libbar', + ], + 'direct_dependent_settings': { + 'defines': [ + 'DEFINE_TO_USE_LIBBAR', + ], + 'include_dirs': [ + 'include/libbar', + ], + }, + }, + ], + } +``` + +In the above example, the sources of the `foo` executable will be +compiled with the options `-DDEFINE_TO_USE_LIBBAR -Iinclude/libbar`, +because of those settings' being listed in the +`direct_dependent_settings` block. + +Note that these settings will likely need to be replicated in the +settings for the library target itsef, so that the library will build +with the same options. This does not prevent the target from defining +additional options for its "internal" use when compiling its own source +files. (In the above example, these are the `LOCAL_DEFINE_FOR_LIBBAR` +define, and the `..` entry in the `include_dirs` list.) + +#### When a library depends on an additional library at final link time + +``` + { + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'dependencies': [ + 'libbar', + ], + }, + { + 'target_name': 'libbar', + 'type': '<(library)', + 'dependencies': [ + 'libother' + ], + 'export_dependent_settings': [ + 'libother' + ], + }, + { + 'target_name': 'libother', + 'type': '<(library)', + 'direct_dependent_settings': { + 'defines': [ + 'DEFINE_FOR_LIBOTHER', + ], + 'include_dirs': [ + 'include/libother', + ], + }, + }, + ], + } +``` + +### Support for Mac OS X bundles + +gyp supports building bundles on OS X (.app, .framework, .bundle, etc). +Here is an example of this: + +``` + { + 'target_name': 'test_app', + 'product_name': 'Test App Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.m', + 'TestAppAppDelegate.h', + 'TestAppAppDelegate.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + }, + }, +``` + +The `mac_bundle` key tells gyp that this target should be a bundle. +`executable` targets get extension `.app` by default, `shared_library` +targets get `.framework` – but you can change the bundle extensions by +setting `product_extension` if you want. Files listed in +`mac_bundle_resources` will be copied to the bundle's `Resource` folder +of the bundle. You can also set +`process_outputs_as_mac_bundle_resources` to 1 in actions and rules to +let the output of actions and rules be added to that folder (similar to +`process_outputs_as_sources`). If `product_name` is not set, the bundle +will be named after `target_name`as usual. + +### Move files (refactoring) + +TODO(sgk) + +### Custom build steps + +TODO(sgk) + +#### Adding an explicit build step to generate specific files + +TODO(sgk) + +#### Adding a rule to handle files with a new suffix + +TODO(sgk) + +### Build flavors + +TODO(sgk) diff -Nru gyp-0.1~svn1729/gyp gyp-0.1+20150913git1f374df9/gyp --- gyp-0.1~svn1729/gyp 2013-07-09 14:54:55.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/gyp 2015-09-13 13:41:20.000000000 +0000 @@ -1,7 +1,8 @@ -#!/bin/bash +#!/bin/sh # Copyright 2013 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -BASE=`dirname $0` -python $BASE/gyp_main.py "$@" +set -e +base=$(dirname "$0") +exec python "${base}/gyp_main.py" "$@" diff -Nru gyp-0.1~svn1729/gyp_dummy.c gyp-0.1+20150913git1f374df9/gyp_dummy.c --- gyp-0.1~svn1729/gyp_dummy.c 2010-01-08 14:58:07.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/gyp_dummy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -/* Copyright (c) 2009 Google Inc. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -int main() { - return 0; -} diff -Nru gyp-0.1~svn1729/gyp_main.py gyp-0.1+20150913git1f374df9/gyp_main.py --- gyp-0.1~svn1729/gyp_main.py 2013-09-04 17:51:09.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/gyp_main.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,15 +4,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import os import sys -# TODO(mark): sys.path manipulation is some temporary testing stuff. -try: - import gyp -except ImportError, e: - import os.path - sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), 'pylib')) - import gyp +# Make sure we're using the version of pylib in this repo, not one installed +# elsewhere on the system. +sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), 'pylib')) +import gyp if __name__ == '__main__': sys.exit(gyp.script_main()) diff -Nru gyp-0.1~svn1729/gyptest.py gyp-0.1+20150913git1f374df9/gyptest.py --- gyp-0.1~svn1729/gyptest.py 2013-09-03 20:30:56.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/gyptest.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,7 +13,7 @@ import subprocess import sys -class CommandRunner: +class CommandRunner(object): """ Executor class for commands, including "commands" implemented by Python functions. @@ -117,7 +117,7 @@ return self.execute(command, stdout, stderr) -class Unbuffered: +class Unbuffered(object): def __init__(self, fp): self.fp = fp def write(self, arg): @@ -176,7 +176,7 @@ if opts.path: extra_path = [os.path.abspath(p) for p in opts.path] extra_path = os.pathsep.join(extra_path) - os.environ['PATH'] += os.pathsep + extra_path + os.environ['PATH'] = extra_path + os.pathsep + os.environ['PATH'] if not args: if not opts.all: @@ -216,6 +216,7 @@ else: # TODO: not duplicate this mapping from pylib/gyp/__init__.py format_list = { + 'aix5': ['make'], 'freebsd7': ['make'], 'freebsd8': ['make'], 'openbsd5': ['make'], @@ -223,7 +224,7 @@ 'win32': ['msvs', 'ninja'], 'linux2': ['make', 'ninja'], 'linux3': ['make', 'ninja'], - 'darwin': ['make', 'ninja', 'xcode'], + 'darwin': ['make', 'ninja', 'xcode', 'xcode-ninja'], }[sys.platform] for format in format_list: diff -Nru gyp-0.1~svn1729/PRESUBMIT.py gyp-0.1+20150913git1f374df9/PRESUBMIT.py --- gyp-0.1~svn1729/PRESUBMIT.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/PRESUBMIT.py 2015-09-13 13:41:20.000000000 +0000 @@ -16,8 +16,6 @@ 'test/lib/TestCmd.py', 'test/lib/TestCommon.py', 'test/lib/TestGyp.py', - # Needs style fix. - 'pylib/gyp/generator/xcode.py', ] @@ -25,6 +23,10 @@ # TODO: fix me. # Many tests include modules they don't use. 'W0611', + # Possible unbalanced tuple unpacking with sequence. + 'W0632', + # Attempting to unpack a non-sequence. + 'W0633', # Include order doesn't properly include local files? 'F0401', # Some use of built-in names. @@ -40,6 +42,10 @@ 'W0613', # String has no effect (docstring in wrong place). 'W0105', + # map/filter on lambda could be replaced by comprehension. + 'W0110', + # Use of eval. + 'W0123', # Comma not followed by space. 'C0324', # Access to a protected member. @@ -56,6 +62,8 @@ 'E1101', # Dangerous default {}. 'W0102', + # Cyclic import. + 'R0401', # Others, too many to sort. 'W0201', 'W0232', 'E1103', 'W0621', 'W0108', 'W0223', 'W0231', 'R0201', 'E0101', 'C0321', @@ -97,19 +105,33 @@ 'http://gyp-status.appspot.com/status', 'http://gyp-status.appspot.com/current')) + import os import sys old_sys_path = sys.path try: sys.path = ['pylib', 'test/lib'] + sys.path + blacklist = PYLINT_BLACKLIST + if sys.platform == 'win32': + blacklist = [os.path.normpath(x).replace('\\', '\\\\') + for x in PYLINT_BLACKLIST] report.extend(input_api.canned_checks.RunPylint( input_api, output_api, - black_list=PYLINT_BLACKLIST, + black_list=blacklist, disabled_warnings=PYLINT_DISABLED_WARNINGS)) finally: sys.path = old_sys_path return report -def GetPreferredTrySlaves(): - return ['gyp-win32', 'gyp-win64', 'gyp-linux', 'gyp-mac', 'gyp-android'] +TRYBOTS = [ + 'linux_try', + 'mac_try', + 'win_try', +] + + +def GetPreferredTryMasters(_, change): + return { + 'client.gyp': { t: set(['defaulttests']) for t in TRYBOTS }, + } diff -Nru gyp-0.1~svn1729/pylib/gyp/common.py gyp-0.1+20150913git1f374df9/pylib/gyp/common.py --- gyp-0.1~svn1729/pylib/gyp/common.py 2013-07-22 20:30:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/common.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,6 +4,7 @@ from __future__ import with_statement +import collections import errno import filecmp import os.path @@ -44,6 +45,14 @@ e.args = (str(e.args[0]) + ' ' + msg,) + e.args[1:] +def FindQualifiedTargets(target, qualified_list): + """ + Given a list of qualified targets, return the qualified targets for the + specified |target|. + """ + return [t for t in qualified_list if ParseQualifiedTarget(t)[1] == target] + + def ParseQualifiedTarget(target): # Splits a qualified target into a build file, target name and toolset. @@ -320,7 +329,7 @@ the target if it differs (on close). """ - class Writer: + class Writer(object): """Wrapper around file which only covers the target if it differs.""" def __init__(self): # Pick temporary file. @@ -383,6 +392,14 @@ return Writer() +def EnsureDirExists(path): + """Make sure the directory for |path| exists.""" + try: + os.makedirs(os.path.dirname(path)) + except OSError: + pass + + def GetFlavor(params): """Returns |params.flavor| if it's set, the system's default flavor else.""" flavors = { @@ -408,9 +425,16 @@ def CopyTool(flavor, out_path): - """Finds (mac|sun|win)_tool.gyp in the gyp directory and copies it + """Finds (flock|mac|win)_tool.gyp in the gyp directory and copies it to |out_path|.""" - prefix = { 'solaris': 'sun', 'mac': 'mac', 'win': 'win' }.get(flavor, None) + # aix and solaris just need flock emulation. mac and win use more complicated + # support scripts. + prefix = { + 'aix': 'flock', + 'solaris': 'flock', + 'mac': 'mac', + 'win': 'win' + }.get(flavor, None) if not prefix: return @@ -449,6 +473,72 @@ return result +# Based on http://code.activestate.com/recipes/576694/. +class OrderedSet(collections.MutableSet): + def __init__(self, iterable=None): + self.end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.map = {} # key --> [key, prev, next] + if iterable is not None: + self |= iterable + + def __len__(self): + return len(self.map) + + def __contains__(self, key): + return key in self.map + + def add(self, key): + if key not in self.map: + end = self.end + curr = end[1] + curr[2] = end[1] = self.map[key] = [key, curr, end] + + def discard(self, key): + if key in self.map: + key, prev_item, next_item = self.map.pop(key) + prev_item[2] = next_item + next_item[1] = prev_item + + def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + # The second argument is an addition that causes a pylint warning. + def pop(self, last=True): # pylint: disable=W0221 + if not self: + raise KeyError('set is empty') + key = self.end[1][0] if last else self.end[2][0] + self.discard(key) + return key + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + return set(self) == set(other) + + # Extensions to the recipe. + def update(self, iterable): + for i in iterable: + if i not in self: + self.add(i) + + class CycleError(Exception): """An exception raised when an unexpected cycle is detected.""" def __init__(self, nodes): @@ -458,7 +548,7 @@ def TopologicallySorted(graph, get_edges): - """Topologically sort based on a user provided edge definition. + r"""Topologically sort based on a user provided edge definition. Args: graph: A list of node names. @@ -496,3 +586,14 @@ for node in sorted(graph): Visit(node) return ordered_nodes + +def CrossCompileRequested(): + # TODO: figure out how to not build extra host objects in the + # non-cross-compile case when this is enabled, and enable unconditionally. + return (os.environ.get('GYP_CROSSCOMPILE') or + os.environ.get('AR_host') or + os.environ.get('CC_host') or + os.environ.get('CXX_host') or + os.environ.get('AR_target') or + os.environ.get('CC_target') or + os.environ.get('CXX_target')) diff -Nru gyp-0.1~svn1729/pylib/gyp/flock_tool.py gyp-0.1+20150913git1f374df9/pylib/gyp/flock_tool.py --- gyp-0.1~svn1729/pylib/gyp/flock_tool.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/flock_tool.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""These functions are executed via gyp-flock-tool when using the Makefile +generator. Used on systems that don't have a built-in flock.""" + +import fcntl +import os +import struct +import subprocess +import sys + + +def main(args): + executor = FlockTool() + executor.Dispatch(args) + + +class FlockTool(object): + """This class emulates the 'flock' command.""" + def Dispatch(self, args): + """Dispatches a string command to a method.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + method = "Exec%s" % self._CommandifyName(args[0]) + getattr(self, method)(*args[1:]) + + def _CommandifyName(self, name_string): + """Transforms a tool name like copy-info-plist to CopyInfoPlist""" + return name_string.title().replace('-', '') + + def ExecFlock(self, lockfile, *cmd_list): + """Emulates the most basic behavior of Linux's flock(1).""" + # Rely on exception handling to report errors. + # Note that the stock python on SunOS has a bug + # where fcntl.flock(fd, LOCK_EX) always fails + # with EBADF, that's why we use this F_SETLK + # hack instead. + fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666) + if sys.platform.startswith('aix'): + # Python on AIX is compiled with LARGEFILE support, which changes the + # struct size. + op = struct.pack('hhIllqq', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) + else: + op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) + fcntl.fcntl(fd, fcntl.F_SETLK, op) + return subprocess.call(cmd_list) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/analyzer.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/analyzer.py --- gyp-0.1~svn1729/pylib/gyp/generator/analyzer.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/analyzer.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,608 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +This script is intended for use as a GYP_GENERATOR. It takes as input (by way of +the generator flag config_path) the path of a json file that dictates the files +and targets to search for. The following keys are supported: +files: list of paths (relative) of the files to search for. +targets: list of targets to search for. The target names are unqualified. + +The following is output: +error: only supplied if there is an error. +targets: the set of targets passed in via targets that either directly or + indirectly depend upon the set of paths supplied in files. +build_targets: minimal set of targets that directly depend on the changed + files and need to be built. The expectation is this set of targets is passed + into a build step. +status: outputs one of three values: none of the supplied files were found, + one of the include files changed so that it should be assumed everything + changed (in this case targets and build_targets are not output) or at + least one file was found. +invalid_targets: list of supplied targets thare were not found. + +If the generator flag analyzer_output_path is specified, output is written +there. Otherwise output is written to stdout. +""" + +import gyp.common +import gyp.ninja_syntax as ninja_syntax +import json +import os +import posixpath +import sys + +debug = False + +found_dependency_string = 'Found dependency' +no_dependency_string = 'No dependencies' +# Status when it should be assumed that everything has changed. +all_changed_string = 'Found dependency (all)' + +# MatchStatus is used indicate if and how a target depends upon the supplied +# sources. +# The target's sources contain one of the supplied paths. +MATCH_STATUS_MATCHES = 1 +# The target has a dependency on another target that contains one of the +# supplied paths. +MATCH_STATUS_MATCHES_BY_DEPENDENCY = 2 +# The target's sources weren't in the supplied paths and none of the target's +# dependencies depend upon a target that matched. +MATCH_STATUS_DOESNT_MATCH = 3 +# The target doesn't contain the source, but the dependent targets have not yet +# been visited to determine a more specific status yet. +MATCH_STATUS_TBD = 4 + +generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() + +generator_wants_static_library_dependencies_adjusted = False + +generator_default_variables = { +} +for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', + 'LIB_DIR', 'SHARED_LIB_DIR']: + generator_default_variables[dirname] = '!!!' + +for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', + 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', + 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', + 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', + 'CONFIGURATION_NAME']: + generator_default_variables[unused] = '' + + +def _ToGypPath(path): + """Converts a path to the format used by gyp.""" + if os.sep == '\\' and os.altsep == '/': + return path.replace('\\', '/') + return path + + +def _ResolveParent(path, base_path_components): + """Resolves |path|, which starts with at least one '../'. Returns an empty + string if the path shouldn't be considered. See _AddSources() for a + description of |base_path_components|.""" + depth = 0 + while path.startswith('../'): + depth += 1 + path = path[3:] + # Relative includes may go outside the source tree. For example, an action may + # have inputs in /usr/include, which are not in the source tree. + if depth > len(base_path_components): + return '' + if depth == len(base_path_components): + return path + return '/'.join(base_path_components[0:len(base_path_components) - depth]) + \ + '/' + path + + +def _AddSources(sources, base_path, base_path_components, result): + """Extracts valid sources from |sources| and adds them to |result|. Each + source file is relative to |base_path|, but may contain '..'. To make + resolving '..' easier |base_path_components| contains each of the + directories in |base_path|. Additionally each source may contain variables. + Such sources are ignored as it is assumed dependencies on them are expressed + and tracked in some other means.""" + # NOTE: gyp paths are always posix style. + for source in sources: + if not len(source) or source.startswith('!!!') or source.startswith('$'): + continue + # variable expansion may lead to //. + org_source = source + source = source[0] + source[1:].replace('//', '/') + if source.startswith('../'): + source = _ResolveParent(source, base_path_components) + if len(source): + result.append(source) + continue + result.append(base_path + source) + if debug: + print 'AddSource', org_source, result[len(result) - 1] + + +def _ExtractSourcesFromAction(action, base_path, base_path_components, + results): + if 'inputs' in action: + _AddSources(action['inputs'], base_path, base_path_components, results) + + +def _ToLocalPath(toplevel_dir, path): + """Converts |path| to a path relative to |toplevel_dir|.""" + if path == toplevel_dir: + return '' + if path.startswith(toplevel_dir + '/'): + return path[len(toplevel_dir) + len('/'):] + return path + + +def _ExtractSources(target, target_dict, toplevel_dir): + # |target| is either absolute or relative and in the format of the OS. Gyp + # source paths are always posix. Convert |target| to a posix path relative to + # |toplevel_dir_|. This is done to make it easy to build source paths. + base_path = posixpath.dirname(_ToLocalPath(toplevel_dir, _ToGypPath(target))) + base_path_components = base_path.split('/') + + # Add a trailing '/' so that _AddSources() can easily build paths. + if len(base_path): + base_path += '/' + + if debug: + print 'ExtractSources', target, base_path + + results = [] + if 'sources' in target_dict: + _AddSources(target_dict['sources'], base_path, base_path_components, + results) + # Include the inputs from any actions. Any changes to these affect the + # resulting output. + if 'actions' in target_dict: + for action in target_dict['actions']: + _ExtractSourcesFromAction(action, base_path, base_path_components, + results) + if 'rules' in target_dict: + for rule in target_dict['rules']: + _ExtractSourcesFromAction(rule, base_path, base_path_components, results) + + return results + + +class Target(object): + """Holds information about a particular target: + deps: set of Targets this Target depends upon. This is not recursive, only the + direct dependent Targets. + match_status: one of the MatchStatus values. + back_deps: set of Targets that have a dependency on this Target. + visited: used during iteration to indicate whether we've visited this target. + This is used for two iterations, once in building the set of Targets and + again in _GetBuildTargets(). + name: fully qualified name of the target. + requires_build: True if the target type is such that it needs to be built. + See _DoesTargetTypeRequireBuild for details. + added_to_compile_targets: used when determining if the target was added to the + set of targets that needs to be built. + in_roots: true if this target is a descendant of one of the root nodes. + is_executable: true if the type of target is executable. + is_static_library: true if the type of target is static_library. + is_or_has_linked_ancestor: true if the target does a link (eg executable), or + if there is a target in back_deps that does a link.""" + def __init__(self, name): + self.deps = set() + self.match_status = MATCH_STATUS_TBD + self.back_deps = set() + self.name = name + # TODO(sky): I don't like hanging this off Target. This state is specific + # to certain functions and should be isolated there. + self.visited = False + self.requires_build = False + self.added_to_compile_targets = False + self.in_roots = False + self.is_executable = False + self.is_static_library = False + self.is_or_has_linked_ancestor = False + + +class Config(object): + """Details what we're looking for + files: set of files to search for + targets: see file description for details.""" + def __init__(self): + self.files = [] + self.targets = set() + + def Init(self, params): + """Initializes Config. This is a separate method as it raises an exception + if there is a parse error.""" + generator_flags = params.get('generator_flags', {}) + config_path = generator_flags.get('config_path', None) + if not config_path: + return + try: + f = open(config_path, 'r') + config = json.load(f) + f.close() + except IOError: + raise Exception('Unable to open file ' + config_path) + except ValueError as e: + raise Exception('Unable to parse config file ' + config_path + str(e)) + if not isinstance(config, dict): + raise Exception('config_path must be a JSON file containing a dictionary') + self.files = config.get('files', []) + self.targets = set(config.get('targets', [])) + + +def _WasBuildFileModified(build_file, data, files, toplevel_dir): + """Returns true if the build file |build_file| is either in |files| or + one of the files included by |build_file| is in |files|. |toplevel_dir| is + the root of the source tree.""" + if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: + if debug: + print 'gyp file modified', build_file + return True + + # First element of included_files is the file itself. + if len(data[build_file]['included_files']) <= 1: + return False + + for include_file in data[build_file]['included_files'][1:]: + # |included_files| are relative to the directory of the |build_file|. + rel_include_file = \ + _ToGypPath(gyp.common.UnrelativePath(include_file, build_file)) + if _ToLocalPath(toplevel_dir, rel_include_file) in files: + if debug: + print 'included gyp file modified, gyp_file=', build_file, \ + 'included file=', rel_include_file + return True + return False + + +def _GetOrCreateTargetByName(targets, target_name): + """Creates or returns the Target at targets[target_name]. If there is no + Target for |target_name| one is created. Returns a tuple of whether a new + Target was created and the Target.""" + if target_name in targets: + return False, targets[target_name] + target = Target(target_name) + targets[target_name] = target + return True, target + + +def _DoesTargetTypeRequireBuild(target_dict): + """Returns true if the target type is such that it needs to be built.""" + # If a 'none' target has rules or actions we assume it requires a build. + return bool(target_dict['type'] != 'none' or + target_dict.get('actions') or target_dict.get('rules')) + + +def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, + build_files): + """Returns a tuple of the following: + . A dictionary mapping from fully qualified name to Target. + . A list of the targets that have a source file in |files|. + . Set of root Targets reachable from the the files |build_files|. + This sets the |match_status| of the targets that contain any of the source + files in |files| to MATCH_STATUS_MATCHES. + |toplevel_dir| is the root of the source tree.""" + # Maps from target name to Target. + targets = {} + + # Targets that matched. + matching_targets = [] + + # Queue of targets to visit. + targets_to_visit = target_list[:] + + # Maps from build file to a boolean indicating whether the build file is in + # |files|. + build_file_in_files = {} + + # Root targets across all files. + roots = set() + + # Set of Targets in |build_files|. + build_file_targets = set() + + while len(targets_to_visit) > 0: + target_name = targets_to_visit.pop() + created_target, target = _GetOrCreateTargetByName(targets, target_name) + if created_target: + roots.add(target) + elif target.visited: + continue + + target.visited = True + target.requires_build = _DoesTargetTypeRequireBuild( + target_dicts[target_name]) + target_type = target_dicts[target_name]['type'] + target.is_executable = target_type == 'executable' + target.is_static_library = target_type == 'static_library' + target.is_or_has_linked_ancestor = (target_type == 'executable' or + target_type == 'shared_library') + + build_file = gyp.common.ParseQualifiedTarget(target_name)[0] + if not build_file in build_file_in_files: + build_file_in_files[build_file] = \ + _WasBuildFileModified(build_file, data, files, toplevel_dir) + + if build_file in build_files: + build_file_targets.add(target) + + # If a build file (or any of its included files) is modified we assume all + # targets in the file are modified. + if build_file_in_files[build_file]: + print 'matching target from modified build file', target_name + target.match_status = MATCH_STATUS_MATCHES + matching_targets.append(target) + else: + sources = _ExtractSources(target_name, target_dicts[target_name], + toplevel_dir) + for source in sources: + if _ToGypPath(os.path.normpath(source)) in files: + print 'target', target_name, 'matches', source + target.match_status = MATCH_STATUS_MATCHES + matching_targets.append(target) + break + + # Add dependencies to visit as well as updating back pointers for deps. + for dep in target_dicts[target_name].get('dependencies', []): + targets_to_visit.append(dep) + + created_dep_target, dep_target = _GetOrCreateTargetByName(targets, dep) + if not created_dep_target: + roots.discard(dep_target) + + target.deps.add(dep_target) + dep_target.back_deps.add(target) + + return targets, matching_targets, roots & build_file_targets + + +def _GetUnqualifiedToTargetMapping(all_targets, to_find): + """Returns a mapping (dictionary) from unqualified name to Target for all the + Targets in |to_find|.""" + result = {} + if not to_find: + return result + to_find = set(to_find) + for target_name in all_targets.keys(): + extracted = gyp.common.ParseQualifiedTarget(target_name) + if len(extracted) > 1 and extracted[1] in to_find: + to_find.remove(extracted[1]) + result[extracted[1]] = all_targets[target_name] + if not to_find: + return result + return result + + +def _DoesTargetDependOn(target): + """Returns true if |target| or any of its dependencies matches the supplied + set of paths. This updates |matches| of the Targets as it recurses. + target: the Target to look for.""" + if target.match_status == MATCH_STATUS_DOESNT_MATCH: + return False + if target.match_status == MATCH_STATUS_MATCHES or \ + target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY: + return True + for dep in target.deps: + if _DoesTargetDependOn(dep): + target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY + print '\t', target.name, 'matches by dep', dep.name + return True + target.match_status = MATCH_STATUS_DOESNT_MATCH + return False + + +def _GetTargetsDependingOn(possible_targets): + """Returns the list of Targets in |possible_targets| that depend (either + directly on indirectly) on the matched targets. + possible_targets: targets to search from.""" + found = [] + print 'Targets that matched by dependency:' + for target in possible_targets: + if _DoesTargetDependOn(target): + found.append(target) + return found + + +def _AddBuildTargets(target, roots, add_if_no_ancestor, result): + """Recurses through all targets that depend on |target|, adding all targets + that need to be built (and are in |roots|) to |result|. + roots: set of root targets. + add_if_no_ancestor: If true and there are no ancestors of |target| then add + |target| to |result|. |target| must still be in |roots|. + result: targets that need to be built are added here.""" + if target.visited: + return + + target.visited = True + target.in_roots = not target.back_deps and target in roots + + for back_dep_target in target.back_deps: + _AddBuildTargets(back_dep_target, roots, False, result) + target.added_to_compile_targets |= back_dep_target.added_to_compile_targets + target.in_roots |= back_dep_target.in_roots + target.is_or_has_linked_ancestor |= ( + back_dep_target.is_or_has_linked_ancestor) + + # Always add 'executable' targets. Even though they may be built by other + # targets that depend upon them it makes detection of what is going to be + # built easier. + # And always add static_libraries that have no dependencies on them from + # linkables. This is necessary as the other dependencies on them may be + # static libraries themselves, which are not compile time dependencies. + if target.in_roots and \ + (target.is_executable or + (not target.added_to_compile_targets and + (add_if_no_ancestor or target.requires_build)) or + (target.is_static_library and add_if_no_ancestor and + not target.is_or_has_linked_ancestor)): + print '\t\tadding to build targets', target.name, 'executable', \ + target.is_executable, 'added_to_compile_targets', \ + target.added_to_compile_targets, 'add_if_no_ancestor', \ + add_if_no_ancestor, 'requires_build', target.requires_build, \ + 'is_static_library', target.is_static_library, \ + 'is_or_has_linked_ancestor', target.is_or_has_linked_ancestor + result.add(target) + target.added_to_compile_targets = True + + +def _GetBuildTargets(matching_targets, roots): + """Returns the set of Targets that require a build. + matching_targets: targets that changed and need to be built. + roots: set of root targets in the build files to search from.""" + result = set() + for target in matching_targets: + print '\tfinding build targets for match', target.name + _AddBuildTargets(target, roots, True, result) + return result + + +def _WriteOutput(params, **values): + """Writes the output, either to stdout or a file is specified.""" + if 'error' in values: + print 'Error:', values['error'] + if 'status' in values: + print values['status'] + if 'targets' in values: + values['targets'].sort() + print 'Supplied targets that depend on changed files:' + for target in values['targets']: + print '\t', target + if 'invalid_targets' in values: + values['invalid_targets'].sort() + print 'The following targets were not found:' + for target in values['invalid_targets']: + print '\t', target + if 'build_targets' in values: + values['build_targets'].sort() + print 'Targets that require a build:' + for target in values['build_targets']: + print '\t', target + + output_path = params.get('generator_flags', {}).get( + 'analyzer_output_path', None) + if not output_path: + print json.dumps(values) + return + try: + f = open(output_path, 'w') + f.write(json.dumps(values) + '\n') + f.close() + except IOError as e: + print 'Error writing to output file', output_path, str(e) + + +def _WasGypIncludeFileModified(params, files): + """Returns true if one of the files in |files| is in the set of included + files.""" + if params['options'].includes: + for include in params['options'].includes: + if _ToGypPath(os.path.normpath(include)) in files: + print 'Include file modified, assuming all changed', include + return True + return False + + +def _NamesNotIn(names, mapping): + """Returns a list of the values in |names| that are not in |mapping|.""" + return [name for name in names if name not in mapping] + + +def _LookupTargets(names, mapping): + """Returns a list of the mapping[name] for each value in |names| that is in + |mapping|.""" + return [mapping[name] for name in names if name in mapping] + + +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + flavor = gyp.common.GetFlavor(params) + if flavor == 'mac': + default_variables.setdefault('OS', 'mac') + elif flavor == 'win': + default_variables.setdefault('OS', 'win') + # Copy additional generator configuration data from VS, which is shared + # by the Windows Ninja generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) + else: + operating_system = flavor + if flavor == 'android': + operating_system = 'linux' # Keep this legacy behavior for now. + default_variables.setdefault('OS', operating_system) + + +def GenerateOutput(target_list, target_dicts, data, params): + """Called by gyp as the final stage. Outputs results.""" + config = Config() + try: + config.Init(params) + if not config.files: + raise Exception('Must specify files to analyze via config_path generator ' + 'flag') + + toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) + if debug: + print 'toplevel_dir', toplevel_dir + + if _WasGypIncludeFileModified(params, config.files): + result_dict = { 'status': all_changed_string, + 'targets': list(config.targets) } + _WriteOutput(params, **result_dict) + return + + all_targets, matching_targets, roots = _GenerateTargets( + data, target_list, target_dicts, toplevel_dir, frozenset(config.files), + params['build_files']) + + print 'roots:' + for root in roots: + print '\t', root.name + + unqualified_mapping = _GetUnqualifiedToTargetMapping(all_targets, + config.targets) + invalid_targets = None + if len(unqualified_mapping) != len(config.targets): + invalid_targets = _NamesNotIn(config.targets, unqualified_mapping) + + if matching_targets: + search_targets = _LookupTargets(config.targets, unqualified_mapping) + print 'supplied targets' + for target in config.targets: + print '\t', target + print 'expanded supplied targets' + for target in search_targets: + print '\t', target.name + matched_search_targets = _GetTargetsDependingOn(search_targets) + print 'raw matched search targets:' + for target in matched_search_targets: + print '\t', target.name + # Reset the visited status for _GetBuildTargets. + for target in all_targets.itervalues(): + target.visited = False + print 'Finding build targets' + build_targets = _GetBuildTargets(matching_targets, roots) + matched_search_targets = [gyp.common.ParseQualifiedTarget(target.name)[1] + for target in matched_search_targets] + build_targets = [gyp.common.ParseQualifiedTarget(target.name)[1] + for target in build_targets] + else: + matched_search_targets = [] + build_targets = [] + + result_dict = { 'targets': matched_search_targets, + 'status': found_dependency_string if matching_targets else + no_dependency_string, + 'build_targets': build_targets} + if invalid_targets: + result_dict['invalid_targets'] = invalid_targets + _WriteOutput(params, **result_dict) + + except Exception as e: + _WriteOutput(params, error=str(e)) diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/android.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/android.py --- gyp-0.1~svn1729/pylib/gyp/generator/android.py 2013-06-24 23:04:55.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/android.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,1069 +0,0 @@ -# Copyright (c) 2012 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Notes: -# -# This generates makefiles suitable for inclusion into the Android build system -# via an Android.mk file. It is based on make.py, the standard makefile -# generator. -# -# The code below generates a separate .mk file for each target, but -# all are sourced by the top-level GypAndroid.mk. This means that all -# variables in .mk-files clobber one another, and furthermore that any -# variables set potentially clash with other Android build system variables. -# Try to avoid setting global variables where possible. - -import gyp -import gyp.common -import gyp.generator.make as make # Reuse global functions from make backend. -import os -import re -import subprocess - -generator_default_variables = { - 'OS': 'android', - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'SHARED_LIB_SUFFIX': '.so', - 'INTERMEDIATE_DIR': '$(gyp_intermediate_dir)', - 'SHARED_INTERMEDIATE_DIR': '$(gyp_shared_intermediate_dir)', - 'PRODUCT_DIR': '$(gyp_shared_intermediate_dir)', - 'SHARED_LIB_DIR': '$(builddir)/lib.$(TOOLSET)', - 'LIB_DIR': '$(obj).$(TOOLSET)', - 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. - 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python. - 'RULE_INPUT_PATH': '$(RULE_SOURCES)', - 'RULE_INPUT_EXT': '$(suffix $<)', - 'RULE_INPUT_NAME': '$(notdir $<)', - 'CONFIGURATION_NAME': '$(GYP_CONFIGURATION)', -} - -# Make supports multiple toolsets -generator_supports_multiple_toolsets = True - - -# Generator-specific gyp specs. -generator_additional_non_configuration_keys = [ - # Boolean to declare that this target does not want its name mangled. - 'android_unmangled_name', -] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] - - -SHARED_FOOTER = """\ -# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from -# all the included sub-makefiles. This is just here to clarify. -gyp_all_modules: -""" - -header = """\ -# This file is generated by gyp; do not edit. - -""" - -android_standard_include_paths = set([ - # JNI_H_INCLUDE in build/core/binary.mk - 'dalvik/libnativehelper/include/nativehelper', - # from SRC_HEADERS in build/core/config.mk - 'system/core/include', - 'hardware/libhardware/include', - 'hardware/libhardware_legacy/include', - 'hardware/ril/include', - 'dalvik/libnativehelper/include', - 'frameworks/native/include', - 'frameworks/native/opengl/include', - 'frameworks/base/include', - 'frameworks/base/opengl/include', - 'frameworks/base/native/include', - 'external/skia/include', - # TARGET_C_INCLUDES in build/core/combo/TARGET_linux-arm.mk - 'bionic/libc/arch-arm/include', - 'bionic/libc/include', - 'bionic/libstdc++/include', - 'bionic/libc/kernel/common', - 'bionic/libc/kernel/arch-arm', - 'bionic/libm/include', - 'bionic/libm/include/arm', - 'bionic/libthread_db/include', - ]) - - -# Map gyp target types to Android module classes. -MODULE_CLASSES = { - 'static_library': 'STATIC_LIBRARIES', - 'shared_library': 'SHARED_LIBRARIES', - 'executable': 'EXECUTABLES', -} - - -def IsCPPExtension(ext): - return make.COMPILABLE_EXTENSIONS.get(ext) == 'cxx' - - -def Sourceify(path): - """Convert a path to its source directory form. The Android backend does not - support options.generator_output, so this function is a noop.""" - return path - - -# Map from qualified target to path to output. -# For Android, the target of these maps is a tuple ('static', 'modulename'), -# ('dynamic', 'modulename'), or ('path', 'some/path') instead of a string, -# since we link by module. -target_outputs = {} -# Map from qualified target to any linkable output. A subset -# of target_outputs. E.g. when mybinary depends on liba, we want to -# include liba in the linker line; when otherbinary depends on -# mybinary, we just want to build mybinary first. -target_link_deps = {} - - -class AndroidMkWriter(object): - """AndroidMkWriter packages up the writing of one target-specific Android.mk. - - Its only real entry point is Write(), and is mostly used for namespacing. - """ - - def __init__(self, android_top_dir): - self.android_top_dir = android_top_dir - - def Write(self, qualified_target, relative_target, base_path, output_filename, - spec, configs, part_of_all): - """The main entry point: writes a .mk file for a single target. - - Arguments: - qualified_target: target we're generating - relative_target: qualified target name relative to the root - base_path: path relative to source root we're building in, used to resolve - target-relative paths - output_filename: output .mk file name to write - spec, configs: gyp info - part_of_all: flag indicating this target is part of 'all' - """ - make.ensure_directory_exists(output_filename) - - self.fp = open(output_filename, 'w') - - self.fp.write(header) - - self.qualified_target = qualified_target - self.relative_target = relative_target - self.path = base_path - self.target = spec['target_name'] - self.type = spec['type'] - self.toolset = spec['toolset'] - - deps, link_deps = self.ComputeDeps(spec) - - # Some of the generation below can add extra output, sources, or - # link dependencies. All of the out params of the functions that - # follow use names like extra_foo. - extra_outputs = [] - extra_sources = [] - - self.android_class = MODULE_CLASSES.get(self.type, 'GYP') - self.android_module = self.ComputeAndroidModule(spec) - (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec) - self.output = self.output_binary = self.ComputeOutput(spec) - - # Standard header. - self.WriteLn('include $(CLEAR_VARS)\n') - - # Module class and name. - self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class) - self.WriteLn('LOCAL_MODULE := ' + self.android_module) - # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE. - # The library module classes fail if the stem is set. ComputeOutputParts - # makes sure that stem == modulename in these cases. - if self.android_stem != self.android_module: - self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem) - self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix) - self.WriteLn('LOCAL_MODULE_TAGS := optional') - if self.toolset == 'host': - self.WriteLn('LOCAL_IS_HOST_MODULE := true') - - # Grab output directories; needed for Actions and Rules. - self.WriteLn('gyp_intermediate_dir := $(call local-intermediates-dir)') - self.WriteLn('gyp_shared_intermediate_dir := ' - '$(call intermediates-dir-for,GYP,shared)') - self.WriteLn() - - # List files this target depends on so that actions/rules/copies/sources - # can depend on the list. - # TODO: doesn't pull in things through transitive link deps; needed? - target_dependencies = [x[1] for x in deps if x[0] == 'path'] - self.WriteLn('# Make sure our deps are built first.') - self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES', - local_pathify=True) - - # Actions must come first, since they can generate more OBJs for use below. - if 'actions' in spec: - self.WriteActions(spec['actions'], extra_sources, extra_outputs) - - # Rules must be early like actions. - if 'rules' in spec: - self.WriteRules(spec['rules'], extra_sources, extra_outputs) - - if 'copies' in spec: - self.WriteCopies(spec['copies'], extra_outputs) - - # GYP generated outputs. - self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True) - - # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend - # on both our dependency targets and our generated files. - self.WriteLn('# Make sure our deps and generated files are built first.') - self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) ' - '$(GYP_GENERATED_OUTPUTS)') - self.WriteLn() - - # Sources. - if spec.get('sources', []) or extra_sources: - self.WriteSources(spec, configs, extra_sources) - - self.WriteTarget(spec, configs, deps, link_deps, part_of_all) - - # Update global list of target outputs, used in dependency tracking. - target_outputs[qualified_target] = ('path', self.output_binary) - - # Update global list of link dependencies. - if self.type == 'static_library': - target_link_deps[qualified_target] = ('static', self.android_module) - elif self.type == 'shared_library': - target_link_deps[qualified_target] = ('shared', self.android_module) - - self.fp.close() - return self.android_module - - - def WriteActions(self, actions, extra_sources, extra_outputs): - """Write Makefile code for any 'actions' from the gyp input. - - extra_sources: a list that will be filled in with newly generated source - files, if any - extra_outputs: a list that will be filled in with any outputs of these - actions (used to make other pieces dependent on these - actions) - """ - for action in actions: - name = make.StringToMakefileVariable('%s_%s' % (self.relative_target, - action['action_name'])) - self.WriteLn('### Rules for action "%s":' % action['action_name']) - inputs = action['inputs'] - outputs = action['outputs'] - - # Build up a list of outputs. - # Collect the output dirs we'll need. - dirs = set() - for out in outputs: - if not out.startswith('$'): - print ('WARNING: Action for target "%s" writes output to local path ' - '"%s".' % (self.target, out)) - dir = os.path.split(out)[0] - if dir: - dirs.add(dir) - if int(action.get('process_outputs_as_sources', False)): - extra_sources += outputs - - # Prepare the actual command. - command = gyp.common.EncodePOSIXShellList(action['action']) - if 'message' in action: - quiet_cmd = 'Gyp action: %s ($@)' % action['message'] - else: - quiet_cmd = 'Gyp action: %s ($@)' % name - if len(dirs) > 0: - command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command - - cd_action = 'cd $(gyp_local_path)/%s; ' % self.path - command = cd_action + command - - # The makefile rules are all relative to the top dir, but the gyp actions - # are defined relative to their containing dir. This replaces the gyp_* - # variables for the action rule with an absolute version so that the - # output goes in the right place. - # Only write the gyp_* rules for the "primary" output (:1); - # it's superfluous for the "extra outputs", and this avoids accidentally - # writing duplicate dummy rules for those outputs. - main_output = make.QuoteSpaces(self.LocalPathify(outputs[0])) - self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output) - self.WriteLn('%s: gyp_intermediate_dir := ' - '$(abspath $(gyp_intermediate_dir))' % main_output) - self.WriteLn('%s: gyp_shared_intermediate_dir := ' - '$(abspath $(gyp_shared_intermediate_dir))' % main_output) - - # Android's envsetup.sh adds a number of directories to the path including - # the built host binary directory. This causes actions/rules invoked by - # gyp to sometimes use these instead of system versions, e.g. bison. - # The built host binaries may not be suitable, and can cause errors. - # So, we remove them from the PATH using the ANDROID_BUILD_PATHS variable - # set by envsetup. - self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))' - % main_output) - - for input in inputs: - assert ' ' not in input, ( - "Spaces in action input filenames not supported (%s)" % input) - for output in outputs: - assert ' ' not in output, ( - "Spaces in action output filenames not supported (%s)" % output) - - self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' % - (main_output, ' '.join(map(self.LocalPathify, inputs)))) - self.WriteLn('\t@echo "%s"' % quiet_cmd) - self.WriteLn('\t$(hide)%s\n' % command) - for output in outputs[1:]: - # Make each output depend on the main output, with an empty command - # to force make to notice that the mtime has changed. - self.WriteLn('%s: %s ;' % (self.LocalPathify(output), main_output)) - - extra_outputs += outputs - self.WriteLn() - - self.WriteLn() - - - def WriteRules(self, rules, extra_sources, extra_outputs): - """Write Makefile code for any 'rules' from the gyp input. - - extra_sources: a list that will be filled in with newly generated source - files, if any - extra_outputs: a list that will be filled in with any outputs of these - rules (used to make other pieces dependent on these rules) - """ - if len(rules) == 0: - return - rule_trigger = '%s_rule_trigger' % self.android_module - - did_write_rule = False - for rule in rules: - if len(rule.get('rule_sources', [])) == 0: - continue - did_write_rule = True - name = make.StringToMakefileVariable('%s_%s' % (self.relative_target, - rule['rule_name'])) - self.WriteLn('\n### Generated for rule "%s":' % name) - self.WriteLn('# "%s":' % rule) - - inputs = rule.get('inputs') - for rule_source in rule.get('rule_sources', []): - (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) - (rule_source_root, rule_source_ext) = \ - os.path.splitext(rule_source_basename) - - outputs = [self.ExpandInputRoot(out, rule_source_root, - rule_source_dirname) - for out in rule['outputs']] - - dirs = set() - for out in outputs: - if not out.startswith('$'): - print ('WARNING: Rule for target %s writes output to local path %s' - % (self.target, out)) - dir = os.path.dirname(out) - if dir: - dirs.add(dir) - extra_outputs += outputs - if int(rule.get('process_outputs_as_sources', False)): - extra_sources.extend(outputs) - - components = [] - for component in rule['action']: - component = self.ExpandInputRoot(component, rule_source_root, - rule_source_dirname) - if '$(RULE_SOURCES)' in component: - component = component.replace('$(RULE_SOURCES)', - rule_source) - components.append(component) - - command = gyp.common.EncodePOSIXShellList(components) - cd_action = 'cd $(gyp_local_path)/%s; ' % self.path - command = cd_action + command - if dirs: - command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command - - # We set up a rule to build the first output, and then set up - # a rule for each additional output to depend on the first. - outputs = map(self.LocalPathify, outputs) - main_output = outputs[0] - self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output) - self.WriteLn('%s: gyp_intermediate_dir := ' - '$(abspath $(gyp_intermediate_dir))' % main_output) - self.WriteLn('%s: gyp_shared_intermediate_dir := ' - '$(abspath $(gyp_shared_intermediate_dir))' % main_output) - - # See explanation in WriteActions. - self.WriteLn('%s: export PATH := ' - '$(subst $(ANDROID_BUILD_PATHS),,$(PATH))' % main_output) - - main_output_deps = self.LocalPathify(rule_source) - if inputs: - main_output_deps += ' ' - main_output_deps += ' '.join([self.LocalPathify(f) for f in inputs]) - - self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' % - (main_output, main_output_deps)) - self.WriteLn('\t%s\n' % command) - for output in outputs[1:]: - # Make each output depend on the main output, with an empty command - # to force make to notice that the mtime has changed. - self.WriteLn('%s: %s ;' % (output, main_output)) - self.WriteLn('.PHONY: %s' % (rule_trigger)) - self.WriteLn('%s: %s' % (rule_trigger, main_output)) - self.WriteLn('') - if did_write_rule: - extra_sources.append(rule_trigger) # Force all rules to run. - self.WriteLn('### Finished generating for all rules') - self.WriteLn('') - - - def WriteCopies(self, copies, extra_outputs): - """Write Makefile code for any 'copies' from the gyp input. - - extra_outputs: a list that will be filled in with any outputs of this action - (used to make other pieces dependent on this action) - """ - self.WriteLn('### Generated for copy rule.') - - variable = make.StringToMakefileVariable(self.relative_target + '_copies') - outputs = [] - for copy in copies: - for path in copy['files']: - # The Android build system does not allow generation of files into the - # source tree. The destination should start with a variable, which will - # typically be $(gyp_intermediate_dir) or - # $(gyp_shared_intermediate_dir). Note that we can't use an assertion - # because some of the gyp tests depend on this. - if not copy['destination'].startswith('$'): - print ('WARNING: Copy rule for target %s writes output to ' - 'local path %s' % (self.target, copy['destination'])) - - # LocalPathify() calls normpath, stripping trailing slashes. - path = Sourceify(self.LocalPathify(path)) - filename = os.path.split(path)[1] - output = Sourceify(self.LocalPathify(os.path.join(copy['destination'], - filename))) - - self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES) | $(ACP)' % - (output, path)) - self.WriteLn('\t@echo Copying: $@') - self.WriteLn('\t$(hide) mkdir -p $(dir $@)') - self.WriteLn('\t$(hide) $(ACP) -r $< $@') - self.WriteLn() - outputs.append(output) - self.WriteLn('%s = %s' % (variable, - ' '.join(map(make.QuoteSpaces, outputs)))) - extra_outputs.append('$(%s)' % variable) - self.WriteLn() - - - def WriteSourceFlags(self, spec, configs): - """Write out the flags and include paths used to compile source files for - the current target. - - Args: - spec, configs: input from gyp. - """ - for configname, config in sorted(configs.iteritems()): - extracted_includes = [] - - self.WriteLn('\n# Flags passed to both C and C++ files.') - cflags, includes_from_cflags = self.ExtractIncludesFromCFlags( - config.get('cflags', []) + config.get('cflags_c', [])) - extracted_includes.extend(includes_from_cflags) - self.WriteList(cflags, 'MY_CFLAGS_%s' % configname) - - self.WriteList(config.get('defines'), 'MY_DEFS_%s' % configname, - prefix='-D', quoter=make.EscapeCppDefine) - - self.WriteLn('\n# Include paths placed before CFLAGS/CPPFLAGS') - includes = list(config.get('include_dirs', [])) - includes.extend(extracted_includes) - includes = map(Sourceify, map(self.LocalPathify, includes)) - includes = self.NormalizeIncludePaths(includes) - self.WriteList(includes, 'LOCAL_C_INCLUDES_%s' % configname) - - self.WriteLn('\n# Flags passed to only C++ (and not C) files.') - self.WriteList(config.get('cflags_cc'), 'LOCAL_CPPFLAGS_%s' % configname) - - self.WriteLn('\nLOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) ' - '$(MY_DEFS_$(GYP_CONFIGURATION))') - # Undefine ANDROID for host modules - # TODO: the source code should not use macro ANDROID to tell if it's host - # or target module. - if self.toolset == 'host': - self.WriteLn('# Undefine ANDROID for host modules') - self.WriteLn('LOCAL_CFLAGS += -UANDROID') - self.WriteLn('LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) ' - '$(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))') - self.WriteLn('LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))') - - - def WriteSources(self, spec, configs, extra_sources): - """Write Makefile code for any 'sources' from the gyp input. - These are source files necessary to build the current target. - We need to handle shared_intermediate directory source files as - a special case by copying them to the intermediate directory and - treating them as a genereated sources. Otherwise the Android build - rules won't pick them up. - - Args: - spec, configs: input from gyp. - extra_sources: Sources generated from Actions or Rules. - """ - sources = filter(make.Compilable, spec.get('sources', [])) - generated_not_sources = [x for x in extra_sources if not make.Compilable(x)] - extra_sources = filter(make.Compilable, extra_sources) - - # Determine and output the C++ extension used by these sources. - # We simply find the first C++ file and use that extension. - all_sources = sources + extra_sources - local_cpp_extension = '.cpp' - for source in all_sources: - (root, ext) = os.path.splitext(source) - if IsCPPExtension(ext): - local_cpp_extension = ext - break - if local_cpp_extension != '.cpp': - self.WriteLn('LOCAL_CPP_EXTENSION := %s' % local_cpp_extension) - - # We need to move any non-generated sources that are coming from the - # shared intermediate directory out of LOCAL_SRC_FILES and put them - # into LOCAL_GENERATED_SOURCES. We also need to move over any C++ files - # that don't match our local_cpp_extension, since Android will only - # generate Makefile rules for a single LOCAL_CPP_EXTENSION. - local_files = [] - for source in sources: - (root, ext) = os.path.splitext(source) - if '$(gyp_shared_intermediate_dir)' in source: - extra_sources.append(source) - elif '$(gyp_intermediate_dir)' in source: - extra_sources.append(source) - elif IsCPPExtension(ext) and ext != local_cpp_extension: - extra_sources.append(source) - else: - local_files.append(os.path.normpath(os.path.join(self.path, source))) - - # For any generated source, if it is coming from the shared intermediate - # directory then we add a Make rule to copy them to the local intermediate - # directory first. This is because the Android LOCAL_GENERATED_SOURCES - # must be in the local module intermediate directory for the compile rules - # to work properly. If the file has the wrong C++ extension, then we add - # a rule to copy that to intermediates and use the new version. - final_generated_sources = [] - # If a source file gets copied, we still need to add the orginal source - # directory as header search path, for GCC searches headers in the - # directory that contains the source file by default. - origin_src_dirs = [] - for source in extra_sources: - local_file = source - if not '$(gyp_intermediate_dir)/' in local_file: - basename = os.path.basename(local_file) - local_file = '$(gyp_intermediate_dir)/' + basename - (root, ext) = os.path.splitext(local_file) - if IsCPPExtension(ext) and ext != local_cpp_extension: - local_file = root + local_cpp_extension - if local_file != source: - self.WriteLn('%s: %s' % (local_file, self.LocalPathify(source))) - self.WriteLn('\tmkdir -p $(@D); cp $< $@') - origin_src_dirs.append(os.path.dirname(source)) - final_generated_sources.append(local_file) - - # We add back in all of the non-compilable stuff to make sure that the - # make rules have dependencies on them. - final_generated_sources.extend(generated_not_sources) - self.WriteList(final_generated_sources, 'LOCAL_GENERATED_SOURCES') - - origin_src_dirs = gyp.common.uniquer(origin_src_dirs) - origin_src_dirs = map(Sourceify, map(self.LocalPathify, origin_src_dirs)) - self.WriteList(origin_src_dirs, 'GYP_COPIED_SOURCE_ORIGIN_DIRS') - - self.WriteList(local_files, 'LOCAL_SRC_FILES') - - # Write out the flags used to compile the source; this must be done last - # so that GYP_COPIED_SOURCE_ORIGIN_DIRS can be used as an include path. - self.WriteSourceFlags(spec, configs) - - - def ComputeAndroidModule(self, spec): - """Return the Android module name used for a gyp spec. - - We use the complete qualified target name to avoid collisions between - duplicate targets in different directories. We also add a suffix to - distinguish gyp-generated module names. - """ - - if int(spec.get('android_unmangled_name', 0)): - assert self.type != 'shared_library' or self.target.startswith('lib') - return self.target - - if self.type == 'shared_library': - # For reasons of convention, the Android build system requires that all - # shared library modules are named 'libfoo' when generating -l flags. - prefix = 'lib_' - else: - prefix = '' - - if spec['toolset'] == 'host': - suffix = '_host_gyp' - else: - suffix = '_gyp' - - if self.path: - name = '%s%s_%s%s' % (prefix, self.path, self.target, suffix) - else: - name = '%s%s%s' % (prefix, self.target, suffix) - - return make.StringToMakefileVariable(name) - - - def ComputeOutputParts(self, spec): - """Return the 'output basename' of a gyp spec, split into filename + ext. - - Android libraries must be named the same thing as their module name, - otherwise the linker can't find them, so product_name and so on must be - ignored if we are building a library, and the "lib" prepending is - not done for Android. - """ - assert self.type != 'loadable_module' # TODO: not supported? - - target = spec['target_name'] - target_prefix = '' - target_ext = '' - if self.type == 'static_library': - target = self.ComputeAndroidModule(spec) - target_ext = '.a' - elif self.type == 'shared_library': - target = self.ComputeAndroidModule(spec) - target_ext = '.so' - elif self.type == 'none': - target_ext = '.stamp' - elif self.type != 'executable': - print ("ERROR: What output file should be generated?", - "type", self.type, "target", target) - - if self.type != 'static_library' and self.type != 'shared_library': - target_prefix = spec.get('product_prefix', target_prefix) - target = spec.get('product_name', target) - product_ext = spec.get('product_extension') - if product_ext: - target_ext = '.' + product_ext - - target_stem = target_prefix + target - return (target_stem, target_ext) - - - def ComputeOutputBasename(self, spec): - """Return the 'output basename' of a gyp spec. - - E.g., the loadable module 'foobar' in directory 'baz' will produce - 'libfoobar.so' - """ - return ''.join(self.ComputeOutputParts(spec)) - - - def ComputeOutput(self, spec): - """Return the 'output' (full output path) of a gyp spec. - - E.g., the loadable module 'foobar' in directory 'baz' will produce - '$(obj)/baz/libfoobar.so' - """ - if self.type == 'executable' and self.toolset == 'host': - # We install host executables into shared_intermediate_dir so they can be - # run by gyp rules that refer to PRODUCT_DIR. - path = '$(gyp_shared_intermediate_dir)' - elif self.type == 'shared_library': - if self.toolset == 'host': - path = '$(HOST_OUT_INTERMEDIATE_LIBRARIES)' - else: - path = '$(TARGET_OUT_INTERMEDIATE_LIBRARIES)' - else: - # Other targets just get built into their intermediate dir. - if self.toolset == 'host': - path = '$(call intermediates-dir-for,%s,%s,true)' % (self.android_class, - self.android_module) - else: - path = '$(call intermediates-dir-for,%s,%s)' % (self.android_class, - self.android_module) - - assert spec.get('product_dir') is None # TODO: not supported? - return os.path.join(path, self.ComputeOutputBasename(spec)) - - def NormalizeIncludePaths(self, include_paths): - """ Normalize include_paths. - Convert absolute paths to relative to the Android top directory; - filter out include paths that are already brought in by the Android build - system. - - Args: - include_paths: A list of unprocessed include paths. - Returns: - A list of normalized include paths. - """ - normalized = [] - for path in include_paths: - if path[0] == '/': - path = gyp.common.RelativePath(path, self.android_top_dir) - - # Filter out the Android standard search path. - if path not in android_standard_include_paths: - normalized.append(path) - return normalized - - def ExtractIncludesFromCFlags(self, cflags): - """Extract includes "-I..." out from cflags - - Args: - cflags: A list of compiler flags, which may be mixed with "-I.." - Returns: - A tuple of lists: (clean_clfags, include_paths). "-I.." is trimmed. - """ - clean_cflags = [] - include_paths = [] - for flag in cflags: - if flag.startswith('-I'): - include_paths.append(flag[2:]) - else: - clean_cflags.append(flag) - - return (clean_cflags, include_paths) - - def ComputeAndroidLibraryModuleNames(self, libraries): - """Compute the Android module names from libraries, ie spec.get('libraries') - - Args: - libraries: the value of spec.get('libraries') - Returns: - A tuple (static_lib_modules, dynamic_lib_modules) - """ - static_lib_modules = [] - dynamic_lib_modules = [] - for libs in libraries: - # Libs can have multiple words. - for lib in libs.split(): - # Filter the system libraries, which are added by default by the Android - # build system. - if (lib == '-lc' or lib == '-lstdc++' or lib == '-lm' or - lib.endswith('libgcc.a')): - continue - match = re.search(r'([^/]+)\.a$', lib) - if match: - static_lib_modules.append(match.group(1)) - continue - match = re.search(r'([^/]+)\.so$', lib) - if match: - dynamic_lib_modules.append(match.group(1)) - continue - # "-lstlport" -> libstlport - if lib.startswith('-l'): - if lib.endswith('_static'): - static_lib_modules.append('lib' + lib[2:]) - else: - dynamic_lib_modules.append('lib' + lib[2:]) - return (static_lib_modules, dynamic_lib_modules) - - - def ComputeDeps(self, spec): - """Compute the dependencies of a gyp spec. - - Returns a tuple (deps, link_deps), where each is a list of - filenames that will need to be put in front of make for either - building (deps) or linking (link_deps). - """ - deps = [] - link_deps = [] - if 'dependencies' in spec: - deps.extend([target_outputs[dep] for dep in spec['dependencies'] - if target_outputs[dep]]) - for dep in spec['dependencies']: - if dep in target_link_deps: - link_deps.append(target_link_deps[dep]) - deps.extend(link_deps) - return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps)) - - - def WriteTargetFlags(self, spec, configs, link_deps): - """Write Makefile code to specify the link flags and library dependencies. - - spec, configs: input from gyp. - link_deps: link dependency list; see ComputeDeps() - """ - for configname, config in sorted(configs.iteritems()): - ldflags = list(config.get('ldflags', [])) - self.WriteLn('') - self.WriteList(ldflags, 'LOCAL_LDFLAGS_%s' % configname) - self.WriteLn('\nLOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))') - - # Libraries (i.e. -lfoo) - libraries = gyp.common.uniquer(spec.get('libraries', [])) - static_libs, dynamic_libs = self.ComputeAndroidLibraryModuleNames( - libraries) - - # Link dependencies (i.e. libfoo.a, libfoo.so) - static_link_deps = [x[1] for x in link_deps if x[0] == 'static'] - shared_link_deps = [x[1] for x in link_deps if x[0] == 'shared'] - self.WriteLn('') - self.WriteList(static_libs + static_link_deps, - 'LOCAL_STATIC_LIBRARIES') - self.WriteLn('# Enable grouping to fix circular references') - self.WriteLn('LOCAL_GROUP_STATIC_LIBRARIES := true') - self.WriteLn('') - self.WriteList(dynamic_libs + shared_link_deps, - 'LOCAL_SHARED_LIBRARIES') - - - def WriteTarget(self, spec, configs, deps, link_deps, part_of_all): - """Write Makefile code to produce the final target of the gyp spec. - - spec, configs: input from gyp. - deps, link_deps: dependency lists; see ComputeDeps() - part_of_all: flag indicating this target is part of 'all' - """ - self.WriteLn('### Rules for final target.') - - if self.type != 'none': - self.WriteTargetFlags(spec, configs, link_deps) - - # Add to the set of targets which represent the gyp 'all' target. We use the - # name 'gyp_all_modules' as the Android build system doesn't allow the use - # of the Make target 'all' and because 'all_modules' is the equivalent of - # the Make target 'all' on Android. - if part_of_all: - self.WriteLn('# Add target alias to "gyp_all_modules" target.') - self.WriteLn('.PHONY: gyp_all_modules') - self.WriteLn('gyp_all_modules: %s' % self.android_module) - self.WriteLn('') - - # Add an alias from the gyp target name to the Android module name. This - # simplifies manual builds of the target, and is required by the test - # framework. - if self.target != self.android_module: - self.WriteLn('# Alias gyp target name.') - self.WriteLn('.PHONY: %s' % self.target) - self.WriteLn('%s: %s' % (self.target, self.android_module)) - self.WriteLn('') - - # Add the command to trigger build of the target type depending - # on the toolset. Ex: BUILD_STATIC_LIBRARY vs. BUILD_HOST_STATIC_LIBRARY - # NOTE: This has to come last! - modifier = '' - if self.toolset == 'host': - modifier = 'HOST_' - if self.type == 'static_library': - self.WriteLn('include $(BUILD_%sSTATIC_LIBRARY)' % modifier) - elif self.type == 'shared_library': - self.WriteLn('LOCAL_PRELINK_MODULE := false') - self.WriteLn('include $(BUILD_%sSHARED_LIBRARY)' % modifier) - elif self.type == 'executable': - if self.toolset == 'host': - self.WriteLn('LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)') - else: - # Don't install target executables for now, as it results in them being - # included in ROM. This can be revisited if there's a reason to install - # them later. - self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true') - self.WriteLn('include $(BUILD_%sEXECUTABLE)' % modifier) - else: - self.WriteLn('LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp') - self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true') - self.WriteLn() - self.WriteLn('include $(BUILD_SYSTEM)/base_rules.mk') - self.WriteLn() - self.WriteLn('$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)') - self.WriteLn('\t$(hide) echo "Gyp timestamp: $@"') - self.WriteLn('\t$(hide) mkdir -p $(dir $@)') - self.WriteLn('\t$(hide) touch $@') - - - def WriteList(self, value_list, variable=None, prefix='', - quoter=make.QuoteIfNecessary, local_pathify=False): - """Write a variable definition that is a list of values. - - E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out - foo = blaha blahb - but in a pretty-printed style. - """ - values = '' - if value_list: - value_list = [quoter(prefix + l) for l in value_list] - if local_pathify: - value_list = [self.LocalPathify(l) for l in value_list] - values = ' \\\n\t' + ' \\\n\t'.join(value_list) - self.fp.write('%s :=%s\n\n' % (variable, values)) - - - def WriteLn(self, text=''): - self.fp.write(text + '\n') - - - def LocalPathify(self, path): - """Convert a subdirectory-relative path into a normalized path which starts - with the make variable $(LOCAL_PATH) (i.e. the top of the project tree). - Absolute paths, or paths that contain variables, are just normalized.""" - if '$(' in path or os.path.isabs(path): - # path is not a file in the project tree in this case, but calling - # normpath is still important for trimming trailing slashes. - return os.path.normpath(path) - local_path = os.path.join('$(LOCAL_PATH)', self.path, path) - local_path = os.path.normpath(local_path) - # Check that normalizing the path didn't ../ itself out of $(LOCAL_PATH) - # - i.e. that the resulting path is still inside the project tree. The - # path may legitimately have ended up containing just $(LOCAL_PATH), though, - # so we don't look for a slash. - assert local_path.startswith('$(LOCAL_PATH)'), ( - 'Path %s attempts to escape from gyp path %s !)' % (path, self.path)) - return local_path - - - def ExpandInputRoot(self, template, expansion, dirname): - if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template: - return template - path = template % { - 'INPUT_ROOT': expansion, - 'INPUT_DIRNAME': dirname, - } - return path - - -def PerformBuild(data, configurations, params): - # The android backend only supports the default configuration. - options = params['options'] - makefile = os.path.abspath(os.path.join(options.toplevel_dir, - 'GypAndroid.mk')) - env = dict(os.environ) - env['ONE_SHOT_MAKEFILE'] = makefile - arguments = ['make', '-C', os.environ['ANDROID_BUILD_TOP'], 'gyp_all_modules'] - print 'Building: %s' % arguments - subprocess.check_call(arguments, env=env) - - -def GenerateOutput(target_list, target_dicts, data, params): - options = params['options'] - generator_flags = params.get('generator_flags', {}) - builddir_name = generator_flags.get('output_dir', 'out') - limit_to_target_all = generator_flags.get('limit_to_target_all', False) - android_top_dir = os.environ.get('ANDROID_BUILD_TOP') - assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.' - - def CalculateMakefilePath(build_file, base_name): - """Determine where to write a Makefile for a given gyp file.""" - # Paths in gyp files are relative to the .gyp file, but we want - # paths relative to the source root for the master makefile. Grab - # the path of the .gyp file as the base to relativize against. - # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". - base_path = gyp.common.RelativePath(os.path.dirname(build_file), - options.depth) - # We write the file in the base_path directory. - output_file = os.path.join(options.depth, base_path, base_name) - assert not options.generator_output, ( - 'The Android backend does not support options.generator_output.') - base_path = gyp.common.RelativePath(os.path.dirname(build_file), - options.toplevel_dir) - return base_path, output_file - - # TODO: search for the first non-'Default' target. This can go - # away when we add verification that all targets have the - # necessary configurations. - default_configuration = None - toolsets = set([target_dicts[target]['toolset'] for target in target_list]) - for target in target_list: - spec = target_dicts[target] - if spec['default_configuration'] != 'Default': - default_configuration = spec['default_configuration'] - break - if not default_configuration: - default_configuration = 'Default' - - srcdir = '.' - makefile_name = 'GypAndroid' + options.suffix + '.mk' - makefile_path = os.path.join(options.toplevel_dir, makefile_name) - assert not options.generator_output, ( - 'The Android backend does not support options.generator_output.') - make.ensure_directory_exists(makefile_path) - root_makefile = open(makefile_path, 'w') - - root_makefile.write(header) - - # We set LOCAL_PATH just once, here, to the top of the project tree. This - # allows all the other paths we use to be relative to the Android.mk file, - # as the Android build system expects. - root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n') - - # Find the list of targets that derive from the gyp file(s) being built. - needed_targets = set() - for build_file in params['build_files']: - for target in gyp.common.AllTargets(target_list, target_dicts, build_file): - needed_targets.add(target) - - build_files = set() - include_list = set() - android_modules = {} - for qualified_target in target_list: - build_file, target, toolset = gyp.common.ParseQualifiedTarget( - qualified_target) - relative_build_file = gyp.common.RelativePath(build_file, - options.toplevel_dir) - build_files.add(relative_build_file) - included_files = data[build_file]['included_files'] - for included_file in included_files: - # The included_files entries are relative to the dir of the build file - # that included them, so we have to undo that and then make them relative - # to the root dir. - relative_include_file = gyp.common.RelativePath( - gyp.common.UnrelativePath(included_file, build_file), - options.toplevel_dir) - abs_include_file = os.path.abspath(relative_include_file) - # If the include file is from the ~/.gyp dir, we should use absolute path - # so that relocating the src dir doesn't break the path. - if (params['home_dot_gyp'] and - abs_include_file.startswith(params['home_dot_gyp'])): - build_files.add(abs_include_file) - else: - build_files.add(relative_include_file) - - base_path, output_file = CalculateMakefilePath(build_file, - target + '.' + toolset + options.suffix + '.mk') - - spec = target_dicts[qualified_target] - configs = spec['configurations'] - - part_of_all = (qualified_target in needed_targets and - not int(spec.get('suppress_wildcard', False))) - if limit_to_target_all and not part_of_all: - continue - - relative_target = gyp.common.QualifiedTarget(relative_build_file, target, - toolset) - writer = AndroidMkWriter(android_top_dir) - android_module = writer.Write(qualified_target, relative_target, base_path, - output_file, spec, configs, - part_of_all=part_of_all) - if android_module in android_modules: - print ('ERROR: Android module names must be unique. The following ' - 'targets both generate Android module name %s.\n %s\n %s' % - (android_module, android_modules[android_module], - qualified_target)) - return - android_modules[android_module] = qualified_target - - # Our root_makefile lives at the source root. Compute the relative path - # from there to the output_file for including. - mkfile_rel_path = gyp.common.RelativePath(output_file, - os.path.dirname(makefile_path)) - include_list.add(mkfile_rel_path) - - root_makefile.write('GYP_CONFIGURATION ?= %s\n' % default_configuration) - - # Write out the sorted list of includes. - root_makefile.write('\n') - for include_file in sorted(include_list): - root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n') - root_makefile.write('\n') - - root_makefile.write(SHARED_FOOTER) - - root_makefile.close() diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/cmake.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/cmake.py --- gyp-0.1~svn1729/pylib/gyp/generator/cmake.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/cmake.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,1221 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""cmake output module + +This module is under development and should be considered experimental. + +This module produces cmake (2.8.8+) input as its output. One CMakeLists.txt is +created for each configuration. + +This module's original purpose was to support editing in IDEs like KDevelop +which use CMake for project management. It is also possible to use CMake to +generate projects for other IDEs such as eclipse cdt and code::blocks. QtCreator +will convert the CMakeLists.txt to a code::blocks cbp for the editor to read, +but build using CMake. As a result QtCreator editor is unaware of compiler +defines. The generated CMakeLists.txt can also be used to build on Linux. There +is currently no support for building on platforms other than Linux. + +The generated CMakeLists.txt should properly compile all projects. However, +there is a mismatch between gyp and cmake with regard to linking. All attempts +are made to work around this, but CMake sometimes sees -Wl,--start-group as a +library and incorrectly repeats it. As a result the output of this generator +should not be relied on for building. + +When using with kdevelop, use version 4.4+. Previous versions of kdevelop will +not be able to find the header file directories described in the generated +CMakeLists.txt file. +""" + +import multiprocessing +import os +import signal +import string +import subprocess +import gyp.common + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'SHARED_LIB_PREFIX': 'lib', + 'SHARED_LIB_SUFFIX': '.so', + 'SHARED_LIB_DIR': '${builddir}/lib.${TOOLSET}', + 'LIB_DIR': '${obj}.${TOOLSET}', + 'INTERMEDIATE_DIR': '${obj}.${TOOLSET}/${TARGET}/geni', + 'SHARED_INTERMEDIATE_DIR': '${obj}/gen', + 'PRODUCT_DIR': '${builddir}', + 'RULE_INPUT_PATH': '${RULE_INPUT_PATH}', + 'RULE_INPUT_DIRNAME': '${RULE_INPUT_DIRNAME}', + 'RULE_INPUT_NAME': '${RULE_INPUT_NAME}', + 'RULE_INPUT_ROOT': '${RULE_INPUT_ROOT}', + 'RULE_INPUT_EXT': '${RULE_INPUT_EXT}', + 'CONFIGURATION_NAME': '${configuration}', +} + +FULL_PATH_VARS = ('${CMAKE_SOURCE_DIR}', '${builddir}', '${obj}') + +generator_supports_multiple_toolsets = True +generator_wants_static_library_dependencies_adjusted = True + +COMPILABLE_EXTENSIONS = { + '.c': 'cc', + '.cc': 'cxx', + '.cpp': 'cxx', + '.cxx': 'cxx', + '.s': 's', # cc + '.S': 's', # cc +} + + +def RemovePrefix(a, prefix): + """Returns 'a' without 'prefix' if it starts with 'prefix'.""" + return a[len(prefix):] if a.startswith(prefix) else a + + +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + default_variables.setdefault('OS', gyp.common.GetFlavor(params)) + + +def Compilable(filename): + """Return true if the file is compilable (should be in OBJS).""" + return any(filename.endswith(e) for e in COMPILABLE_EXTENSIONS) + + +def Linkable(filename): + """Return true if the file is linkable (should be on the link line).""" + return filename.endswith('.o') + + +def NormjoinPathForceCMakeSource(base_path, rel_path): + """Resolves rel_path against base_path and returns the result. + + If rel_path is an absolute path it is returned unchanged. + Otherwise it is resolved against base_path and normalized. + If the result is a relative path, it is forced to be relative to the + CMakeLists.txt. + """ + if os.path.isabs(rel_path): + return rel_path + if any([rel_path.startswith(var) for var in FULL_PATH_VARS]): + return rel_path + # TODO: do we need to check base_path for absolute variables as well? + return os.path.join('${CMAKE_SOURCE_DIR}', + os.path.normpath(os.path.join(base_path, rel_path))) + + +def NormjoinPath(base_path, rel_path): + """Resolves rel_path against base_path and returns the result. + TODO: what is this really used for? + If rel_path begins with '$' it is returned unchanged. + Otherwise it is resolved against base_path if relative, then normalized. + """ + if rel_path.startswith('$') and not rel_path.startswith('${configuration}'): + return rel_path + return os.path.normpath(os.path.join(base_path, rel_path)) + + +def CMakeStringEscape(a): + """Escapes the string 'a' for use inside a CMake string. + + This means escaping + '\' otherwise it may be seen as modifying the next character + '"' otherwise it will end the string + ';' otherwise the string becomes a list + + The following do not need to be escaped + '#' when the lexer is in string state, this does not start a comment + + The following are yet unknown + '$' generator variables (like ${obj}) must not be escaped, + but text $ should be escaped + what is wanted is to know which $ come from generator variables + """ + return a.replace('\\', '\\\\').replace(';', '\\;').replace('"', '\\"') + + +def SetFileProperty(output, source_name, property_name, values, sep): + """Given a set of source file, sets the given property on them.""" + output.write('set_source_files_properties(') + output.write(source_name) + output.write(' PROPERTIES ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('")\n') + + +def SetFilesProperty(output, variable, property_name, values, sep): + """Given a set of source files, sets the given property on them.""" + output.write('set_source_files_properties(') + WriteVariable(output, variable) + output.write(' PROPERTIES ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('")\n') + + +def SetTargetProperty(output, target_name, property_name, values, sep=''): + """Given a target, sets the given property.""" + output.write('set_target_properties(') + output.write(target_name) + output.write(' PROPERTIES ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('")\n') + + +def SetVariable(output, variable_name, value): + """Sets a CMake variable.""" + output.write('set(') + output.write(variable_name) + output.write(' "') + output.write(CMakeStringEscape(value)) + output.write('")\n') + + +def SetVariableList(output, variable_name, values): + """Sets a CMake variable to a list.""" + if not values: + return SetVariable(output, variable_name, "") + if len(values) == 1: + return SetVariable(output, variable_name, values[0]) + output.write('list(APPEND ') + output.write(variable_name) + output.write('\n "') + output.write('"\n "'.join([CMakeStringEscape(value) for value in values])) + output.write('")\n') + + +def UnsetVariable(output, variable_name): + """Unsets a CMake variable.""" + output.write('unset(') + output.write(variable_name) + output.write(')\n') + + +def WriteVariable(output, variable_name, prepend=None): + if prepend: + output.write(prepend) + output.write('${') + output.write(variable_name) + output.write('}') + + +class CMakeTargetType(object): + def __init__(self, command, modifier, property_modifier): + self.command = command + self.modifier = modifier + self.property_modifier = property_modifier + + +cmake_target_type_from_gyp_target_type = { + 'executable': CMakeTargetType('add_executable', None, 'RUNTIME'), + 'static_library': CMakeTargetType('add_library', 'STATIC', 'ARCHIVE'), + 'shared_library': CMakeTargetType('add_library', 'SHARED', 'LIBRARY'), + 'loadable_module': CMakeTargetType('add_library', 'MODULE', 'LIBRARY'), + 'none': CMakeTargetType('add_custom_target', 'SOURCES', None), +} + + +def StringToCMakeTargetName(a): + """Converts the given string 'a' to a valid CMake target name. + + All invalid characters are replaced by '_'. + Invalid for cmake: ' ', '/', '(', ')', '"' + Invalid for make: ':' + Invalid for unknown reasons but cause failures: '.' + """ + return a.translate(string.maketrans(' /():."', '_______')) + + +def WriteActions(target_name, actions, extra_sources, extra_deps, + path_to_gyp, output): + """Write CMake for the 'actions' in the target. + + Args: + target_name: the name of the CMake target being generated. + actions: the Gyp 'actions' dict for this target. + extra_sources: [(, )] to append with generated source files. + extra_deps: [] to append with generated targets. + path_to_gyp: relative path from CMakeLists.txt being generated to + the Gyp file in which the target being generated is defined. + """ + for action in actions: + action_name = StringToCMakeTargetName(action['action_name']) + action_target_name = '%s__%s' % (target_name, action_name) + + inputs = action['inputs'] + inputs_name = action_target_name + '__input' + SetVariableList(output, inputs_name, + [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) + + outputs = action['outputs'] + cmake_outputs = [NormjoinPathForceCMakeSource(path_to_gyp, out) + for out in outputs] + outputs_name = action_target_name + '__output' + SetVariableList(output, outputs_name, cmake_outputs) + + # Build up a list of outputs. + # Collect the output dirs we'll need. + dirs = set(dir for dir in (os.path.dirname(o) for o in outputs) if dir) + + if int(action.get('process_outputs_as_sources', False)): + extra_sources.extend(zip(cmake_outputs, outputs)) + + # add_custom_command + output.write('add_custom_command(OUTPUT ') + WriteVariable(output, outputs_name) + output.write('\n') + + if len(dirs) > 0: + for directory in dirs: + output.write(' COMMAND ${CMAKE_COMMAND} -E make_directory ') + output.write(directory) + output.write('\n') + + output.write(' COMMAND ') + output.write(gyp.common.EncodePOSIXShellList(action['action'])) + output.write('\n') + + output.write(' DEPENDS ') + WriteVariable(output, inputs_name) + output.write('\n') + + output.write(' WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/') + output.write(path_to_gyp) + output.write('\n') + + output.write(' COMMENT ') + if 'message' in action: + output.write(action['message']) + else: + output.write(action_target_name) + output.write('\n') + + output.write(' VERBATIM\n') + output.write(')\n') + + # add_custom_target + output.write('add_custom_target(') + output.write(action_target_name) + output.write('\n DEPENDS ') + WriteVariable(output, outputs_name) + output.write('\n SOURCES ') + WriteVariable(output, inputs_name) + output.write('\n)\n') + + extra_deps.append(action_target_name) + + +def NormjoinRulePathForceCMakeSource(base_path, rel_path, rule_source): + if rel_path.startswith(("${RULE_INPUT_PATH}","${RULE_INPUT_DIRNAME}")): + if any([rule_source.startswith(var) for var in FULL_PATH_VARS]): + return rel_path + return NormjoinPathForceCMakeSource(base_path, rel_path) + + +def WriteRules(target_name, rules, extra_sources, extra_deps, + path_to_gyp, output): + """Write CMake for the 'rules' in the target. + + Args: + target_name: the name of the CMake target being generated. + actions: the Gyp 'actions' dict for this target. + extra_sources: [(, )] to append with generated source files. + extra_deps: [] to append with generated targets. + path_to_gyp: relative path from CMakeLists.txt being generated to + the Gyp file in which the target being generated is defined. + """ + for rule in rules: + rule_name = StringToCMakeTargetName(target_name + '__' + rule['rule_name']) + + inputs = rule.get('inputs', []) + inputs_name = rule_name + '__input' + SetVariableList(output, inputs_name, + [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) + outputs = rule['outputs'] + var_outputs = [] + + for count, rule_source in enumerate(rule.get('rule_sources', [])): + action_name = rule_name + '_' + str(count) + + rule_source_dirname, rule_source_basename = os.path.split(rule_source) + rule_source_root, rule_source_ext = os.path.splitext(rule_source_basename) + + SetVariable(output, 'RULE_INPUT_PATH', rule_source) + SetVariable(output, 'RULE_INPUT_DIRNAME', rule_source_dirname) + SetVariable(output, 'RULE_INPUT_NAME', rule_source_basename) + SetVariable(output, 'RULE_INPUT_ROOT', rule_source_root) + SetVariable(output, 'RULE_INPUT_EXT', rule_source_ext) + + # Build up a list of outputs. + # Collect the output dirs we'll need. + dirs = set(dir for dir in (os.path.dirname(o) for o in outputs) if dir) + + # Create variables for the output, as 'local' variable will be unset. + these_outputs = [] + for output_index, out in enumerate(outputs): + output_name = action_name + '_' + str(output_index) + SetVariable(output, output_name, + NormjoinRulePathForceCMakeSource(path_to_gyp, out, + rule_source)) + if int(rule.get('process_outputs_as_sources', False)): + extra_sources.append(('${' + output_name + '}', out)) + these_outputs.append('${' + output_name + '}') + var_outputs.append('${' + output_name + '}') + + # add_custom_command + output.write('add_custom_command(OUTPUT\n') + for out in these_outputs: + output.write(' ') + output.write(out) + output.write('\n') + + for directory in dirs: + output.write(' COMMAND ${CMAKE_COMMAND} -E make_directory ') + output.write(directory) + output.write('\n') + + output.write(' COMMAND ') + output.write(gyp.common.EncodePOSIXShellList(rule['action'])) + output.write('\n') + + output.write(' DEPENDS ') + WriteVariable(output, inputs_name) + output.write(' ') + output.write(NormjoinPath(path_to_gyp, rule_source)) + output.write('\n') + + # CMAKE_SOURCE_DIR is where the CMakeLists.txt lives. + # The cwd is the current build directory. + output.write(' WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/') + output.write(path_to_gyp) + output.write('\n') + + output.write(' COMMENT ') + if 'message' in rule: + output.write(rule['message']) + else: + output.write(action_name) + output.write('\n') + + output.write(' VERBATIM\n') + output.write(')\n') + + UnsetVariable(output, 'RULE_INPUT_PATH') + UnsetVariable(output, 'RULE_INPUT_DIRNAME') + UnsetVariable(output, 'RULE_INPUT_NAME') + UnsetVariable(output, 'RULE_INPUT_ROOT') + UnsetVariable(output, 'RULE_INPUT_EXT') + + # add_custom_target + output.write('add_custom_target(') + output.write(rule_name) + output.write(' DEPENDS\n') + for out in var_outputs: + output.write(' ') + output.write(out) + output.write('\n') + output.write('SOURCES ') + WriteVariable(output, inputs_name) + output.write('\n') + for rule_source in rule.get('rule_sources', []): + output.write(' ') + output.write(NormjoinPath(path_to_gyp, rule_source)) + output.write('\n') + output.write(')\n') + + extra_deps.append(rule_name) + + +def WriteCopies(target_name, copies, extra_deps, path_to_gyp, output): + """Write CMake for the 'copies' in the target. + + Args: + target_name: the name of the CMake target being generated. + actions: the Gyp 'actions' dict for this target. + extra_deps: [] to append with generated targets. + path_to_gyp: relative path from CMakeLists.txt being generated to + the Gyp file in which the target being generated is defined. + """ + copy_name = target_name + '__copies' + + # CMake gets upset with custom targets with OUTPUT which specify no output. + have_copies = any(copy['files'] for copy in copies) + if not have_copies: + output.write('add_custom_target(') + output.write(copy_name) + output.write(')\n') + extra_deps.append(copy_name) + return + + class Copy(object): + def __init__(self, ext, command): + self.cmake_inputs = [] + self.cmake_outputs = [] + self.gyp_inputs = [] + self.gyp_outputs = [] + self.ext = ext + self.inputs_name = None + self.outputs_name = None + self.command = command + + file_copy = Copy('', 'copy') + dir_copy = Copy('_dirs', 'copy_directory') + + for copy in copies: + files = copy['files'] + destination = copy['destination'] + for src in files: + path = os.path.normpath(src) + basename = os.path.split(path)[1] + dst = os.path.join(destination, basename) + + copy = file_copy if os.path.basename(src) else dir_copy + + copy.cmake_inputs.append(NormjoinPathForceCMakeSource(path_to_gyp, src)) + copy.cmake_outputs.append(NormjoinPathForceCMakeSource(path_to_gyp, dst)) + copy.gyp_inputs.append(src) + copy.gyp_outputs.append(dst) + + for copy in (file_copy, dir_copy): + if copy.cmake_inputs: + copy.inputs_name = copy_name + '__input' + copy.ext + SetVariableList(output, copy.inputs_name, copy.cmake_inputs) + + copy.outputs_name = copy_name + '__output' + copy.ext + SetVariableList(output, copy.outputs_name, copy.cmake_outputs) + + # add_custom_command + output.write('add_custom_command(\n') + + output.write('OUTPUT') + for copy in (file_copy, dir_copy): + if copy.outputs_name: + WriteVariable(output, copy.outputs_name, ' ') + output.write('\n') + + for copy in (file_copy, dir_copy): + for src, dst in zip(copy.gyp_inputs, copy.gyp_outputs): + # 'cmake -E copy src dst' will create the 'dst' directory if needed. + output.write('COMMAND ${CMAKE_COMMAND} -E %s ' % copy.command) + output.write(src) + output.write(' ') + output.write(dst) + output.write("\n") + + output.write('DEPENDS') + for copy in (file_copy, dir_copy): + if copy.inputs_name: + WriteVariable(output, copy.inputs_name, ' ') + output.write('\n') + + output.write('WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/') + output.write(path_to_gyp) + output.write('\n') + + output.write('COMMENT Copying for ') + output.write(target_name) + output.write('\n') + + output.write('VERBATIM\n') + output.write(')\n') + + # add_custom_target + output.write('add_custom_target(') + output.write(copy_name) + output.write('\n DEPENDS') + for copy in (file_copy, dir_copy): + if copy.outputs_name: + WriteVariable(output, copy.outputs_name, ' ') + output.write('\n SOURCES') + if file_copy.inputs_name: + WriteVariable(output, file_copy.inputs_name, ' ') + output.write('\n)\n') + + extra_deps.append(copy_name) + + +def CreateCMakeTargetBaseName(qualified_target): + """This is the name we would like the target to have.""" + _, gyp_target_name, gyp_target_toolset = ( + gyp.common.ParseQualifiedTarget(qualified_target)) + cmake_target_base_name = gyp_target_name + if gyp_target_toolset and gyp_target_toolset != 'target': + cmake_target_base_name += '_' + gyp_target_toolset + return StringToCMakeTargetName(cmake_target_base_name) + + +def CreateCMakeTargetFullName(qualified_target): + """An unambiguous name for the target.""" + gyp_file, gyp_target_name, gyp_target_toolset = ( + gyp.common.ParseQualifiedTarget(qualified_target)) + cmake_target_full_name = gyp_file + ':' + gyp_target_name + if gyp_target_toolset and gyp_target_toolset != 'target': + cmake_target_full_name += '_' + gyp_target_toolset + return StringToCMakeTargetName(cmake_target_full_name) + + +class CMakeNamer(object): + """Converts Gyp target names into CMake target names. + + CMake requires that target names be globally unique. One way to ensure + this is to fully qualify the names of the targets. Unfortunatly, this + ends up with all targets looking like "chrome_chrome_gyp_chrome" instead + of just "chrome". If this generator were only interested in building, it + would be possible to fully qualify all target names, then create + unqualified target names which depend on all qualified targets which + should have had that name. This is more or less what the 'make' generator + does with aliases. However, one goal of this generator is to create CMake + files for use with IDEs, and fully qualified names are not as user + friendly. + + Since target name collision is rare, we do the above only when required. + + Toolset variants are always qualified from the base, as this is required for + building. However, it also makes sense for an IDE, as it is possible for + defines to be different. + """ + def __init__(self, target_list): + self.cmake_target_base_names_conficting = set() + + cmake_target_base_names_seen = set() + for qualified_target in target_list: + cmake_target_base_name = CreateCMakeTargetBaseName(qualified_target) + + if cmake_target_base_name not in cmake_target_base_names_seen: + cmake_target_base_names_seen.add(cmake_target_base_name) + else: + self.cmake_target_base_names_conficting.add(cmake_target_base_name) + + def CreateCMakeTargetName(self, qualified_target): + base_name = CreateCMakeTargetBaseName(qualified_target) + if base_name in self.cmake_target_base_names_conficting: + return CreateCMakeTargetFullName(qualified_target) + return base_name + + +def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, + options, generator_flags, all_qualified_targets, output): + + # The make generator does this always. + # TODO: It would be nice to be able to tell CMake all dependencies. + circular_libs = generator_flags.get('circular', True) + + if not generator_flags.get('standalone', False): + output.write('\n#') + output.write(qualified_target) + output.write('\n') + + gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) + rel_gyp_file = gyp.common.RelativePath(gyp_file, options.toplevel_dir) + rel_gyp_dir = os.path.dirname(rel_gyp_file) + + # Relative path from build dir to top dir. + build_to_top = gyp.common.InvertRelativePath(build_dir, options.toplevel_dir) + # Relative path from build dir to gyp dir. + build_to_gyp = os.path.join(build_to_top, rel_gyp_dir) + + path_from_cmakelists_to_gyp = build_to_gyp + + spec = target_dicts.get(qualified_target, {}) + config = spec.get('configurations', {}).get(config_to_use, {}) + + target_name = spec.get('target_name', '') + target_type = spec.get('type', '') + target_toolset = spec.get('toolset') + + cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) + if cmake_target_type is None: + print ('Target %s has unknown target type %s, skipping.' % + ( target_name, target_type ) ) + return + + SetVariable(output, 'TARGET', target_name) + SetVariable(output, 'TOOLSET', target_toolset) + + cmake_target_name = namer.CreateCMakeTargetName(qualified_target) + + extra_sources = [] + extra_deps = [] + + # Actions must come first, since they can generate more OBJs for use below. + if 'actions' in spec: + WriteActions(cmake_target_name, spec['actions'], extra_sources, extra_deps, + path_from_cmakelists_to_gyp, output) + + # Rules must be early like actions. + if 'rules' in spec: + WriteRules(cmake_target_name, spec['rules'], extra_sources, extra_deps, + path_from_cmakelists_to_gyp, output) + + # Copies + if 'copies' in spec: + WriteCopies(cmake_target_name, spec['copies'], extra_deps, + path_from_cmakelists_to_gyp, output) + + # Target and sources + srcs = spec.get('sources', []) + + # Gyp separates the sheep from the goats based on file extensions. + # A full separation is done here because of flag handing (see below). + s_sources = [] + c_sources = [] + cxx_sources = [] + linkable_sources = [] + other_sources = [] + for src in srcs: + _, ext = os.path.splitext(src) + src_type = COMPILABLE_EXTENSIONS.get(ext, None) + src_norm_path = NormjoinPath(path_from_cmakelists_to_gyp, src); + + if src_type == 's': + s_sources.append(src_norm_path) + elif src_type == 'cc': + c_sources.append(src_norm_path) + elif src_type == 'cxx': + cxx_sources.append(src_norm_path) + elif Linkable(ext): + linkable_sources.append(src_norm_path) + else: + other_sources.append(src_norm_path) + + for extra_source in extra_sources: + src, real_source = extra_source + _, ext = os.path.splitext(real_source) + src_type = COMPILABLE_EXTENSIONS.get(ext, None) + + if src_type == 's': + s_sources.append(src) + elif src_type == 'cc': + c_sources.append(src) + elif src_type == 'cxx': + cxx_sources.append(src) + elif Linkable(ext): + linkable_sources.append(src) + else: + other_sources.append(src) + + s_sources_name = None + if s_sources: + s_sources_name = cmake_target_name + '__asm_srcs' + SetVariableList(output, s_sources_name, s_sources) + + c_sources_name = None + if c_sources: + c_sources_name = cmake_target_name + '__c_srcs' + SetVariableList(output, c_sources_name, c_sources) + + cxx_sources_name = None + if cxx_sources: + cxx_sources_name = cmake_target_name + '__cxx_srcs' + SetVariableList(output, cxx_sources_name, cxx_sources) + + linkable_sources_name = None + if linkable_sources: + linkable_sources_name = cmake_target_name + '__linkable_srcs' + SetVariableList(output, linkable_sources_name, linkable_sources) + + other_sources_name = None + if other_sources: + other_sources_name = cmake_target_name + '__other_srcs' + SetVariableList(output, other_sources_name, other_sources) + + # CMake gets upset when executable targets provide no sources. + # http://www.cmake.org/pipermail/cmake/2010-July/038461.html + dummy_sources_name = None + has_sources = (s_sources_name or + c_sources_name or + cxx_sources_name or + linkable_sources_name or + other_sources_name) + if target_type == 'executable' and not has_sources: + dummy_sources_name = cmake_target_name + '__dummy_srcs' + SetVariable(output, dummy_sources_name, + "${obj}.${TOOLSET}/${TARGET}/genc/dummy.c") + output.write('if(NOT EXISTS "') + WriteVariable(output, dummy_sources_name) + output.write('")\n') + output.write(' file(WRITE "') + WriteVariable(output, dummy_sources_name) + output.write('" "")\n') + output.write("endif()\n") + + + # CMake is opposed to setting linker directories and considers the practice + # of setting linker directories dangerous. Instead, it favors the use of + # find_library and passing absolute paths to target_link_libraries. + # However, CMake does provide the command link_directories, which adds + # link directories to targets defined after it is called. + # As a result, link_directories must come before the target definition. + # CMake unfortunately has no means of removing entries from LINK_DIRECTORIES. + library_dirs = config.get('library_dirs') + if library_dirs is not None: + output.write('link_directories(') + for library_dir in library_dirs: + output.write(' ') + output.write(NormjoinPath(path_from_cmakelists_to_gyp, library_dir)) + output.write('\n') + output.write(')\n') + + output.write(cmake_target_type.command) + output.write('(') + output.write(cmake_target_name) + + if cmake_target_type.modifier is not None: + output.write(' ') + output.write(cmake_target_type.modifier) + + if s_sources_name: + WriteVariable(output, s_sources_name, ' ') + if c_sources_name: + WriteVariable(output, c_sources_name, ' ') + if cxx_sources_name: + WriteVariable(output, cxx_sources_name, ' ') + if linkable_sources_name: + WriteVariable(output, linkable_sources_name, ' ') + if other_sources_name: + WriteVariable(output, other_sources_name, ' ') + if dummy_sources_name: + WriteVariable(output, dummy_sources_name, ' ') + + output.write(')\n') + + # Let CMake know if the 'all' target should depend on this target. + exclude_from_all = ('TRUE' if qualified_target not in all_qualified_targets + else 'FALSE') + SetTargetProperty(output, cmake_target_name, + 'EXCLUDE_FROM_ALL', exclude_from_all) + for extra_target_name in extra_deps: + SetTargetProperty(output, extra_target_name, + 'EXCLUDE_FROM_ALL', exclude_from_all) + + # Output name and location. + if target_type != 'none': + # Link as 'C' if there are no other files + if not c_sources and not cxx_sources: + SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) + + # Mark uncompiled sources as uncompiled. + if other_sources_name: + output.write('set_source_files_properties(') + WriteVariable(output, other_sources_name, '') + output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') + + # Mark object sources as linkable. + if linkable_sources_name: + output.write('set_source_files_properties(') + WriteVariable(output, other_sources_name, '') + output.write(' PROPERTIES EXTERNAL_OBJECT "TRUE")\n') + + # Output directory + target_output_directory = spec.get('product_dir') + if target_output_directory is None: + if target_type in ('executable', 'loadable_module'): + target_output_directory = generator_default_variables['PRODUCT_DIR'] + elif target_type == 'shared_library': + target_output_directory = '${builddir}/lib.${TOOLSET}' + elif spec.get('standalone_static_library', False): + target_output_directory = generator_default_variables['PRODUCT_DIR'] + else: + base_path = gyp.common.RelativePath(os.path.dirname(gyp_file), + options.toplevel_dir) + target_output_directory = '${obj}.${TOOLSET}' + target_output_directory = ( + os.path.join(target_output_directory, base_path)) + + cmake_target_output_directory = NormjoinPathForceCMakeSource( + path_from_cmakelists_to_gyp, + target_output_directory) + SetTargetProperty(output, + cmake_target_name, + cmake_target_type.property_modifier + '_OUTPUT_DIRECTORY', + cmake_target_output_directory) + + # Output name + default_product_prefix = '' + default_product_name = target_name + default_product_ext = '' + if target_type == 'static_library': + static_library_prefix = generator_default_variables['STATIC_LIB_PREFIX'] + default_product_name = RemovePrefix(default_product_name, + static_library_prefix) + default_product_prefix = static_library_prefix + default_product_ext = generator_default_variables['STATIC_LIB_SUFFIX'] + + elif target_type in ('loadable_module', 'shared_library'): + shared_library_prefix = generator_default_variables['SHARED_LIB_PREFIX'] + default_product_name = RemovePrefix(default_product_name, + shared_library_prefix) + default_product_prefix = shared_library_prefix + default_product_ext = generator_default_variables['SHARED_LIB_SUFFIX'] + + elif target_type != 'executable': + print ('ERROR: What output file should be generated?', + 'type', target_type, 'target', target_name) + + product_prefix = spec.get('product_prefix', default_product_prefix) + product_name = spec.get('product_name', default_product_name) + product_ext = spec.get('product_extension') + if product_ext: + product_ext = '.' + product_ext + else: + product_ext = default_product_ext + + SetTargetProperty(output, cmake_target_name, 'PREFIX', product_prefix) + SetTargetProperty(output, cmake_target_name, + cmake_target_type.property_modifier + '_OUTPUT_NAME', + product_name) + SetTargetProperty(output, cmake_target_name, 'SUFFIX', product_ext) + + # Make the output of this target referenceable as a source. + cmake_target_output_basename = product_prefix + product_name + product_ext + cmake_target_output = os.path.join(cmake_target_output_directory, + cmake_target_output_basename) + SetFileProperty(output, cmake_target_output, 'GENERATED', ['TRUE'], '') + + # Includes + includes = config.get('include_dirs') + if includes: + # This (target include directories) is what requires CMake 2.8.8 + includes_name = cmake_target_name + '__include_dirs' + SetVariableList(output, includes_name, + [NormjoinPathForceCMakeSource(path_from_cmakelists_to_gyp, include) + for include in includes]) + output.write('set_property(TARGET ') + output.write(cmake_target_name) + output.write(' APPEND PROPERTY INCLUDE_DIRECTORIES ') + WriteVariable(output, includes_name, '') + output.write(')\n') + + # Defines + defines = config.get('defines') + if defines is not None: + SetTargetProperty(output, + cmake_target_name, + 'COMPILE_DEFINITIONS', + defines, + ';') + + # Compile Flags - http://www.cmake.org/Bug/view.php?id=6493 + # CMake currently does not have target C and CXX flags. + # So, instead of doing... + + # cflags_c = config.get('cflags_c') + # if cflags_c is not None: + # SetTargetProperty(output, cmake_target_name, + # 'C_COMPILE_FLAGS', cflags_c, ' ') + + # cflags_cc = config.get('cflags_cc') + # if cflags_cc is not None: + # SetTargetProperty(output, cmake_target_name, + # 'CXX_COMPILE_FLAGS', cflags_cc, ' ') + + # Instead we must... + cflags = config.get('cflags', []) + cflags_c = config.get('cflags_c', []) + cflags_cxx = config.get('cflags_cc', []) + if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): + SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') + + elif c_sources and not (s_sources or cxx_sources): + flags = [] + flags.extend(cflags) + flags.extend(cflags_c) + SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') + + elif cxx_sources and not (s_sources or c_sources): + flags = [] + flags.extend(cflags) + flags.extend(cflags_cxx) + SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') + + else: + # TODO: This is broken, one cannot generally set properties on files, + # as other targets may require different properties on the same files. + if s_sources and cflags: + SetFilesProperty(output, s_sources_name, 'COMPILE_FLAGS', cflags, ' ') + + if c_sources and (cflags or cflags_c): + flags = [] + flags.extend(cflags) + flags.extend(cflags_c) + SetFilesProperty(output, c_sources_name, 'COMPILE_FLAGS', flags, ' ') + + if cxx_sources and (cflags or cflags_cxx): + flags = [] + flags.extend(cflags) + flags.extend(cflags_cxx) + SetFilesProperty(output, cxx_sources_name, 'COMPILE_FLAGS', flags, ' ') + + # Linker flags + ldflags = config.get('ldflags') + if ldflags is not None: + SetTargetProperty(output, cmake_target_name, 'LINK_FLAGS', ldflags, ' ') + + # Note on Dependencies and Libraries: + # CMake wants to handle link order, resolving the link line up front. + # Gyp does not retain or enforce specifying enough information to do so. + # So do as other gyp generators and use --start-group and --end-group. + # Give CMake as little information as possible so that it doesn't mess it up. + + # Dependencies + rawDeps = spec.get('dependencies', []) + + static_deps = [] + shared_deps = [] + other_deps = [] + for rawDep in rawDeps: + dep_cmake_name = namer.CreateCMakeTargetName(rawDep) + dep_spec = target_dicts.get(rawDep, {}) + dep_target_type = dep_spec.get('type', None) + + if dep_target_type == 'static_library': + static_deps.append(dep_cmake_name) + elif dep_target_type == 'shared_library': + shared_deps.append(dep_cmake_name) + else: + other_deps.append(dep_cmake_name) + + # ensure all external dependencies are complete before internal dependencies + # extra_deps currently only depend on their own deps, so otherwise run early + if static_deps or shared_deps or other_deps: + for extra_dep in extra_deps: + output.write('add_dependencies(') + output.write(extra_dep) + output.write('\n') + for deps in (static_deps, shared_deps, other_deps): + for dep in gyp.common.uniquer(deps): + output.write(' ') + output.write(dep) + output.write('\n') + output.write(')\n') + + linkable = target_type in ('executable', 'loadable_module', 'shared_library') + other_deps.extend(extra_deps) + if other_deps or (not linkable and (static_deps or shared_deps)): + output.write('add_dependencies(') + output.write(cmake_target_name) + output.write('\n') + for dep in gyp.common.uniquer(other_deps): + output.write(' ') + output.write(dep) + output.write('\n') + if not linkable: + for deps in (static_deps, shared_deps): + for lib_dep in gyp.common.uniquer(deps): + output.write(' ') + output.write(lib_dep) + output.write('\n') + output.write(')\n') + + # Libraries + if linkable: + external_libs = [lib for lib in spec.get('libraries', []) if len(lib) > 0] + if external_libs or static_deps or shared_deps: + output.write('target_link_libraries(') + output.write(cmake_target_name) + output.write('\n') + if static_deps: + write_group = circular_libs and len(static_deps) > 1 + if write_group: + output.write('-Wl,--start-group\n') + for dep in gyp.common.uniquer(static_deps): + output.write(' ') + output.write(dep) + output.write('\n') + if write_group: + output.write('-Wl,--end-group\n') + if shared_deps: + for dep in gyp.common.uniquer(shared_deps): + output.write(' ') + output.write(dep) + output.write('\n') + if external_libs: + for lib in gyp.common.uniquer(external_libs): + output.write(' ') + output.write(lib) + output.write('\n') + + output.write(')\n') + + UnsetVariable(output, 'TOOLSET') + UnsetVariable(output, 'TARGET') + + +def GenerateOutputForConfig(target_list, target_dicts, data, + params, config_to_use): + options = params['options'] + generator_flags = params['generator_flags'] + + # generator_dir: relative path from pwd to where make puts build files. + # Makes migrating from make to cmake easier, cmake doesn't put anything here. + # Each Gyp configuration creates a different CMakeLists.txt file + # to avoid incompatibilities between Gyp and CMake configurations. + generator_dir = os.path.relpath(options.generator_output or '.') + + # output_dir: relative path from generator_dir to the build directory. + output_dir = generator_flags.get('output_dir', 'out') + + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.normpath(os.path.join(generator_dir, + output_dir, + config_to_use)) + + toplevel_build = os.path.join(options.toplevel_dir, build_dir) + + output_file = os.path.join(toplevel_build, 'CMakeLists.txt') + gyp.common.EnsureDirExists(output_file) + + output = open(output_file, 'w') + output.write('cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)\n') + output.write('cmake_policy(VERSION 2.8.8)\n') + + gyp_file, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1]) + output.write('project(') + output.write(project_target) + output.write(')\n') + + SetVariable(output, 'configuration', config_to_use) + + ar = None + cc = None + cxx = None + + make_global_settings = data[gyp_file].get('make_global_settings', []) + build_to_top = gyp.common.InvertRelativePath(build_dir, + options.toplevel_dir) + for key, value in make_global_settings: + if key == 'AR': + ar = os.path.join(build_to_top, value) + if key == 'CC': + cc = os.path.join(build_to_top, value) + if key == 'CXX': + cxx = os.path.join(build_to_top, value) + + ar = gyp.common.GetEnvironFallback(['AR_target', 'AR'], ar) + cc = gyp.common.GetEnvironFallback(['CC_target', 'CC'], cc) + cxx = gyp.common.GetEnvironFallback(['CXX_target', 'CXX'], cxx) + + if ar: + SetVariable(output, 'CMAKE_AR', ar) + if cc: + SetVariable(output, 'CMAKE_C_COMPILER', cc) + if cxx: + SetVariable(output, 'CMAKE_CXX_COMPILER', cxx) + + # The following appears to be as-yet undocumented. + # http://public.kitware.com/Bug/view.php?id=8392 + output.write('enable_language(ASM)\n') + # ASM-ATT does not support .S files. + # output.write('enable_language(ASM-ATT)\n') + + if cc: + SetVariable(output, 'CMAKE_ASM_COMPILER', cc) + + SetVariable(output, 'builddir', '${CMAKE_BINARY_DIR}') + SetVariable(output, 'obj', '${builddir}/obj') + output.write('\n') + + # TODO: Undocumented/unsupported (the CMake Java generator depends on it). + # CMake by default names the object resulting from foo.c to be foo.c.o. + # Gyp traditionally names the object resulting from foo.c foo.o. + # This should be irrelevant, but some targets extract .o files from .a + # and depend on the name of the extracted .o files. + output.write('set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)\n') + output.write('set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)\n') + output.write('\n') + + # Force ninja to use rsp files. Otherwise link and ar lines can get too long, + # resulting in 'Argument list too long' errors. + output.write('set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1)\n') + output.write('\n') + + namer = CMakeNamer(target_list) + + # The list of targets upon which the 'all' target should depend. + # CMake has it's own implicit 'all' target, one is not created explicitly. + all_qualified_targets = set() + for build_file in params['build_files']: + for qualified_target in gyp.common.AllTargets(target_list, + target_dicts, + os.path.normpath(build_file)): + all_qualified_targets.add(qualified_target) + + for qualified_target in target_list: + WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, + options, generator_flags, all_qualified_targets, output) + + output.close() + + +def PerformBuild(data, configurations, params): + options = params['options'] + generator_flags = params['generator_flags'] + + # generator_dir: relative path from pwd to where make puts build files. + # Makes migrating from make to cmake easier, cmake doesn't put anything here. + generator_dir = os.path.relpath(options.generator_output or '.') + + # output_dir: relative path from generator_dir to the build directory. + output_dir = generator_flags.get('output_dir', 'out') + + for config_name in configurations: + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.normpath(os.path.join(generator_dir, + output_dir, + config_name)) + arguments = ['cmake', '-G', 'Ninja'] + print 'Generating [%s]: %s' % (config_name, arguments) + subprocess.check_call(arguments, cwd=build_dir) + + arguments = ['ninja', '-C', build_dir] + print 'Building [%s]: %s' % (config_name, arguments) + subprocess.check_call(arguments) + + +def CallGenerateOutputForConfig(arglist): + # Ignore the interrupt signal so that the parent process catches it and + # kills all multiprocessing children. + signal.signal(signal.SIGINT, signal.SIG_IGN) + + target_list, target_dicts, data, params, config_name = arglist + GenerateOutputForConfig(target_list, target_dicts, data, params, config_name) + + +def GenerateOutput(target_list, target_dicts, data, params): + user_config = params.get('generator_flags', {}).get('config', None) + if user_config: + GenerateOutputForConfig(target_list, target_dicts, data, + params, user_config) + else: + config_names = target_dicts[target_list[0]]['configurations'].keys() + if params['parallel']: + try: + pool = multiprocessing.Pool(len(config_names)) + arglists = [] + for config_name in config_names: + arglists.append((target_list, target_dicts, data, + params, config_name)) + pool.map(CallGenerateOutputForConfig, arglists) + except KeyboardInterrupt, e: + pool.terminate() + raise e + else: + for config_name in config_names: + GenerateOutputForConfig(target_list, target_dicts, data, + params, config_name) diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/dump_dependency_json.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/dump_dependency_json.py --- gyp-0.1~svn1729/pylib/gyp/generator/dump_dependency_json.py 2012-10-26 08:14:28.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/dump_dependency_json.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,6 +14,9 @@ generator_wants_static_library_dependencies_adjusted = False +generator_filelist_paths = { +} + generator_default_variables = { } for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', @@ -45,19 +48,7 @@ generator_additional_path_sections = getattr(msvs_generator, 'generator_additional_path_sections', []) - # Set a variable so conditions can be based on msvs_version. - msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags) - default_variables['MSVS_VERSION'] = msvs_version.ShortName() - - # To determine processor word size on Windows, in addition to checking - # PROCESSOR_ARCHITECTURE (which reflects the word size of the current - # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which - # contains the actual word size of the system when running thru WOW64). - if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or - '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): - default_variables['MSVS_OS_BITS'] = 64 - else: - default_variables['MSVS_OS_BITS'] = 32 + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) def CalculateGeneratorInputInfo(params): @@ -68,6 +59,17 @@ global generator_wants_static_library_dependencies_adjusted generator_wants_static_library_dependencies_adjusted = True + toplevel = params['options'].toplevel_dir + generator_dir = os.path.relpath(params['options'].generator_output or '.') + # output_dir: relative path from generator_dir to the build directory. + output_dir = generator_flags.get('output_dir', 'out') + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, generator_dir, output_dir, 'gypfiles')) + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': toplevel, + 'qualified_out_dir': qualified_out_dir, + } def GenerateOutput(target_list, target_dicts, data, params): # Map of target -> list of targets it depends on. @@ -86,7 +88,11 @@ edges[target].append(dep) targets_to_visit.append(dep) - filename = 'dump.json' + try: + filepath = params['generator_flags']['output_dir'] + except KeyError: + filepath = '.' + filename = os.path.join(filepath, 'dump.json') f = open(filename, 'w') json.dump(edges, f) f.close() diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/eclipse.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/eclipse.py --- gyp-0.1~svn1729/pylib/gyp/generator/eclipse.py 2013-02-13 19:15:24.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/eclipse.py 2015-09-13 13:41:20.000000000 +0000 @@ -22,7 +22,9 @@ import subprocess import gyp import gyp.common +import gyp.msvs_emulation import shlex +import xml.etree.cElementTree as ET generator_wants_static_library_dependencies_adjusted = False @@ -30,8 +32,8 @@ } for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']: - # Some gyp steps fail if these are empty(!). - generator_default_variables[dirname] = 'dir' + # Some gyp steps fail if these are empty(!), so we convert them to variables + generator_default_variables[dirname] = '$' + dirname for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', @@ -52,7 +54,18 @@ generator_flags = params.get('generator_flags', {}) for key, val in generator_flags.items(): default_variables.setdefault(key, val) - default_variables.setdefault('OS', gyp.common.GetFlavor(params)) + flavor = gyp.common.GetFlavor(params) + default_variables.setdefault('OS', flavor) + if flavor == 'win': + # Copy additional generator configuration data from VS, which is shared + # by the Eclipse generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) def CalculateGeneratorInputInfo(params): @@ -65,7 +78,8 @@ def GetAllIncludeDirectories(target_list, target_dicts, - shared_intermediate_dirs, config_name): + shared_intermediate_dirs, config_name, params, + compiler_path): """Calculate the set of include directories to be used. Returns: @@ -76,6 +90,36 @@ gyp_includes_set = set() compiler_includes_list = [] + # Find compiler's default include dirs. + if compiler_path: + command = shlex.split(compiler_path) + command.extend(['-E', '-xc++', '-v', '-']) + proc = subprocess.Popen(args=command, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output = proc.communicate()[1] + # Extract the list of include dirs from the output, which has this format: + # ... + # #include "..." search starts here: + # #include <...> search starts here: + # /usr/include/c++/4.6 + # /usr/local/include + # End of search list. + # ... + in_include_list = False + for line in output.splitlines(): + if line.startswith('#include'): + in_include_list = True + continue + if line.startswith('End of search list.'): + break + if in_include_list: + include_dir = line.strip() + if include_dir not in compiler_includes_list: + compiler_includes_list.append(include_dir) + + flavor = gyp.common.GetFlavor(params) + if flavor == 'win': + generator_flags = params.get('generator_flags', {}) for target_name in target_list: target = target_dicts[target_name] if config_name in target['configurations']: @@ -85,13 +129,16 @@ # may be done in gyp files to force certain includes to come at the end. # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and # remove this. - cflags = config['cflags'] + if flavor == 'win': + msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) + cflags = msvs_settings.GetCflags(config_name) + else: + cflags = config['cflags'] for cflag in cflags: - include_dir = '' if cflag.startswith('-I'): include_dir = cflag[2:] - if include_dir and not include_dir in compiler_includes_list: - compiler_includes_list.append(include_dir) + if include_dir not in compiler_includes_list: + compiler_includes_list.append(include_dir) # Find standard gyp include dirs. if config.has_key('include_dirs'): @@ -106,9 +153,7 @@ include_dir = base_dir + '/' + include_dir include_dir = os.path.abspath(include_dir) - if not include_dir in gyp_includes_set: - gyp_includes_set.add(include_dir) - + gyp_includes_set.add(include_dir) # Generate a list that has all the include dirs. all_includes_list = list(gyp_includes_set) @@ -121,7 +166,7 @@ return all_includes_list -def GetCompilerPath(target_list, target_dicts, data): +def GetCompilerPath(target_list, data, options): """Determine a command that can be used to invoke the compiler. Returns: @@ -129,13 +174,12 @@ the compiler from that. Otherwise, see if a compiler was specified via the CC_target environment variable. """ - # First, see if the compiler is configured in make's settings. build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) make_global_settings_dict = data[build_file].get('make_global_settings', {}) for key, value in make_global_settings_dict: if key in ['CC', 'CXX']: - return value + return os.path.join(options.toplevel_dir, value) # Check to see if the compiler was specified as an environment variable. for key in ['CC_target', 'CC', 'CXX']: @@ -146,7 +190,8 @@ return 'gcc' -def GetAllDefines(target_list, target_dicts, data, config_name): +def GetAllDefines(target_list, target_dicts, data, config_name, params, + compiler_path): """Calculate the defines for a project. Returns: @@ -156,25 +201,35 @@ # Get defines declared in the gyp files. all_defines = {} + flavor = gyp.common.GetFlavor(params) + if flavor == 'win': + generator_flags = params.get('generator_flags', {}) for target_name in target_list: target = target_dicts[target_name] + if flavor == 'win': + msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) + extra_defines = msvs_settings.GetComputedDefines(config_name) + else: + extra_defines = [] if config_name in target['configurations']: config = target['configurations'][config_name] - for define in config['defines']: - split_define = define.split('=', 1) - if len(split_define) == 1: - split_define.append('1') - if split_define[0].strip() in all_defines: - # Already defined - continue - - all_defines[split_define[0].strip()] = split_define[1].strip() - + target_defines = config['defines'] + else: + target_defines = [] + for define in target_defines + extra_defines: + split_define = define.split('=', 1) + if len(split_define) == 1: + split_define.append('1') + if split_define[0].strip() in all_defines: + # Already defined + continue + all_defines[split_define[0].strip()] = split_define[1].strip() # Get default compiler defines (if possible). - cc_target = GetCompilerPath(target_list, target_dicts, data) - if cc_target: - command = shlex.split(cc_target) + if flavor == 'win': + return all_defines # Default defines already processed in the loop above. + if compiler_path: + command = shlex.split(compiler_path) command.extend(['-E', '-dM', '-']) cpp_proc = subprocess.Popen(args=command, cwd='.', stdin=subprocess.PIPE, stdout=subprocess.PIPE) @@ -240,30 +295,123 @@ shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'), os.path.join(toplevel_build, 'gen')] - if not os.path.exists(toplevel_build): - os.makedirs(toplevel_build) - out = open(os.path.join(toplevel_build, 'eclipse-cdt-settings.xml'), 'w') - - out.write('\n') - out.write('\n') - - eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File', - 'GNU C++', 'GNU C', 'Assembly'] - include_dirs = GetAllIncludeDirectories(target_list, target_dicts, - shared_intermediate_dirs, config_name) - WriteIncludePaths(out, eclipse_langs, include_dirs) - defines = GetAllDefines(target_list, target_dicts, data, config_name) - WriteMacros(out, eclipse_langs, defines) + GenerateCdtSettingsFile(target_list, + target_dicts, + data, + params, + config_name, + os.path.join(toplevel_build, + 'eclipse-cdt-settings.xml'), + options, + shared_intermediate_dirs) + GenerateClasspathFile(target_list, + target_dicts, + options.toplevel_dir, + toplevel_build, + os.path.join(toplevel_build, + 'eclipse-classpath.xml')) + + +def GenerateCdtSettingsFile(target_list, target_dicts, data, params, + config_name, out_name, options, + shared_intermediate_dirs): + gyp.common.EnsureDirExists(out_name) + with open(out_name, 'w') as out: + out.write('\n') + out.write('\n') + + eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File', + 'GNU C++', 'GNU C', 'Assembly'] + compiler_path = GetCompilerPath(target_list, data, options) + include_dirs = GetAllIncludeDirectories(target_list, target_dicts, + shared_intermediate_dirs, + config_name, params, compiler_path) + WriteIncludePaths(out, eclipse_langs, include_dirs) + defines = GetAllDefines(target_list, target_dicts, data, config_name, + params, compiler_path) + WriteMacros(out, eclipse_langs, defines) + + out.write('\n') + + +def GenerateClasspathFile(target_list, target_dicts, toplevel_dir, + toplevel_build, out_name): + '''Generates a classpath file suitable for symbol navigation and code + completion of Java code (such as in Android projects) by finding all + .java and .jar files used as action inputs.''' + gyp.common.EnsureDirExists(out_name) + result = ET.Element('classpath') + + def AddElements(kind, paths): + # First, we need to normalize the paths so they are all relative to the + # toplevel dir. + rel_paths = set() + for path in paths: + if os.path.isabs(path): + rel_paths.add(os.path.relpath(path, toplevel_dir)) + else: + rel_paths.add(path) + + for path in sorted(rel_paths): + entry_element = ET.SubElement(result, 'classpathentry') + entry_element.set('kind', kind) + entry_element.set('path', path) + + AddElements('lib', GetJavaJars(target_list, target_dicts, toplevel_dir)) + AddElements('src', GetJavaSourceDirs(target_list, target_dicts, toplevel_dir)) + # Include the standard JRE container and a dummy out folder + AddElements('con', ['org.eclipse.jdt.launching.JRE_CONTAINER']) + # Include a dummy out folder so that Eclipse doesn't use the default /bin + # folder in the root of the project. + AddElements('output', [os.path.join(toplevel_build, '.eclipse-java-build')]) + + ET.ElementTree(result).write(out_name) + + +def GetJavaJars(target_list, target_dicts, toplevel_dir): + '''Generates a sequence of all .jars used as inputs.''' + for target_name in target_list: + target = target_dicts[target_name] + for action in target.get('actions', []): + for input_ in action['inputs']: + if os.path.splitext(input_)[1] == '.jar' and not input_.startswith('$'): + if os.path.isabs(input_): + yield input_ + else: + yield os.path.join(os.path.dirname(target_name), input_) + - out.write('\n') - out.close() +def GetJavaSourceDirs(target_list, target_dicts, toplevel_dir): + '''Generates a sequence of all likely java package root directories.''' + for target_name in target_list: + target = target_dicts[target_name] + for action in target.get('actions', []): + for input_ in action['inputs']: + if (os.path.splitext(input_)[1] == '.java' and + not input_.startswith('$')): + dir_ = os.path.dirname(os.path.join(os.path.dirname(target_name), + input_)) + # If there is a parent 'src' or 'java' folder, navigate up to it - + # these are canonical package root names in Chromium. This will + # break if 'src' or 'java' exists in the package structure. This + # could be further improved by inspecting the java file for the + # package name if this proves to be too fragile in practice. + parent_search = dir_ + while os.path.basename(parent_search) not in ['src', 'java']: + parent_search, _ = os.path.split(parent_search) + if not parent_search or parent_search == toplevel_dir: + # Didn't find a known root, just return the original path + yield dir_ + break + else: + yield parent_search def GenerateOutput(target_list, target_dicts, data, params): """Generate an XML settings file that can be imported into a CDT project.""" if params['options'].generator_output: - raise NotImplementedError, "--generator_output not implemented for eclipse" + raise NotImplementedError("--generator_output not implemented for eclipse") user_config = params.get('generator_flags', {}).get('config', None) if user_config: diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/gypd.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/gypd.py --- gyp-0.1~svn1729/pylib/gyp/generator/gypd.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/gypd.py 2015-09-13 13:41:20.000000000 +0000 @@ -39,9 +39,11 @@ # These variables should just be spit back out as variable references. _generator_identity_variables = [ + 'CONFIGURATION_NAME', 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', 'INTERMEDIATE_DIR', + 'LIB_DIR', 'PRODUCT_DIR', 'RULE_INPUT_ROOT', 'RULE_INPUT_DIRNAME', @@ -49,6 +51,11 @@ 'RULE_INPUT_NAME', 'RULE_INPUT_PATH', 'SHARED_INTERMEDIATE_DIR', + 'SHARED_LIB_DIR', + 'SHARED_LIB_PREFIX', + 'SHARED_LIB_SUFFIX', + 'STATIC_LIB_PREFIX', + 'STATIC_LIB_SUFFIX', ] # gypd doesn't define a default value for OS like many other generator diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/make.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/make.py --- gyp-0.1~svn1729/pylib/gyp/generator/make.py 2013-09-10 22:45:33.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/make.py 2015-09-13 13:41:20.000000000 +0000 @@ -29,6 +29,7 @@ import gyp.common import gyp.xcode_emulation from gyp.common import GetEnvironFallback +from gyp.common import GypError generator_default_variables = { 'EXECUTABLE_PREFIX': '', @@ -57,6 +58,7 @@ generator_additional_non_configuration_keys = [] generator_additional_path_sections = [] generator_extra_sources_for_rules = [] +generator_filelist_paths = None def CalculateVariables(default_variables, params): @@ -103,11 +105,17 @@ global generator_wants_sorted_dependencies generator_wants_sorted_dependencies = True + output_dir = params['options'].generator_output or \ + params['options'].toplevel_dir + builddir_name = generator_flags.get('output_dir', 'out') + qualified_out_dir = os.path.normpath(os.path.join( + output_dir, builddir_name, 'gypfiles')) -def ensure_directory_exists(path): - dir = os.path.dirname(path) - if dir and not os.path.exists(dir): - os.makedirs(dir) + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': params['options'].toplevel_dir, + 'qualified_out_dir': qualified_out_dir, + } # The .d checking code below uses these functions: @@ -201,6 +209,24 @@ """ +LINK_COMMANDS_AIX = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) +""" + + # Header of toplevel Makefile. # This should go into the build tree, but it's easier to keep it here for now. SHARED_HEADER = ("""\ @@ -255,15 +281,7 @@ AR.target ?= $(AR) # C++ apps need to be linked with g++. -# -# Note: flock is used to seralize linking. Linking is a memory-intensive -# process so running parallel links can often lead to thrashing. To disable -# the serialization, override LINK via an envrionment variable as follows: -# -# export LINK=g++ -# -# This will allow make to invoke N linker processes as specified in -jN. -LINK ?= %(flock)s $(builddir)/linker.lock $(CXX.target) +LINK ?= $(CXX.target) # TODO(evan): move all cross-compilation logic to gyp-time so we don't need # to replicate this environment fallback in make as well. @@ -479,14 +497,6 @@ cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" """ -SHARED_HEADER_SUN_COMMANDS = """ -# gyp-sun-tool is written next to the root Makefile by gyp. -# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd -# already. -quiet_cmd_sun_tool = SUNTOOL $(4) $< -cmd_sun_tool = ./gyp-sun-tool $(4) $< "$@" -""" - def WriteRootHeaderSuffixRules(writer): extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower) @@ -614,6 +624,38 @@ return s.replace(' ', quote) +# TODO: Avoid code duplication with _ValidateSourcesForMSVSProject in msvs.py. +def _ValidateSourcesForOSX(spec, all_sources): + """Makes sure if duplicate basenames are not specified in the source list. + + Arguments: + spec: The target dictionary containing the properties of the target. + """ + if spec.get('type', None) != 'static_library': + return + + basenames = {} + for source in all_sources: + name, ext = os.path.splitext(source) + is_compiled_file = ext in [ + '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] + if not is_compiled_file: + continue + basename = os.path.basename(name) # Don't include extension. + basenames.setdefault(basename, []).append(source) + + error = '' + for basename, files in basenames.iteritems(): + if len(files) > 1: + error += ' %s: %s\n' % (basename, ' '.join(files)) + + if error: + print('static library %s has several files with the same basename:\n' % + spec['target_name'] + error + 'libtool on OS X will generate' + + ' warnings for them.') + raise GypError('Duplicate basenames in sources section, see list above') + + # Map from qualified target to path to output. target_outputs = {} # Map from qualified target to any linkable output. A subset @@ -623,7 +665,7 @@ target_link_deps = {} -class MakefileWriter: +class MakefileWriter(object): """MakefileWriter packages up the writing of one target-specific foobar.mk. Its only real entry point is Write(), and is mostly used for namespacing. @@ -668,7 +710,7 @@ spec, configs: gyp info part_of_all: flag indicating this target is part of 'all' """ - ensure_directory_exists(output_filename) + gyp.common.EnsureDirExists(output_filename) self.fp = open(output_filename, 'w') @@ -741,6 +783,10 @@ # Sources. all_sources = spec.get('sources', []) + extra_sources if all_sources: + if self.flavor == 'mac': + # libtool on OS X generates warnings for duplicate basenames in the same + # target. + _ValidateSourcesForOSX(spec, all_sources) self.WriteSources( configs, deps, all_sources, extra_outputs, extra_link_deps, part_of_all, @@ -797,7 +843,7 @@ targets: list of "all" targets for this sub-project build_dir: build output directory, relative to the sub-project """ - ensure_directory_exists(output_filename) + gyp.common.EnsureDirExists(output_filename) self.fp = open(output_filename, 'w') self.fp.write(header) # For consistency with other builders, put sub-project build output in the @@ -973,7 +1019,8 @@ # accidentally writing duplicate dummy rules for those outputs. self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) - self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions) + self.WriteMakeRule(outputs, inputs, actions, + command="%s_%d" % (name, count)) # Spaces in rule filenames are not supported, but rule variables have # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)'). # The spaces within the variables are valid, so remove the variables @@ -1084,9 +1131,12 @@ for output, res in gyp.xcode_emulation.GetMacBundleResources( generator_default_variables['PRODUCT_DIR'], self.xcode_settings, map(Sourceify, map(self.Absolutify, resources))): - self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource', - part_of_all=True) - bundle_deps.append(output) + _, ext = os.path.splitext(output) + if ext != '.xcassets': + # Make does not supports '.xcassets' emulation. + self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource', + part_of_all=True) + bundle_deps.append(output) def WriteMacInfoPlist(self, bundle_deps): @@ -1404,7 +1454,7 @@ # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on. gyp_to_build = gyp.common.InvertRelativePath(self.path) - target_postbuild = self.xcode_settings.GetTargetPostbuilds( + target_postbuild = self.xcode_settings.AddImplicitPostbuilds( configname, QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, self.output))), @@ -1639,6 +1689,7 @@ self.WriteMakeRule(outputs, inputs, actions = ['$(call do_cmd,%s%s)' % (command, suffix)], comment = comment, + command = command, force = True) # Add our outputs to the list of targets we read depfiles from. # all_deps is only used for deps file reading, and for deps files we replace @@ -1649,7 +1700,7 @@ def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, - order_only=False, force=False, phony=False): + order_only=False, force=False, phony=False, command=None): """Write a Makefile rule, with some extra tricks. outputs: a list of outputs for the rule (note: this is not directly @@ -1662,6 +1713,7 @@ force: if true, include FORCE_DO_CMD as an order-only dep phony: if true, the rule does not actually generate the named output, the output is just a name to run the rule + command: (optional) command name to generate unambiguous labels """ outputs = map(QuoteSpaces, outputs) inputs = map(QuoteSpaces, inputs) @@ -1670,44 +1722,38 @@ self.WriteLn('# ' + comment) if phony: self.WriteLn('.PHONY: ' + ' '.join(outputs)) - # TODO(evanm): just make order_only a list of deps instead of these hacks. - if order_only: - order_insert = '| ' - pick_output = ' '.join(outputs) - else: - order_insert = '' - pick_output = outputs[0] - if force: - force_append = ' FORCE_DO_CMD' - else: - force_append = '' if actions: self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0]) - self.WriteLn('%s: %s%s%s' % (pick_output, order_insert, ' '.join(inputs), - force_append)) + force_append = ' FORCE_DO_CMD' if force else '' + + if order_only: + # Order only rule: Just write a simple rule. + # TODO(evanm): just make order_only a list of deps instead of this hack. + self.WriteLn('%s: | %s%s' % + (' '.join(outputs), ' '.join(inputs), force_append)) + elif len(outputs) == 1: + # Regular rule, one output: Just write a simple rule. + self.WriteLn('%s: %s%s' % (outputs[0], ' '.join(inputs), force_append)) + else: + # Regular rule, more than one output: Multiple outputs are tricky in + # make. We will write three rules: + # - All outputs depend on an intermediate file. + # - Make .INTERMEDIATE depend on the intermediate. + # - The intermediate file depends on the inputs and executes the + # actual command. + # - The intermediate recipe will 'touch' the intermediate file. + # - The multi-output rule will have an do-nothing recipe. + intermediate = "%s.intermediate" % (command if command else self.target) + self.WriteLn('%s: %s' % (' '.join(outputs), intermediate)) + self.WriteLn('\t%s' % '@:'); + self.WriteLn('%s: %s' % ('.INTERMEDIATE', intermediate)) + self.WriteLn('%s: %s%s' % + (intermediate, ' '.join(inputs), force_append)) + actions.insert(0, '$(call do_cmd,touch)') + if actions: for action in actions: self.WriteLn('\t%s' % action) - if not order_only and len(outputs) > 1: - # If we have more than one output, a rule like - # foo bar: baz - # that for *each* output we must run the action, potentially - # in parallel. That is not what we're trying to write -- what - # we want is that we run the action once and it generates all - # the files. - # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html - # discusses this problem and has this solution: - # 1) Write the naive rule that would produce parallel runs of - # the action. - # 2) Make the outputs seralized on each other, so we won't start - # a parallel run until the first run finishes, at which point - # we'll have generated all the outputs and we're done. - self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0])) - # Add a dummy command to the "extra outputs" rule, otherwise make seems to - # think these outputs haven't (couldn't have?) changed, and thus doesn't - # flag them as changed (i.e. include in '$?') when evaluating dependent - # rules, which in turn causes do_cmd() to skip running dependent commands. - self.WriteLn('%s: ;' % (' '.join(outputs[1:]))) self.WriteLn() @@ -1934,7 +1980,8 @@ # We write the file in the base_path directory. output_file = os.path.join(options.depth, base_path, base_name) if options.generator_output: - output_file = os.path.join(options.generator_output, output_file) + output_file = os.path.join( + options.depth, options.generator_output, base_path, base_name) base_path = gyp.common.RelativePath(os.path.dirname(build_file), options.toplevel_dir) return base_path, output_file @@ -1957,7 +2004,8 @@ makefile_path = os.path.join(options.toplevel_dir, makefile_name) if options.generator_output: global srcdir_prefix - makefile_path = os.path.join(options.generator_output, makefile_path) + makefile_path = os.path.join( + options.toplevel_dir, options.generator_output, makefile_name) srcdir = gyp.common.RelativePath(srcdir, options.generator_output) srcdir_prefix = '$(srcdir)/' @@ -1986,15 +2034,20 @@ }) elif flavor == 'solaris': header_params.update({ - 'flock': './gyp-sun-tool flock', + 'flock': './gyp-flock-tool flock', 'flock_index': 2, - 'extra_commands': SHARED_HEADER_SUN_COMMANDS, }) elif flavor == 'freebsd': # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific. header_params.update({ 'flock': 'lockf', }) + elif flavor == 'aix': + header_params.update({ + 'link_commands': LINK_COMMANDS_AIX, + 'flock': './gyp-flock-tool flock', + 'flock_index': 2, + }) header_params.update({ 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), @@ -2010,7 +2063,6 @@ build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) make_global_settings_array = data[build_file].get('make_global_settings', []) wrappers = {} - wrappers['LINK'] = '%s $(builddir)/linker.lock' % flock_command for key, value in make_global_settings_array: if key.endswith('_wrapper'): wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value @@ -2028,8 +2080,9 @@ make_global_settings += ( 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) # Let gyp-time envvars win over global settings. - if key in os.environ: - value = os.environ[key] + env_key = key.replace('.', '_') # CC.host -> CC_host + if env_key in os.environ: + value = os.environ[env_key] make_global_settings += ' %s = %s\n' % (key, value) make_global_settings += 'endif\n' else: @@ -2039,7 +2092,7 @@ header_params['make_global_settings'] = make_global_settings - ensure_directory_exists(makefile_path) + gyp.common.EnsureDirExists(makefile_path) root_makefile = open(makefile_path, 'w') root_makefile.write(SHARED_HEADER % header_params) # Currently any versions have the same effect, but in future the behavior @@ -2071,7 +2124,8 @@ this_make_global_settings = data[build_file].get('make_global_settings', []) assert make_global_settings_array == this_make_global_settings, ( - "make_global_settings needs to be the same for all targets.") + "make_global_settings needs to be the same for all targets. %s vs. %s" % + (this_make_global_settings, make_global_settings)) build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir)) included_files = data[build_file]['included_files'] diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/msvs.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/msvs.py --- gyp-0.1~svn1729/pylib/gyp/generator/msvs.py 2013-07-02 00:49:07.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/msvs.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,6 +12,7 @@ import gyp.common import gyp.easy_xml as easy_xml +import gyp.generator.ninja as ninja_generator import gyp.MSVSNew as MSVSNew import gyp.MSVSProject as MSVSProject import gyp.MSVSSettings as MSVSSettings @@ -20,6 +21,17 @@ import gyp.MSVSUtil as MSVSUtil import gyp.MSVSVersion as MSVSVersion from gyp.common import GypError +from gyp.common import OrderedSet + +# TODO: Remove once bots are on 2.7, http://crbug.com/241769 +def _import_OrderedDict(): + import collections + try: + return collections.OrderedDict + except AttributeError: + import gyp.ordered_dict + return gyp.ordered_dict.OrderedDict +OrderedDict = _import_OrderedDict() # Regular expression for validating Visual Studio GUIDs. If the GUID @@ -30,7 +42,7 @@ # if IncrediBuild is executed from inside Visual Studio. This regex # validates that the string looks like a GUID with all uppercase hex # letters. -VALID_MSVS_GUID_CHARS = re.compile('^[A-F0-9\-]+$') +VALID_MSVS_GUID_CHARS = re.compile(r'^[A-F0-9\-]+$') generator_default_variables = { @@ -70,6 +82,13 @@ 'msvs_external_builder_out_dir', 'msvs_external_builder_build_cmd', 'msvs_external_builder_clean_cmd', + 'msvs_external_builder_clcompile_cmd', + 'msvs_enable_winrt', + 'msvs_requires_importlibrary', + 'msvs_enable_winphone', + 'msvs_application_type_revision', + 'msvs_target_platform_version', + 'msvs_target_platform_minversion', ] @@ -102,11 +121,11 @@ call = subprocess.Popen(['net', 'config', 'Workstation'], stdout=subprocess.PIPE) config = call.communicate()[0] - username_re = re.compile('^User name\s+(\S+)', re.MULTILINE) + username_re = re.compile(r'^User name\s+(\S+)', re.MULTILINE) username_match = username_re.search(config) if username_match: username = username_match.group(1) - domain_re = re.compile('^Logon domain\s+(\S+)', re.MULTILINE) + domain_re = re.compile(r'^Logon domain\s+(\S+)', re.MULTILINE) domain_match = domain_re.search(config) if domain_match: domain = domain_match.group(1) @@ -158,13 +177,14 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, - list_excluded=True): + list_excluded=True, msvs_version=None): """Converts a list split source file paths into a vcproj folder hierarchy. Arguments: sources: A list of source file paths split. prefix: A list of source file path layers meant to apply to each of sources. excluded: A set of excluded files. + msvs_version: A MSVSVersion object. Returns: A hierarchy of filenames and MSVSProject.Filter objects that matches the @@ -179,7 +199,7 @@ if not prefix: prefix = [] result = [] excluded_result = [] - folders = dict() + folders = OrderedDict() # Gather files into the final result, excluded, or folders. for s in sources: if len(s) == 1: @@ -188,23 +208,36 @@ excluded_result.append(filename) else: result.append(filename) - else: + elif msvs_version and not msvs_version.UsesVcxproj(): + # For MSVS 2008 and earlier, we need to process all files before walking + # the sub folders. if not folders.get(s[0]): folders[s[0]] = [] folders[s[0]].append(s[1:]) + else: + contents = _ConvertSourcesToFilterHierarchy([s[1:]], prefix + [s[0]], + excluded=excluded, + list_excluded=list_excluded, + msvs_version=msvs_version) + contents = MSVSProject.Filter(s[0], contents=contents) + result.append(contents) # Add a folder for excluded files. if excluded_result and list_excluded: excluded_folder = MSVSProject.Filter('_excluded_files', contents=excluded_result) result.append(excluded_folder) + + if msvs_version and msvs_version.UsesVcxproj(): + return result + # Populate all the folders. for f in folders: contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f], excluded=excluded, - list_excluded=list_excluded) + list_excluded=list_excluded, + msvs_version=msvs_version) contents = MSVSProject.Filter(f, contents=contents) result.append(contents) - return result @@ -225,7 +258,7 @@ tool = tools[tool_name] if tool.get(setting): if only_if_unset: return - if type(tool[setting]) == list: + if type(tool[setting]) == list and type(value) == list: tool[setting] += value else: raise TypeError( @@ -258,7 +291,7 @@ if [x for x in cmd if '$(InputDir)' in x]: input_dir_preamble = ( 'set INPUTDIR=$(InputDir)\n' - 'set INPUTDIR=%INPUTDIR:$(ProjectDir)=%\n' + 'if NOT DEFINED INPUTDIR set INPUTDIR=.\\\n' 'set INPUTDIR=%INPUTDIR:~0,-1%\n' ) else: @@ -415,13 +448,13 @@ dicts describing the actions attached to that input file. """ for primary_input in actions_dict: - inputs = set() - outputs = set() + inputs = OrderedSet() + outputs = OrderedSet() descriptions = [] commands = [] for action in actions_dict[primary_input]: - inputs.update(set(action['inputs'])) - outputs.update(set(action['outputs'])) + inputs.update(OrderedSet(action['inputs'])) + outputs.update(OrderedSet(action['outputs'])) descriptions.append(action['description']) commands.append(action['command']) # Add the custom build step for one input file. @@ -477,8 +510,8 @@ """ raw_inputs = _FixPaths(rule.get('inputs', [])) raw_outputs = _FixPaths(rule.get('outputs', [])) - inputs = set() - outputs = set() + inputs = OrderedSet() + outputs = OrderedSet() inputs.add(trigger_file) for i in raw_inputs: inputs.add(_RuleExpandPath(i, trigger_file)) @@ -549,16 +582,16 @@ mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n') mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n') # Gather stuff needed to emit all: target. - all_inputs = set() - all_outputs = set() - all_output_dirs = set() + all_inputs = OrderedSet() + all_outputs = OrderedSet() + all_output_dirs = OrderedSet() first_outputs = [] for rule in rules: trigger_files = _FindRuleTriggerFiles(rule, sources) for tf in trigger_files: inputs, outputs = _RuleInputsAndOutputs(rule, tf) - all_inputs.update(set(inputs)) - all_outputs.update(set(outputs)) + all_inputs.update(OrderedSet(inputs)) + all_outputs.update(OrderedSet(outputs)) # Only use one target from each rule as the dependency for # 'all' so we don't try to build each rule multiple times. first_outputs.append(list(outputs)[0]) @@ -787,23 +820,27 @@ if rules_external: _GenerateExternalRules(rules_external, output_dir, spec, sources, options, actions_to_add) - _AdjustSourcesForRules(spec, rules, sources, excluded_sources) + _AdjustSourcesForRules(rules, sources, excluded_sources, False) -def _AdjustSourcesForRules(spec, rules, sources, excluded_sources): +def _AdjustSourcesForRules(rules, sources, excluded_sources, is_msbuild): # Add outputs generated by each rule (if applicable). for rule in rules: - # Done if not processing outputs as sources. - if int(rule.get('process_outputs_as_sources', False)): - # Add in the outputs from this rule. - trigger_files = _FindRuleTriggerFiles(rule, sources) - for trigger_file in trigger_files: + # Add in the outputs from this rule. + trigger_files = _FindRuleTriggerFiles(rule, sources) + for trigger_file in trigger_files: + # Remove trigger_file from excluded_sources to let the rule be triggered + # (e.g. rule trigger ax_enums.idl is added to excluded_sources + # because it's also in an action's inputs in the same project) + excluded_sources.discard(_FixPath(trigger_file)) + # Done if not processing outputs as sources. + if int(rule.get('process_outputs_as_sources', False)): inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file) - inputs = set(_FixPaths(inputs)) - outputs = set(_FixPaths(outputs)) + inputs = OrderedSet(_FixPaths(inputs)) + outputs = OrderedSet(_FixPaths(outputs)) inputs.remove(_FixPath(trigger_file)) sources.update(inputs) - if not spec.get('msvs_external_builder'): + if not is_msbuild: excluded_sources.update(inputs) sources.update(outputs) @@ -817,7 +854,7 @@ Returns: excluded_sources with files that have actions attached removed. """ - must_keep = set(_FixPaths(actions_to_add.keys())) + must_keep = OrderedSet(_FixPaths(actions_to_add.keys())) return [s for s in excluded_sources if s not in must_keep] @@ -890,6 +927,42 @@ return _GenerateMSVSProject(project, options, version, generator_flags) +# TODO: Avoid code duplication with _ValidateSourcesForOSX in make.py. +def _ValidateSourcesForMSVSProject(spec, version): + """Makes sure if duplicate basenames are not specified in the source list. + + Arguments: + spec: The target dictionary containing the properties of the target. + version: The VisualStudioVersion object. + """ + # This validation should not be applied to MSVC2010 and later. + assert not version.UsesVcxproj() + + # TODO: Check if MSVC allows this for loadable_module targets. + if spec.get('type', None) not in ('static_library', 'shared_library'): + return + sources = spec.get('sources', []) + basenames = {} + for source in sources: + name, ext = os.path.splitext(source) + is_compiled_file = ext in [ + '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] + if not is_compiled_file: + continue + basename = os.path.basename(name) # Don't include extension. + basenames.setdefault(basename, []).append(source) + + error = '' + for basename, files in basenames.iteritems(): + if len(files) > 1: + error += ' %s: %s\n' % (basename, ' '.join(files)) + + if error: + print('static library %s has several files with the same basename:\n' % + spec['target_name'] + error + 'MSVC08 cannot handle that.') + raise GypError('Duplicate basenames in sources section, see list above') + + def _GenerateMSVSProject(project, options, version, generator_flags): """Generates a .vcproj file. It may create .rules and .user files too. @@ -900,9 +973,7 @@ generator_flags: dict of generator-specific flags. """ spec = project.spec - vcproj_dir = os.path.dirname(project.path) - if vcproj_dir and not os.path.exists(vcproj_dir): - os.makedirs(vcproj_dir) + gyp.common.EnsureDirExists(project.path) platforms = _GetUniquePlatforms(spec) p = MSVSProject.Writer(project.path, version, spec['target_name'], @@ -917,6 +988,11 @@ for config_name, config in spec['configurations'].iteritems(): _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config) + # MSVC08 and prior version cannot handle duplicate basenames in the same + # target. + # TODO: Take excluded sources into consideration if possible. + _ValidateSourcesForMSVSProject(spec, version) + # Prepare list of sources and excluded sources. gyp_file = os.path.split(project.build_file)[1] sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, @@ -929,8 +1005,9 @@ actions_to_add) list_excluded = generator_flags.get('msvs_list_excluded_files', True) sources, excluded_sources, excluded_idl = ( - _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, project_dir, sources, excluded_sources, list_excluded)) + _AdjustSourcesAndConvertToFilterHierarchy(spec, options, project_dir, + sources, excluded_sources, + list_excluded, version)) # Add in files. missing_sources = _VerifySourcesExist(sources, project_dir) @@ -965,7 +1042,7 @@ The MSVSUserFile object created. """ # Gather list of unique platforms. - platforms = set() + platforms = OrderedSet() for configuration in spec['configurations']: platforms.add(_ConfigPlatform(spec['configurations'][configuration])) platforms = list(platforms) @@ -1035,7 +1112,8 @@ for this configuration. """ # Get the information for this configuration - include_dirs, resource_include_dirs = _GetIncludeDirs(config) + include_dirs, midl_include_dirs, resource_include_dirs = \ + _GetIncludeDirs(config) libraries = _GetLibraries(spec) library_dirs = _GetLibraryDirs(config) out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec, msbuild=False) @@ -1063,6 +1141,8 @@ # Add the information to the appropriate tool _ToolAppend(tools, 'VCCLCompilerTool', 'AdditionalIncludeDirectories', include_dirs) + _ToolAppend(tools, 'VCMIDLTool', + 'AdditionalIncludeDirectories', midl_include_dirs) _ToolAppend(tools, 'VCResourceCompilerTool', 'AdditionalIncludeDirectories', resource_include_dirs) # Add in libraries. @@ -1118,10 +1198,14 @@ include_dirs = ( config.get('include_dirs', []) + config.get('msvs_system_include_dirs', [])) + midl_include_dirs = ( + config.get('midl_include_dirs', []) + + config.get('msvs_system_include_dirs', [])) resource_include_dirs = config.get('resource_include_dirs', include_dirs) include_dirs = _FixPaths(include_dirs) + midl_include_dirs = _FixPaths(midl_include_dirs) resource_include_dirs = _FixPaths(resource_include_dirs) - return include_dirs, resource_include_dirs + return include_dirs, midl_include_dirs, resource_include_dirs def _GetLibraryDirs(config): @@ -1152,10 +1236,10 @@ # in libraries that are assumed to be in the default library path). # Also remove duplicate entries, leaving only the last duplicate, while # preserving order. - found = set() + found = OrderedSet() unique_libraries_list = [] for entry in reversed(libraries): - library = re.sub('^\-l', '', entry) + library = re.sub(r'^\-l', '', entry) if not os.path.splitext(library)[1]: library += '.lib' if library not in found: @@ -1203,6 +1287,24 @@ return out_file, vc_tool, msbuild_tool +def _GetOutputTargetExt(spec): + """Returns the extension for this target, including the dot + + If product_extension is specified, set target_extension to this to avoid + MSB8012, returns None otherwise. Ignores any target_extension settings in + the input files. + + Arguments: + spec: The target dictionary containing the properties of the target. + Returns: + A string with the extension, or None + """ + target_extension = spec.get('product_extension') + if target_extension: + return '.' + target_extension + return None + + def _GetDefines(config): """Returns the list of preprocessor definitions for this configuation. @@ -1313,8 +1415,7 @@ def _AddNormalizedSources(sources_set, sources_array): - sources = [_NormalizedSource(s) for s in sources_array] - sources_set.update(set(sources)) + sources_set.update(_NormalizedSource(s) for s in sources_array) def _PrepareListOfSources(spec, generator_flags, gyp_file): @@ -1332,9 +1433,9 @@ A pair of (list of sources, list of excluded sources). The sources will be relative to the gyp file. """ - sources = set() + sources = OrderedSet() _AddNormalizedSources(sources, spec.get('sources', [])) - excluded_sources = set() + excluded_sources = OrderedSet() # Add in the gyp file. if not generator_flags.get('standalone'): sources.add(gyp_file) @@ -1344,7 +1445,7 @@ inputs = a['inputs'] inputs = [_NormalizedSource(i) for i in inputs] # Add all inputs to sources and excluded sources. - inputs = set(inputs) + inputs = OrderedSet(inputs) sources.update(inputs) if not spec.get('msvs_external_builder'): excluded_sources.update(inputs) @@ -1357,7 +1458,7 @@ def _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, gyp_dir, sources, excluded_sources, list_excluded): + spec, options, gyp_dir, sources, excluded_sources, list_excluded, version): """Adjusts the list of sources and excluded sources. Also converts the sets to lists. @@ -1368,12 +1469,13 @@ gyp_dir: The path to the gyp file being processed. sources: A set of sources to be included for this project. excluded_sources: A set of sources to be excluded for this project. + version: A MSVSVersion object. Returns: A trio of (list of sources, list of excluded sources, path of excluded IDL file) """ # Exclude excluded sources coming into the generator. - excluded_sources.update(set(spec.get('sources_excluded', []))) + excluded_sources.update(OrderedSet(spec.get('sources_excluded', []))) # Add excluded sources into sources for good measure. sources.update(excluded_sources) # Convert to proper windows form. @@ -1392,7 +1494,19 @@ # Convert to folders and the right slashes. sources = [i.split('\\') for i in sources] sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded, - list_excluded=list_excluded) + list_excluded=list_excluded, + msvs_version=version) + + # Prune filters with a single child to flatten ugly directory structures + # such as ../../src/modules/module1 etc. + if version.UsesVcxproj(): + while all([isinstance(s, MSVSProject.Filter) for s in sources]) \ + and len(set([s.name for s in sources])) == 1: + assert all([len(s.contents) == 1 for s in sources]) + sources = [s.contents[0] for s in sources] + else: + while len(sources) == 1 and isinstance(sources[0], MSVSProject.Filter): + sources = sources[0].contents return sources, excluded_sources, excluded_idl @@ -1461,7 +1575,7 @@ def _AddToolFilesToMSVS(p, spec): # Add in tool files (rules). - tool_files = set() + tool_files = OrderedSet() for _, config in spec['configurations'].iteritems(): for f in config.get('msvs_tool_files', []): tool_files.add(f) @@ -1728,7 +1842,7 @@ return projects -def _InitNinjaFlavor(options, target_list, target_dicts): +def _InitNinjaFlavor(params, target_list, target_dicts): """Initialize targets for the ninja flavor. This sets up the necessary variables in the targets to generate msvs projects @@ -1736,7 +1850,7 @@ if they have not been set. This allows individual specs to override the default values initialized here. Arguments: - options: Options provided to the generator. + params: Params provided to the generator. target_list: List of target pairs: 'base/base.gyp:base'. target_dicts: Dict of target properties keyed on target pair. """ @@ -1750,8 +1864,15 @@ spec['msvs_external_builder'] = 'ninja' if not spec.get('msvs_external_builder_out_dir'): - spec['msvs_external_builder_out_dir'] = \ - options.depth + '/out/$(Configuration)' + gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) + gyp_dir = os.path.dirname(gyp_file) + configuration = '$(Configuration)' + if params.get('target_arch') == 'x64': + configuration += '_x64' + spec['msvs_external_builder_out_dir'] = os.path.join( + gyp.common.RelativePath(params['options'].toplevel_dir, gyp_dir), + ninja_generator.ComputeOutputDir(params), + configuration) if not spec.get('msvs_external_builder_build_cmd'): spec['msvs_external_builder_build_cmd'] = [ path_to_ninja, @@ -1764,8 +1885,7 @@ path_to_ninja, '-C', '$(OutDir)', - '-t', - 'clean', + '-tclean', '$(ProjectName)', ] @@ -1846,7 +1966,7 @@ # Optionally configure each spec to use ninja as the external builder. if params.get('flavor') == 'ninja': - _InitNinjaFlavor(options, target_list, target_dicts) + _InitNinjaFlavor(params, target_list, target_dicts) # Prepare the set of configurations. configs = set() @@ -1899,7 +2019,7 @@ def _GenerateMSBuildFiltersFile(filters_path, source_files, - extension_to_rule_name): + rule_dependencies, extension_to_rule_name): """Generate the filters file. This file is used by Visual Studio to organize the presentation of source @@ -1912,8 +2032,8 @@ """ filter_group = [] source_group = [] - _AppendFiltersForMSBuild('', source_files, extension_to_rule_name, - filter_group, source_group) + _AppendFiltersForMSBuild('', source_files, rule_dependencies, + extension_to_rule_name, filter_group, source_group) if filter_group: content = ['Project', {'ToolsVersion': '4.0', @@ -1928,7 +2048,7 @@ os.unlink(filters_path) -def _AppendFiltersForMSBuild(parent_filter_name, sources, +def _AppendFiltersForMSBuild(parent_filter_name, sources, rule_dependencies, extension_to_rule_name, filter_group, source_group): """Creates the list of filters and sources to be added in the filter file. @@ -1954,11 +2074,12 @@ ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]]) # Recurse and add its dependents. _AppendFiltersForMSBuild(filter_name, source.contents, - extension_to_rule_name, + rule_dependencies, extension_to_rule_name, filter_group, source_group) else: # It's a source. Create a source entry. - _, element = _MapFileToMsBuildSourceType(source, extension_to_rule_name) + _, element = _MapFileToMsBuildSourceType(source, rule_dependencies, + extension_to_rule_name) source_entry = [element, {'Include': source}] # Specify the filter it is part of, if any. if parent_filter_name: @@ -1966,7 +2087,8 @@ source_group.append(source_entry) -def _MapFileToMsBuildSourceType(source, extension_to_rule_name): +def _MapFileToMsBuildSourceType(source, rule_dependencies, + extension_to_rule_name): """Returns the group and element type of the source file. Arguments: @@ -1989,9 +2111,15 @@ elif ext == '.rc': group = 'resource' element = 'ResourceCompile' + elif ext == '.asm': + group = 'masm' + element = 'MASM' elif ext == '.idl': group = 'midl' element = 'Midl' + elif source in rule_dependencies: + group = 'rule_dependency' + element = 'CustomBuild' else: group = 'none' element = 'None' @@ -2001,7 +2129,8 @@ def _GenerateRulesForMSBuild(output_dir, options, spec, sources, excluded_sources, props_files_of_rules, targets_files_of_rules, - actions_to_add, extension_to_rule_name): + actions_to_add, rule_dependencies, + extension_to_rule_name): # MSBuild rules are implemented using three files: an XML file, a .targets # file and a .props file. # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx @@ -2017,6 +2146,7 @@ continue msbuild_rule = MSBuildRule(rule, spec) msbuild_rules.append(msbuild_rule) + rule_dependencies.update(msbuild_rule.additional_dependencies.split(';')) extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name if msbuild_rules: base = spec['target_name'] + options.suffix @@ -2038,7 +2168,7 @@ if rules_external: _GenerateExternalRules(rules_external, output_dir, spec, sources, options, actions_to_add) - _AdjustSourcesForRules(spec, rules, sources, excluded_sources) + _AdjustSourcesForRules(rules, sources, excluded_sources, True) class MSBuildRule(object): @@ -2217,6 +2347,9 @@ rule_name, {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " "'true'" % (rule_name, rule_name), + 'EchoOff': 'true', + 'StandardOutputImportance': 'High', + 'StandardErrorImportance': 'High', 'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name, 'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name, 'Inputs': rule_inputs @@ -2491,14 +2624,45 @@ def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): namespace = os.path.splitext(gyp_file_name)[0] - return [ + properties = [ ['PropertyGroup', {'Label': 'Globals'}, - ['ProjectGuid', guid], - ['Keyword', 'Win32Proj'], - ['RootNamespace', namespace], + ['ProjectGuid', guid], + ['Keyword', 'Win32Proj'], + ['RootNamespace', namespace], + ['IgnoreWarnCompileDuplicatedFilename', 'true'], ] - ] + ] + if os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or \ + os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64': + properties[0].append(['PreferredToolArchitecture', 'x64']) + + if spec.get('msvs_enable_winrt'): + properties[0].append(['DefaultLanguage', 'en-US']) + properties[0].append(['AppContainerApplication', 'true']) + if spec.get('msvs_application_type_revision'): + app_type_revision = spec.get('msvs_application_type_revision') + properties[0].append(['ApplicationTypeRevision', app_type_revision]) + else: + properties[0].append(['ApplicationTypeRevision', '8.1']) + + if spec.get('msvs_target_platform_version'): + target_platform_version = spec.get('msvs_target_platform_version') + properties[0].append(['WindowsTargetPlatformVersion', + target_platform_version]) + if spec.get('msvs_target_platform_minversion'): + target_platform_minversion = spec.get('msvs_target_platform_minversion') + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_minversion]) + else: + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_version]) + if spec.get('msvs_enable_winphone'): + properties[0].append(['ApplicationType', 'Windows Phone']) + else: + properties[0].append(['ApplicationType', 'Windows Store']) + + return properties def _GetMSBuildConfigurationDetails(spec, build_file): properties = {} @@ -2509,8 +2673,9 @@ _AddConditionalProperty(properties, condition, 'ConfigurationType', msbuild_attributes['ConfigurationType']) if character_set: - _AddConditionalProperty(properties, condition, 'CharacterSet', - character_set) + if 'msvs_enable_winrt' not in spec : + _AddConditionalProperty(properties, condition, 'CharacterSet', + character_set) return _GetMSBuildPropertyGroup(spec, 'Configuration', properties) @@ -2652,6 +2817,9 @@ out_file = msbuild_settings[msbuild_tool].get('OutputFile') if out_file: msbuild_attributes['TargetPath'] = _FixPath(out_file) + target_ext = msbuild_settings[msbuild_tool].get('TargetExt') + if target_ext: + msbuild_attributes['TargetExt'] = target_ext return msbuild_attributes @@ -2687,6 +2855,9 @@ if attributes.get('TargetPath'): _AddConditionalProperty(properties, condition, 'TargetPath', attributes['TargetPath']) + if attributes.get('TargetExt'): + _AddConditionalProperty(properties, condition, 'TargetExt', + attributes['TargetExt']) if new_paths: _AddConditionalProperty(properties, condition, 'ExecutablePath', @@ -2719,7 +2890,7 @@ # Regex for msvs variable references ( i.e. $(FOO) ). -MSVS_VARIABLE_REFERENCE = re.compile('\$\(([a-zA-Z_][a-zA-Z0-9_]*)\)') +MSVS_VARIABLE_REFERENCE = re.compile(r'\$\(([a-zA-Z_][a-zA-Z0-9_]*)\)') def _GetMSBuildPropertyGroup(spec, label, properties): @@ -2803,16 +2974,18 @@ converted = True msvs_settings = configuration.get('msvs_settings', {}) msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings) - include_dirs, resource_include_dirs = _GetIncludeDirs(configuration) + include_dirs, midl_include_dirs, resource_include_dirs = \ + _GetIncludeDirs(configuration) libraries = _GetLibraries(spec) library_dirs = _GetLibraryDirs(configuration) out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec, msbuild=True) + target_ext = _GetOutputTargetExt(spec) defines = _GetDefines(configuration) if converted: # Visual Studio 2010 has TR1 defines = [d for d in defines if d != '_HAS_TR1=0'] # Warn of ignored settings - ignored_settings = ['msvs_prebuild', 'msvs_postbuild', 'msvs_tool_files'] + ignored_settings = ['msvs_tool_files'] for ignored_setting in ignored_settings: value = configuration.get(ignored_setting) if value: @@ -2821,9 +2994,8 @@ defines = [_EscapeCppDefineForMSBuild(d) for d in defines] disabled_warnings = _GetDisabledWarnings(configuration) - # TODO(jeanluc) Validate & warn that we don't translate - # prebuild = configuration.get('msvs_prebuild') - # postbuild = configuration.get('msvs_postbuild') + prebuild = configuration.get('msvs_prebuild') + postbuild = configuration.get('msvs_postbuild') def_file = _GetModuleDefinition(spec) precompiled_header = configuration.get('msvs_precompiled_header') @@ -2833,6 +3005,8 @@ # if you don't have any resources. _ToolAppend(msbuild_settings, 'ClCompile', 'AdditionalIncludeDirectories', include_dirs) + _ToolAppend(msbuild_settings, 'Midl', + 'AdditionalIncludeDirectories', midl_include_dirs) _ToolAppend(msbuild_settings, 'ResourceCompile', 'AdditionalIncludeDirectories', resource_include_dirs) # Add in libraries, note that even for empty libraries, we want this @@ -2844,6 +3018,9 @@ if out_file: _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file, only_if_unset=True) + if target_ext: + _ToolAppend(msbuild_settings, msbuild_tool, 'TargetExt', target_ext, + only_if_unset=True) # Add defines. _ToolAppend(msbuild_settings, 'ClCompile', 'PreprocessorDefinitions', defines) @@ -2859,7 +3036,14 @@ _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeaderFile', precompiled_header) _ToolAppend(msbuild_settings, 'ClCompile', - 'ForcedIncludeFiles', precompiled_header) + 'ForcedIncludeFiles', [precompiled_header]) + else: + _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'NotUsing') + # Turn off WinRT compilation + _ToolAppend(msbuild_settings, 'ClCompile', 'CompileAsWinRT', 'false') + # Turn on import libraries if appropriate + if spec.get('msvs_requires_importlibrary'): + _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'false') # Loadable modules don't generate import libraries; # tell dependent projects to not expect one. if spec['type'] == 'loadable_module': @@ -2868,6 +3052,10 @@ if def_file: _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file) configuration['finalized_msbuild_settings'] = msbuild_settings + if prebuild: + _ToolAppend(msbuild_settings, 'PreBuildEvent', 'Command', prebuild) + if postbuild: + _ToolAppend(msbuild_settings, 'PostBuildEvent', 'Command', postbuild) def _GetValueFormattedForMSBuild(tool_name, name, value): @@ -2923,15 +3111,18 @@ return missing_sources -def _GetMSBuildSources(spec, sources, exclusions, extension_to_rule_name, - actions_spec, sources_handled_by_action, list_excluded): - groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule'] +def _GetMSBuildSources(spec, sources, exclusions, rule_dependencies, + extension_to_rule_name, actions_spec, + sources_handled_by_action, list_excluded): + groups = ['none', 'masm', 'midl', 'include', 'compile', 'resource', 'rule', + 'rule_dependency'] grouped_sources = {} for g in groups: grouped_sources[g] = [] _AddSources2(spec, sources, exclusions, grouped_sources, - extension_to_rule_name, sources_handled_by_action, list_excluded) + rule_dependencies, extension_to_rule_name, + sources_handled_by_action, list_excluded) sources = [] for g in groups: if grouped_sources[g]: @@ -2942,13 +3133,15 @@ def _AddSources2(spec, sources, exclusions, grouped_sources, - extension_to_rule_name, sources_handled_by_action, + rule_dependencies, extension_to_rule_name, + sources_handled_by_action, list_excluded): extensions_excluded_from_precompile = [] for source in sources: if isinstance(source, MSVSProject.Filter): _AddSources2(spec, source.contents, exclusions, grouped_sources, - extension_to_rule_name, sources_handled_by_action, + rule_dependencies, extension_to_rule_name, + sources_handled_by_action, list_excluded) else: if not source in sources_handled_by_action: @@ -2991,7 +3184,7 @@ detail.append(['PrecompiledHeader', '']) detail.append(['ForcedIncludeFiles', '']) - group, element = _MapFileToMsBuildSourceType(source, + group, element = _MapFileToMsBuildSourceType(source, rule_dependencies, extension_to_rule_name) grouped_sources[group].append([element, {'Include': source}] + detail) @@ -3023,9 +3216,7 @@ spec = project.spec configurations = spec['configurations'] project_dir, project_file_name = os.path.split(project.path) - msbuildproj_dir = os.path.dirname(project.path) - if msbuildproj_dir and not os.path.exists(msbuildproj_dir): - os.makedirs(msbuildproj_dir) + gyp.common.EnsureDirExists(project.path) # Prepare list of sources and excluded sources. gyp_path = _NormalizedSource(project.build_file) relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) @@ -3037,6 +3228,7 @@ actions_to_add = {} props_files_of_rules = set() targets_files_of_rules = set() + rule_dependencies = set() extension_to_rule_name = {} list_excluded = generator_flags.get('msvs_list_excluded_files', True) @@ -3045,16 +3237,17 @@ _GenerateRulesForMSBuild(project_dir, options, spec, sources, excluded_sources, props_files_of_rules, targets_files_of_rules, - actions_to_add, extension_to_rule_name) + actions_to_add, rule_dependencies, + extension_to_rule_name) else: rules = spec.get('rules', []) - _AdjustSourcesForRules(spec, rules, sources, excluded_sources) + _AdjustSourcesForRules(rules, sources, excluded_sources, True) sources, excluded_sources, excluded_idl = ( _AdjustSourcesAndConvertToFilterHierarchy(spec, options, project_dir, sources, excluded_sources, - list_excluded)) + list_excluded, version)) # Don't add actions if we are using an external builder like ninja. if not spec.get('msvs_external_builder'): @@ -3071,6 +3264,7 @@ spec, actions_to_add) _GenerateMSBuildFiltersFile(project.path + '.filters', sources, + rule_dependencies, extension_to_rule_name) missing_sources = _VerifySourcesExist(sources, project_dir) @@ -3085,6 +3279,12 @@ ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]] import_cpp_targets_section = [ ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]] + import_masm_props_section = [ + ['Import', + {'Project': r'$(VCTargetsPath)\BuildCustomizations\masm.props'}]] + import_masm_targets_section = [ + ['Import', + {'Project': r'$(VCTargetsPath)\BuildCustomizations\masm.targets'}]] macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]] content = [ @@ -3098,8 +3298,12 @@ content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name) content += import_default_section content += _GetMSBuildConfigurationDetails(spec, project.build_file) - content += _GetMSBuildLocalProperties(project.msbuild_toolset) + if spec.get('msvs_enable_winphone'): + content += _GetMSBuildLocalProperties('v120_wp81') + else: + content += _GetMSBuildLocalProperties(project.msbuild_toolset) content += import_cpp_props_section + content += import_masm_props_section content += _GetMSBuildExtensions(props_files_of_rules) content += _GetMSBuildPropertySheets(configurations) content += macro_section @@ -3107,10 +3311,11 @@ project.build_file) content += _GetMSBuildToolSettingsSections(spec, configurations) content += _GetMSBuildSources( - spec, sources, exclusions, extension_to_rule_name, actions_spec, - sources_handled_by_action, list_excluded) + spec, sources, exclusions, rule_dependencies, extension_to_rule_name, + actions_spec, sources_handled_by_action, list_excluded) content += _GetMSBuildProjectReferences(project) content += import_cpp_targets_section + content += import_masm_targets_section content += _GetMSBuildExtensionTargets(targets_files_of_rules) if spec.get('msvs_external_builder'): @@ -3127,7 +3332,9 @@ def _GetMSBuildExternalBuilderTargets(spec): """Return a list of MSBuild targets for external builders. - Right now, only "Build" and "Clean" targets are generated. + The "Build" and "Clean" targets are always generated. If the spec contains + 'msvs_external_builder_clcompile_cmd', then the "ClCompile" target will also + be generated, to support building selected C/C++ files. Arguments: spec: The gyp target spec. @@ -3146,7 +3353,17 @@ clean_target = ['Target', {'Name': 'Clean'}] clean_target.append(['Exec', {'Command': clean_cmd}]) - return [build_target, clean_target] + targets = [build_target, clean_target] + + if spec.get('msvs_external_builder_clcompile_cmd'): + clcompile_cmd = _BuildCommandLineForRuleRaw( + spec, spec['msvs_external_builder_clcompile_cmd'], + False, False, False, False) + clcompile_target = ['Target', {'Name': 'ClCompile'}] + clcompile_target.append(['Exec', {'Command': clcompile_cmd}]) + targets.append(clcompile_target) + + return targets def _GetMSBuildExtensions(props_files_of_rules): @@ -3174,16 +3391,16 @@ Returns: A pair of (action specification, the sources handled by this action). """ - sources_handled_by_action = set() + sources_handled_by_action = OrderedSet() actions_spec = [] for primary_input, actions in actions_to_add.iteritems(): - inputs = set() - outputs = set() + inputs = OrderedSet() + outputs = OrderedSet() descriptions = [] commands = [] for action in actions: - inputs.update(set(action['inputs'])) - outputs.update(set(action['outputs'])) + inputs.update(OrderedSet(action['inputs'])) + outputs.update(OrderedSet(action['outputs'])) descriptions.append(action['description']) cmd = action['command'] # For most actions, add 'call' so that actions that invoke batch files @@ -3200,8 +3417,8 @@ # get too long. See also _AddActions: cygwin's setup_env mustn't be called # for every invocation or the command that sets the PATH will grow too # long. - command = ( - '\r\nif %errorlevel% neq 0 exit /b %errorlevel%\r\n'.join(commands)) + command = '\r\n'.join([c + '\r\nif %errorlevel% neq 0 exit /b %errorlevel%' + for c in commands]) _AddMSBuildAction(spec, primary_input, inputs, diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/ninja.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/ninja.py --- gyp-0.1~svn1729/pylib/gyp/generator/ninja.py 2013-09-13 16:47:45.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/ninja.py 2015-09-13 13:41:20.000000000 +0000 @@ -2,8 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import collections import copy import hashlib +import json import multiprocessing import os.path import re @@ -12,6 +14,7 @@ import sys import gyp import gyp.common +from gyp.common import OrderedSet import gyp.msvs_emulation import gyp.MSVSUtil as MSVSUtil import gyp.xcode_emulation @@ -57,18 +60,9 @@ generator_additional_non_configuration_keys = [] generator_additional_path_sections = [] generator_extra_sources_for_rules = [] +generator_filelist_paths = None -# TODO: figure out how to not build extra host objects in the non-cross-compile -# case when this is enabled, and enable unconditionally. -generator_supports_multiple_toolsets = ( - os.environ.get('GYP_CROSSCOMPILE') or - os.environ.get('AR_host') or - os.environ.get('CC_host') or - os.environ.get('CXX_host') or - os.environ.get('AR_target') or - os.environ.get('CC_target') or - os.environ.get('CXX_target')) - +generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() def StripPrefix(arg, prefix): if arg.startswith(prefix): @@ -104,7 +98,7 @@ return '%s.%s%s' % (output, arch, extension) -class Target: +class Target(object): """Target represents the paths used within a single gyp target. Conceptually, building a single target A is a series of steps: @@ -208,10 +202,10 @@ # an output file; the result can be namespaced such that it is unique # to the input file name as well as the output target name. -class NinjaWriter: - def __init__(self, qualified_target, target_outputs, base_dir, build_dir, +class NinjaWriter(object): + def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir, output_file, toplevel_build, output_file_name, flavor, - deps_file=None, toplevel_dir=None): + toplevel_dir=None): """ base_dir: path from source root to directory containing this gyp file, by gyp semantics, all input paths are relative to this @@ -219,7 +213,7 @@ toplevel_dir: path to the toplevel directory """ - self.qualified_target = qualified_target + self.hash_for_rules = hash_for_rules self.target_outputs = target_outputs self.base_dir = base_dir self.build_dir = build_dir @@ -245,7 +239,6 @@ # Relative path from base dir to build dir. base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir) self.base_to_build = os.path.join(base_to_top, build_dir) - self.link_deps_file = deps_file def ExpandSpecial(self, path, product_dir=None): """Expand specials like $!PRODUCT_DIR in |path|. @@ -337,12 +330,15 @@ obj += '.' + self.toolset path_dir, path_basename = os.path.split(path) + assert not os.path.isabs(path_dir), ( + "'%s' can not be absolute path (see crbug.com/462153)." % path_dir) + if qualified: path_basename = self.name + '.' + path_basename return os.path.normpath(os.path.join(obj, self.base_dir, path_dir, path_basename)) - def WriteCollapsedDependencies(self, name, targets): + def WriteCollapsedDependencies(self, name, targets, order_only=None): """Given a list of targets, return a path for a single file representing the result of building all the targets or None. @@ -350,10 +346,11 @@ assert targets == filter(None, targets), targets if len(targets) == 0: + assert not order_only return None - if len(targets) > 1: + if len(targets) > 1 or order_only: stamp = self.GypPathToUniqueOutput(name + '.stamp') - targets = self.ninja.build(stamp, 'stamp', targets) + targets = self.ninja.build(stamp, 'stamp', targets, order_only=order_only) self.ninja.newline() return targets[0] @@ -390,6 +387,9 @@ self.ninja.variable('arch', self.win_env[arch]) self.ninja.variable('cc', '$cl_' + arch) self.ninja.variable('cxx', '$cl_' + arch) + self.ninja.variable('cc_host', '$cl_' + arch) + self.ninja.variable('cxx_host', '$cl_' + arch) + self.ninja.variable('asm', '$ml_' + arch) if self.flavor == 'mac': self.archs = self.xcode_settings.GetActiveArchs(config_name) @@ -441,7 +441,7 @@ # Write out the compilation steps, if any. link_deps = [] - sources = spec.get('sources', []) + extra_sources + sources = extra_sources + spec.get('sources', []) if sources: if self.flavor == 'mac' and len(self.archs) > 1: # Write subninja file containing compile and link commands scoped to @@ -471,6 +471,8 @@ else: print "Warning: Actions/rules writing object files don't work with " \ "multiarch targets, dropping. (target %s)" % spec['target_name'] + elif self.flavor == 'mac' and len(self.archs) > 1: + link_deps = collections.defaultdict(list) if self.flavor == 'win' and self.target.type == 'static_library': @@ -522,7 +524,7 @@ def WriteWinIdlFiles(self, spec, prebuild): """Writes rules to match MSVS's implicit idl handling.""" assert self.flavor == 'win' - if self.msvs_settings.HasExplicitIdlRules(spec): + if self.msvs_settings.HasExplicitIdlRulesOrActions(spec): return [] outputs = [] for source in filter(lambda x: x.endswith('.idl'), spec['sources']): @@ -556,9 +558,10 @@ stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) if self.is_mac_bundle: - self.WriteMacBundleResources( - mac_bundle_resources + extra_mac_bundle_resources, mac_bundle_depends) - self.WriteMacInfoPlist(mac_bundle_depends) + xcassets = self.WriteMacBundleResources( + extra_mac_bundle_resources + mac_bundle_resources, mac_bundle_depends) + partial_info_plist = self.WriteMacXCassets(xcassets, mac_bundle_depends) + self.WriteMacInfoPlist(partial_info_plist, mac_bundle_depends) return stamp @@ -579,23 +582,24 @@ def WriteActions(self, actions, extra_sources, prebuild, extra_mac_bundle_resources): # Actions cd into the base directory. - env = self.GetSortedXcodeEnv() - if self.flavor == 'win': - env = self.msvs_settings.GetVSMacroEnv( - '$!PRODUCT_DIR', config=self.config_name) + env = self.GetToolchainEnv() all_outputs = [] for action in actions: # First write out a rule for the action. - name = '%s_%s' % (action['action_name'], - hashlib.md5(self.qualified_target).hexdigest()) + name = '%s_%s' % (action['action_name'], self.hash_for_rules) description = self.GenerateDescription('ACTION', action.get('message', None), name) is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action) if self.flavor == 'win' else False) args = action['action'] + depfile = action.get('depfile', None) + if depfile: + depfile = self.ExpandSpecial(depfile, self.base_to_build) + pool = 'console' if int(action.get('ninja_use_console', 0)) else None rule_name, _ = self.WriteNewNinjaRule(name, args, description, - is_cygwin, env=env) + is_cygwin, env, pool, + depfile=depfile) inputs = [self.GypPathToNinja(i, env) for i in action['inputs']] if int(action.get('process_outputs_as_sources', False)): @@ -615,15 +619,16 @@ def WriteRules(self, rules, extra_sources, prebuild, mac_bundle_resources, extra_mac_bundle_resources): - env = self.GetSortedXcodeEnv() + env = self.GetToolchainEnv() all_outputs = [] for rule in rules: - # First write out a rule for the rule action. - name = '%s_%s' % (rule['rule_name'], - hashlib.md5(self.qualified_target).hexdigest()) # Skip a rule with no action and no inputs. if 'action' not in rule and not rule.get('rule_sources', []): continue + + # First write out a rule for the rule action. + name = '%s_%s' % (rule['rule_name'], self.hash_for_rules) + args = rule['action'] description = self.GenerateDescription( 'RULE', @@ -631,8 +636,9 @@ ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name) is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule) if self.flavor == 'win' else False) + pool = 'console' if int(rule.get('ninja_use_console', 0)) else None rule_name, args = self.WriteNewNinjaRule( - name, args, description, is_cygwin, env=env) + name, args, description, is_cygwin, env, pool) # TODO: if the command references the outputs directly, we should # simplify it to just use $out. @@ -644,16 +650,31 @@ needed_variables = set(['source']) for argument in args: for var in special_locals: - if ('${%s}' % var) in argument: + if '${%s}' % var in argument: needed_variables.add(var) def cygwin_munge(path): + # pylint: disable=cell-var-from-loop if is_cygwin: return path.replace('\\', '/') return path + inputs = [self.GypPathToNinja(i, env) for i in rule.get('inputs', [])] + + # If there are n source files matching the rule, and m additional rule + # inputs, then adding 'inputs' to each build edge written below will + # write m * n inputs. Collapsing reduces this to m + n. + sources = rule.get('rule_sources', []) + num_inputs = len(inputs) + if prebuild: + num_inputs += 1 + if num_inputs > 2 and len(sources) > 2: + inputs = [self.WriteCollapsedDependencies( + rule['rule_name'], inputs, order_only=prebuild)] + prebuild = [] + # For each source file, write an edge that generates all the outputs. - for source in rule.get('rule_sources', []): + for source in sources: source = os.path.normpath(source) dirname, basename = os.path.split(source) root, ext = os.path.splitext(basename) @@ -662,9 +683,6 @@ outputs = [self.ExpandRuleVariables(o, root, dirname, source, ext, basename) for o in rule['outputs']] - inputs = [self.ExpandRuleVariables(i, root, dirname, - source, ext, basename) - for i in rule.get('inputs', [])] if int(rule.get('process_outputs_as_sources', False)): extra_sources += outputs @@ -702,10 +720,11 @@ else: assert var == None, repr(var) - inputs = [self.GypPathToNinja(i, env) for i in inputs] outputs = [self.GypPathToNinja(o, env) for o in outputs] - extra_bindings.append(('unique_name', - hashlib.md5(outputs[0]).hexdigest())) + if self.flavor == 'win': + # WriteNewNinjaRule uses unique_name for creating an rsp file on win. + extra_bindings.append(('unique_name', + hashlib.md5(outputs[0]).hexdigest())) self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), implicit=inputs, order_only=prebuild, @@ -717,7 +736,7 @@ def WriteCopies(self, copies, prebuild, mac_bundle_depends): outputs = [] - env = self.GetSortedXcodeEnv() + env = self.GetToolchainEnv() for copy in copies: for path in copy['files']: # Normalize the path so trailing slashes don't confuse us. @@ -741,15 +760,68 @@ def WriteMacBundleResources(self, resources, bundle_depends): """Writes ninja edges for 'mac_bundle_resources'.""" + xcassets = [] for output, res in gyp.xcode_emulation.GetMacBundleResources( generator_default_variables['PRODUCT_DIR'], self.xcode_settings, map(self.GypPathToNinja, resources)): output = self.ExpandSpecial(output) - self.ninja.build(output, 'mac_tool', res, - variables=[('mactool_cmd', 'copy-bundle-resource')]) - bundle_depends.append(output) + if os.path.splitext(output)[-1] != '.xcassets': + isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) + self.ninja.build(output, 'mac_tool', res, + variables=[('mactool_cmd', 'copy-bundle-resource'), \ + ('binary', isBinary)]) + bundle_depends.append(output) + else: + xcassets.append(res) + return xcassets + + def WriteMacXCassets(self, xcassets, bundle_depends): + """Writes ninja edges for 'mac_bundle_resources' .xcassets files. + + This add an invocation of 'actool' via the 'mac_tool.py' helper script. + It assumes that the assets catalogs define at least one imageset and + thus an Assets.car file will be generated in the application resources + directory. If this is not the case, then the build will probably be done + at each invocation of ninja.""" + if not xcassets: + return + + extra_arguments = {} + settings_to_arg = { + 'XCASSETS_APP_ICON': 'app-icon', + 'XCASSETS_LAUNCH_IMAGE': 'launch-image', + } + settings = self.xcode_settings.xcode_settings[self.config_name] + for settings_key, arg_name in settings_to_arg.iteritems(): + value = settings.get(settings_key) + if value: + extra_arguments[arg_name] = value + + partial_info_plist = None + if extra_arguments: + partial_info_plist = self.GypPathToUniqueOutput( + 'assetcatalog_generated_info.plist') + extra_arguments['output-partial-info-plist'] = partial_info_plist + + outputs = [] + outputs.append( + os.path.join( + self.xcode_settings.GetBundleResourceFolder(), + 'Assets.car')) + if partial_info_plist: + outputs.append(partial_info_plist) + + keys = QuoteShellArgument(json.dumps(extra_arguments), self.flavor) + extra_env = self.xcode_settings.GetPerTargetSettings() + env = self.GetSortedXcodeEnv(additional_settings=extra_env) + env = self.ComputeExportEnvString(env) + + bundle_depends.extend(self.ninja.build( + outputs, 'compile_xcassets', xcassets, + variables=[('env', env), ('keys', keys)])) + return partial_info_plist - def WriteMacInfoPlist(self, bundle_depends): + def WriteMacInfoPlist(self, partial_info_plist, bundle_depends): """Write build rules for bundle Info.plist files.""" info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist( generator_default_variables['PRODUCT_DIR'], @@ -762,15 +834,25 @@ intermediate_plist = self.GypPathToUniqueOutput( os.path.basename(info_plist)) defines = ' '.join([Define(d, self.flavor) for d in defines]) - info_plist = self.ninja.build(intermediate_plist, 'infoplist', info_plist, - variables=[('defines',defines)]) + info_plist = self.ninja.build( + intermediate_plist, 'preprocess_infoplist', info_plist, + variables=[('defines',defines)]) env = self.GetSortedXcodeEnv(additional_settings=extra_env) env = self.ComputeExportEnvString(env) - self.ninja.build(out, 'mac_tool', info_plist, - variables=[('mactool_cmd', 'copy-info-plist'), - ('env', env)]) + if partial_info_plist: + intermediate_plist = self.GypPathToUniqueOutput('merged_info.plist') + info_plist = self.ninja.build( + intermediate_plist, 'merge_infoplist', + [partial_info_plist, info_plist]) + + keys = self.xcode_settings.GetExtraPlistItems(self.config_name) + keys = QuoteShellArgument(json.dumps(keys), self.flavor) + isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) + self.ninja.build(out, 'copy_infoplist', info_plist, + variables=[('env', env), ('keys', keys), + ('binary', isBinary)]) bundle_depends.append(out) def WriteSources(self, ninja_file, config_name, config, sources, predepends, @@ -782,6 +864,8 @@ self.ninja.variable('cxx', '$cxx_host') self.ninja.variable('ld', '$ld_host') self.ninja.variable('ldxx', '$ldxx_host') + self.ninja.variable('nm', '$nm_host') + self.ninja.variable('readelf', '$readelf_host') if self.flavor != 'mac' or len(self.archs) == 1: return self.WriteSourcesForArch( @@ -807,19 +891,23 @@ cflags_objcc = ['$cflags_cc'] + \ self.xcode_settings.GetCflagsObjCC(config_name) elif self.flavor == 'win': + asmflags = self.msvs_settings.GetAsmflags(config_name) cflags = self.msvs_settings.GetCflags(config_name) cflags_c = self.msvs_settings.GetCflagsC(config_name) cflags_cc = self.msvs_settings.GetCflagsCC(config_name) extra_defines = self.msvs_settings.GetComputedDefines(config_name) - pdbpath = self.msvs_settings.GetCompilerPdbName( + # See comment at cc_command for why there's two .pdb files. + pdbpath_c = pdbpath_cc = self.msvs_settings.GetCompilerPdbName( config_name, self.ExpandSpecial) - if not pdbpath: + if not pdbpath_c: obj = 'obj' if self.toolset != 'target': obj += '.' + self.toolset - pdbpath = os.path.normpath(os.path.join(obj, self.base_dir, - self.name + '.pdb')) - self.WriteVariableList(ninja_file, 'pdbname', [pdbpath]) + pdbpath = os.path.normpath(os.path.join(obj, self.base_dir, self.name)) + pdbpath_c = pdbpath + '.c.pdb' + pdbpath_cc = pdbpath + '.cc.pdb' + self.WriteVariableList(ninja_file, 'pdbname_c', [pdbpath_c]) + self.WriteVariableList(ninja_file, 'pdbname_cc', [pdbpath_cc]) self.WriteVariableList(ninja_file, 'pchprefix', [self.name]) else: cflags = config.get('cflags', []) @@ -838,20 +926,31 @@ self.WriteVariableList(ninja_file, 'defines', [Define(d, self.flavor) for d in defines]) if self.flavor == 'win': + self.WriteVariableList(ninja_file, 'asmflags', + map(self.ExpandSpecial, asmflags)) self.WriteVariableList(ninja_file, 'rcflags', [QuoteShellArgument(self.ExpandSpecial(f), self.flavor) for f in self.msvs_settings.GetRcflags(config_name, self.GypPathToNinja)]) include_dirs = config.get('include_dirs', []) + + env = self.GetToolchainEnv() if self.flavor == 'win': include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs, config_name) - env = self.GetSortedXcodeEnv() self.WriteVariableList(ninja_file, 'includes', [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) for i in include_dirs]) + if self.flavor == 'win': + midl_include_dirs = config.get('midl_include_dirs', []) + midl_include_dirs = self.msvs_settings.AdjustMidlIncludeDirs( + midl_include_dirs, config_name) + self.WriteVariableList(ninja_file, 'midl_includes', + [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) + for i in midl_include_dirs]) + pch_commands = precompiled_header.GetPchBuildCommands(arch) if self.flavor == 'mac': # Most targets use no precompiled headers, so only write these if needed. @@ -860,6 +959,8 @@ include = precompiled_header.GetInclude(ext, arch) if include: ninja_file.variable(var, include) + arflags = config.get('arflags', []) + self.WriteVariableList(ninja_file, 'cflags', map(self.ExpandSpecial, cflags)) self.WriteVariableList(ninja_file, 'cflags_c', @@ -871,8 +972,11 @@ map(self.ExpandSpecial, cflags_objc)) self.WriteVariableList(ninja_file, 'cflags_objcc', map(self.ExpandSpecial, cflags_objcc)) + self.WriteVariableList(ninja_file, 'arflags', + map(self.ExpandSpecial, arflags)) ninja_file.newline() outputs = [] + has_rc_source = False for source in sources: filename, ext = os.path.splitext(source) ext = ext[1:] @@ -885,9 +989,7 @@ elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files. command = 'cc_s' elif (self.flavor == 'win' and ext == 'asm' and - self.msvs_settings.GetArch(config_name) == 'x86' and not self.msvs_settings.HasExplicitAsmRules(spec)): - # Asm files only get auto assembled for x86 (not x64). command = 'asm' # Add the _asm suffix as msvs is capable of handling .cc and # .asm files of the same name without collision. @@ -900,6 +1002,7 @@ elif self.flavor == 'win' and ext == 'rc': command = 'rc' obj_ext = '.res' + has_rc_source = True else: # Ignore unhandled extensions. continue @@ -918,6 +1021,12 @@ order_only=predepends, variables=variables) outputs.append(output) + if has_rc_source: + resource_include_dirs = config.get('resource_include_dirs', include_dirs) + self.WriteVariableList(ninja_file, 'resource_includes', + [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) + for i in resource_include_dirs]) + self.WritePchTargets(ninja_file, pch_commands) ninja_file.newline() @@ -952,9 +1061,19 @@ arch=arch) for arch in self.archs] extra_bindings = [] + build_output = output if not self.is_mac_bundle: self.AppendPostbuildVariable(extra_bindings, spec, output, output) - self.ninja.build(output, 'lipo', inputs, variables=extra_bindings) + + # TODO(yyanagisawa): more work needed to fix: + # https://code.google.com/p/gyp/issues/detail?id=411 + if (spec['type'] in ('shared_library', 'loadable_module') and + not self.is_mac_bundle): + extra_bindings.append(('lib', output)) + self.ninja.build([output, output + '.TOC'], 'solipo', inputs, + variables=extra_bindings) + else: + self.ninja.build(build_output, 'lipo', inputs, variables=extra_bindings) return output def WriteLinkForArch(self, ninja_file, spec, config_name, config, @@ -982,31 +1101,27 @@ continue linkable = target.Linkable() if linkable: - if self.link_deps_file: - # Save the mapping of link deps. - self.link_deps_file.write(self.qualified_target) - self.link_deps_file.write(' ') - self.link_deps_file.write(target.binary) - self.link_deps_file.write('\n') - + new_deps = [] if (self.flavor == 'win' and target.component_objs and self.msvs_settings.IsUseLibraryDependencyInputs(config_name)): - extra_link_deps |= set(target.component_objs) + new_deps = target.component_objs elif self.flavor == 'win' and target.import_lib: - extra_link_deps.add(target.import_lib) + new_deps = [target.import_lib] elif target.UsesToc(self.flavor): solibs.add(target.binary) implicit_deps.add(target.binary + '.TOC') else: - extra_link_deps.add(target.binary) + new_deps = [target.binary] + for new_dep in new_deps: + if new_dep not in extra_link_deps: + extra_link_deps.add(new_dep) + link_deps.append(new_dep) final_output = target.FinalOutput() if not linkable or final_output != target.binary: implicit_deps.add(final_output) - link_deps.extend(list(extra_link_deps)) - extra_bindings = [] if self.uses_cpp and self.flavor != 'win': extra_bindings.append(('ld', '$ldxx')) @@ -1016,42 +1131,52 @@ self.AppendPostbuildVariable(extra_bindings, spec, output, output) is_executable = spec['type'] == 'executable' + # The ldflags config key is not used on mac or win. On those platforms + # linker flags are set via xcode_settings and msvs_settings, respectively. + env_ldflags = os.environ.get('LDFLAGS', '').split() if self.flavor == 'mac': ldflags = self.xcode_settings.GetLdflags(config_name, self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']), self.GypPathToNinja, arch) + ldflags = env_ldflags + ldflags elif self.flavor == 'win': - manifest_name = self.GypPathToUniqueOutput( + manifest_base_name = self.GypPathToUniqueOutput( self.ComputeOutputFileName(spec)) - ldflags, manifest_files = self.msvs_settings.GetLdflags(config_name, - self.GypPathToNinja, self.ExpandSpecial, manifest_name, is_executable) + ldflags, intermediate_manifest, manifest_files = \ + self.msvs_settings.GetLdflags(config_name, self.GypPathToNinja, + self.ExpandSpecial, manifest_base_name, + output, is_executable, + self.toplevel_build) + ldflags = env_ldflags + ldflags self.WriteVariableList(ninja_file, 'manifests', manifest_files) + implicit_deps = implicit_deps.union(manifest_files) + if intermediate_manifest: + self.WriteVariableList( + ninja_file, 'intermediatemanifest', [intermediate_manifest]) command_suffix = _GetWinLinkRuleNameSuffix( - self.msvs_settings.IsEmbedManifest(config_name), - self.msvs_settings.IsLinkIncremental(config_name)) + self.msvs_settings.IsEmbedManifest(config_name)) def_file = self.msvs_settings.GetDefFile(self.GypPathToNinja) if def_file: implicit_deps.add(def_file) else: # Respect environment variables related to build, but target-specific # flags can still override them. - ldflags = (os.environ.get('LDFLAGS', '').split() + - config.get('ldflags', [])) + ldflags = env_ldflags + config.get('ldflags', []) if is_executable and len(solibs): rpath = 'lib/' if self.toolset != 'target': rpath += self.toolset - ldflags.append('-Wl,-rpath=\$$ORIGIN/%s' % rpath) + ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) ldflags.append('-Wl,-rpath-link=%s' % rpath) self.WriteVariableList(ninja_file, 'ldflags', - gyp.common.uniquer(map(self.ExpandSpecial, ldflags))) + map(self.ExpandSpecial, ldflags)) library_dirs = config.get('library_dirs', []) if self.flavor == 'win': library_dirs = [self.msvs_settings.ConvertVSMacros(l, config_name) for l in library_dirs] - library_dirs = [QuoteShellArgument('-LIBPATH:' + self.GypPathToNinja(l), - self.flavor) + library_dirs = ['/LIBPATH:' + QuoteShellArgument(self.GypPathToNinja(l), + self.flavor) for l in library_dirs] else: library_dirs = [QuoteShellArgument('-L' + self.GypPathToNinja(l), @@ -1061,7 +1186,7 @@ libraries = gyp.common.uniquer(map(self.ExpandSpecial, spec.get('libraries', []))) if self.flavor == 'mac': - libraries = self.xcode_settings.AdjustLibraries(libraries) + libraries = self.xcode_settings.AdjustLibraries(libraries, config_name) elif self.flavor == 'win': libraries = self.msvs_settings.AdjustLibraries(libraries) @@ -1073,17 +1198,46 @@ extra_bindings.append(('soname', os.path.split(output)[1])) extra_bindings.append(('lib', gyp.common.EncodePOSIXShellArgument(output))) + if self.flavor != 'win': + link_file_list = output + if self.is_mac_bundle: + # 'Dependency Framework.framework/Versions/A/Dependency Framework' -> + # 'Dependency Framework.framework.rsp' + link_file_list = self.xcode_settings.GetWrapperName() + if arch: + link_file_list += '.' + arch + link_file_list += '.rsp' + # If an rspfile contains spaces, ninja surrounds the filename with + # quotes around it and then passes it to open(), creating a file with + # quotes in its name (and when looking for the rsp file, the name + # makes it through bash which strips the quotes) :-/ + link_file_list = link_file_list.replace(' ', '_') + extra_bindings.append( + ('link_file_list', + gyp.common.EncodePOSIXShellArgument(link_file_list))) if self.flavor == 'win': - extra_bindings.append(('dll', output)) - if '/NOENTRY' not in ldflags: + extra_bindings.append(('binary', output)) + if ('/NOENTRY' not in ldflags and + not self.msvs_settings.GetNoImportLibrary(config_name)): self.target.import_lib = output + '.lib' extra_bindings.append(('implibflag', '/IMPLIB:%s' % self.target.import_lib)) + pdbname = self.msvs_settings.GetPDBName( + config_name, self.ExpandSpecial, output + '.pdb') output = [output, self.target.import_lib] + if pdbname: + output.append(pdbname) elif not self.is_mac_bundle: output = [output, output + '.TOC'] else: command = command + '_notoc' + elif self.flavor == 'win': + extra_bindings.append(('binary', output)) + pdbname = self.msvs_settings.GetPDBName( + config_name, self.ExpandSpecial, output + '.pdb') + if pdbname: + output = [output, pdbname] + if len(solibs): extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) @@ -1163,6 +1317,19 @@ self.target.bundle = output return output + def GetToolchainEnv(self, additional_settings=None): + """Returns the variables toolchain would set for build steps.""" + env = self.GetSortedXcodeEnv(additional_settings=additional_settings) + if self.flavor == 'win': + env = self.GetMsvsToolchainEnv( + additional_settings=additional_settings) + return env + + def GetMsvsToolchainEnv(self, additional_settings=None): + """Returns the variables Visual Studio would set for build steps.""" + return self.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR', + config=self.config_name) + def GetSortedXcodeEnv(self, additional_settings=None): """Returns the variables Xcode would set for build steps.""" assert self.abs_build_dir @@ -1197,17 +1364,16 @@ if not self.xcode_settings or spec['type'] == 'none' or not output: return '' output = QuoteShellArgument(output, self.flavor) - target_postbuilds = [] + postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True) if output_binary is not None: - target_postbuilds = self.xcode_settings.GetTargetPostbuilds( + postbuilds = self.xcode_settings.AddImplicitPostbuilds( self.config_name, os.path.normpath(os.path.join(self.base_to_build, output)), QuoteShellArgument( os.path.normpath(os.path.join(self.base_to_build, output_binary)), self.flavor), - quiet=True) - postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True) - postbuilds = target_postbuilds + postbuilds + postbuilds, quiet=True) + if not postbuilds: return '' # Postbuilds expect to be run in the gyp file's directory, so insert an @@ -1345,7 +1511,8 @@ values = [] ninja_file.variable(var, ' '.join(values)) - def WriteNewNinjaRule(self, name, args, description, is_cygwin, env): + def WriteNewNinjaRule(self, name, args, description, is_cygwin, env, pool, + depfile=None): """Write out a new ninja "rule" statement for a given command. Returns the name of the new rule, and a copy of |args| with variables @@ -1403,7 +1570,8 @@ # GYP rules/actions express being no-ops by not touching their outputs. # Avoid executing downstream dependencies in this case by specifying # restat=1 to ninja. - self.ninja.rule(rule_name, command, description, restat=True, + self.ninja.rule(rule_name, command, description, depfile=depfile, + restat=True, pool=pool, rspfile=rspfile, rspfile_content=rspfile_content) self.ninja.newline() @@ -1434,13 +1602,13 @@ generator_extra_sources_for_rules = getattr(xcode_generator, 'generator_extra_sources_for_rules', []) elif flavor == 'win': + exts = gyp.MSVSUtil.TARGET_TYPE_EXT default_variables.setdefault('OS', 'win') - default_variables['EXECUTABLE_SUFFIX'] = '.exe' + default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable'] default_variables['STATIC_LIB_PREFIX'] = '' - default_variables['STATIC_LIB_SUFFIX'] = '.lib' + default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library'] default_variables['SHARED_LIB_PREFIX'] = '' - default_variables['SHARED_LIB_SUFFIX'] = '.dll' - generator_flags = params.get('generator_flags', {}) + default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library'] # Copy additional generator configuration data from VS, which is shared # by the Windows Ninja generator. @@ -1450,19 +1618,7 @@ generator_additional_path_sections = getattr(msvs_generator, 'generator_additional_path_sections', []) - # Set a variable so conditions can be based on msvs_version. - msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags) - default_variables['MSVS_VERSION'] = msvs_version.ShortName() - - # To determine processor word size on Windows, in addition to checking - # PROCESSOR_ARCHITECTURE (which reflects the word size of the current - # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which - # contains the actual word size of the system when running thru WOW64). - if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or - '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): - default_variables['MSVS_OS_BITS'] = 64 - else: - default_variables['MSVS_OS_BITS'] = 32 + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) else: operating_system = flavor if flavor == 'android': @@ -1474,13 +1630,36 @@ default_variables.setdefault('LIB_DIR', os.path.join('$!PRODUCT_DIR', 'obj')) +def ComputeOutputDir(params): + """Returns the path from the toplevel_dir to the build output directory.""" + # generator_dir: relative path from pwd to where make puts build files. + # Makes migrating from make to ninja easier, ninja doesn't put anything here. + generator_dir = os.path.relpath(params['options'].generator_output or '.') + + # output_dir: relative path from generator_dir to the build directory. + output_dir = params.get('generator_flags', {}).get('output_dir', 'out') + + # Relative path from source root to our output files. e.g. "out" + return os.path.normpath(os.path.join(generator_dir, output_dir)) + + +def CalculateGeneratorInputInfo(params): + """Called by __init__ to initialize generator values based on params.""" + # E.g. "out/gypfiles" + toplevel = params['options'].toplevel_dir + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, ComputeOutputDir(params), 'gypfiles')) + + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': toplevel, + 'qualified_out_dir': qualified_out_dir, + } + def OpenOutput(path, mode='w'): """Open |path| for writing, creating directories if necessary.""" - try: - os.makedirs(os.path.dirname(path)) - except OSError: - pass + gyp.common.EnsureDirExists(path) return open(path, mode) @@ -1493,6 +1672,10 @@ def GetDefaultConcurrentLinks(): """Returns a best-guess for a number of concurrent links.""" + pool_size = int(os.getenv('GYP_LINK_CONCURRENCY', 0)) + if pool_size: + return pool_size + if sys.platform in ('win32', 'cygwin'): import ctypes @@ -1513,18 +1696,21 @@ stat.dwLength = ctypes.sizeof(stat) ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) - mem_limit = max(1, stat.ullTotalPhys / (4 * (2 ** 30))) # total / 4GB + # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM + # on a 64 GB machine. + mem_limit = max(1, stat.ullTotalPhys / (5 * (2 ** 30))) # total / 5GB hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32))) return min(mem_limit, hard_cap) elif sys.platform.startswith('linux'): - with open("/proc/meminfo") as meminfo: - memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB') - for line in meminfo: - match = memtotal_re.match(line) - if not match: - continue - # Allow 8Gb per link on Linux because Gold is quite memory hungry - return max(1, int(match.group(1)) / (8 * (2 ** 20))) + if os.path.exists("/proc/meminfo"): + with open("/proc/meminfo") as meminfo: + memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB') + for line in meminfo: + match = memtotal_re.match(line) + if not match: + continue + # Allow 8Gb per link on Linux because Gold is quite memory hungry + return max(1, int(match.group(1)) / (8 * (2 ** 20))) return 1 elif sys.platform == 'darwin': try: @@ -1539,80 +1725,59 @@ return 1 -def _GetWinLinkRuleNameSuffix(embed_manifest, link_incremental): +def _GetWinLinkRuleNameSuffix(embed_manifest): """Returns the suffix used to select an appropriate linking rule depending on - whether the manifest embedding and/or incremental linking is enabled.""" - suffix = '' - if embed_manifest: - suffix += '_embed' - if link_incremental: - suffix += '_inc' - return suffix + whether the manifest embedding is enabled.""" + return '_embed' if embed_manifest else '' -def _AddWinLinkRules(master_ninja, embed_manifest, link_incremental): +def _AddWinLinkRules(master_ninja, embed_manifest): """Adds link rules for Windows platform to |master_ninja|.""" def FullLinkCommand(ldcmd, out, binary_type): - cmd = ('cmd /c %(ldcmd)s' - ' && %(python)s gyp-win-tool manifest-wrapper $arch' - ' cmd /c if exist %(out)s.manifest del %(out)s.manifest' - ' && %(python)s gyp-win-tool manifest-wrapper $arch' - ' $mt -nologo -manifest $manifests') - if embed_manifest and not link_incremental: - # Embed manifest into a binary. If incremental linking is enabled, - # embedding is postponed to the re-linking stage (see below). - cmd += ' -outputresource:%(out)s;%(resname)s' - else: - # Save manifest as an external file. - cmd += ' -out:%(out)s.manifest' - if link_incremental: - # There is no point in generating separate rule for the case when - # incremental linking is enabled, but manifest embedding is disabled. - # In that case the basic rule should be used (e.g. 'link'). - # See also implementation of _GetWinLinkRuleNameSuffix(). - assert embed_manifest - # Make .rc file out of manifest, compile it to .res file and re-link. - cmd += (' && %(python)s gyp-win-tool manifest-to-rc $arch' - ' %(out)s.manifest %(out)s.manifest.rc %(resname)s' - ' && %(python)s gyp-win-tool rc-wrapper $arch $rc' - ' %(out)s.manifest.rc' - ' && %(ldcmd)s %(out)s.manifest.res') resource_name = { 'exe': '1', 'dll': '2', }[binary_type] - return cmd % {'python': sys.executable, - 'out': out, - 'ldcmd': ldcmd, - 'resname': resource_name} - - rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest, link_incremental) - dlldesc = 'LINK%s(DLL) $dll' % rule_name_suffix.upper() - dllcmd = ('%s gyp-win-tool link-wrapper $arch ' - '$ld /nologo $implibflag /DLL /OUT:$dll ' - '/PDB:$dll.pdb @$dll.rsp' % sys.executable) - dllcmd = FullLinkCommand(dllcmd, '$dll', 'dll') + return '%(python)s gyp-win-tool link-with-manifests $arch %(embed)s ' \ + '%(out)s "%(ldcmd)s" %(resname)s $mt $rc "$intermediatemanifest" ' \ + '$manifests' % { + 'python': sys.executable, + 'out': out, + 'ldcmd': ldcmd, + 'resname': resource_name, + 'embed': embed_manifest } + rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest) + use_separate_mspdbsrv = ( + int(os.environ.get('GYP_USE_SEPARATE_MSPDBSRV', '0')) != 0) + dlldesc = 'LINK%s(DLL) $binary' % rule_name_suffix.upper() + dllcmd = ('%s gyp-win-tool link-wrapper $arch %s ' + '$ld /nologo $implibflag /DLL /OUT:$binary ' + '@$binary.rsp' % (sys.executable, use_separate_mspdbsrv)) + dllcmd = FullLinkCommand(dllcmd, '$binary', 'dll') master_ninja.rule('solink' + rule_name_suffix, description=dlldesc, command=dllcmd, - rspfile='$dll.rsp', + rspfile='$binary.rsp', rspfile_content='$libs $in_newline $ldflags', - restat=True) + restat=True, + pool='link_pool') master_ninja.rule('solink_module' + rule_name_suffix, description=dlldesc, command=dllcmd, - rspfile='$dll.rsp', + rspfile='$binary.rsp', rspfile_content='$libs $in_newline $ldflags', - restat=True) + restat=True, + pool='link_pool') # Note that ldflags goes at the end so that it has the option of # overriding default settings earlier in the command line. - exe_cmd = ('%s gyp-win-tool link-wrapper $arch ' - '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' % - sys.executable) - exe_cmd = FullLinkCommand(exe_cmd, '$out', 'exe') + exe_cmd = ('%s gyp-win-tool link-wrapper $arch %s ' + '$ld /nologo /OUT:$binary @$binary.rsp' % + (sys.executable, use_separate_mspdbsrv)) + exe_cmd = FullLinkCommand(exe_cmd, '$binary', 'exe') master_ninja.rule('link' + rule_name_suffix, - description='LINK%s $out' % rule_name_suffix.upper(), + description='LINK%s $binary' % rule_name_suffix.upper(), command=exe_cmd, - rspfile='$out.rsp', - rspfile_content='$in_newline $libs $ldflags') + rspfile='$binary.rsp', + rspfile_content='$in_newline $libs $ldflags', + pool='link_pool') def GenerateOutputForConfig(target_list, target_dicts, data, params, @@ -1621,24 +1786,15 @@ flavor = gyp.common.GetFlavor(params) generator_flags = params.get('generator_flags', {}) - # generator_dir: relative path from pwd to where make puts build files. - # Makes migrating from make to ninja easier, ninja doesn't put anything here. - generator_dir = os.path.relpath(params['options'].generator_output or '.') - - # output_dir: relative path from generator_dir to the build directory. - output_dir = generator_flags.get('output_dir', 'out') - # build_dir: relative path from source root to our output files. # e.g. "out/Debug" - build_dir = os.path.normpath(os.path.join(generator_dir, - output_dir, - config_name)) + build_dir = os.path.normpath( + os.path.join(ComputeOutputDir(params), config_name)) toplevel_build = os.path.join(options.toplevel_dir, build_dir) - master_ninja = ninja_syntax.Writer( - OpenOutput(os.path.join(toplevel_build, 'build.ninja')), - width=120) + master_ninja_file = OpenOutput(os.path.join(toplevel_build, 'build.ninja')) + master_ninja = ninja_syntax.Writer(master_ninja_file, width=120) # Put build-time support tools in out/{config_name}. gyp.common.CopyTool(flavor, toplevel_build) @@ -1651,25 +1807,32 @@ # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set # to cc/cxx. if flavor == 'win': - # Overridden by local arch choice in the use_deps case. - # Chromium's ffmpeg c99conv.py currently looks for a 'cc =' line in - # build.ninja so needs something valid here. http://crbug.com/233985 - cc = 'cl.exe' - cxx = 'cl.exe' + ar = 'lib.exe' + # cc and cxx must be set to the correct architecture by overriding with one + # of cl_x86 or cl_x64 below. + cc = 'UNSET' + cxx = 'UNSET' ld = 'link.exe' ld_host = '$ld' else: - cc = 'gcc' - cxx = 'g++' + ar = 'ar' + cc = 'cc' + cxx = 'c++' ld = '$cc' ldxx = '$cxx' ld_host = '$cc_host' ldxx_host = '$cxx_host' + ar_host = 'ar' cc_host = None cxx_host = None cc_host_global_setting = None cxx_host_global_setting = None + clang_cl = None + nm = 'nm' + nm_host = 'nm' + readelf = 'readelf' + readelf_host = 'readelf' build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) make_global_settings = data[build_file].get('make_global_settings', []) @@ -1677,8 +1840,14 @@ options.toplevel_dir) wrappers = {} for key, value in make_global_settings: + if key == 'AR': + ar = os.path.join(build_to_root, value) + if key == 'AR.host': + ar_host = os.path.join(build_to_root, value) if key == 'CC': cc = os.path.join(build_to_root, value) + if cc.endswith('clang-cl'): + clang_cl = cc if key == 'CXX': cxx = os.path.join(build_to_root, value) if key == 'CC.host': @@ -1687,6 +1856,18 @@ if key == 'CXX.host': cxx_host = os.path.join(build_to_root, value) cxx_host_global_setting = value + if key == 'LD': + ld = os.path.join(build_to_root, value) + if key == 'LD.host': + ld_host = os.path.join(build_to_root, value) + if key == 'NM': + nm = os.path.join(build_to_root, value) + if key == 'NM.host': + nm_host = os.path.join(build_to_root, value) + if key == 'READELF': + readelf = os.path.join(build_to_root, value) + if key == 'READELF.host': + readelf_host = os.path.join(build_to_root, value) if key.endswith('_wrapper'): wrappers[key[:-len('_wrapper')]] = os.path.join(build_to_root, value) @@ -1698,12 +1879,25 @@ wrappers[key_prefix] = os.path.join(build_to_root, value) if flavor == 'win': + configs = [target_dicts[qualified_target]['configurations'][config_name] + for qualified_target in target_list] + shared_system_includes = None + if not generator_flags.get('ninja_use_custom_environment_files', 0): + shared_system_includes = \ + gyp.msvs_emulation.ExtractSharedMSVSSystemIncludes( + configs, generator_flags) cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles( - toplevel_build, generator_flags, OpenOutput) + toplevel_build, generator_flags, shared_system_includes, OpenOutput) for arch, path in cl_paths.iteritems(): - master_ninja.variable( - 'cl_' + arch, CommandWithWrapper('CC', wrappers, - QuoteShellArgument(path, flavor))) + if clang_cl: + # If we have selected clang-cl, use that instead. + path = clang_cl + command = CommandWithWrapper('CC', wrappers, + QuoteShellArgument(path, 'win')) + if clang_cl: + # Use clang-cl to cross-compile for x86 or x86_64. + command += (' -m32' if arch == 'x86' else ' -m64') + master_ninja.variable('cl_' + arch, command) cc = GetEnvironFallback(['CC_target', 'CC'], cc) master_ninja.variable('cc', CommandWithWrapper('CC', wrappers, cc)) @@ -1713,14 +1907,22 @@ if flavor == 'win': master_ninja.variable('ld', ld) master_ninja.variable('idl', 'midl.exe') - master_ninja.variable('ar', 'lib.exe') + master_ninja.variable('ar', ar) master_ninja.variable('rc', 'rc.exe') - master_ninja.variable('asm', 'ml.exe') + master_ninja.variable('ml_x86', 'ml.exe') + master_ninja.variable('ml_x64', 'ml64.exe') master_ninja.variable('mt', 'mt.exe') else: master_ninja.variable('ld', CommandWithWrapper('LINK', wrappers, ld)) master_ninja.variable('ldxx', CommandWithWrapper('LINK', wrappers, ldxx)) - master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], 'ar')) + master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], ar)) + if flavor != 'mac': + # Mac does not use readelf/nm for .TOC generation, so avoiding polluting + # the master ninja with extra unused variables. + master_ninja.variable( + 'nm', GetEnvironFallback(['NM_target', 'NM'], nm)) + master_ninja.variable( + 'readelf', GetEnvironFallback(['READELF_target', 'READELF'], readelf)) if generator_supports_multiple_toolsets: if not cc_host: @@ -1728,7 +1930,10 @@ if not cxx_host: cxx_host = cxx - master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], 'ar')) + master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], ar_host)) + master_ninja.variable('nm_host', GetEnvironFallback(['NM_host'], nm_host)) + master_ninja.variable('readelf_host', + GetEnvironFallback(['READELF_host'], readelf_host)) cc_host = GetEnvironFallback(['CC_host'], cc_host) cxx_host = GetEnvironFallback(['CXX_host'], cxx_host) @@ -1778,14 +1983,20 @@ depfile='$out.d', deps=deps) else: + # TODO(scottmg) Separate pdb names is a test to see if it works around + # http://crbug.com/142362. It seems there's a race between the creation of + # the .pdb by the precompiled header step for .cc and the compilation of + # .c files. This should be handled by mspdbsrv, but rarely errors out with + # c1xx : fatal error C1033: cannot open program database + # By making the rules target separate pdb files this might be avoided. cc_command = ('ninja -t msvc -e $arch ' + '-- ' '$cc /nologo /showIncludes /FC ' - '@$out.rsp /c $in /Fo$out /Fd$pdbname ') + '@$out.rsp /c $in /Fo$out /Fd$pdbname_c ') cxx_command = ('ninja -t msvc -e $arch ' + '-- ' '$cxx /nologo /showIncludes /FC ' - '@$out.rsp /c $in /Fo$out /Fd$pdbname ') + '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ') master_ninja.rule( 'cc', description='CC $out', @@ -1805,30 +2016,30 @@ description='IDL $in', command=('%s gyp-win-tool midl-wrapper $arch $outdir ' '$tlb $h $dlldata $iid $proxy $in ' - '$idlflags' % sys.executable)) + '$midl_includes $idlflags' % sys.executable)) master_ninja.rule( 'rc', description='RC $in', # Note: $in must be last otherwise rc.exe complains. command=('%s gyp-win-tool rc-wrapper ' - '$arch $rc $defines $includes $rcflags /fo$out $in' % + '$arch $rc $defines $resource_includes $rcflags /fo$out $in' % sys.executable)) master_ninja.rule( 'asm', - description='ASM $in', + description='ASM $out', command=('%s gyp-win-tool asm-wrapper ' - '$arch $asm $defines $includes /c /Fo $out $in' % + '$arch $asm $defines $includes $asmflags /c /Fo $out $in' % sys.executable)) if flavor != 'mac' and flavor != 'win': master_ninja.rule( 'alink', description='AR $out', - command='rm -f $out && $ar rcs $out $in') + command='rm -f $out && $ar rcs $arflags $out $in') master_ninja.rule( 'alink_thin', description='AR $out', - command='rm -f $out && $ar rcsT $out $in') + command='rm -f $out && $ar rcsT $arflags $out $in') # This allows targets that only need to depend on $lib's API to declare an # order-only dependency on $lib.TOC and avoid relinking such downstream @@ -1836,54 +2047,51 @@ # The resulting string leaves an uninterpolated %{suffix} which # is used in the final substitution below. mtime_preserving_solink_base = ( - 'if [ ! -e $lib -o ! -e ${lib}.TOC ]; then ' - '%(solink)s && %(extract_toc)s > ${lib}.TOC; else ' - '%(solink)s && %(extract_toc)s > ${lib}.tmp && ' - 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then mv ${lib}.tmp ${lib}.TOC ; ' + 'if [ ! -e $lib -o ! -e $lib.TOC ]; then ' + '%(solink)s && %(extract_toc)s > $lib.TOC; else ' + '%(solink)s && %(extract_toc)s > $lib.tmp && ' + 'if ! cmp -s $lib.tmp $lib.TOC; then mv $lib.tmp $lib.TOC ; ' 'fi; fi' % { 'solink': '$ld -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s', 'extract_toc': - ('{ readelf -d ${lib} | grep SONAME ; ' - 'nm -gD -f p ${lib} | cut -f1-2 -d\' \'; }')}) + ('{ $readelf -d $lib | grep SONAME ; ' + '$nm -gD -f p $lib | cut -f1-2 -d\' \'; }')}) master_ninja.rule( 'solink', description='SOLINK $lib', restat=True, - command=(mtime_preserving_solink_base % { - 'suffix': '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive ' - '$libs'}), + command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'}, + rspfile='$link_file_list', + rspfile_content= + '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive $libs', pool='link_pool') master_ninja.rule( 'solink_module', description='SOLINK(module) $lib', restat=True, - command=(mtime_preserving_solink_base % { - 'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group ' - '$libs'}), + command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'}, + rspfile='$link_file_list', + rspfile_content='-Wl,--start-group $in -Wl,--end-group $solibs $libs', pool='link_pool') master_ninja.rule( 'link', description='LINK $out', command=('$ld $ldflags -o $out ' - '-Wl,--start-group $in $solibs -Wl,--end-group $libs'), + '-Wl,--start-group $in -Wl,--end-group $solibs $libs'), pool='link_pool') elif flavor == 'win': master_ninja.rule( 'alink', description='LIB $out', - command=('%s gyp-win-tool link-wrapper $arch ' + command=('%s gyp-win-tool link-wrapper $arch False ' '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % sys.executable), rspfile='$out.rsp', rspfile_content='$in_newline $libflags') - _AddWinLinkRules(master_ninja, embed_manifest=True, link_incremental=True) - _AddWinLinkRules(master_ninja, embed_manifest=True, link_incremental=False) - _AddWinLinkRules(master_ninja, embed_manifest=False, link_incremental=False) - # Do not generate rules for embed_manifest=False and link_incremental=True - # because in that case rules for (False, False) should be used (see - # implementation of _GetWinLinkRuleNameSuffix()). + _AddWinLinkRules(master_ninja, embed_manifest=True) + _AddWinLinkRules(master_ninja, embed_manifest=False) else: master_ninja.rule( 'objc', @@ -1910,21 +2118,31 @@ 'lipo', description='LIPO $out, POSTBUILDS', command='rm -f $out && lipo -create $in -output $out$postbuilds') + master_ninja.rule( + 'solipo', + description='SOLIPO $out, POSTBUILDS', + command=( + 'rm -f $lib $lib.TOC && lipo -create $in -output $lib$postbuilds &&' + '%(extract_toc)s > $lib.TOC' + % { 'extract_toc': + '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' + 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})) + # Record the public interface of $lib in $lib.TOC. See the corresponding # comment in the posix section above for details. solink_base = '$ld %(type)s $ldflags -o $lib %(suffix)s' mtime_preserving_solink_base = ( - 'if [ ! -e $lib -o ! -e ${lib}.TOC ] || ' + 'if [ ! -e $lib -o ! -e $lib.TOC ] || ' # Always force dependent targets to relink if this library # reexports something. Handling this correctly would require # recursive TOC dumping but this is rare in practice, so punt. 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then ' - '%(solink)s && %(extract_toc)s > ${lib}.TOC; ' + '%(solink)s && %(extract_toc)s > $lib.TOC; ' 'else ' - '%(solink)s && %(extract_toc)s > ${lib}.tmp && ' - 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then ' - 'mv ${lib}.tmp ${lib}.TOC ; ' + '%(solink)s && %(extract_toc)s > $lib.tmp && ' + 'if ! cmp -s $lib.tmp $lib.TOC; then ' + 'mv $lib.tmp $lib.TOC ; ' 'fi; ' 'fi' % { 'solink': solink_base, @@ -1932,34 +2150,42 @@ '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'}) - solink_suffix = '$in $solibs $libs$postbuilds' + + solink_suffix = '@$link_file_list$postbuilds' master_ninja.rule( 'solink', description='SOLINK $lib, POSTBUILDS', restat=True, command=mtime_preserving_solink_base % {'suffix': solink_suffix, 'type': '-shared'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', pool='link_pool') master_ninja.rule( 'solink_notoc', description='SOLINK $lib, POSTBUILDS', restat=True, command=solink_base % {'suffix':solink_suffix, 'type': '-shared'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', pool='link_pool') - solink_module_suffix = '$in $solibs $libs$postbuilds' master_ninja.rule( 'solink_module', description='SOLINK(module) $lib, POSTBUILDS', restat=True, - command=mtime_preserving_solink_base % {'suffix': solink_module_suffix, + command=mtime_preserving_solink_base % {'suffix': solink_suffix, 'type': '-bundle'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', pool='link_pool') master_ninja.rule( 'solink_module_notoc', description='SOLINK(module) $lib, POSTBUILDS', restat=True, - command=solink_base % {'suffix': solink_module_suffix, 'type': '-bundle'}, + command=solink_base % {'suffix': solink_suffix, 'type': '-bundle'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', pool='link_pool') master_ninja.rule( @@ -1969,14 +2195,26 @@ '$in $solibs $libs$postbuilds'), pool='link_pool') master_ninja.rule( - 'infoplist', - description='INFOPLIST $out', + 'preprocess_infoplist', + description='PREPROCESS INFOPLIST $out', command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && ' 'plutil -convert xml1 $out $out')) master_ninja.rule( + 'copy_infoplist', + description='COPY INFOPLIST $in', + command='$env ./gyp-mac-tool copy-info-plist $in $out $binary $keys') + master_ninja.rule( + 'merge_infoplist', + description='MERGE INFOPLISTS $in', + command='$env ./gyp-mac-tool merge-info-plist $out $in') + master_ninja.rule( + 'compile_xcassets', + description='COMPILE XCASSETS $in', + command='$env ./gyp-mac-tool compile-xcassets $keys $in') + master_ninja.rule( 'mac_tool', description='MACTOOL $mactool_cmd $in', - command='$env ./gyp-mac-tool $mactool_cmd $in $out') + command='$env ./gyp-mac-tool $mactool_cmd $in $out $binary') master_ninja.rule( 'package_framework', description='PACKAGE FRAMEWORK $out, POSTBUILDS', @@ -2016,12 +2254,14 @@ # objects. target_short_names = {} - # Extract the optional link deps file name. - LINK_DEPS_FILE = 'link_deps_file' - if LINK_DEPS_FILE in generator_flags: - link_deps_file = open(generator_flags.get(LINK_DEPS_FILE), 'wb') - else: - link_deps_file = None + # short name of targets that were skipped because they didn't contain anything + # interesting. + # NOTE: there may be overlap between this an non_empty_target_names. + empty_target_names = set() + + # Set of non-empty short target names. + # NOTE: there may be overlap between this an empty_target_names. + non_empty_target_names = set() for qualified_target in target_list: # qualified_target is like: third_party/icu/icu.gyp:icui18n#target @@ -2030,7 +2270,8 @@ this_make_global_settings = data[build_file].get('make_global_settings', []) assert make_global_settings == this_make_global_settings, ( - "make_global_settings needs to be the same for all targets.") + "make_global_settings needs to be the same for all targets. %s vs. %s" % + (this_make_global_settings, make_global_settings)) spec = target_dicts[qualified_target] if flavor == 'mac': @@ -2038,6 +2279,10 @@ build_file = gyp.common.RelativePath(build_file, options.toplevel_dir) + qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name, + toolset) + hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest() + base_path = os.path.dirname(build_file) obj = 'obj' if toolset != 'target': @@ -2045,11 +2290,10 @@ output_file = os.path.join(obj, base_path, name + '.ninja') ninja_output = StringIO() - writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir, + writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir, ninja_output, toplevel_build, output_file, - flavor, link_deps_file, - toplevel_dir=options.toplevel_dir) + flavor, toplevel_dir=options.toplevel_dir) target = writer.WriteSpec(spec, config_name, generator_flags) @@ -2066,6 +2310,9 @@ target_outputs[qualified_target] = target if qualified_target in all_targets: all_outputs.add(target.FinalOutput()) + non_empty_target_names.add(name) + else: + empty_target_names.add(name) if target_short_names: # Write a short name to build this target. This benefits both the @@ -2077,11 +2324,23 @@ master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in target_short_names[short_name]]) + # Write phony targets for any empty targets that weren't written yet. As + # short names are not necessarily unique only do this for short names that + # haven't already been output for another target. + empty_target_names = empty_target_names - non_empty_target_names + if empty_target_names: + master_ninja.newline() + master_ninja.comment('Empty targets (output for completeness).') + for name in sorted(empty_target_names): + master_ninja.build(name, 'phony') + if all_outputs: master_ninja.newline() master_ninja.build('all', 'phony', list(all_outputs)) master_ninja.default(generator_flags.get('default_target', 'all')) + master_ninja_file.close() + def PerformBuild(data, configurations, params): options = params['options'] @@ -2102,6 +2361,10 @@ def GenerateOutput(target_list, target_dicts, data, params): + # Update target_dicts for iOS device builds. + target_dicts = gyp.xcode_emulation.CloneConfigurationForDeviceAndEmulator( + target_dicts) + user_config = params.get('generator_flags', {}).get('config', None) if gyp.common.GetFlavor(params) == 'win': target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts) diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/ninja_test.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/ninja_test.py --- gyp-0.1~svn1729/pylib/gyp/generator/ninja_test.py 2013-08-12 13:39:13.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/ninja_test.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,15 +15,18 @@ class TestPrefixesAndSuffixes(unittest.TestCase): def test_BinaryNamesWindows(self): - writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', - 'build.ninja', 'win') - spec = { 'target_name': 'wee' } - self.assertTrue(writer.ComputeOutputFileName(spec, 'executable'). - endswith('.exe')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). - endswith('.dll')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). - endswith('.lib')) + # These cannot run on non-Windows as they require a VS installation to + # correctly handle variable expansion. + if sys.platform.startswith('win'): + writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', + 'build.ninja', 'win') + spec = { 'target_name': 'wee' } + self.assertTrue(writer.ComputeOutputFileName(spec, 'executable'). + endswith('.exe')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). + endswith('.dll')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). + endswith('.lib')) def test_BinaryNamesLinux(self): writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', diff -Nru gyp-0.1~svn1729/pylib/gyp/generator/xcode.py gyp-0.1+20150913git1f374df9/pylib/gyp/generator/xcode.py --- gyp-0.1~svn1729/pylib/gyp/generator/xcode.py 2013-07-08 15:11:20.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/generator/xcode.py 2015-09-13 13:41:20.000000000 +0000 @@ -5,6 +5,7 @@ import filecmp import gyp.common import gyp.xcodeproj_file +import gyp.xcode_ninja import errno import os import sys @@ -68,10 +69,14 @@ # The Xcode-specific keys that exist on targets and aren't moved down to # configurations. generator_additional_non_configuration_keys = [ + 'ios_app_extension', + 'ios_watch_app', + 'ios_watchkit_extension', 'mac_bundle', 'mac_bundle_resources', 'mac_framework_headers', 'mac_framework_private_headers', + 'mac_xctest_bundle', 'xcode_create_dependents_test_runner', ] @@ -480,43 +485,10 @@ raise -cached_xcode_version = None -def InstalledXcodeVersion(): - """Fetches the installed version of Xcode, returns empty string if it is - unable to figure it out.""" - - global cached_xcode_version - if not cached_xcode_version is None: - return cached_xcode_version - - # Default to an empty string - cached_xcode_version = '' - - # Collect the xcodebuild's version information. - try: - import subprocess - cmd = ['/usr/bin/xcodebuild', '-version'] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) - xcodebuild_version_info = proc.communicate()[0] - # Any error, return empty string - if proc.returncode: - xcodebuild_version_info = '' - except OSError: - # We failed to launch the tool - xcodebuild_version_info = '' - - # Pull out the Xcode version itself. - match_line = re.search('^Xcode (.*)$', xcodebuild_version_info, re.MULTILINE) - if match_line: - cached_xcode_version = match_line.group(1) - # Done! - return cached_xcode_version - - def AddSourceToTarget(source, type, pbxp, xct): # TODO(mark): Perhaps source_extensions and library_extensions can be made a # little bit fancier. - source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's'] + source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's', 'swift'] # .o is conceptually more of a "source" than a "library," but Xcode thinks # of "sources" as things to compile and "libraries" (or "frameworks") as @@ -552,7 +524,7 @@ xct.HeadersPhase().AddFile(header, settings) -_xcode_variable_re = re.compile('(\$\((.*?)\))') +_xcode_variable_re = re.compile(r'(\$\((.*?)\))') def ExpandXcodeVariables(string, expansions): """Expands Xcode-style $(VARIABLES) in string per the expansions dict. @@ -607,12 +579,17 @@ def GenerateOutput(target_list, target_dicts, data, params): + # Optionally configure each spec to use ninja as the external builder. + ninja_wrapper = params.get('flavor') == 'ninja' + if ninja_wrapper: + (target_list, target_dicts, data) = \ + gyp.xcode_ninja.CreateWrapper(target_list, target_dicts, data, params) + options = params['options'] generator_flags = params.get('generator_flags', {}) parallel_builds = generator_flags.get('xcode_parallel_builds', True) serialize_all_tests = \ generator_flags.get('xcode_serialize_all_test_runs', True) - project_version = generator_flags.get('xcode_project_version', None) skip_excluded_files = \ not generator_flags.get('xcode_list_excluded_files', True) xcode_projects = {} @@ -630,8 +607,6 @@ if parallel_builds: pbxp.SetProperty('attributes', {'BuildIndependentTargetsInParallel': 'YES'}) - if project_version: - xcp.project_file.SetXcodeVersion(project_version) # Add gyp/gypi files to project if not generator_flags.get('standalone'): @@ -669,13 +644,18 @@ # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets # to create a single-file mh_bundle. _types = { - 'executable': 'com.apple.product-type.tool', - 'loadable_module': 'com.googlecode.gyp.xcode.bundle', - 'shared_library': 'com.apple.product-type.library.dynamic', - 'static_library': 'com.apple.product-type.library.static', - 'executable+bundle': 'com.apple.product-type.application', - 'loadable_module+bundle': 'com.apple.product-type.bundle', - 'shared_library+bundle': 'com.apple.product-type.framework', + 'executable': 'com.apple.product-type.tool', + 'loadable_module': 'com.googlecode.gyp.xcode.bundle', + 'shared_library': 'com.apple.product-type.library.dynamic', + 'static_library': 'com.apple.product-type.library.static', + 'executable+bundle': 'com.apple.product-type.application', + 'loadable_module+bundle': 'com.apple.product-type.bundle', + 'loadable_module+xctest': 'com.apple.product-type.bundle.unit-test', + 'shared_library+bundle': 'com.apple.product-type.framework', + 'executable+extension+bundle': 'com.apple.product-type.app-extension', + 'executable+watch+extension+bundle': + 'com.apple.product-type.watchkit-extension', + 'executable+watch+bundle': 'com.apple.product-type.application.watchapp', } target_properties = { @@ -684,11 +664,33 @@ } type = spec['type'] - is_bundle = int(spec.get('mac_bundle', 0)) + is_xctest = int(spec.get('mac_xctest_bundle', 0)) + is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest + is_app_extension = int(spec.get('ios_app_extension', 0)) + is_watchkit_extension = int(spec.get('ios_watchkit_extension', 0)) + is_watch_app = int(spec.get('ios_watch_app', 0)) if type != 'none': type_bundle_key = type - if is_bundle: + if is_xctest: + type_bundle_key += '+xctest' + assert type == 'loadable_module', ( + 'mac_xctest_bundle targets must have type loadable_module ' + '(target %s)' % target_name) + elif is_app_extension: + assert is_bundle, ('ios_app_extension flag requires mac_bundle ' + '(target %s)' % target_name) + type_bundle_key += '+extension+bundle' + elif is_watchkit_extension: + assert is_bundle, ('ios_watchkit_extension flag requires mac_bundle ' + '(target %s)' % target_name) + type_bundle_key += '+watch+extension+bundle' + elif is_watch_app: + assert is_bundle, ('ios_watch_app flag requires mac_bundle ' + '(target %s)' % target_name) + type_bundle_key += '+watch+bundle' + elif is_bundle: type_bundle_key += '+bundle' + xctarget_type = gyp.xcodeproj_file.PBXNativeTarget try: target_properties['productType'] = _types[type_bundle_key] @@ -701,6 +703,9 @@ assert not is_bundle, ( 'mac_bundle targets cannot have type none (target "%s")' % target_name) + assert not is_xctest, ( + 'mac_xctest_bundle targets cannot have type none (target "%s")' % + target_name) target_product_name = spec.get('product_name') if target_product_name is not None: @@ -724,11 +729,16 @@ # and is made a dependency of this target. This way the work is done # before the dependency checks for what should be recompiled. support_xct = None - if type != 'none' and (spec_actions or spec_rules): + # The Xcode "issues" don't affect xcode-ninja builds, since the dependency + # logic all happens in ninja. Don't bother creating the extra targets in + # that case. + if type != 'none' and (spec_actions or spec_rules) and not ninja_wrapper: support_xccl = CreateXCConfigurationList(configuration_names); + support_target_suffix = generator_flags.get( + 'support_target_suffix', ' Support') support_target_properties = { 'buildConfigurationList': support_xccl, - 'name': target_name + ' Support', + 'name': target_name + support_target_suffix, } if target_product_name: support_target_properties['productName'] = \ @@ -1053,7 +1063,7 @@ if [ "${JOB_COUNT}" -gt 4 ]; then JOB_COUNT=4 fi -exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" +exec xcrun make -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" exit 1 """ % makefile_name ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ @@ -1117,6 +1127,9 @@ # Relative paths are relative to $(SRCROOT). dest = '$(SRCROOT)/' + dest + code_sign = int(copy_group.get('xcode_code_sign', 0)) + settings = (None, '{ATTRIBUTES = (CodeSignOnCopy, ); }')[code_sign]; + # Coalesce multiple "copies" sections in the same target with the same # "destination" property into the same PBXCopyFilesBuildPhase, otherwise # they'll wind up with ID collisions. @@ -1135,7 +1148,7 @@ pbxcp_dict[dest] = pbxcp for file in copy_group['files']: - pbxcp.AddFile(file) + pbxcp.AddFile(file, settings) # Excluded files can also go into the project file. if not skip_excluded_files: diff -Nru gyp-0.1~svn1729/pylib/gyp/__init__.py gyp-0.1+20150913git1f374df9/pylib/gyp/__init__.py --- gyp-0.1~svn1729/pylib/gyp/__init__.py 2013-09-04 17:51:09.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/__init__.py 2015-09-13 13:41:20.000000000 +0000 @@ -49,7 +49,7 @@ def Load(build_files, format, default_variables={}, includes=[], depth='.', params=None, check=False, - circular_check=True): + circular_check=True, duplicate_basename_check=True): """ Loads one or more specified build files. default_variables and includes will be copied before use. @@ -59,7 +59,6 @@ if params is None: params = {} - flavor = None if '-' in format: format, params['flavor'] = format.split('-', 1) @@ -69,6 +68,7 @@ # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace, # avoiding collisions with user and automatic variables. default_variables['GENERATOR'] = format + default_variables['GENERATOR_FLAVOR'] = params.get('flavor', '') # Format can be a custom python file, or by default the name of a module # within gyp.generator. @@ -106,10 +106,6 @@ # so we can default things and the generators only have to provide what # they need. generator_input_info = { - 'generator_wants_absolute_build_file_paths': - getattr(generator, 'generator_wants_absolute_build_file_paths', False), - 'generator_handles_variants': - getattr(generator, 'generator_handles_variants', False), 'non_configuration_keys': getattr(generator, 'generator_additional_non_configuration_keys', []), 'path_sections': @@ -123,12 +119,15 @@ 'generator_wants_static_library_dependencies_adjusted', True), 'generator_wants_sorted_dependencies': getattr(generator, 'generator_wants_sorted_dependencies', False), + 'generator_filelist_paths': + getattr(generator, 'generator_filelist_paths', None), } # Process the input specific to this generator. result = gyp.input.Load(build_files, default_variables, includes[:], depth, generator_input_info, check, circular_check, - params['parallel']) + duplicate_basename_check, + params['parallel'], params['root_targets']) return [generator] + result def NameValueListToDict(name_value_list): @@ -316,9 +315,6 @@ parser.add_option('-I', '--include', dest='includes', action='append', metavar='INCLUDE', type='path', help='files to include in all loaded .gyp files') - parser.add_option('--msvs-version', dest='msvs_version', - regenerate=False, - help='Deprecated; use -G msvs_version=MSVS_VERSION instead') # --no-circular-check disables the check for circular relationships between # .gyp files. These relationships should not exist, but they've only been # observed to be harmful with the Xcode generator. Chromium's .gyp files @@ -329,14 +325,26 @@ parser.add_option('--no-circular-check', dest='circular_check', action='store_false', default=True, regenerate=False, help="don't check for circular relationships between files") - parser.add_option('--parallel', action='store_true', - env_name='GYP_PARALLEL', - help='Use multiprocessing for speed (experimental)') + # --no-duplicate-basename-check disables the check for duplicate basenames + # in a static_library/shared_library project. Visual C++ 2008 generator + # doesn't support this configuration. Libtool on Mac also generates warnings + # when duplicate basenames are passed into Make generator on Mac. + # TODO(yukawa): Remove this option when these legacy generators are + # deprecated. + parser.add_option('--no-duplicate-basename-check', + dest='duplicate_basename_check', action='store_false', + default=True, regenerate=False, + help="don't check for duplicate basenames") + parser.add_option('--no-parallel', action='store_true', default=False, + help='Disable multiprocessing') parser.add_option('-S', '--suffix', dest='suffix', default='', help='suffix to add to generated files') parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store', default=None, metavar='DIR', type='path', help='directory to use as the root of the source tree') + parser.add_option('-R', '--root-target', dest='root_targets', + action='append', metavar='TARGET', + help='include only TARGET and its deep dependencies') options, build_files_arg = parser.parse_args(args) build_files = build_files_arg @@ -374,7 +382,7 @@ if options.use_environment: generate_formats = os.environ.get('GYP_GENERATORS', []) if generate_formats: - generate_formats = re.split('[\s,]', generate_formats) + generate_formats = re.split(r'[\s,]', generate_formats) if generate_formats: options.formats = generate_formats else: @@ -391,9 +399,7 @@ if g_o: options.generator_output = g_o - if not options.parallel and options.use_environment: - p = os.environ.get('GYP_PARALLEL') - options.parallel = bool(p and p != '0') + options.parallel = not options.no_parallel for mode in options.debug: gyp.debug[mode] = 1 @@ -487,15 +493,6 @@ if DEBUG_GENERAL in gyp.debug.keys(): DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags) - # TODO: Remove this and the option after we've gotten folks to move to the - # generator flag. - if options.msvs_version: - print >>sys.stderr, \ - 'DEPRECATED: Use generator flag (-G msvs_version=' + \ - options.msvs_version + ') instead of --msvs-version=' + \ - options.msvs_version - generator_flags['msvs_version'] = options.msvs_version - # Generate all requested formats (use a set in case we got one format request # twice) for format in set(options.formats): @@ -506,14 +503,15 @@ 'build_files_arg': build_files_arg, 'gyp_binary': sys.argv[0], 'home_dot_gyp': home_dot_gyp, - 'parallel': options.parallel} + 'parallel': options.parallel, + 'root_targets': options.root_targets, + 'target_arch': cmdline_default_variables.get('target_arch', '')} # Start with the default variables from the command line. - [generator, flat_list, targets, data] = Load(build_files, format, - cmdline_default_variables, - includes, options.depth, - params, options.check, - options.circular_check) + [generator, flat_list, targets, data] = Load( + build_files, format, cmdline_default_variables, includes, options.depth, + params, options.check, options.circular_check, + options.duplicate_basename_check) # TODO(mark): Pass |data| for now because the generator needs a list of # build files that came in. In the future, maybe it should just accept diff -Nru gyp-0.1~svn1729/pylib/gyp/input.py gyp-0.1+20150913git1f374df9/pylib/gyp/input.py --- gyp-0.1~svn1729/pylib/gyp/input.py 2013-09-11 15:20:09.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/input.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,8 +10,8 @@ from compiler.ast import Node from compiler.ast import Stmt import compiler -import copy import gyp.common +import gyp.simple_copy import multiprocessing import optparse import os.path @@ -22,7 +22,9 @@ import sys import threading import time +import traceback from gyp.common import GypError +from gyp.common import OrderedSet # A list of types that are treated as linkable. @@ -44,20 +46,38 @@ 'outputs', 'sources', ] -path_sections = [] +path_sections = set() -is_path_section_charset = set('=+?!') -is_path_section_match_re = re.compile('_(dir|file|path)s?$') +# These per-process dictionaries are used to cache build file data when loading +# in parallel mode. +per_process_data = {} +per_process_aux_data = {} def IsPathSection(section): - # If section ends in one of these characters, it's applied to a section + # If section ends in one of the '=+?!' characters, it's applied to a section # without the trailing characters. '/' is notably absent from this list, # because there's no way for a regular expression to be treated as a path. - while section[-1:] in is_path_section_charset: + while section[-1:] in '=+?!': section = section[:-1] - return section in path_sections or is_path_section_match_re.search(section) -# base_non_configuraiton_keys is a list of key names that belong in the target + if section in path_sections: + return True + + # Sections mathing the regexp '_(dir|file|path)s?$' are also + # considered PathSections. Using manual string matching since that + # is much faster than the regexp and this can be called hundreds of + # thousands of times so micro performance matters. + if "_" in section: + tail = section[-6:] + if tail[-1] == 's': + tail = tail[:-1] + if tail[-5:] in ('_file', '_path'): + return True + return tail[-4:] == '_dir' + + return False + +# base_non_configuration_keys is a list of key names that belong in the target # itself and should not be propagated into its configurations. It is merged # with a list that can come from the generator to # create non_configuration_keys. @@ -84,7 +104,6 @@ 'toolset', 'toolsets', 'type', - 'variants', # Sections that can be found inside targets or configurations, but that # should not be propagated from targets into their configurations. @@ -107,12 +126,14 @@ 'type', ] -# Controls how the generator want the build file paths. -absolute_build_file_paths = False - # Controls whether or not the generator supports multiple toolsets. multiple_toolsets = False +# Paths for converting filelist paths to output paths: { +# toplevel, +# qualified_output_dir, +# } +generator_filelist_paths = None def GetIncludedBuildFiles(build_file_path, aux_data, included=None): """Return a list of all build files included into build_file_path. @@ -194,11 +215,11 @@ elif isinstance(node, Const): return node.getChildren()[0] else: - raise TypeError, "Unknown AST node at key path '" + '.'.join(keypath) + \ - "': " + repr(node) + raise TypeError("Unknown AST node at key path '" + '.'.join(keypath) + + "': " + repr(node)) -def LoadOneBuildFile(build_file_path, data, aux_data, variables, includes, +def LoadOneBuildFile(build_file_path, data, aux_data, includes, is_target, check): if build_file_path in data: return data[build_file_path] @@ -222,30 +243,32 @@ gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path) raise - if not isinstance(build_file_data, dict): + if type(build_file_data) is not dict: raise GypError("%s does not evaluate to a dictionary." % build_file_path) data[build_file_path] = build_file_data aux_data[build_file_path] = {} # Scan for includes and merge them in. - try: - if is_target: - LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, - aux_data, variables, includes, check) - else: - LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, - aux_data, variables, None, check) - except Exception, e: - gyp.common.ExceptionAppend(e, - 'while reading includes of ' + build_file_path) - raise + if ('skip_includes' not in build_file_data or + not build_file_data['skip_includes']): + try: + if is_target: + LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, + aux_data, includes, check) + else: + LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, + aux_data, None, check) + except Exception, e: + gyp.common.ExceptionAppend(e, + 'while reading includes of ' + build_file_path) + raise return build_file_data def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, - variables, includes, check): + includes, check): includes_list = [] if includes != None: includes_list.extend(includes) @@ -269,30 +292,27 @@ gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) MergeDicts(subdict, - LoadOneBuildFile(include, data, aux_data, variables, None, - False, check), + LoadOneBuildFile(include, data, aux_data, None, False, check), subdict_path, include) # Recurse into subdictionaries. for k, v in subdict.iteritems(): - if v.__class__ == dict: - LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, variables, + if type(v) is dict: + LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, None, check) - elif v.__class__ == list: - LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, variables, + elif type(v) is list: + LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, check) # This recurses into lists so that it can look for dicts. -def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data, - variables, check): +def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data, check): for item in sublist: - if item.__class__ == dict: + if type(item) is dict: LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data, - variables, None, check) - elif item.__class__ == list: - LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data, - variables, check) + None, check) + elif type(item) is list: + LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data, check) # Processes toolsets in all the targets. This recurses into condition entries # since they can contain toolsets as well. @@ -316,7 +336,7 @@ if len(toolsets) > 0: # Optimization: only do copies if more than one toolset is specified. for build in toolsets[1:]: - new_target = copy.deepcopy(target) + new_target = gyp.simple_copy.deepcopy(target) new_target['toolset'] = build new_target_list.append(new_target) target['toolset'] = toolsets[0] @@ -324,9 +344,10 @@ data['targets'] = new_target_list if 'conditions' in data: for condition in data['conditions']: - if isinstance(condition, list): + if type(condition) is list: for condition_dict in condition[1:]: - ProcessToolsetsInDict(condition_dict) + if type(condition_dict) is dict: + ProcessToolsetsInDict(condition_dict) # TODO(mark): I don't love this name. It just means that it's going to load @@ -346,19 +367,22 @@ else: variables['DEPTH'] = d.replace('\\', '/') - # If the generator needs absolue paths, then do so. - if absolute_build_file_paths: - build_file_path = os.path.abspath(build_file_path) - - if build_file_path in data['target_build_files']: - # Already loaded. - return False - data['target_build_files'].add(build_file_path) + # The 'target_build_files' key is only set when loading target build files in + # the non-parallel code path, where LoadTargetBuildFile is called + # recursively. In the parallel code path, we don't need to check whether the + # |build_file_path| has already been loaded, because the 'scheduled' set in + # ParallelState guarantees that we never load the same |build_file_path| + # twice. + if 'target_build_files' in data: + if build_file_path in data['target_build_files']: + # Already loaded. + return False + data['target_build_files'].add(build_file_path) gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Target Build File '%s'", build_file_path) - build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, variables, + build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, includes, True, check) # Store DEPTH for later use in generators. @@ -408,7 +432,8 @@ # copy with the target-specific data merged into it as the replacement # target dict. old_target_dict = build_file_data['targets'][index] - new_target_dict = copy.deepcopy(build_file_data['target_defaults']) + new_target_dict = gyp.simple_copy.deepcopy( + build_file_data['target_defaults']) MergeDicts(new_target_dict, old_target_dict, build_file_path, build_file_path) build_file_data['targets'][index] = new_target_dict @@ -443,11 +468,10 @@ else: return (build_file_path, dependencies) - def CallLoadTargetBuildFile(global_flags, - build_file_path, data, - aux_data, variables, - includes, depth, check): + build_file_path, variables, + includes, depth, check, + generator_input_info): """Wrapper around LoadTargetBuildFile for parallel processing. This wrapper is used when LoadTargetBuildFile is executed in @@ -461,37 +485,31 @@ for key, value in global_flags.iteritems(): globals()[key] = value - # Save the keys so we can return data that changed. - data_keys = set(data) - aux_data_keys = set(aux_data) - - result = LoadTargetBuildFile(build_file_path, data, - aux_data, variables, + SetGeneratorGlobals(generator_input_info) + result = LoadTargetBuildFile(build_file_path, per_process_data, + per_process_aux_data, variables, includes, depth, check, False) if not result: return result (build_file_path, dependencies) = result - data_out = {} - for key in data: - if key == 'target_build_files': - continue - if key not in data_keys: - data_out[key] = data[key] - aux_data_out = {} - for key in aux_data: - if key not in aux_data_keys: - aux_data_out[key] = aux_data[key] + # We can safely pop the build_file_data from per_process_data because it + # will never be referenced by this process again, so we don't need to keep + # it in the cache. + build_file_data = per_process_data.pop(build_file_path) # This gets serialized and sent back to the main process via a pipe. # It's handled in LoadTargetBuildFileCallback. return (build_file_path, - data_out, - aux_data_out, + build_file_data, dependencies) + except GypError, e: + sys.stderr.write("gyp: %s\n" % e) + return None except Exception, e: - print >>sys.stderr, 'Exception: ', e + print >>sys.stderr, 'Exception:', e + print >>sys.stderr, traceback.format_exc() return None @@ -515,8 +533,6 @@ self.condition = None # The "data" dict that was passed to LoadTargetBuildFileParallel self.data = None - # The "aux_data" dict that was passed to LoadTargetBuildFileParallel - self.aux_data = None # The number of parallel calls outstanding; decremented when a response # was received. self.pending = 0 @@ -537,12 +553,9 @@ self.condition.notify() self.condition.release() return - (build_file_path0, data0, aux_data0, dependencies0) = result + (build_file_path0, build_file_data0, dependencies0) = result + self.data[build_file_path0] = build_file_data0 self.data['target_build_files'].add(build_file_path0) - for key in data0: - self.data[key] = data0[key] - for key in aux_data0: - self.aux_data[key] = aux_data0[key] for new_dependency in dependencies0: if new_dependency not in self.scheduled: self.scheduled.add(new_dependency) @@ -552,26 +565,20 @@ self.condition.release() -def LoadTargetBuildFileParallel(build_file_path, data, aux_data, - variables, includes, depth, check): +def LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, + check, generator_input_info): parallel_state = ParallelState() parallel_state.condition = threading.Condition() - parallel_state.dependencies = [build_file_path] - parallel_state.scheduled = set([build_file_path]) + # Make copies of the build_files argument that we can modify while working. + parallel_state.dependencies = list(build_files) + parallel_state.scheduled = set(build_files) parallel_state.pending = 0 parallel_state.data = data - parallel_state.aux_data = aux_data try: parallel_state.condition.acquire() while parallel_state.dependencies or parallel_state.pending: if parallel_state.error: - print >>sys.stderr, ( - '\n' - 'Note: an error occurred while running gyp using multiprocessing.\n' - 'For more verbose output, set GYP_PARALLEL=0 in your environment.\n' - 'If the error only occurs when GYP_PARALLEL=1, ' - 'please report a bug!') break if not parallel_state.dependencies: parallel_state.condition.wait() @@ -580,31 +587,30 @@ dependency = parallel_state.dependencies.pop() parallel_state.pending += 1 - data_in = {} - data_in['target_build_files'] = data['target_build_files'] - aux_data_in = {} global_flags = { 'path_sections': globals()['path_sections'], 'non_configuration_keys': globals()['non_configuration_keys'], - 'absolute_build_file_paths': globals()['absolute_build_file_paths'], 'multiple_toolsets': globals()['multiple_toolsets']} if not parallel_state.pool: - parallel_state.pool = multiprocessing.Pool(8) + parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count()) parallel_state.pool.apply_async( CallLoadTargetBuildFile, args = (global_flags, dependency, - data_in, aux_data_in, - variables, includes, depth, check), + variables, includes, depth, check, generator_input_info), callback = parallel_state.LoadTargetBuildFileCallback) except KeyboardInterrupt, e: parallel_state.pool.terminate() raise e parallel_state.condition.release() - if parallel_state.error: - sys.exit() + parallel_state.pool.close() + parallel_state.pool.join() + parallel_state.pool = None + + if parallel_state.error: + sys.exit(1) # Look for the bracket that matches the first bracket seen in a # string, and return the start and end as a tuple. For example, if @@ -631,39 +637,50 @@ return (-1, -1) -canonical_int_re = re.compile('(0|-?[1-9][0-9]*)$') - - def IsStrCanonicalInt(string): """Returns True if |string| is in its canonical integer form. The canonical form is such that str(int(string)) == string. """ - return isinstance(string, str) and canonical_int_re.match(string) + if type(string) is str: + # This function is called a lot so for maximum performance, avoid + # involving regexps which would otherwise make the code much + # shorter. Regexps would need twice the time of this function. + if string: + if string == "0": + return True + if string[0] == "-": + string = string[1:] + if not string: + return False + if '1' <= string[0] <= '9': + return string.isdigit() + + return False # This matches things like "<(asdf)", "(?P<(?:(?:!?@?)|\|)?)' - '(?P[-a-zA-Z0-9_.]+)?' - '\((?P\s*\[?)' - '(?P.*?)(\]?)\))') + r'(?P(?P<(?:(?:!?@?)|\|)?)' + r'(?P[-a-zA-Z0-9_.]+)?' + r'\((?P\s*\[?)' + r'(?P.*?)(\]?)\))') # This matches the same as early_variable_re, but with '>' instead of '<'. late_variable_re = re.compile( - '(?P(?P>(?:(?:!?@?)|\|)?)' - '(?P[-a-zA-Z0-9_.]+)?' - '\((?P\s*\[?)' - '(?P.*?)(\]?)\))') + r'(?P(?P>(?:(?:!?@?)|\|)?)' + r'(?P[-a-zA-Z0-9_.]+)?' + r'\((?P\s*\[?)' + r'(?P.*?)(\]?)\))') # This matches the same as early_variable_re, but with '^' instead of '<'. latelate_variable_re = re.compile( - '(?P(?P[\^](?:(?:!?@?)|\|)?)' - '(?P[-a-zA-Z0-9_.]+)?' - '\((?P\s*\[?)' - '(?P.*?)(\]?)\))') + r'(?P(?P[\^](?:(?:!?@?)|\|)?)' + r'(?P[-a-zA-Z0-9_.]+)?' + r'\((?P\s*\[?)' + r'(?P.*?)(\]?)\))') # Global cache of results from running commands so they don't have to be run # more then once. @@ -672,7 +689,7 @@ def FixupPlatformCommand(cmd): if sys.platform == 'win32': - if type(cmd) == list: + if type(cmd) is list: cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:] else: cmd = re.sub('^cat ', 'type ', cmd) @@ -762,7 +779,7 @@ # contexts. However, since filtration has no chance to run on <|(), # this seems like the only obvious way to give them access to filters. if file_list: - processed_variables = copy.deepcopy(variables) + processed_variables = gyp.simple_copy.deepcopy(variables) ProcessListFiltersInDict(contents, processed_variables) # Recurse to expand variables in the contents contents = ExpandVariables(contents, phase, @@ -787,7 +804,7 @@ # Find the build file's directory, so commands can be run or file lists # generated relative to it. build_file_dir = os.path.dirname(build_file) - if build_file_dir == '': + if build_file_dir == '' and not file_list: # If build_file is just a leaf filename indicating a file in the # current directory, build_file_dir might be an empty string. Set # it to None to signal to subprocess.Popen that it should run the @@ -799,14 +816,27 @@ # This works around actions/rules which have more inputs than will # fit on the command line. if file_list: - if type(contents) == list: + if type(contents) is list: contents_list = contents else: contents_list = contents.split(' ') replacement = contents_list[0] - path = replacement - if build_file_dir and not os.path.isabs(path): - path = os.path.join(build_file_dir, path) + if os.path.isabs(replacement): + raise GypError('| cannot handle absolute paths, got "%s"' % replacement) + + if not generator_filelist_paths: + path = os.path.join(build_file_dir, replacement) + else: + if os.path.isabs(build_file_dir): + toplevel = generator_filelist_paths['toplevel'] + rel_build_file_dir = gyp.common.RelativePath(build_file_dir, toplevel) + else: + rel_build_file_dir = build_file_dir + qualified_out_dir = generator_filelist_paths['qualified_out_dir'] + path = os.path.join(qualified_out_dir, rel_build_file_dir, replacement) + gyp.common.EnsureDirExists(path) + + replacement = gyp.common.RelativePath(path, build_file_dir) f = gyp.common.WriteOnDiff(path) for i in contents_list[1:]: f.write('%s\n' % i) @@ -819,17 +849,15 @@ use_shell = False # Check for a cached value to avoid executing commands, or generating - # file lists more than once. - # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is - # possible that the command being invoked depends on the current - # directory. For that case the syntax needs to be extended so that the - # directory is also used in cache_key (it becomes a tuple). + # file lists more than once. The cache key contains the command to be + # run as well as the directory to run it from, to account for commands + # that depend on their current directory. # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory, # someone could author a set of GYP files where each time the command # is invoked it produces different output by design. When the need # arises, the syntax should be extended to support no caching off a # command's output so it is run every time. - cache_key = str(contents) + cache_key = (str(contents), build_file_dir) cached_value = cached_command_results.get(cache_key, None) if cached_value is None: gyp.DebugOutput(gyp.DEBUG_VARIABLES, @@ -865,11 +893,15 @@ else: # Fix up command with platform specific workarounds. contents = FixupPlatformCommand(contents) - p = subprocess.Popen(contents, shell=use_shell, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE, - cwd=build_file_dir) + try: + p = subprocess.Popen(contents, shell=use_shell, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE, + cwd=build_file_dir) + except Exception, e: + raise GypError("%s while executing command '%s' in %s" % + (e, contents, build_file)) p_stdout, p_stderr = p.communicate('') @@ -877,8 +909,8 @@ sys.stderr.write(p_stderr) # Simulate check_call behavior, since check_call only exists # in python 2.5 and later. - raise GypError("Call to '%s' returned exit status %d." % - (contents, p.returncode)) + raise GypError("Call to '%s' returned exit status %d while in %s." % + (contents, p.returncode, build_file)) replacement = p_stdout.rstrip() cached_command_results[cache_key] = replacement @@ -907,10 +939,9 @@ else: replacement = variables[contents] - if isinstance(replacement, list): + if type(replacement) is list: for item in replacement: - if (not contents[-1] == '/' and - not isinstance(item, str) and not isinstance(item, int)): + if not contents[-1] == '/' and type(item) not in (str, int): raise GypError('Variable ' + contents + ' must expand to a string or list of strings; ' + 'list contains a ' + @@ -920,8 +951,7 @@ # with conditions sections. ProcessVariablesAndConditionsInList(replacement, phase, variables, build_file) - elif not isinstance(replacement, str) and \ - not isinstance(replacement, int): + elif type(replacement) not in (str, int): raise GypError('Variable ' + contents + ' must expand to a string or list of strings; ' + 'found a ' + replacement.__class__.__name__) @@ -930,7 +960,7 @@ # Expanding in list context. It's guaranteed that there's only one # replacement to do in |input_str| and that it's this replacement. See # above. - if isinstance(replacement, list): + if type(replacement) is list: # If it's already a list, make a copy. output = replacement[:] else: @@ -939,7 +969,7 @@ else: # Expanding in string context. encoded_replacement = '' - if isinstance(replacement, list): + if type(replacement) is list: # When expanding a list into string context, turn the list items # into a string in a way that will work with a subprocess call. # @@ -957,26 +987,32 @@ # Prepare for the next match iteration. input_str = output - # Look for more matches now that we've replaced some, to deal with - # expanding local variables (variables defined in the same - # variables block as this one). - gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output) - if isinstance(output, list): - if output and isinstance(output[0], list): - # Leave output alone if it's a list of lists. - # We don't want such lists to be stringified. - pass - else: - new_output = [] - for item in output: - new_output.append( - ExpandVariables(item, phase, variables, build_file)) - output = new_output + if output == input: + gyp.DebugOutput(gyp.DEBUG_VARIABLES, + "Found only identity matches on %r, avoiding infinite " + "recursion.", + output) else: - output = ExpandVariables(output, phase, variables, build_file) + # Look for more matches now that we've replaced some, to deal with + # expanding local variables (variables defined in the same + # variables block as this one). + gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output) + if type(output) is list: + if output and type(output[0]) is list: + # Leave output alone if it's a list of lists. + # We don't want such lists to be stringified. + pass + else: + new_output = [] + for item in output: + new_output.append( + ExpandVariables(item, phase, variables, build_file)) + output = new_output + else: + output = ExpandVariables(output, phase, variables, build_file) # Convert all strings that are canonically-represented integers into integers. - if isinstance(output, list): + if type(output) is list: for index in xrange(0, len(output)): if IsStrCanonicalInt(output[index]): output[index] = int(output[index]) @@ -985,6 +1021,80 @@ return output +# The same condition is often evaluated over and over again so it +# makes sense to cache as much as possible between evaluations. +cached_conditions_asts = {} + +def EvalCondition(condition, conditions_key, phase, variables, build_file): + """Returns the dict that should be used or None if the result was + that nothing should be used.""" + if type(condition) is not list: + raise GypError(conditions_key + ' must be a list') + if len(condition) < 2: + # It's possible that condition[0] won't work in which case this + # attempt will raise its own IndexError. That's probably fine. + raise GypError(conditions_key + ' ' + condition[0] + + ' must be at least length 2, not ' + str(len(condition))) + + i = 0 + result = None + while i < len(condition): + cond_expr = condition[i] + true_dict = condition[i + 1] + if type(true_dict) is not dict: + raise GypError('{} {} must be followed by a dictionary, not {}'.format( + conditions_key, cond_expr, type(true_dict))) + if len(condition) > i + 2 and type(condition[i + 2]) is dict: + false_dict = condition[i + 2] + i = i + 3 + if i != len(condition): + raise GypError('{} {} has {} unexpected trailing items'.format( + conditions_key, cond_expr, len(condition) - i)) + else: + false_dict = None + i = i + 2 + if result == None: + result = EvalSingleCondition( + cond_expr, true_dict, false_dict, phase, variables, build_file) + + return result + + +def EvalSingleCondition( + cond_expr, true_dict, false_dict, phase, variables, build_file): + """Returns true_dict if cond_expr evaluates to true, and false_dict + otherwise.""" + # Do expansions on the condition itself. Since the conditon can naturally + # contain variable references without needing to resort to GYP expansion + # syntax, this is of dubious value for variables, but someone might want to + # use a command expansion directly inside a condition. + cond_expr_expanded = ExpandVariables(cond_expr, phase, variables, + build_file) + if type(cond_expr_expanded) not in (str, int): + raise ValueError( + 'Variable expansion in this context permits str and int ' + \ + 'only, found ' + cond_expr_expanded.__class__.__name__) + + try: + if cond_expr_expanded in cached_conditions_asts: + ast_code = cached_conditions_asts[cond_expr_expanded] + else: + ast_code = compile(cond_expr_expanded, '', 'eval') + cached_conditions_asts[cond_expr_expanded] = ast_code + if eval(ast_code, {'__builtins__': None}, variables): + return true_dict + return false_dict + except SyntaxError, e: + syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s ' + 'at character %d.' % + (str(e.args[0]), e.text, build_file, e.offset), + e.filename, e.lineno, e.offset, e.text) + raise syntax_error + except NameError, e: + gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % + (cond_expr_expanded, build_file)) + raise GypError(e) + def ProcessConditionsInDict(the_dict, phase, variables, build_file): # Process a 'conditions' or 'target_conditions' section in the_dict, @@ -1020,48 +1130,8 @@ del the_dict[conditions_key] for condition in conditions_list: - if not isinstance(condition, list): - raise GypError(conditions_key + ' must be a list') - if len(condition) != 2 and len(condition) != 3: - # It's possible that condition[0] won't work in which case this - # attempt will raise its own IndexError. That's probably fine. - raise GypError(conditions_key + ' ' + condition[0] + - ' must be length 2 or 3, not ' + str(len(condition))) - - [cond_expr, true_dict] = condition[0:2] - false_dict = None - if len(condition) == 3: - false_dict = condition[2] - - # Do expansions on the condition itself. Since the conditon can naturally - # contain variable references without needing to resort to GYP expansion - # syntax, this is of dubious value for variables, but someone might want to - # use a command expansion directly inside a condition. - cond_expr_expanded = ExpandVariables(cond_expr, phase, variables, - build_file) - if not isinstance(cond_expr_expanded, str) and \ - not isinstance(cond_expr_expanded, int): - raise ValueError, \ - 'Variable expansion in this context permits str and int ' + \ - 'only, found ' + expanded.__class__.__name__ - - try: - ast_code = compile(cond_expr_expanded, '', 'eval') - - if eval(ast_code, {'__builtins__': None}, variables): - merge_dict = true_dict - else: - merge_dict = false_dict - except SyntaxError, e: - syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s ' - 'at character %d.' % - (str(e.args[0]), e.text, build_file, e.offset), - e.filename, e.lineno, e.offset, e.text) - raise syntax_error - except NameError, e: - gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % - (cond_expr_expanded, build_file)) - raise GypError(e) + merge_dict = EvalCondition(condition, conditions_key, phase, variables, + build_file) if merge_dict != None: # Expand variables and nested conditinals in the merge_dict before @@ -1076,8 +1146,7 @@ # Any keys with plain string values in the_dict become automatic variables. # The variable name is the key name with a "_" character prepended. for key, value in the_dict.iteritems(): - if isinstance(value, str) or isinstance(value, int) or \ - isinstance(value, list): + if type(value) in (str, int, list): variables['_' + key] = value @@ -1090,8 +1159,7 @@ # (it could be a list or it could be parentless because it is a root dict), # the_dict_key will be None. for key, value in the_dict.get('variables', {}).iteritems(): - if not isinstance(value, str) and not isinstance(value, int) and \ - not isinstance(value, list): + if type(value) not in (str, int, list): continue if key.endswith('%'): @@ -1144,12 +1212,12 @@ for key, value in the_dict.iteritems(): # Skip "variables", which was already processed if present. - if key != 'variables' and isinstance(value, str): + if key != 'variables' and type(value) is str: expanded = ExpandVariables(value, phase, variables, build_file) - if not isinstance(expanded, str) and not isinstance(expanded, int): - raise ValueError, \ + if type(expanded) not in (str, int): + raise ValueError( 'Variable expansion in this context permits str and int ' + \ - 'only, found ' + expanded.__class__.__name__ + ' for ' + key + 'only, found ' + expanded.__class__.__name__ + ' for ' + key) the_dict[key] = expanded # Variable expansion may have resulted in changes to automatics. Reload. @@ -1203,23 +1271,23 @@ for key, value in the_dict.iteritems(): # Skip "variables" and string values, which were already processed if # present. - if key == 'variables' or isinstance(value, str): + if key == 'variables' or type(value) is str: continue - if isinstance(value, dict): + if type(value) is dict: # Pass a copy of the variables dict so that subdicts can't influence # parents. ProcessVariablesAndConditionsInDict(value, phase, variables, build_file, key) - elif isinstance(value, list): + elif type(value) is list: # The list itself can't influence the variables dict, and # ProcessVariablesAndConditionsInList will make copies of the variables # dict if it needs to pass it to something that can influence it. No # copy is necessary here. ProcessVariablesAndConditionsInList(value, phase, variables, build_file) - elif not isinstance(value, int): - raise TypeError, 'Unknown type ' + value.__class__.__name__ + \ - ' for ' + key + elif type(value) is not int: + raise TypeError('Unknown type ' + value.__class__.__name__ + \ + ' for ' + key) def ProcessVariablesAndConditionsInList(the_list, phase, variables, @@ -1228,17 +1296,17 @@ index = 0 while index < len(the_list): item = the_list[index] - if isinstance(item, dict): + if type(item) is dict: # Make a copy of the variables dict so that it won't influence anything # outside of its own scope. ProcessVariablesAndConditionsInDict(item, phase, variables, build_file) - elif isinstance(item, list): + elif type(item) is list: ProcessVariablesAndConditionsInList(item, phase, variables, build_file) - elif isinstance(item, str): + elif type(item) is str: expanded = ExpandVariables(item, phase, variables, build_file) - if isinstance(expanded, str) or isinstance(expanded, int): + if type(expanded) in (str, int): the_list[index] = expanded - elif isinstance(expanded, list): + elif type(expanded) is list: the_list[index:index+1] = expanded index += len(expanded) @@ -1246,13 +1314,13 @@ # without falling into the index increment below. continue else: - raise ValueError, \ + raise ValueError( 'Variable expansion in this context permits strings and ' + \ 'lists only, found ' + expanded.__class__.__name__ + ' at ' + \ - index - elif not isinstance(item, int): - raise TypeError, 'Unknown type ' + item.__class__.__name__ + \ - ' at index ' + index + index) + elif type(item) is not int: + raise TypeError('Unknown type ' + item.__class__.__name__ + \ + ' at index ' + index) index = index + 1 @@ -1425,6 +1493,20 @@ target_dict[dependency_key] = Filter(dependencies, target_name) +def RemoveLinkDependenciesFromNoneTargets(targets): + """Remove dependencies having the 'link_dependency' attribute from the 'none' + targets.""" + for target_name, target_dict in targets.iteritems(): + for dependency_key in dependency_sections: + dependencies = target_dict.get(dependency_key, []) + if dependencies: + for t in dependencies: + if target_dict.get('type', None) == 'none': + if targets[t].get('variables', {}).get('link_dependency', 0): + target_dict[dependency_key] = \ + Filter(target_dict[dependency_key], t) + + class DependencyGraphNode(object): """ @@ -1450,7 +1532,7 @@ # are the "ref" attributes of DependencyGraphNodes. Every target will # appear in flat_list after all of its dependencies, and before all of its # dependents. - flat_list = [] + flat_list = OrderedSet() # in_degree_zeros is the list of DependencyGraphNodes that have no # dependencies not in flat_list. Initially, it is a copy of the children @@ -1464,12 +1546,15 @@ # as work progresses, so that the next node to process from the list can # always be accessed at a consistent position. node = in_degree_zeros.pop() - flat_list.append(node.ref) + flat_list.add(node.ref) # Look at dependents of the node just added to flat_list. Some of them # may now belong in in_degree_zeros. for node_dependent in node.dependents: is_in_degree_zero = True + # TODO: We want to check through the + # node_dependent.dependencies list but if it's long and we + # always start at the beginning, then we get O(n^2) behaviour. for node_dependent_dependency in node_dependent.dependencies: if not node_dependent_dependency.ref in flat_list: # The dependent one or more dependencies not in flat_list. There @@ -1485,28 +1570,27 @@ # iteration of the outer loop. in_degree_zeros.add(node_dependent) - return flat_list + return list(flat_list) - def FindCycles(self, path=None): + def FindCycles(self): """ Returns a list of cycles in the graph, where each cycle is its own list. """ - if path is None: - path = [self] - results = [] - for node in self.dependents: - if node in path: - cycle = [node] - for part in path: - cycle.append(part) - if part == node: - break - results.append(tuple(cycle)) - else: - results.extend(node.FindCycles([node] + path)) + visited = set() + + def Visit(node, path): + for child in node.dependents: + if child in path: + results.append([child] + path[:path.index(child) + 1]) + elif not child in visited: + visited.add(child) + Visit(child, [child] + path) - return list(set(results)) + visited.add(self) + Visit(self, [self]) + + return results def DirectDependencies(self, dependencies=None): """Returns a list of just direct dependencies.""" @@ -1571,21 +1655,26 @@ return self._AddImportedDependencies(targets, dependencies) def DeepDependencies(self, dependencies=None): - """Returns a list of all of a target's dependencies, recursively.""" - if dependencies == None: - dependencies = [] + """Returns an OrderedSet of all of a target's dependencies, recursively.""" + if dependencies is None: + # Using a list to get ordered output and a set to do fast "is it + # already added" checks. + dependencies = OrderedSet() for dependency in self.dependencies: # Check for None, corresponding to the root node. - if dependency.ref != None and dependency.ref not in dependencies: - dependencies.append(dependency.ref) + if dependency.ref is None: + continue + if dependency.ref not in dependencies: dependency.DeepDependencies(dependencies) + dependencies.add(dependency.ref) return dependencies def _LinkDependenciesInternal(self, targets, include_shared_libraries, dependencies=None, initial=True): - """Returns a list of dependency targets that are linked into this target. + """Returns an OrderedSet of dependency targets that are linked + into this target. This function has a split personality, depending on the setting of |initial|. Outside callers should always leave |initial| at its default @@ -1598,11 +1687,13 @@ If |include_shared_libraries| is False, the resulting dependencies will not include shared_library targets that are linked into this target. """ - if dependencies == None: - dependencies = [] + if dependencies is None: + # Using a list to get ordered output and a set to do fast "is it + # already added" checks. + dependencies = OrderedSet() # Check for None, corresponding to the root node. - if self.ref == None: + if self.ref is None: return dependencies # It's kind of sucky that |targets| has to be passed into this function, @@ -1630,8 +1721,7 @@ # Don't traverse 'none' targets if explicitly excluded. if (target_type == 'none' and not targets[self.ref].get('dependencies_traverse', True)): - if self.ref not in dependencies: - dependencies.append(self.ref) + dependencies.add(self.ref) return dependencies # Executables and loadable modules are already fully and finally linked. @@ -1653,7 +1743,7 @@ # The target is linkable, add it to the list of link dependencies. if self.ref not in dependencies: - dependencies.append(self.ref) + dependencies.add(self.ref) if initial or not is_linkable: # If this is a subsequent target and it's linkable, don't look any # further for linkable dependencies, as they'll already be linked into @@ -1717,12 +1807,22 @@ flat_list = root_node.FlattenToList() # If there's anything left unvisited, there must be a circular dependency - # (cycle). If you need to figure out what's wrong, look for elements of - # targets that are not in flat_list. + # (cycle). if len(flat_list) != len(targets): + if not root_node.dependents: + # If all targets have dependencies, add the first target as a dependent + # of root_node so that the cycle can be discovered from root_node. + target = targets.keys()[0] + target_node = dependency_nodes[target] + target_node.dependencies.append(root_node) + root_node.dependents.append(target_node) + + cycles = [] + for cycle in root_node.FindCycles(): + paths = [node.ref for node in cycle] + cycles.append('Cycle: %s' % ' -> '.join(paths)) raise DependencyGraphNode.CircularException( - 'Some targets not reachable, cycle in dependency graph detected: ' + - ' '.join(set(flat_list) ^ set(targets))) + 'Cycles in dependency graph detected:\n' + '\n'.join(cycles)) return [dependency_nodes, flat_list] @@ -1772,20 +1872,18 @@ # If there's anything left unvisited, there must be a circular dependency # (cycle). if len(flat_list) != len(dependency_nodes): - bad_files = [] - for file in dependency_nodes.iterkeys(): - if not file in flat_list: - bad_files.append(file) - common_path_prefix = os.path.commonprefix(dependency_nodes) + if not root_node.dependents: + # If all files have dependencies, add the first file as a dependent + # of root_node so that the cycle can be discovered from root_node. + file_node = dependency_nodes.values()[0] + file_node.dependencies.append(root_node) + root_node.dependents.append(file_node) cycles = [] for cycle in root_node.FindCycles(): - simplified_paths = [] - for node in cycle: - assert(node.ref.startswith(common_path_prefix)) - simplified_paths.append(node.ref[len(common_path_prefix):]) - cycles.append('Cycle: %s' % ' -> '.join(simplified_paths)) - raise DependencyGraphNode.CircularException, \ - 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles) + paths = [node.ref for node in cycle] + cycles.append('Cycle: %s' % ' -> '.join(paths)) + raise DependencyGraphNode.CircularException( + 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles)) def DoDependentSettings(key, flat_list, targets, dependency_nodes): @@ -1948,25 +2046,25 @@ hashable_to_set = set(x for x in to if is_hashable(x)) for item in fro: singleton = False - if isinstance(item, str) or isinstance(item, int): + if type(item) in (str, int): # The cheap and easy case. if is_paths: to_item = MakePathRelative(to_file, fro_file, item) else: to_item = item - if not isinstance(item, str) or not item.startswith('-'): + if not (type(item) is str and item.startswith('-')): # Any string that doesn't begin with a "-" is a singleton - it can # only appear once in a list, to be enforced by the list merge append # or prepend. singleton = True - elif isinstance(item, dict): + elif type(item) is dict: # Make a copy of the dictionary, continuing to look for paths to fix. # The other intelligent aspects of merge processing won't apply because # item is being merged into an empty dict. to_item = {} MergeDicts(to_item, item, to_file, fro_file) - elif isinstance(item, list): + elif type(item) is list: # Recurse, making a copy of the list. If the list contains any # descendant dicts, path fixing will occur. Note that here, custom # values for is_paths and append are dropped; those are only to be @@ -1975,9 +2073,9 @@ to_item = [] MergeLists(to_item, item, to_file, fro_file) else: - raise TypeError, \ + raise TypeError( 'Attempt to merge list item of unsupported type ' + \ - item.__class__.__name__ + item.__class__.__name__) if append: # If appending a singleton that's already in the list, don't append. @@ -2012,30 +2110,30 @@ # modified. if k in to: bad_merge = False - if isinstance(v, str) or isinstance(v, int): - if not (isinstance(to[k], str) or isinstance(to[k], int)): + if type(v) in (str, int): + if type(to[k]) not in (str, int): bad_merge = True - elif v.__class__ != to[k].__class__: + elif type(v) is not type(to[k]): bad_merge = True if bad_merge: - raise TypeError, \ + raise TypeError( 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ ' into incompatible type ' + to[k].__class__.__name__ + \ - ' for key ' + k - if isinstance(v, str) or isinstance(v, int): + ' for key ' + k) + if type(v) in (str, int): # Overwrite the existing value, if any. Cheap and easy. is_path = IsPathSection(k) if is_path: to[k] = MakePathRelative(to_file, fro_file, v) else: to[k] = v - elif isinstance(v, dict): + elif type(v) is dict: # Recurse, guaranteeing copies will be made of objects that require it. if not k in to: to[k] = {} MergeDicts(to[k], v, to_file, fro_file) - elif isinstance(v, list): + elif type(v) is list: # Lists in dicts can be merged with different policies, depending on # how the key in the "from" dict (k, the from-key) is written. # @@ -2078,13 +2176,13 @@ # If the key ends in "?", the list will only be merged if it doesn't # already exist. continue - if not isinstance(to[list_base], list): + elif type(to[list_base]) is not list: # This may not have been checked above if merging in a list with an # extension character. - raise TypeError, \ + raise TypeError( 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ ' into incompatible type ' + to[list_base].__class__.__name__ + \ - ' for key ' + list_base + '(' + k + ')' + ' for key ' + list_base + '(' + k + ')') else: to[list_base] = [] @@ -2096,9 +2194,9 @@ is_paths = IsPathSection(list_base) MergeLists(to[list_base], v, to_file, fro_file, is_paths, append) else: - raise TypeError, \ + raise TypeError( 'Attempt to merge dict value of unsupported type ' + \ - v.__class__.__name__ + ' for key ' + k + v.__class__.__name__ + ' for key ' + k) def MergeConfigWithInheritance(new_configuration_dict, build_file, @@ -2139,43 +2237,39 @@ if not 'configurations' in target_dict: target_dict['configurations'] = {'Default': {}} if not 'default_configuration' in target_dict: - concrete = [i for i in target_dict['configurations'].iterkeys() - if not target_dict['configurations'][i].get('abstract')] + concrete = [i for (i, config) in target_dict['configurations'].iteritems() + if not config.get('abstract')] target_dict['default_configuration'] = sorted(concrete)[0] - for configuration in target_dict['configurations'].keys(): - old_configuration_dict = target_dict['configurations'][configuration] + merged_configurations = {} + configs = target_dict['configurations'] + for (configuration, old_configuration_dict) in configs.iteritems(): # Skip abstract configurations (saves work only). if old_configuration_dict.get('abstract'): continue # Configurations inherit (most) settings from the enclosing target scope. # Get the inheritance relationship right by making a copy of the target # dict. - new_configuration_dict = copy.deepcopy(target_dict) - - # Take out the bits that don't belong in a "configurations" section. - # Since configuration setup is done before conditional, exclude, and rules - # processing, be careful with handling of the suffix characters used in - # those phases. - delete_keys = [] - for key in new_configuration_dict: + new_configuration_dict = {} + for (key, target_val) in target_dict.iteritems(): key_ext = key[-1:] if key_ext in key_suffixes: key_base = key[:-1] else: key_base = key - if key_base in non_configuration_keys: - delete_keys.append(key) - - for key in delete_keys: - del new_configuration_dict[key] + if not key_base in non_configuration_keys: + new_configuration_dict[key] = gyp.simple_copy.deepcopy(target_val) # Merge in configuration (with all its parents first). MergeConfigWithInheritance(new_configuration_dict, build_file, target_dict, configuration, []) - # Put the new result back into the target dict as a configuration. - target_dict['configurations'][configuration] = new_configuration_dict + merged_configurations[configuration] = new_configuration_dict + + # Put the new configurations back into the target dict as a configuration. + for configuration in merged_configurations.keys(): + target_dict['configurations'][configuration] = ( + merged_configurations[configuration]) # Now drop all the abstract ones. for configuration in target_dict['configurations'].keys(): @@ -2246,9 +2340,9 @@ if operation != '!' and operation != '/': continue - if not isinstance(value, list): - raise ValueError, name + ' key ' + key + ' must be list, not ' + \ - value.__class__.__name__ + if type(value) is not list: + raise ValueError(name + ' key ' + key + ' must be list, not ' + \ + value.__class__.__name__) list_key = key[:-1] if list_key not in the_dict: @@ -2258,11 +2352,12 @@ del_lists.append(key) continue - if not isinstance(the_dict[list_key], list): - raise ValueError, name + ' key ' + list_key + \ - ' must be list, not ' + \ - value.__class__.__name__ + ' when applying ' + \ - {'!': 'exclusion', '/': 'regex'}[operation] + if type(the_dict[list_key]) is not list: + value = the_dict[list_key] + raise ValueError(name + ' key ' + list_key + \ + ' must be list, not ' + \ + value.__class__.__name__ + ' when applying ' + \ + {'!': 'exclusion', '/': 'regex'}[operation]) if not list_key in lists: lists.append(list_key) @@ -2311,8 +2406,8 @@ action_value = 1 else: # This is an action that doesn't make any sense. - raise ValueError, 'Unrecognized action ' + action + ' in ' + name + \ - ' key ' + regex_key + raise ValueError('Unrecognized action ' + action + ' in ' + name + \ + ' key ' + regex_key) for index in xrange(0, len(the_list)): list_item = the_list[index] @@ -2359,17 +2454,17 @@ # Now recurse into subdicts and lists that may contain dicts. for key, value in the_dict.iteritems(): - if isinstance(value, dict): + if type(value) is dict: ProcessListFiltersInDict(key, value) - elif isinstance(value, list): + elif type(value) is list: ProcessListFiltersInList(key, value) def ProcessListFiltersInList(name, the_list): for item in the_list: - if isinstance(item, dict): + if type(item) is dict: ProcessListFiltersInDict(name, item) - elif isinstance(item, list): + elif type(item) is list: ProcessListFiltersInList(name, item) @@ -2397,9 +2492,11 @@ target_type)) -def ValidateSourcesInTarget(target, target_dict, build_file): - # TODO: Check if MSVC allows this for loadable_module targets. - if target_dict.get('type', None) not in ('static_library', 'shared_library'): +def ValidateSourcesInTarget(target, target_dict, build_file, + duplicate_basename_check): + if not duplicate_basename_check: + return + if target_dict.get('type', None) != 'static_library': return sources = target_dict.get('sources', []) basenames = {} @@ -2419,8 +2516,8 @@ if error: print('static library %s has several files with the same basename:\n' % - target + error + 'Some build systems, e.g. MSVC08, ' - 'cannot handle that.') + target + error + 'libtool on Mac cannot handle that. Use ' + '--no-duplicate-basename-check to disable this validation.') raise GypError('Duplicate basenames in sources section, see list above') @@ -2487,7 +2584,7 @@ run_as = target_dict.get('run_as') if not run_as: return - if not isinstance(run_as, dict): + if type(run_as) is not dict: raise GypError("The 'run_as' in target %s from file %s should be a " "dictionary." % (target_name, build_file)) @@ -2496,17 +2593,17 @@ raise GypError("The 'run_as' in target %s from file %s must have an " "'action' section." % (target_name, build_file)) - if not isinstance(action, list): + if type(action) is not list: raise GypError("The 'action' for 'run_as' in target %s from file %s " "must be a list." % (target_name, build_file)) working_directory = run_as.get('working_directory') - if working_directory and not isinstance(working_directory, str): + if working_directory and type(working_directory) is not str: raise GypError("The 'working_directory' for 'run_as' in target %s " "in file %s should be a string." % (target_name, build_file)) environment = run_as.get('environment') - if environment and not isinstance(environment, dict): + if environment and type(environment) is not dict: raise GypError("The 'environment' for 'run_as' in target %s " "in file %s should be a dictionary." % (target_name, build_file)) @@ -2536,17 +2633,17 @@ # Use items instead of iteritems because there's no need to try to look at # reinserted keys and their associated values. for k, v in the_dict.items(): - if isinstance(v, int): + if type(v) is int: v = str(v) the_dict[k] = v - elif isinstance(v, dict): + elif type(v) is dict: TurnIntIntoStrInDict(v) - elif isinstance(v, list): + elif type(v) is list: TurnIntIntoStrInList(v) - if isinstance(k, int): - the_dict[str(k)] = v + if type(k) is int: del the_dict[k] + the_dict[str(k)] = v def TurnIntIntoStrInList(the_list): @@ -2554,14 +2651,49 @@ """ for index in xrange(0, len(the_list)): item = the_list[index] - if isinstance(item, int): + if type(item) is int: the_list[index] = str(item) - elif isinstance(item, dict): + elif type(item) is dict: TurnIntIntoStrInDict(item) - elif isinstance(item, list): + elif type(item) is list: TurnIntIntoStrInList(item) +def PruneUnwantedTargets(targets, flat_list, dependency_nodes, root_targets, + data): + """Return only the targets that are deep dependencies of |root_targets|.""" + qualified_root_targets = [] + for target in root_targets: + target = target.strip() + qualified_targets = gyp.common.FindQualifiedTargets(target, flat_list) + if not qualified_targets: + raise GypError("Could not find target %s" % target) + qualified_root_targets.extend(qualified_targets) + + wanted_targets = {} + for target in qualified_root_targets: + wanted_targets[target] = targets[target] + for dependency in dependency_nodes[target].DeepDependencies(): + wanted_targets[dependency] = targets[dependency] + + wanted_flat_list = [t for t in flat_list if t in wanted_targets] + + # Prune unwanted targets from each build_file's data dict. + for build_file in data['target_build_files']: + if not 'targets' in data[build_file]: + continue + new_targets = [] + for target in data[build_file]['targets']: + qualified_name = gyp.common.QualifiedTarget(build_file, + target['target_name'], + target['toolset']) + if qualified_name in wanted_targets: + new_targets.append(target) + data[build_file]['targets'] = new_targets + + return wanted_targets, wanted_flat_list + + def VerifyNoCollidingTargets(targets): """Verify that no two targets in the same directory share the same name. @@ -2589,30 +2721,28 @@ used[key] = gyp -def Load(build_files, variables, includes, depth, generator_input_info, check, - circular_check, parallel): +def SetGeneratorGlobals(generator_input_info): # Set up path_sections and non_configuration_keys with the default data plus - # the generator-specifc data. + # the generator-specific data. global path_sections - path_sections = base_path_sections[:] - path_sections.extend(generator_input_info['path_sections']) + path_sections = set(base_path_sections) + path_sections.update(generator_input_info['path_sections']) global non_configuration_keys non_configuration_keys = base_non_configuration_keys[:] non_configuration_keys.extend(generator_input_info['non_configuration_keys']) - # TODO(mark) handle variants if the generator doesn't want them directly. - generator_handles_variants = \ - generator_input_info['generator_handles_variants'] - - global absolute_build_file_paths - absolute_build_file_paths = \ - generator_input_info['generator_wants_absolute_build_file_paths'] - global multiple_toolsets multiple_toolsets = generator_input_info[ 'generator_supports_multiple_toolsets'] + global generator_filelist_paths + generator_filelist_paths = generator_input_info['generator_filelist_paths'] + + +def Load(build_files, variables, includes, depth, generator_input_info, check, + circular_check, duplicate_basename_check, parallel, root_targets): + SetGeneratorGlobals(generator_input_info) # A generator can have other lists (in addition to sources) be processed # for rules. extra_sources_for_rules = generator_input_info['extra_sources_for_rules'] @@ -2625,21 +2755,21 @@ # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps # track of the keys corresponding to "target" files. data = {'target_build_files': set()} - aux_data = {} - for build_file in build_files: - # Normalize paths everywhere. This is important because paths will be - # used as keys to the data dict and for references between input files. - build_file = os.path.normpath(build_file) - try: - if parallel: - LoadTargetBuildFileParallel(build_file, data, aux_data, - variables, includes, depth, check) - else: + # Normalize paths everywhere. This is important because paths will be + # used as keys to the data dict and for references between input files. + build_files = set(map(os.path.normpath, build_files)) + if parallel: + LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, + check, generator_input_info) + else: + aux_data = {} + for build_file in build_files: + try: LoadTargetBuildFile(build_file, data, aux_data, variables, includes, depth, check, True) - except Exception, e: - gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file) - raise + except Exception, e: + gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file) + raise # Build a dict to access each target's subdict by qualified name. targets = BuildTargetsDict(data) @@ -2654,6 +2784,10 @@ # Expand dependencies specified as build_file:*. ExpandWildcardDependencies(targets, data) + # Remove all dependencies marked as 'link_dependency' from the targets of + # type 'none'. + RemoveLinkDependenciesFromNoneTargets(targets) + # Apply exclude (!) and regex (/) list filters only for dependency_sections. for target_name, target_dict in targets.iteritems(): tmp_dict = {} @@ -2678,6 +2812,12 @@ [dependency_nodes, flat_list] = BuildDependencyList(targets) + if root_targets: + # Remove, from |targets| and |flat_list|, the targets that are not deep + # dependencies of the targets specified in |root_targets|. + targets, flat_list = PruneUnwantedTargets( + targets, flat_list, dependency_nodes, root_targets, data) + # Check that no two targets in the same directory have the same name. VerifyNoCollidingTargets(flat_list) @@ -2733,10 +2873,8 @@ target_dict = targets[target] build_file = gyp.common.BuildFile(target) ValidateTargetType(target, target_dict) - # TODO(thakis): Get vpx_scale/arm/scalesystemdependent.c to be renamed to - # scalesystemdependent_arm_additions.c or similar. - if 'arm' not in variables.get('target_arch', ''): - ValidateSourcesInTarget(target, target_dict, build_file) + ValidateSourcesInTarget(target, target_dict, build_file, + duplicate_basename_check) ValidateRulesInTarget(target, target_dict, extra_sources_for_rules) ValidateRunAsInTarget(target, target_dict, build_file) ValidateActionsInTarget(target, target_dict, build_file) diff -Nru gyp-0.1~svn1729/pylib/gyp/input_test.py gyp-0.1+20150913git1f374df9/pylib/gyp/input_test.py --- gyp-0.1~svn1729/pylib/gyp/input_test.py 2013-08-20 13:28:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/input_test.py 2015-09-13 13:41:20.000000000 +0000 @@ -44,16 +44,16 @@ def test_cycle_self_reference(self): self._create_dependency(self.nodes['a'], self.nodes['a']) - self.assertEquals([(self.nodes['a'], self.nodes['a'])], + self.assertEquals([[self.nodes['a'], self.nodes['a']]], self.nodes['a'].FindCycles()) def test_cycle_two_nodes(self): self._create_dependency(self.nodes['a'], self.nodes['b']) self._create_dependency(self.nodes['b'], self.nodes['a']) - self.assertEquals([(self.nodes['a'], self.nodes['b'], self.nodes['a'])], + self.assertEquals([[self.nodes['a'], self.nodes['b'], self.nodes['a']]], self.nodes['a'].FindCycles()) - self.assertEquals([(self.nodes['b'], self.nodes['a'], self.nodes['b'])], + self.assertEquals([[self.nodes['b'], self.nodes['a'], self.nodes['b']]], self.nodes['b'].FindCycles()) def test_two_cycles(self): @@ -65,9 +65,9 @@ cycles = self.nodes['a'].FindCycles() self.assertTrue( - (self.nodes['a'], self.nodes['b'], self.nodes['a']) in cycles) + [self.nodes['a'], self.nodes['b'], self.nodes['a']] in cycles) self.assertTrue( - (self.nodes['b'], self.nodes['c'], self.nodes['b']) in cycles) + [self.nodes['b'], self.nodes['c'], self.nodes['b']] in cycles) self.assertEquals(2, len(cycles)) def test_big_cycle(self): @@ -77,12 +77,12 @@ self._create_dependency(self.nodes['d'], self.nodes['e']) self._create_dependency(self.nodes['e'], self.nodes['a']) - self.assertEquals([(self.nodes['a'], + self.assertEquals([[self.nodes['a'], self.nodes['b'], self.nodes['c'], self.nodes['d'], self.nodes['e'], - self.nodes['a'])], + self.nodes['a']]], self.nodes['a'].FindCycles()) diff -Nru gyp-0.1~svn1729/pylib/gyp/mac_tool.py gyp-0.1+20150913git1f374df9/pylib/gyp/mac_tool.py --- gyp-0.1~svn1729/pylib/gyp/mac_tool.py 2013-09-06 15:17:23.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/mac_tool.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,9 @@ """ import fcntl +import fnmatch +import glob +import json import os import plistlib import re @@ -16,6 +19,7 @@ import string import subprocess import sys +import tempfile def main(args): @@ -41,28 +45,39 @@ """Transforms a tool name like copy-info-plist to CopyInfoPlist""" return name_string.title().replace('-', '') - def ExecCopyBundleResource(self, source, dest): + def ExecCopyBundleResource(self, source, dest, convert_to_binary): """Copies a resource file to the bundle/Resources directory, performing any necessary compilation on each resource.""" extension = os.path.splitext(source)[1].lower() if os.path.isdir(source): # Copy tree. + # TODO(thakis): This copies file attributes like mtime, while the + # single-file branch below doesn't. This should probably be changed to + # be consistent with the single-file branch. if os.path.exists(dest): shutil.rmtree(dest) shutil.copytree(source, dest) elif extension == '.xib': return self._CopyXIBFile(source, dest) + elif extension == '.storyboard': + return self._CopyXIBFile(source, dest) elif extension == '.strings': - self._CopyStringsFile(source, dest) + self._CopyStringsFile(source, dest, convert_to_binary) else: - shutil.copyfile(source, dest) + shutil.copy(source, dest) def _CopyXIBFile(self, source, dest): """Compiles a XIB file with ibtool into a binary plist in the bundle.""" - tools_dir = os.environ.get('DEVELOPER_BIN_DIR', '/usr/bin') - args = [os.path.join(tools_dir, 'ibtool'), '--errors', '--warnings', - '--notices', '--output-format', 'human-readable-text', '--compile', - dest, source] + + # ibtool sometimes crashes with relative paths. See crbug.com/314728. + base = os.path.dirname(os.path.realpath(__file__)) + if os.path.relpath(source): + source = os.path.join(base, source) + if os.path.relpath(dest): + dest = os.path.join(base, dest) + + args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', + '--output-format', 'human-readable-text', '--compile', dest, source] ibtool_section_re = re.compile(r'/\*.*\*/') ibtool_re = re.compile(r'.*note:.*is clipping its content') ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) @@ -77,7 +92,11 @@ sys.stdout.write(line) return ibtoolout.returncode - def _CopyStringsFile(self, source, dest): + def _ConvertToBinary(self, dest): + subprocess.check_call([ + 'xcrun', 'plutil', '-convert', 'binary1', '-o', dest, dest]) + + def _CopyStringsFile(self, source, dest, convert_to_binary): """Copies a .strings file using iconv to reconvert the input into UTF-16.""" input_code = self._DetectInputEncoding(source) or "UTF-8" @@ -97,6 +116,9 @@ fp.write(s.decode(input_code).encode('UTF-16')) fp.close() + if convert_to_binary == 'True': + self._ConvertToBinary(dest) + def _DetectInputEncoding(self, file_name): """Reads the first few bytes from file_name and tries to guess the text encoding. Returns None as a guess if it can't detect it.""" @@ -116,20 +138,42 @@ else: return None - def ExecCopyInfoPlist(self, source, dest): + def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): """Copies the |source| Info.plist to the destination directory |dest|.""" # Read the source Info.plist into memory. fd = open(source, 'r') lines = fd.read() fd.close() + # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). + plist = plistlib.readPlistFromString(lines) + if keys: + plist = dict(plist.items() + json.loads(keys[0]).items()) + lines = plistlib.writePlistToString(plist) + # Go through all the environment variables and replace them as variables in # the file. + IDENT_RE = re.compile(r'[/\s]') for key in os.environ: if key.startswith('_'): continue evar = '${%s}' % key - lines = string.replace(lines, evar, os.environ[key]) + evalue = os.environ[key] + lines = string.replace(lines, evar, evalue) + + # Xcode supports various suffices on environment variables, which are + # all undocumented. :rfc1034identifier is used in the standard project + # template these days, and :identifier was used earlier. They are used to + # convert non-url characters into things that look like valid urls -- + # except that the replacement character for :identifier, '_' isn't valid + # in a URL either -- oops, hence :rfc1034identifier was born. + evar = '${%s:identifier}' % key + evalue = IDENT_RE.sub('_', os.environ[key]) + lines = string.replace(lines, evar, evalue) + + evar = '${%s:rfc1034identifier}' % key + evalue = IDENT_RE.sub('-', os.environ[key]) + lines = string.replace(lines, evar, evalue) # Remove any keys with values that haven't been replaced. lines = lines.split('\n') @@ -148,6 +192,9 @@ # "compiled". self._WritePkgInfo(dest) + if convert_to_binary == 'True': + self._ConvertToBinary(dest) + def _WritePkgInfo(self, info_plist): """This writes the PkgInfo file from the data stored in Info.plist.""" plist = plistlib.readPlist(info_plist) @@ -179,13 +226,31 @@ return subprocess.call(cmd_list) def ExecFilterLibtool(self, *cmd_list): - """Calls libtool and filters out 'libtool: file: foo.o has no symbols'.""" - libtool_re = re.compile(r'^libtool: file: .* has no symbols$') - libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE) + """Calls libtool and filters out '/path/to/libtool: file: foo.o has no + symbols'.""" + libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') + libtool_re5 = re.compile( + r'^.*libtool: warning for library: ' + + r'.* the table of contents is empty ' + + r'\(no object file members in the library define global symbols\)$') + env = os.environ.copy() + # Ref: + # http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c + # The problem with this flag is that it resets the file mtime on the file to + # epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on timezone. + env['ZERO_AR_DATE'] = '1' + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env) _, err = libtoolout.communicate() for line in err.splitlines(): - if not libtool_re.match(line): + if not libtool_re.match(line) and not libtool_re5.match(line): print >>sys.stderr, line + # Unconditionally touch the output .a file on the command line if present + # and the command succeeded. A bit hacky. + if not libtoolout.returncode: + for i in range(len(cmd_list) - 1): + if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'): + os.utime(cmd_list[i+1], None) + break return libtoolout.returncode def ExecPackageFramework(self, framework, version): @@ -224,6 +289,322 @@ os.remove(link) os.symlink(dest, link) + def ExecCompileXcassets(self, keys, *inputs): + """Compiles multiple .xcassets files into a single .car file. + + This invokes 'actool' to compile all the inputs .xcassets files. The + |keys| arguments is a json-encoded dictionary of extra arguments to + pass to 'actool' when the asset catalogs contains an application icon + or a launch image. + + Note that 'actool' does not create the Assets.car file if the asset + catalogs does not contains imageset. + """ + command_line = [ + 'xcrun', 'actool', '--output-format', 'human-readable-text', + '--compress-pngs', '--notices', '--warnings', '--errors', + ] + is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ + if is_iphone_target: + platform = os.environ['CONFIGURATION'].split('-')[-1] + if platform not in ('iphoneos', 'iphonesimulator'): + platform = 'iphonesimulator' + command_line.extend([ + '--platform', platform, '--target-device', 'iphone', + '--target-device', 'ipad', '--minimum-deployment-target', + os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile', + os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']), + ]) + else: + command_line.extend([ + '--platform', 'macosx', '--target-device', 'mac', + '--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'], + '--compile', + os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']), + ]) + if keys: + keys = json.loads(keys) + for key, value in keys.iteritems(): + arg_name = '--' + key + if isinstance(value, bool): + if value: + command_line.append(arg_name) + elif isinstance(value, list): + for v in value: + command_line.append(arg_name) + command_line.append(str(v)) + else: + command_line.append(arg_name) + command_line.append(str(value)) + # Note: actool crashes if inputs path are relative, so use os.path.abspath + # to get absolute path name for inputs. + command_line.extend(map(os.path.abspath, inputs)) + subprocess.check_call(command_line) + + def ExecMergeInfoPlist(self, output, *inputs): + """Merge multiple .plist files into a single .plist file.""" + merged_plist = {} + for path in inputs: + plist = self._LoadPlistMaybeBinary(path) + self._MergePlist(merged_plist, plist) + plistlib.writePlist(merged_plist, output) + + def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): + """Code sign a bundle. + + This function tries to code sign an iOS bundle, following the same + algorithm as Xcode: + 1. copy ResourceRules.plist from the user or the SDK into the bundle, + 2. pick the provisioning profile that best match the bundle identifier, + and copy it into the bundle as embedded.mobileprovision, + 3. copy Entitlements.plist from user or SDK next to the bundle, + 4. code sign the bundle. + """ + resource_rules_path = self._InstallResourceRules(resource_rules) + substitutions, overrides = self._InstallProvisioningProfile( + provisioning, self._GetCFBundleIdentifier()) + entitlements_path = self._InstallEntitlements( + entitlements, substitutions, overrides) + subprocess.check_call([ + 'codesign', '--force', '--sign', key, '--resource-rules', + resource_rules_path, '--entitlements', entitlements_path, + os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['FULL_PRODUCT_NAME'])]) + + def _InstallResourceRules(self, resource_rules): + """Installs ResourceRules.plist from user or SDK into the bundle. + + Args: + resource_rules: string, optional, path to the ResourceRules.plist file + to use, default to "${SDKROOT}/ResourceRules.plist" + + Returns: + Path to the copy of ResourceRules.plist into the bundle. + """ + source_path = resource_rules + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'ResourceRules.plist') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], 'ResourceRules.plist') + shutil.copy2(source_path, target_path) + return target_path + + def _InstallProvisioningProfile(self, profile, bundle_identifier): + """Installs embedded.mobileprovision into the bundle. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple containing two dictionary: variables substitutions and values + to overrides when generating the entitlements file. + """ + source_path, provisioning_data, team_id = self._FindProvisioningProfile( + profile, bundle_identifier) + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'embedded.mobileprovision') + shutil.copy2(source_path, target_path) + substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') + return substitutions, provisioning_data['Entitlements'] + + def _FindProvisioningProfile(self, profile, bundle_identifier): + """Finds the .mobileprovision file to use for signing the bundle. + + Checks all the installed provisioning profiles (or if the user specified + the PROVISIONING_PROFILE variable, only consult it) and select the most + specific that correspond to the bundle identifier. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple of the path to the selected provisioning profile, the data of + the embedded plist in the provisioning profile and the team identifier + to use for code signing. + + Raises: + SystemExit: if no .mobileprovision can be used to sign the bundle. + """ + profiles_dir = os.path.join( + os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') + if not os.path.isdir(profiles_dir): + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + provisioning_profiles = None + if profile: + profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') + if os.path.exists(profile_path): + provisioning_profiles = [profile_path] + if not provisioning_profiles: + provisioning_profiles = glob.glob( + os.path.join(profiles_dir, '*.mobileprovision')) + valid_provisioning_profiles = {} + for profile_path in provisioning_profiles: + profile_data = self._LoadProvisioningProfile(profile_path) + app_id_pattern = profile_data.get( + 'Entitlements', {}).get('application-identifier', '') + for team_identifier in profile_data.get('TeamIdentifier', []): + app_id = '%s.%s' % (team_identifier, bundle_identifier) + if fnmatch.fnmatch(app_id, app_id_pattern): + valid_provisioning_profiles[app_id_pattern] = ( + profile_path, profile_data, team_identifier) + if not valid_provisioning_profiles: + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + # If the user has multiple provisioning profiles installed that can be + # used for ${bundle_identifier}, pick the most specific one (ie. the + # provisioning profile whose pattern is the longest). + selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) + return valid_provisioning_profiles[selected_key] + + def _LoadProvisioningProfile(self, profile_path): + """Extracts the plist embedded in a provisioning profile. + + Args: + profile_path: string, path to the .mobileprovision file + + Returns: + Content of the plist embedded in the provisioning profile as a dictionary. + """ + with tempfile.NamedTemporaryFile() as temp: + subprocess.check_call([ + 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) + return self._LoadPlistMaybeBinary(temp.name) + + def _MergePlist(self, merged_plist, plist): + """Merge |plist| into |merged_plist|.""" + for key, value in plist.iteritems(): + if isinstance(value, dict): + merged_value = merged_plist.get(key, {}) + if isinstance(merged_value, dict): + self._MergePlist(merged_value, value) + merged_plist[key] = merged_value + else: + merged_plist[key] = value + else: + merged_plist[key] = value + + def _LoadPlistMaybeBinary(self, plist_path): + """Loads into a memory a plist possibly encoded in binary format. + + This is a wrapper around plistlib.readPlist that tries to convert the + plist to the XML format if it can't be parsed (assuming that it is in + the binary format). + + Args: + plist_path: string, path to a plist file, in XML or binary format + + Returns: + Content of the plist as a dictionary. + """ + try: + # First, try to read the file using plistlib that only supports XML, + # and if an exception is raised, convert a temporary copy to XML and + # load that copy. + return plistlib.readPlist(plist_path) + except: + pass + with tempfile.NamedTemporaryFile() as temp: + shutil.copy2(plist_path, temp.name) + subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) + return plistlib.readPlist(temp.name) + + def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): + """Constructs a dictionary of variable substitutions for Entitlements.plist. + + Args: + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + app_identifier_prefix: string, value for AppIdentifierPrefix + + Returns: + Dictionary of substitutions to apply when generating Entitlements.plist. + """ + return { + 'CFBundleIdentifier': bundle_identifier, + 'AppIdentifierPrefix': app_identifier_prefix, + } + + def _GetCFBundleIdentifier(self): + """Extracts CFBundleIdentifier value from Info.plist in the bundle. + + Returns: + Value of CFBundleIdentifier in the Info.plist located in the bundle. + """ + info_plist_path = os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['INFOPLIST_PATH']) + info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) + return info_plist_data['CFBundleIdentifier'] + + def _InstallEntitlements(self, entitlements, substitutions, overrides): + """Generates and install the ${BundleName}.xcent entitlements file. + + Expands variables "$(variable)" pattern in the source entitlements file, + add extra entitlements defined in the .mobileprovision file and the copy + the generated plist to "${BundlePath}.xcent". + + Args: + entitlements: string, optional, path to the Entitlements.plist template + to use, defaults to "${SDKROOT}/Entitlements.plist" + substitutions: dictionary, variable substitutions + overrides: dictionary, values to add to the entitlements + + Returns: + Path to the generated entitlements file. + """ + source_path = entitlements + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['PRODUCT_NAME'] + '.xcent') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], + 'Entitlements.plist') + shutil.copy2(source_path, target_path) + data = self._LoadPlistMaybeBinary(target_path) + data = self._ExpandVariables(data, substitutions) + if overrides: + for key in overrides: + if key not in data: + data[key] = overrides[key] + plistlib.writePlist(data, target_path) + return target_path + + def _ExpandVariables(self, data, substitutions): + """Expands variables "$(variable)" in data. + + Args: + data: object, can be either string, list or dictionary + substitutions: dictionary, variable substitutions to perform + + Returns: + Copy of data where each references to "$(variable)" has been replaced + by the corresponding value found in substitutions, or left intact if + the key was not found. + """ + if isinstance(data, str): + for key, value in substitutions.iteritems(): + data = data.replace('$(%s)' % key, value) + return data + if isinstance(data, list): + return [self._ExpandVariables(v, substitutions) for v in data] + if isinstance(data, dict): + return {k: self._ExpandVariables(data[k], substitutions) for k in data} + return data if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff -Nru gyp-0.1~svn1729/pylib/gyp/msvs_emulation.py gyp-0.1+20150913git1f374df9/pylib/gyp/msvs_emulation.py --- gyp-0.1~svn1729/pylib/gyp/msvs_emulation.py 2013-09-12 18:35:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/msvs_emulation.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,10 +12,14 @@ import subprocess import sys +from gyp.common import OrderedSet +import gyp.MSVSUtil import gyp.MSVSVersion + windows_quoter_regex = re.compile(r'(\\*)"') + def QuoteForRspFile(arg): """Quote a command line argument so that it appears as one argument when processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for @@ -131,6 +135,54 @@ return dxsdk_dir +def GetGlobalVSMacroEnv(vs_version): + """Get a dict of variables mapping internal VS macro names to their gyp + equivalents. Returns all variables that are independent of the target.""" + env = {} + # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when + # Visual Studio is actually installed. + if vs_version.Path(): + env['$(VSInstallDir)'] = vs_version.Path() + env['$(VCInstallDir)'] = os.path.join(vs_version.Path(), 'VC') + '\\' + # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be + # set. This happens when the SDK is sync'd via src-internal, rather than + # by typical end-user installation of the SDK. If it's not set, we don't + # want to leave the unexpanded variable in the path, so simply strip it. + dxsdk_dir = _FindDirectXInstallation() + env['$(DXSDK_DIR)'] = dxsdk_dir if dxsdk_dir else '' + # Try to find an installation location for the Windows DDK by checking + # the WDK_DIR environment variable, may be None. + env['$(WDK_DIR)'] = os.environ.get('WDK_DIR', '') + return env + +def ExtractSharedMSVSSystemIncludes(configs, generator_flags): + """Finds msvs_system_include_dirs that are common to all targets, removes + them from all targets, and returns an OrderedSet containing them.""" + all_system_includes = OrderedSet( + configs[0].get('msvs_system_include_dirs', [])) + for config in configs[1:]: + system_includes = config.get('msvs_system_include_dirs', []) + all_system_includes = all_system_includes & OrderedSet(system_includes) + if not all_system_includes: + return None + # Expand macros in all_system_includes. + env = GetGlobalVSMacroEnv(GetVSVersion(generator_flags)) + expanded_system_includes = OrderedSet([ExpandMacros(include, env) + for include in all_system_includes]) + if any(['$' in include for include in expanded_system_includes]): + # Some path relies on target-specific variables, bail. + return None + + # Remove system includes shared by all targets from the targets. + for config in configs: + includes = config.get('msvs_system_include_dirs', []) + if includes: # Don't insert a msvs_system_include_dirs key if not needed. + # This must check the unexpanded includes list: + new_includes = [i for i in includes if i not in all_system_includes] + config['msvs_system_include_dirs'] = new_includes + return expanded_system_includes + + class MsvsSettings(object): """A class that understands the gyp 'msvs_...' values (especially the msvs_settings field). They largely correpond to the VS2008 IDE DOM. This @@ -139,11 +191,6 @@ def __init__(self, spec, generator_flags): self.spec = spec self.vs_version = GetVSVersion(generator_flags) - self.dxsdk_dir = _FindDirectXInstallation() - - # Try to find an installation location for the Windows DDK by checking - # the WDK_DIR environment variable, may be None. - self.wdk_dir = os.environ.get('WDK_DIR') supported_fields = [ ('msvs_configuration_attributes', dict), @@ -163,6 +210,30 @@ self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) + unsupported_fields = [ + 'msvs_prebuild', + 'msvs_postbuild', + ] + unsupported = [] + for field in unsupported_fields: + for config in configs.values(): + if field in config: + unsupported += ["%s not supported (target %s)." % + (field, spec['target_name'])] + if unsupported: + raise Exception('\n'.join(unsupported)) + + def GetExtension(self): + """Returns the extension for the target, with no leading dot. + + Uses 'product_extension' if specified, otherwise uses MSVS defaults based on + the target type. + """ + ext = self.spec.get('product_extension', None) + if ext: + return ext + return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '') + def GetVSMacroEnv(self, base_to_build=None, config=None): """Get a dict of variables mapping internal VS macro names to their gyp equivalents.""" @@ -170,29 +241,24 @@ target_name = self.spec.get('product_prefix', '') + \ self.spec.get('product_name', self.spec['target_name']) target_dir = base_to_build + '\\' if base_to_build else '' + target_ext = '.' + self.GetExtension() + target_file_name = target_name + target_ext + replacements = { - '$(OutDir)\\': target_dir, - '$(TargetDir)\\': target_dir, - '$(IntDir)': '$!INTERMEDIATE_DIR', - '$(InputPath)': '${source}', '$(InputName)': '${root}', - '$(ProjectName)': self.spec['target_name'], - '$(TargetName)': target_name, + '$(InputPath)': '${source}', + '$(IntDir)': '$!INTERMEDIATE_DIR', + '$(OutDir)\\': target_dir, '$(PlatformName)': target_platform, '$(ProjectDir)\\': '', + '$(ProjectName)': self.spec['target_name'], + '$(TargetDir)\\': target_dir, + '$(TargetExt)': target_ext, + '$(TargetFileName)': target_file_name, + '$(TargetName)': target_name, + '$(TargetPath)': os.path.join(target_dir, target_file_name), } - # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when - # Visual Studio is actually installed. - if self.vs_version.Path(): - replacements['$(VSInstallDir)'] = self.vs_version.Path() - replacements['$(VCInstallDir)'] = os.path.join(self.vs_version.Path(), - 'VC') + '\\' - # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be - # set. This happens when the SDK is sync'd via src-internal, rather than - # by typical end-user installation of the SDK. If it's not set, we don't - # want to leave the unexpanded variable in the path, so simply strip it. - replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else '' - replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else '' + replacements.update(GetGlobalVSMacroEnv(self.vs_version)) return replacements def ConvertVSMacros(self, s, base_to_build=None, config=None): @@ -202,7 +268,8 @@ def AdjustLibraries(self, libraries): """Strip -l from library if it's specified with that.""" - return [lib[2:] if lib.startswith('-l') else lib for lib in libraries] + libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries] + return [lib + '.lib' if not lib.endswith('.lib') else lib for lib in libs] def _GetAndMunge(self, field, path, default, prefix, append, map): """Retrieve a value from |field| at |path| or return |default|. If @@ -271,6 +338,15 @@ ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[])) return [self.ConvertVSMacros(p, config=config) for p in includes] + def AdjustMidlIncludeDirs(self, midl_include_dirs, config): + """Updates midl_include_dirs to expand VS specific paths, and adds the + system include dirs used for platform SDK and similar.""" + config = self._TargetConfig(config) + includes = midl_include_dirs + self.msvs_system_include_dirs[config] + includes.extend(self._Setting( + ('VCMIDLTool', 'AdditionalIncludeDirectories'), config, default=[])) + return [self.ConvertVSMacros(p, config=config) for p in includes] + def GetComputedDefines(self, config): """Returns the set of defines that are injected to the defines list based on other VS settings.""" @@ -316,15 +392,36 @@ output_file, config=config)) return output_file - def GetPDBName(self, config, expand_special): - """Gets the explicitly overridden pdb name for a target or returns None - if it's not overridden.""" + def GetPDBName(self, config, expand_special, default): + """Gets the explicitly overridden pdb name for a target or returns + default if it's not overridden, or if no pdb will be generated.""" config = self._TargetConfig(config) output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config) - if output_file: - output_file = expand_special(self.ConvertVSMacros( - output_file, config=config)) - return output_file + generate_debug_info = self._Setting( + ('VCLinkerTool', 'GenerateDebugInformation'), config) + if generate_debug_info == 'true': + if output_file: + return expand_special(self.ConvertVSMacros(output_file, config=config)) + else: + return default + else: + return None + + def GetNoImportLibrary(self, config): + """If NoImportLibrary: true, ninja will not expect the output to include + an import library.""" + config = self._TargetConfig(config) + noimplib = self._Setting(('NoImportLibrary',), config) + return noimplib == 'true' + + def GetAsmflags(self, config): + """Returns the flags that need to be added to ml invocations.""" + config = self._TargetConfig(config) + asmflags = [] + safeseh = self._Setting(('MASM', 'UseSafeExceptionHandlers'), config) + if safeseh == 'true': + asmflags.append('/safeseh') + return asmflags def GetCflags(self, config): """Returns the flags that need to be added to .c and .cc compilations.""" @@ -336,14 +433,21 @@ cl('Optimization', map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O', default='2') cl('InlineFunctionExpansion', prefix='/Ob') + cl('DisableSpecificWarnings', prefix='/wd') cl('StringPooling', map={'true': '/GF'}) cl('EnableFiberSafeOptimizations', map={'true': '/GT'}) cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy') cl('EnableIntrinsicFunctions', map={'false': '-', 'true': ''}, prefix='/Oi') cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O') + cl('FloatingPointModel', + map={'0': 'precise', '1': 'strict', '2': 'fast'}, prefix='/fp:', + default='0') + cl('CompileAsManaged', map={'false': '', 'true': '/clr'}) cl('WholeProgramOptimization', map={'true': '/GL'}) cl('WarningLevel', prefix='/W') cl('WarnAsError', map={'true': '/WX'}) + cl('CallingConvention', + map={'0': 'd', '1': 'r', '2': 'z', '3': 'v'}, prefix='/G') cl('DebugInformationFormat', map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z') cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'}) @@ -359,21 +463,18 @@ map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t') cl('EnablePREfast', map={'true': '/analyze'}) cl('AdditionalOptions', prefix='') + cl('EnableEnhancedInstructionSet', + map={'1': 'SSE', '2': 'SSE2', '3': 'AVX', '4': 'IA32', '5': 'AVX2'}, + prefix='/arch:') cflags.extend(['/FI' + f for f in self._Setting( ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])]) - if self.vs_version.short_name == '2013' or self.vs_version == '2013e': + if self.vs_version.short_name in ('2013', '2013e', '2015'): # New flag required in 2013 to maintain previous PDB behavior. cflags.append('/FS') # ninja handles parallelism by itself, don't have the compiler do it too. cflags = filter(lambda x: not x.startswith('/MP'), cflags) return cflags - def GetPrecompiledHeader(self, config, gyp_to_build_path): - """Returns an object that handles the generation of precompiled header - build steps.""" - config = self._TargetConfig(config) - return _PchHelper(self, config, gyp_to_build_path) - def _GetPchFlags(self, config, extension): """Get the flags to be added to the cflags for precompiled header support. """ @@ -418,6 +519,8 @@ libflags.extend(self._GetAdditionalLibraryDirectories( 'VCLibrarianTool', config, gyp_to_build_path)) lib('LinkTimeCodeGeneration', map={'true': '/LTCG'}) + lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, + prefix='/MACHINE:') lib('AdditionalOptions') return libflags @@ -439,8 +542,19 @@ if def_file: ldflags.append('/DEF:"%s"' % def_file) + def GetPGDName(self, config, expand_special): + """Gets the explicitly overridden pgd name for a target or returns None + if it's not overridden.""" + config = self._TargetConfig(config) + output_file = self._Setting( + ('VCLinkerTool', 'ProfileGuidedDatabase'), config) + if output_file: + output_file = expand_special(self.ConvertVSMacros( + output_file, config=config)) + return output_file + def GetLdflags(self, config, gyp_to_build_path, expand_special, - manifest_base_name, is_executable): + manifest_base_name, output_name, is_executable, build_dir): """Returns the flags that need to be added to link commands, and the manifest files.""" config = self._TargetConfig(config) @@ -449,32 +563,61 @@ 'VCLinkerTool', append=ldflags) self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) ld('GenerateDebugInformation', map={'true': '/DEBUG'}) - ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:') + ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, + prefix='/MACHINE:') ldflags.extend(self._GetAdditionalLibraryDirectories( 'VCLinkerTool', config, gyp_to_build_path)) ld('DelayLoadDLLs', prefix='/DELAYLOAD:') + ld('TreatLinkerWarningAsErrors', prefix='/WX', + map={'true': '', 'false': ':NO'}) out = self.GetOutputName(config, expand_special) if out: ldflags.append('/OUT:' + out) - pdb = self.GetPDBName(config, expand_special) + pdb = self.GetPDBName(config, expand_special, output_name + '.pdb') if pdb: ldflags.append('/PDB:' + pdb) + pgd = self.GetPGDName(config, expand_special) + if pgd: + ldflags.append('/PGD:' + pgd) map_file = self.GetMapFileName(config, expand_special) ld('GenerateMapFile', map={'true': '/MAP:' + map_file if map_file else '/MAP'}) ld('MapExports', map={'true': '/MAPINFO:EXPORTS'}) ld('AdditionalOptions', prefix='') - ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:') + + minimum_required_version = self._Setting( + ('VCLinkerTool', 'MinimumRequiredVersion'), config, default='') + if minimum_required_version: + minimum_required_version = ',' + minimum_required_version + ld('SubSystem', + map={'1': 'CONSOLE%s' % minimum_required_version, + '2': 'WINDOWS%s' % minimum_required_version}, + prefix='/SUBSYSTEM:') + + stack_reserve_size = self._Setting( + ('VCLinkerTool', 'StackReserveSize'), config, default='') + if stack_reserve_size: + stack_commit_size = self._Setting( + ('VCLinkerTool', 'StackCommitSize'), config, default='') + if stack_commit_size: + stack_commit_size = ',' + stack_commit_size + ldflags.append('/STACK:%s%s' % (stack_reserve_size, stack_commit_size)) + ld('TerminalServerAware', map={'1': ':NO', '2': ''}, prefix='/TSAWARE') ld('LinkIncremental', map={'1': ':NO', '2': ''}, prefix='/INCREMENTAL') + ld('BaseAddress', prefix='/BASE:') ld('FixedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/FIXED') ld('RandomizedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/DYNAMICBASE') ld('DataExecutionPrevention', map={'1': ':NO', '2': ''}, prefix='/NXCOMPAT') ld('OptimizeReferences', map={'1': 'NOREF', '2': 'REF'}, prefix='/OPT:') + ld('ForceSymbolReferences', prefix='/INCLUDE:') ld('EnableCOMDATFolding', map={'1': 'NOICF', '2': 'ICF'}, prefix='/OPT:') - ld('LinkTimeCodeGeneration', map={'1': '/LTCG'}) + ld('LinkTimeCodeGeneration', + map={'1': '', '2': ':PGINSTRUMENT', '3': ':PGOPTIMIZE', + '4': ':PGUPDATE'}, + prefix='/LTCG') ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:') ld('ResourceOnlyDLL', map={'true': '/NOENTRY'}) ld('EntryPointSymbol', prefix='/ENTRY:') @@ -484,6 +627,14 @@ # TODO(scottmg): This should sort of be somewhere else (not really a flag). ld('AdditionalDependencies', prefix='') + if self.GetArch(config) == 'x86': + safeseh_default = 'true' + else: + safeseh_default = None + ld('ImageHasSafeExceptionHandlers', + map={'false': ':NO', 'true': ''}, prefix='/SAFESEH', + default=safeseh_default) + # If the base address is not specifically controlled, DYNAMICBASE should # be on by default. base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED', @@ -499,27 +650,55 @@ ldflags.append('/NXCOMPAT') have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags) - manifest_flags, intermediate_manifest_file = self._GetLdManifestFlags( - config, manifest_base_name, is_executable and not have_def_file) + manifest_flags, intermediate_manifest, manifest_files = \ + self._GetLdManifestFlags(config, manifest_base_name, gyp_to_build_path, + is_executable and not have_def_file, build_dir) ldflags.extend(manifest_flags) - manifest_files = self._GetAdditionalManifestFiles(config, gyp_to_build_path) - manifest_files.append(intermediate_manifest_file) + return ldflags, intermediate_manifest, manifest_files - return ldflags, manifest_files + def _GetLdManifestFlags(self, config, name, gyp_to_build_path, + allow_isolation, build_dir): + """Returns a 3-tuple: + - the set of flags that need to be added to the link to generate + a default manifest + - the intermediate manifest that the linker will generate that should be + used to assert it doesn't add anything to the merged one. + - the list of all the manifest files to be merged by the manifest tool and + included into the link.""" + generate_manifest = self._Setting(('VCLinkerTool', 'GenerateManifest'), + config, + default='true') + if generate_manifest != 'true': + # This means not only that the linker should not generate the intermediate + # manifest but also that the manifest tool should do nothing even when + # additional manifests are specified. + return ['/MANIFEST:NO'], [], [] - def _GetLdManifestFlags(self, config, name, allow_isolation): - """Returns the set of flags that need to be added to the link to generate - a default manifest, as well as the name of the generated file.""" - # The manifest is generated by default. output_name = name + '.intermediate.manifest' flags = [ '/MANIFEST', '/ManifestFile:' + output_name, ] + # Instead of using the MANIFESTUAC flags, we generate a .manifest to + # include into the list of manifests. This allows us to avoid the need to + # do two passes during linking. The /MANIFEST flag and /ManifestFile are + # still used, and the intermediate manifest is used to assert that the + # final manifest we get from merging all the additional manifest files + # (plus the one we generate here) isn't modified by merging the + # intermediate into it. + + # Always NO, because we generate a manifest file that has what we want. + flags.append('/MANIFESTUAC:NO') + config = self._TargetConfig(config) enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config, default='true') + manifest_files = [] + generated_manifest_outer = \ +"" \ +"%s" \ +"" if enable_uac == 'true': execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), config, default='0') @@ -531,14 +710,38 @@ ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, default='false') - flags.append('''/MANIFESTUAC:"level='%s' uiAccess='%s'"''' % - (execution_level_map[execution_level], ui_access)) + + inner = ''' + + + + + + +''' % (execution_level_map[execution_level], ui_access) else: - flags.append('/MANIFESTUAC:NO') + inner = '' + + generated_manifest_contents = generated_manifest_outer % inner + generated_name = name + '.generated.manifest' + # Need to join with the build_dir here as we're writing it during + # generation time, but we return the un-joined version because the build + # will occur in that directory. We only write the file if the contents + # have changed so that simply regenerating the project files doesn't + # cause a relink. + build_dir_generated_name = os.path.join(build_dir, generated_name) + gyp.common.EnsureDirExists(build_dir_generated_name) + f = gyp.common.WriteOnDiff(build_dir_generated_name) + f.write(generated_manifest_contents) + f.close() + manifest_files = [generated_name] if allow_isolation: flags.append('/ALLOWISOLATION') - return flags, output_name + + manifest_files += self._GetAdditionalManifestFiles(config, + gyp_to_build_path) + return flags, output_name, manifest_files def _GetAdditionalManifestFiles(self, config, gyp_to_build_path): """Gets additional manifest files that are added to the default one @@ -561,7 +764,8 @@ def IsEmbedManifest(self, config): """Returns whether manifest should be linked into binary.""" config = self._TargetConfig(config) - embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config) + embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config, + default='true') return embed == 'true' def IsLinkIncremental(self, config): @@ -617,10 +821,16 @@ return True return False - def HasExplicitIdlRules(self, spec): - """Determine if there's an explicit rule for idl files. When there isn't we - need to generate implicit rules to build MIDL .idl files.""" - return self._HasExplicitRuleForExtension(spec, 'idl') + def _HasExplicitIdlActions(self, spec): + """Determine if an action should not run midl for .idl files.""" + return any([action.get('explicit_idl_action', 0) + for action in spec.get('actions', [])]) + + def HasExplicitIdlRulesOrActions(self, spec): + """Determine if there's an explicit rule or action for idl files. When + there isn't we need to generate implicit rules to build MIDL .idl files.""" + return (self._HasExplicitRuleForExtension(spec, 'idl') or + self._HasExplicitIdlActions(spec)) def HasExplicitAsmRules(self, spec): """Determine if there's an explicit rule for asm files. When there isn't we @@ -683,7 +893,7 @@ def GetObjDependencies(self, sources, objs, arch): """Given a list of sources files and the corresponding object files, returns a list of the pch files that should be depended upon. The - additional wrapping in the return value is for interface compatability + additional wrapping in the return value is for interface compatibility with make.py on Mac, and xcode_emulation.py.""" assert arch is None if not self._PchHeader(): @@ -719,7 +929,8 @@ global vs_version if not vs_version: vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( - generator_flags.get('msvs_version', 'auto')) + generator_flags.get('msvs_version', 'auto'), + allow_fallback=False) return vs_version def _GetVsvarsSetupArgs(generator_flags, arch): @@ -787,7 +998,8 @@ if line.startswith('LOC:'): return line[len('LOC:'):].strip() -def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): +def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, + system_includes, open_out): """It's not sufficient to have the absolute path to the compiler, linker, etc. on Windows, as those tools rely on .dlls being in the PATH. We also need to support both x86 and x64 compilers within the same build (to support @@ -818,6 +1030,13 @@ args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) variables, _ = popen.communicate() env = _ExtractImportantEnvironment(variables) + + # Inject system includes from gyp files into INCLUDE. + if system_includes: + system_includes = system_includes | OrderedSet( + env.get('INCLUDE', '').split(';')) + env['INCLUDE'] = ';'.join(system_includes) + env_block = _FormatAsEnvironmentBlock(env) f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') f.write(env_block) @@ -847,3 +1066,22 @@ # path for a slightly less crazy looking output. cleaned_up = [os.path.normpath(x) for x in missing] raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up)) + +# Sets some values in default_variables, which are required for many +# generators, run on Windows. +def CalculateCommonVariables(default_variables, params): + generator_flags = params.get('generator_flags', {}) + + # Set a variable so conditions can be based on msvs_version. + msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags) + default_variables['MSVS_VERSION'] = msvs_version.ShortName() + + # To determine processor word size on Windows, in addition to checking + # PROCESSOR_ARCHITECTURE (which reflects the word size of the current + # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which + # contains the actual word size of the system when running thru WOW64). + if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or + '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): + default_variables['MSVS_OS_BITS'] = 64 + else: + default_variables['MSVS_OS_BITS'] = 32 diff -Nru gyp-0.1~svn1729/pylib/gyp/MSVSNew.py gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSNew.py --- gyp-0.1~svn1729/pylib/gyp/MSVSNew.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSNew.py 2015-09-13 13:41:20.000000000 +0000 @@ -172,7 +172,7 @@ #------------------------------------------------------------------------------ -class MSVSSolution: +class MSVSSolution(object): """Visual Studio solution.""" def __init__(self, path, version, entries=None, variants=None, @@ -325,14 +325,15 @@ f.write('\tEndGlobalSection\r\n') # Folder mappings - # TODO(rspangler): Should omit this section if there are no folders - f.write('\tGlobalSection(NestedProjects) = preSolution\r\n') - for e in all_entries: - if not isinstance(e, MSVSFolder): - continue # Does not apply to projects, only folders - for subentry in e.entries: - f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid())) - f.write('\tEndGlobalSection\r\n') + # Omit this section if there are no folders + if any([e.entries for e in all_entries if isinstance(e, MSVSFolder)]): + f.write('\tGlobalSection(NestedProjects) = preSolution\r\n') + for e in all_entries: + if not isinstance(e, MSVSFolder): + continue # Does not apply to projects, only folders + for subentry in e.entries: + f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid())) + f.write('\tEndGlobalSection\r\n') f.write('EndGlobal\r\n') diff -Nru gyp-0.1~svn1729/pylib/gyp/MSVSSettings.py gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSSettings.py --- gyp-0.1~svn1729/pylib/gyp/MSVSSettings.py 2013-06-17 10:31:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSSettings.py 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Code to validate and convert settings of the Microsoft build tools. +r"""Code to validate and convert settings of the Microsoft build tools. This file contains code to validate and convert settings of the Microsoft build tools. The function ConvertToMSBuildSettings(), ValidateMSVSSettings(), @@ -314,7 +314,14 @@ name: the name of the setting. setting_type: the type of this setting. """ + + def _Translate(value, msbuild_settings): + # Let msbuild-only properties get translated as-is from msvs_settings. + tool_settings = msbuild_settings.setdefault(tool.msbuild_name, {}) + tool_settings[name] = value + _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild + _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate def _ConvertedToAdditionalOption(tool, msvs_name, flag): @@ -367,6 +374,35 @@ r'(\$\((?:%s)\))(?:[\\/]+)' % "|".join(fix_vc_macro_slashes_regex_list) ) +# Regular expression to detect keys that were generated by exclusion lists +_EXCLUDED_SUFFIX_RE = re.compile('^(.*)_excluded$') + + +def _ValidateExclusionSetting(setting, settings, error_msg, stderr=sys.stderr): + """Verify that 'setting' is valid if it is generated from an exclusion list. + + If the setting appears to be generated from an exclusion list, the root name + is checked. + + Args: + setting: A string that is the setting name to validate + settings: A dictionary where the keys are valid settings + error_msg: The message to emit in the event of error + stderr: The stream receiving the error messages. + """ + # This may be unrecognized because it's an exclusion list. If the + # setting name has the _excluded suffix, then check the root name. + unrecognized = True + m = re.match(_EXCLUDED_SUFFIX_RE, setting) + if m: + root_setting = m.group(1) + unrecognized = root_setting not in settings + + if unrecognized: + # We don't know this setting. Give a warning. + print >> stderr, error_msg + + def FixVCMacroSlashes(s): """Replace macros which have excessive following slashes. @@ -388,11 +424,11 @@ if '$' in s: replace_map = { '$(ConfigurationName)': '$(Configuration)', - '$(InputDir)': '%(RootDir)%(Directory)', + '$(InputDir)': '%(RelativeDir)', '$(InputExt)': '%(Extension)', '$(InputFileName)': '%(Filename)%(Extension)', '$(InputName)': '%(Filename)', - '$(InputPath)': '%(FullPath)', + '$(InputPath)': '%(Identity)', '$(ParentName)': '$(ProjectFileName)', '$(PlatformName)': '$(Platform)', '$(SafeInputName)': '%(Filename)', @@ -429,10 +465,12 @@ print >> stderr, ('Warning: while converting %s/%s to MSBuild, ' '%s' % (msvs_tool_name, msvs_setting, e)) else: - # We don't know this setting. Give a warning. - print >> stderr, ('Warning: unrecognized setting %s/%s ' - 'while converting to MSBuild.' % - (msvs_tool_name, msvs_setting)) + _ValidateExclusionSetting(msvs_setting, + msvs_tool, + ('Warning: unrecognized setting %s/%s ' + 'while converting to MSBuild.' % + (msvs_tool_name, msvs_setting)), + stderr) else: print >> stderr, ('Warning: unrecognized tool %s while converting to ' 'MSBuild.' % msvs_tool_name) @@ -483,8 +521,12 @@ print >> stderr, ('Warning: for %s/%s, %s' % (tool_name, setting, e)) else: - print >> stderr, ('Warning: unrecognized setting %s/%s' % - (tool_name, setting)) + _ValidateExclusionSetting(setting, + tool_validators, + ('Warning: unrecognized setting %s/%s' % + (tool_name, setting)), + stderr) + else: print >> stderr, ('Warning: unrecognized tool %s' % tool_name) @@ -496,6 +538,7 @@ _rc = _Tool('VCResourceCompilerTool', 'ResourceCompile') _lib = _Tool('VCLibrarianTool', 'Lib') _manifest = _Tool('VCManifestTool', 'Manifest') +_masm = _Tool('MASM', 'MASM') _AddTool(_compile) @@ -504,6 +547,7 @@ _AddTool(_rc) _AddTool(_lib) _AddTool(_manifest) +_AddTool(_masm) # Add sections only found in the MSBuild settings. _msbuild_validators[''] = {} _msbuild_validators['ProjectReference'] = {} @@ -567,7 +611,8 @@ _Same(_compile, 'CallingConvention', _Enumeration(['Cdecl', # /Gd 'FastCall', # /Gr - 'StdCall'])) # /Gz + 'StdCall', # /Gz + 'VectorCall'])) # /Gv _Same(_compile, 'CompileAs', _Enumeration(['Default', 'CompileAsC', # /TC @@ -581,7 +626,12 @@ _Same(_compile, 'EnableEnhancedInstructionSet', _Enumeration(['NotSet', 'StreamingSIMDExtensions', # /arch:SSE - 'StreamingSIMDExtensions2'])) # /arch:SSE2 + 'StreamingSIMDExtensions2', # /arch:SSE2 + 'AdvancedVectorExtensions', # /arch:AVX (vs2012+) + 'NoExtensions', # /arch:IA32 (vs2012+) + # This one only exists in the new msbuild format. + 'AdvancedVectorExtensions2', # /arch:AVX2 (vs2013r2+) + ])) _Same(_compile, 'ErrorReporting', _Enumeration(['None', # /errorReport:none 'Prompt', # /errorReport:prompt @@ -658,10 +708,7 @@ _MSBuildOnly(_compile, 'BuildingInIDE', _boolean) _MSBuildOnly(_compile, 'CompileAsManaged', _Enumeration([], new=['false', - 'true', # /clr - 'Pure', # /clr:pure - 'Safe', # /clr:safe - 'OldSyntax'])) # /clr:oldSyntax + 'true'])) # /clr _MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean) # /hotpatch _MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean) # /MP _MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi @@ -812,6 +859,8 @@ _Enumeration(['AsInvoker', # /level='asInvoker' 'HighestAvailable', # /level='highestAvailable' 'RequireAdministrator'])) # /level='requireAdministrator' +_Same(_link, 'MinimumRequiredVersion', _string) +_Same(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX # Options found in MSVS that have been renamed in MSBuild. @@ -834,13 +883,6 @@ # MSVS options not found in MSBuild. _MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean) _MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean) -# These settings generate correctly in the MSVS output files when using -# e.g. DelayLoadDLLs! or AdditionalDependencies! to exclude files from -# configuration entries, but result in spurious artifacts which can be -# safely ignored here. See crbug.com/246570 -_MSVSOnly(_link, 'AdditionalLibraryDirectories_excluded', _folder_list) -_MSVSOnly(_link, 'DelayLoadDLLs_excluded', _file_list) -_MSVSOnly(_link, 'AdditionalDependencies_excluded', _file_list) # MSBuild options not found in MSVS. _MSBuildOnly(_link, 'BuildingInIDE', _boolean) @@ -850,8 +892,6 @@ _MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND _MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND _MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name) -_MSBuildOnly(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX -_MSBuildOnly(_link, 'MinimumRequiredVersion', _string) _MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false' _MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN _MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION @@ -985,14 +1025,12 @@ _Same(_lib, 'SuppressStartupBanner', _boolean) # /NOLOGO _Same(_lib, 'UseUnicodeResponseFiles', _boolean) _Same(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG +_Same(_lib, 'TargetMachine', _target_machine_enumeration) # TODO(jeanluc) _link defines the same value that gets moved to # ProjectReference. We may want to validate that they are consistent. _Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean) -# TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp. -_MSVSOnly(_lib, 'AdditionalLibraryDirectories_excluded', _folder_list) - _MSBuildOnly(_lib, 'DisplayLibrary', _string) # /LIST Visible='false' _MSBuildOnly(_lib, 'ErrorReporting', _Enumeration([], new=['PromptImmediately', # /ERRORREPORT:PROMPT @@ -1003,7 +1041,6 @@ _MSBuildOnly(_lib, 'Name', _file_name) # /NAME _MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE _MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration) -_MSBuildOnly(_lib, 'TargetMachine', _target_machine_enumeration) _MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name) _MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX _MSBuildOnly(_lib, 'Verbose', _boolean) @@ -1049,3 +1086,11 @@ _MSBuildOnly(_manifest, 'OutputResourceManifests', _string) # /outputresource _MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean) # /nodependency _MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name) + + +# Directives for MASM. +# See "$(VCTargetsPath)\BuildCustomizations\masm.xml" for the schema of the +# MSBuild MASM settings. + +# Options that have the same name in MSVS and MSBuild. +_Same(_masm, 'UseSafeExceptionHandlers', _boolean) # /safeseh diff -Nru gyp-0.1~svn1729/pylib/gyp/MSVSSettings_test.py gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSSettings_test.py --- gyp-0.1~svn1729/pylib/gyp/MSVSSettings_test.py 2012-05-22 19:39:22.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSSettings_test.py 2015-09-13 13:41:20.000000000 +0000 @@ -109,6 +109,7 @@ 'ZZXYZ': 'bogus'}, 'VCLinkerTool': { 'AdditionalDependencies': 'file1;file2', + 'AdditionalDependencies_excluded': 'file3', 'AdditionalLibraryDirectories': 'folder1;folder2', 'AdditionalManifestDependencies': 'file1;file2', 'AdditionalOptions': 'a string1', @@ -266,7 +267,7 @@ 'Warning: for VCCLCompilerTool/BrowseInformation, ' "invalid literal for int() with base 10: 'fdkslj'", 'Warning: for VCCLCompilerTool/CallingConvention, ' - 'index value (-1) not in expected range [0, 3)', + 'index value (-1) not in expected range [0, 4)', 'Warning: for VCCLCompilerTool/DebugInformationFormat, ' 'converted value for 2 not specified.', 'Warning: unrecognized setting VCCLCompilerTool/Enableprefast', @@ -295,7 +296,7 @@ 'BuildingInIDE': 'true', 'CallingConvention': 'Cdecl', 'CompileAs': 'CompileAsC', - 'CompileAsManaged': 'Pure', + 'CompileAsManaged': 'true', 'CreateHotpatchableImage': 'true', 'DebugInformationFormat': 'ProgramDatabase', 'DisableLanguageExtensions': 'true', diff -Nru gyp-0.1~svn1729/pylib/gyp/MSVSUtil.py gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSUtil.py --- gyp-0.1~svn1729/pylib/gyp/MSVSUtil.py 2013-03-27 14:49:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSUtil.py 2015-09-13 13:41:20.000000000 +0000 @@ -8,10 +8,12 @@ import os -_TARGET_TYPE_EXT = { - 'executable': '.exe', - 'loadable_module': '.dll', - 'shared_library': '.dll', +# A dictionary mapping supported target types to extensions. +TARGET_TYPE_EXT = { + 'executable': 'exe', + 'loadable_module': 'dll', + 'shared_library': 'dll', + 'static_library': 'lib', } @@ -109,15 +111,16 @@ new_target_dicts[t] = target_dicts[t] # Shard dependencies. for t in new_target_dicts: - dependencies = copy.copy(new_target_dicts[t].get('dependencies', [])) - new_dependencies = [] - for d in dependencies: - if d in targets_to_shard: - for i in range(targets_to_shard[d]): - new_dependencies.append(_ShardName(d, i)) - else: - new_dependencies.append(d) - new_target_dicts[t]['dependencies'] = new_dependencies + for deptype in ('dependencies', 'dependencies_original'): + dependencies = copy.copy(new_target_dicts[t].get(deptype, [])) + new_dependencies = [] + for d in dependencies: + if d in targets_to_shard: + for i in range(targets_to_shard[d]): + new_dependencies.append(_ShardName(d, i)) + else: + new_dependencies.append(d) + new_target_dicts[t][deptype] = new_dependencies return (new_target_list, new_target_dicts) @@ -156,7 +159,7 @@ pdb_base = target_dict.get('product_name', target_dict['target_name']) - pdb_base = '%s%s.pdb' % (pdb_base, _TARGET_TYPE_EXT[target_dict['type']]) + pdb_base = '%s.%s.pdb' % (pdb_base, TARGET_TYPE_EXT[target_dict['type']]) pdb_path = vars['PRODUCT_DIR'] + '/' + pdb_base return pdb_path @@ -264,4 +267,4 @@ # Update the original target to depend on the shim target. target_dict.setdefault('dependencies', []).append(full_shim_target_name) - return (target_list, target_dicts) \ No newline at end of file + return (target_list, target_dicts) diff -Nru gyp-0.1~svn1729/pylib/gyp/MSVSVersion.py gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSVersion.py --- gyp-0.1~svn1729/pylib/gyp/MSVSVersion.py 2013-09-12 18:35:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/MSVSVersion.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,6 +10,7 @@ import subprocess import sys import gyp +import glob class VisualStudioVersion(object): @@ -83,10 +84,11 @@ # vcvars32, which it can only find if VS??COMNTOOLS is set, which it # isn't always. if target_arch == 'x86': - if self.short_name == '2013' and ( + if self.short_name >= '2013' and self.short_name[-1] != 'e' and ( os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): - # VS2013 non-Express has a x64-x86 cross that we want to prefer. + # VS2013 and later, non-Express have a x64-x86 cross that we want + # to prefer. return [os.path.normpath( os.path.join(self.path, 'VC/vcvarsall.bat')), 'amd64_x86'] # Otherwise, the standard x86 compiler. @@ -95,9 +97,11 @@ else: assert target_arch == 'x64' arg = 'x86_amd64' - if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + # Use the 64-on-64 compiler if we're not using an express + # edition and we're running on a 64bit OS. + if self.short_name[-1] != 'e' and ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): - # Use the 64-on-64 compiler if we can. arg = 'amd64' return [os.path.normpath( os.path.join(self.path, 'VC/vcvarsall.bat')), arg] @@ -135,7 +139,7 @@ def _RegistryQuery(key, value=None): - """Use reg.exe to read a particular key through _RegistryQueryBase. + r"""Use reg.exe to read a particular key through _RegistryQueryBase. First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If that fails, it falls back to System32. Sysnative is available on Vista and @@ -162,8 +166,33 @@ return text +def _RegistryGetValueUsingWinReg(key, value): + """Use the _winreg module to obtain the value of a registry key. + + Args: + key: The registry key. + value: The particular registry value to read. + Return: + contents of the registry key's value, or None on failure. Throws + ImportError if _winreg is unavailable. + """ + import _winreg + try: + root, subkey = key.split('\\', 1) + assert root == 'HKLM' # Only need HKLM for now. + with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey: + return _winreg.QueryValueEx(hkey, value)[0] + except WindowsError: + return None + + def _RegistryGetValue(key, value): - """Use reg.exe to obtain the value of a registry key. + """Use _winreg or reg.exe to obtain the value of a registry key. + + Using _winreg is preferable because it solves an issue on some corporate + environments where access to reg.exe is locked down. However, we still need + to fallback to reg.exe for the case where the _winreg module is not available + (for example in cygwin python). Args: key: The registry key. @@ -171,6 +200,12 @@ Return: contents of the registry key's value, or None on failure. """ + try: + return _RegistryGetValueUsingWinReg(key, value) + except ImportError: + pass + + # Fallback to reg.exe if we fail to import _winreg. text = _RegistryQuery(key, value) if not text: return None @@ -181,19 +216,6 @@ return match.group(1) -def _RegistryKeyExists(key): - """Use reg.exe to see if a key exists. - - Args: - key: The registry key to check. - Return: - True if the key exists - """ - if not _RegistryQuery(key): - return False - return True - - def _CreateVersion(name, path, sdk_based=False): """Sets up MSVS project generation. @@ -204,6 +226,15 @@ if path: path = os.path.normpath(path) versions = { + '2015': VisualStudioVersion('2015', + 'Visual Studio 2015', + solution_version='12.00', + project_version='14.0', + flat_sln=False, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v140'), '2013': VisualStudioVersion('2013', 'Visual Studio 2013', solution_version='13.00', @@ -249,7 +280,7 @@ path=path, sdk_based=sdk_based), '2010e': VisualStudioVersion('2010e', - 'Visual Studio 2010', + 'Visual C++ Express 2010', solution_version='11.00', project_version='4.0', flat_sln=True, @@ -313,7 +344,8 @@ 2008(e) - Visual Studio 2008 (9) 2010(e) - Visual Studio 2010 (10) 2012(e) - Visual Studio 2012 (11) - 2013(e) - Visual Studio 2013 (11) + 2013(e) - Visual Studio 2013 (12) + 2015 - Visual Studio 2015 (14) Where (e) is e for express editions of MSVS and blank otherwise. """ version_to_year = { @@ -322,6 +354,7 @@ '10.0': '2010', '11.0': '2012', '12.0': '2013', + '14.0': '2015', } versions = [] for version in versions_to_check: @@ -339,13 +372,13 @@ path = _ConvertToCygpath(path) # Check for full. full_path = os.path.join(path, 'devenv.exe') - express_path = os.path.join(path, 'vcexpress.exe') + express_path = os.path.join(path, '*express.exe') if not force_express and os.path.exists(full_path): # Add this one. versions.append(_CreateVersion(version_to_year[version], os.path.join(path, '..', '..'))) # Check for express. - elif os.path.exists(express_path): + elif glob.glob(express_path): # Add this one. versions.append(_CreateVersion(version_to_year[version] + 'e', os.path.join(path, '..', '..'))) @@ -358,13 +391,14 @@ if not path: continue path = _ConvertToCygpath(path) - versions.append(_CreateVersion(version_to_year[version] + 'e', - os.path.join(path, '..'), sdk_based=True)) + if version != '14.0': # There is no Express edition for 2015. + versions.append(_CreateVersion(version_to_year[version] + 'e', + os.path.join(path, '..'), sdk_based=True)) return versions -def SelectVisualStudioVersion(version='auto'): +def SelectVisualStudioVersion(version='auto', allow_fallback=True): """Select which version of Visual Studio projects to generate. Arguments: @@ -376,7 +410,7 @@ if version == 'auto': version = os.environ.get('GYP_MSVS_VERSION', 'auto') version_map = { - 'auto': ('10.0', '9.0', '8.0', '11.0'), + 'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), '2005': ('8.0',), '2005e': ('8.0',), '2008': ('9.0',), @@ -387,17 +421,20 @@ '2012e': ('11.0',), '2013': ('12.0',), '2013e': ('12.0',), + '2015': ('14.0',), } override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') if override_path: msvs_version = os.environ.get('GYP_MSVS_VERSION') - if not msvs_version or 'e' not in msvs_version: + if not msvs_version: raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be ' - 'set to an "e" version (e.g. 2010e)') + 'set to a particular version (e.g. 2010e).') return _CreateVersion(msvs_version, override_path, sdk_based=True) version = str(version) versions = _DetectVisualStudioVersions(version_map[version], 'e' in version) if not versions: + if not allow_fallback: + raise ValueError('Could not locate Visual Studio installation.') if version == 'auto': # Default to 2005 if we couldn't find anything return _CreateVersion('2005', None) diff -Nru gyp-0.1~svn1729/pylib/gyp/ordered_dict.py gyp-0.1+20150913git1f374df9/pylib/gyp/ordered_dict.py --- gyp-0.1~svn1729/pylib/gyp/ordered_dict.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/ordered_dict.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,289 @@ +# Unmodified from http://code.activestate.com/recipes/576693/ +# other than to add MIT license header (as specified on page, but not in code). +# Linked from Python documentation here: +# http://docs.python.org/2/library/collections.html#collections.OrderedDict +# +# This should be deleted once Py2.7 is available on all bots, see +# http://crbug.com/241769. +# +# Copyright (c) 2009 Raymond Hettinger. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. + +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + +try: + from _abcoll import KeysView, ValuesView, ItemsView +except ImportError: + pass + + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + # Suppress 'OrderedDict.update: Method has no argument': + # pylint: disable=E0211 + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + diff -Nru gyp-0.1~svn1729/pylib/gyp/simple_copy.py gyp-0.1+20150913git1f374df9/pylib/gyp/simple_copy.py --- gyp-0.1~svn1729/pylib/gyp/simple_copy.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/simple_copy.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,46 @@ +# Copyright 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""A clone of the default copy.deepcopy that doesn't handle cyclic +structures or complex types except for dicts and lists. This is +because gyp copies so large structure that small copy overhead ends up +taking seconds in a project the size of Chromium.""" + +class Error(Exception): + pass + +__all__ = ["Error", "deepcopy"] + +def deepcopy(x): + """Deep copy operation on gyp objects such as strings, ints, dicts + and lists. More than twice as fast as copy.deepcopy but much less + generic.""" + + try: + return _deepcopy_dispatch[type(x)](x) + except KeyError: + raise Error('Unsupported type %s for deepcopy. Use copy.deepcopy ' + + 'or expand simple_copy support.' % type(x)) + +_deepcopy_dispatch = d = {} + +def _deepcopy_atomic(x): + return x + +for x in (type(None), int, long, float, + bool, str, unicode, type): + d[x] = _deepcopy_atomic + +def _deepcopy_list(x): + return [deepcopy(a) for a in x] +d[list] = _deepcopy_list + +def _deepcopy_dict(x): + y = {} + for key, value in x.iteritems(): + y[deepcopy(key)] = deepcopy(value) + return y +d[dict] = _deepcopy_dict + +del d diff -Nru gyp-0.1~svn1729/pylib/gyp/sun_tool.py gyp-0.1+20150913git1f374df9/pylib/gyp/sun_tool.py --- gyp-0.1~svn1729/pylib/gyp/sun_tool.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/sun_tool.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""These functions are executed via gyp-sun-tool when using the Makefile -generator.""" - -import fcntl -import os -import struct -import subprocess -import sys - - -def main(args): - executor = SunTool() - executor.Dispatch(args) - - -class SunTool(object): - """This class performs all the SunOS tooling steps. The methods can either be - executed directly, or dispatched from an argument list.""" - - def Dispatch(self, args): - """Dispatches a string command to a method.""" - if len(args) < 1: - raise Exception("Not enough arguments") - - method = "Exec%s" % self._CommandifyName(args[0]) - getattr(self, method)(*args[1:]) - - def _CommandifyName(self, name_string): - """Transforms a tool name like copy-info-plist to CopyInfoPlist""" - return name_string.title().replace('-', '') - - def ExecFlock(self, lockfile, *cmd_list): - """Emulates the most basic behavior of Linux's flock(1).""" - # Rely on exception handling to report errors. - # Note that the stock python on SunOS has a bug - # where fcntl.flock(fd, LOCK_EX) always fails - # with EBADF, that's why we use this F_SETLK - # hack instead. - fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666) - op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) - fcntl.fcntl(fd, fcntl.F_SETLK, op) - return subprocess.call(cmd_list) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff -Nru gyp-0.1~svn1729/pylib/gyp/win_tool.py gyp-0.1+20150913git1f374df9/pylib/gyp/win_tool.py --- gyp-0.1~svn1729/pylib/gyp/win_tool.py 2013-07-16 19:08:37.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/win_tool.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,12 +10,18 @@ """ import os +import re import shutil import subprocess +import stat +import string import sys BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +# A regex matching an argument corresponding to the output filename passed to +# link.exe. +_LINK_EXE_OUT_ARG = re.compile('/OUT:(?P.+)$', re.IGNORECASE) def main(args): executor = WinTool() @@ -28,6 +34,33 @@ """This class performs all the Windows tooling steps. The methods can either be executed directly, or dispatched from an argument list.""" + def _UseSeparateMspdbsrv(self, env, args): + """Allows to use a unique instance of mspdbsrv.exe per linker instead of a + shared one.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + if args[0] != 'link.exe': + return + + # Use the output filename passed to the linker to generate an endpoint name + # for mspdbsrv.exe. + endpoint_name = None + for arg in args: + m = _LINK_EXE_OUT_ARG.match(arg) + if m: + endpoint_name = re.sub(r'\W+', '', + '%s_%d' % (m.group('out'), os.getpid())) + break + + if endpoint_name is None: + return + + # Adds the appropriate environment variable. This will be read by link.exe + # to know which instance of mspdbsrv.exe it should connect to (if it's + # not set then the default endpoint is used). + env['_MSPDBSRV_ENDPOINT_'] = endpoint_name + def Dispatch(self, args): """Dispatches a string command to a method.""" if len(args) < 1: @@ -57,27 +90,118 @@ """Emulation of rm -rf out && cp -af in out.""" if os.path.exists(dest): if os.path.isdir(dest): - shutil.rmtree(dest) + def _on_error(fn, path, excinfo): + # The operation failed, possibly because the file is set to + # read-only. If that's why, make it writable and try the op again. + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWRITE) + fn(path) + shutil.rmtree(dest, onerror=_on_error) else: + if not os.access(dest, os.W_OK): + # Attempt to make the file writable before deleting it. + os.chmod(dest, stat.S_IWRITE) os.unlink(dest) + if os.path.isdir(source): shutil.copytree(source, dest) else: shutil.copy2(source, dest) - def ExecLinkWrapper(self, arch, *args): + def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args): """Filter diagnostic output from link that looks like: ' Creating library ui.dll.lib and object ui.dll.exp' This happens when there are exports from the dll or exe. """ env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() + if use_separate_mspdbsrv == 'True': + self._UseSeparateMspdbsrv(env, args) + link = subprocess.Popen([args[0].replace('/', '\\')] + list(args[1:]), + shell=True, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, _ = link.communicate() for line in out.splitlines(): if not line.startswith(' Creating library '): print line - return popen.returncode + return link.returncode + + def ExecLinkWithManifests(self, arch, embed_manifest, out, ldcmd, resname, + mt, rc, intermediate_manifest, *manifests): + """A wrapper for handling creating a manifest resource and then executing + a link command.""" + # The 'normal' way to do manifests is to have link generate a manifest + # based on gathering dependencies from the object files, then merge that + # manifest with other manifests supplied as sources, convert the merged + # manifest to a resource, and then *relink*, including the compiled + # version of the manifest resource. This breaks incremental linking, and + # is generally overly complicated. Instead, we merge all the manifests + # provided (along with one that includes what would normally be in the + # linker-generated one, see msvs_emulation.py), and include that into the + # first and only link. We still tell link to generate a manifest, but we + # only use that to assert that our simpler process did not miss anything. + variables = { + 'python': sys.executable, + 'arch': arch, + 'out': out, + 'ldcmd': ldcmd, + 'resname': resname, + 'mt': mt, + 'rc': rc, + 'intermediate_manifest': intermediate_manifest, + 'manifests': ' '.join(manifests), + } + add_to_ld = '' + if manifests: + subprocess.check_call( + '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo ' + '-manifest %(manifests)s -out:%(out)s.manifest' % variables) + if embed_manifest == 'True': + subprocess.check_call( + '%(python)s gyp-win-tool manifest-to-rc %(arch)s %(out)s.manifest' + ' %(out)s.manifest.rc %(resname)s' % variables) + subprocess.check_call( + '%(python)s gyp-win-tool rc-wrapper %(arch)s %(rc)s ' + '%(out)s.manifest.rc' % variables) + add_to_ld = ' %(out)s.manifest.res' % variables + subprocess.check_call(ldcmd + add_to_ld) + + # Run mt.exe on the theoretically complete manifest we generated, merging + # it with the one the linker generated to confirm that the linker + # generated one does not add anything. This is strictly unnecessary for + # correctness, it's only to verify that e.g. /MANIFESTDEPENDENCY was not + # used in a #pragma comment. + if manifests: + # Merge the intermediate one with ours to .assert.manifest, then check + # that .assert.manifest is identical to ours. + subprocess.check_call( + '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo ' + '-manifest %(out)s.manifest %(intermediate_manifest)s ' + '-out:%(out)s.assert.manifest' % variables) + assert_manifest = '%(out)s.assert.manifest' % variables + our_manifest = '%(out)s.manifest' % variables + # Load and normalize the manifests. mt.exe sometimes removes whitespace, + # and sometimes doesn't unfortunately. + with open(our_manifest, 'rb') as our_f: + with open(assert_manifest, 'rb') as assert_f: + our_data = our_f.read().translate(None, string.whitespace) + assert_data = assert_f.read().translate(None, string.whitespace) + if our_data != assert_data: + os.unlink(out) + def dump(filename): + sys.stderr.write('%s\n-----\n' % filename) + with open(filename, 'rb') as f: + sys.stderr.write(f.read() + '\n-----\n') + dump(intermediate_manifest) + dump(our_manifest) + dump(assert_manifest) + sys.stderr.write( + 'Linker generated manifest "%s" added to final manifest "%s" ' + '(result in "%s"). ' + 'Were /MANIFEST switches used in #pragma statements? ' % ( + intermediate_manifest, our_manifest, assert_manifest)) + return 1 def ExecManifestWrapper(self, arch, *args): """Run manifest tool with environment set. Strip out undesirable warning @@ -124,19 +248,17 @@ # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl # objidl.idl lines = out.splitlines() - prefix = 'Processing ' - processing = set(os.path.basename(x) for x in lines if x.startswith(prefix)) + prefixes = ('Processing ', '64 bit Processing ') + processing = set(os.path.basename(x) + for x in lines if x.startswith(prefixes)) for line in lines: - if not line.startswith(prefix) and line not in processing: + if not line.startswith(prefixes) and line not in processing: print line return popen.returncode def ExecAsmWrapper(self, arch, *args): """Filter logo banner from invocations of asm.exe.""" env = self._GetEnv(arch) - # MSVS doesn't assemble x64 asm files. - if arch == 'environment.x64': - return 0 popen = subprocess.Popen(args, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = popen.communicate() @@ -166,11 +288,25 @@ """Runs an action command line from a response file using the environment for |arch|. If |dir| is supplied, use that as the working directory.""" env = self._GetEnv(arch) + # TODO(scottmg): This is a temporary hack to get some specific variables + # through to actions that are set after gyp-time. http://crbug.com/333738. + for k, v in os.environ.iteritems(): + if k not in env: + env[k] = v args = open(rspfile).read() dir = dir[0] if dir else None - popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) - popen.wait() - return popen.returncode + return subprocess.call(args, shell=True, env=env, cwd=dir) + + def ExecClCompile(self, project_dir, selected_files): + """Executed by msvs-ninja projects when the 'ClCompile' target is used to + build selected C/C++ files.""" + project_dir = os.path.relpath(project_dir, BASE_DIR) + selected_files = selected_files.split(';') + ninja_targets = [os.path.join(project_dir, filename) + '^^' + for filename in selected_files] + cmd = ['ninja.exe'] + cmd.extend(ninja_targets) + return subprocess.call(cmd, shell=True, cwd=BASE_DIR) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff -Nru gyp-0.1~svn1729/pylib/gyp/xcode_emulation.py gyp-0.1+20150913git1f374df9/pylib/gyp/xcode_emulation.py --- gyp-0.1~svn1729/pylib/gyp/xcode_emulation.py 2013-09-05 15:38:18.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/xcode_emulation.py 2015-09-13 13:41:20.000000000 +0000 @@ -7,20 +7,155 @@ other build systems, such as make and ninja. """ +import copy import gyp.common +import os import os.path import re import shlex import subprocess import sys +import tempfile from gyp.common import GypError +# Populated lazily by XcodeVersion, for efficiency, and to fix an issue when +# "xcodebuild" is called too quickly (it has been found to return incorrect +# version number). +XCODE_VERSION_CACHE = None + +# Populated lazily by GetXcodeArchsDefault, to an |XcodeArchsDefault| instance +# corresponding to the installed version of Xcode. +XCODE_ARCHS_DEFAULT_CACHE = None + + +def XcodeArchsVariableMapping(archs, archs_including_64_bit=None): + """Constructs a dictionary with expansion for $(ARCHS_STANDARD) variable, + and optionally for $(ARCHS_STANDARD_INCLUDING_64_BIT).""" + mapping = {'$(ARCHS_STANDARD)': archs} + if archs_including_64_bit: + mapping['$(ARCHS_STANDARD_INCLUDING_64_BIT)'] = archs_including_64_bit + return mapping + +class XcodeArchsDefault(object): + """A class to resolve ARCHS variable from xcode_settings, resolving Xcode + macros and implementing filtering by VALID_ARCHS. The expansion of macros + depends on the SDKROOT used ("macosx", "iphoneos", "iphonesimulator") and + on the version of Xcode. + """ + + # Match variable like $(ARCHS_STANDARD). + variable_pattern = re.compile(r'\$\([a-zA-Z_][a-zA-Z0-9_]*\)$') + + def __init__(self, default, mac, iphonesimulator, iphoneos): + self._default = (default,) + self._archs = {'mac': mac, 'ios': iphoneos, 'iossim': iphonesimulator} + + def _VariableMapping(self, sdkroot): + """Returns the dictionary of variable mapping depending on the SDKROOT.""" + sdkroot = sdkroot.lower() + if 'iphoneos' in sdkroot: + return self._archs['ios'] + elif 'iphonesimulator' in sdkroot: + return self._archs['iossim'] + else: + return self._archs['mac'] + + def _ExpandArchs(self, archs, sdkroot): + """Expands variables references in ARCHS, and remove duplicates.""" + variable_mapping = self._VariableMapping(sdkroot) + expanded_archs = [] + for arch in archs: + if self.variable_pattern.match(arch): + variable = arch + try: + variable_expansion = variable_mapping[variable] + for arch in variable_expansion: + if arch not in expanded_archs: + expanded_archs.append(arch) + except KeyError as e: + print 'Warning: Ignoring unsupported variable "%s".' % variable + elif arch not in expanded_archs: + expanded_archs.append(arch) + return expanded_archs + + def ActiveArchs(self, archs, valid_archs, sdkroot): + """Expands variables references in ARCHS, and filter by VALID_ARCHS if it + is defined (if not set, Xcode accept any value in ARCHS, otherwise, only + values present in VALID_ARCHS are kept).""" + expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') + if valid_archs: + filtered_archs = [] + for arch in expanded_archs: + if arch in valid_archs: + filtered_archs.append(arch) + expanded_archs = filtered_archs + return expanded_archs + + +def GetXcodeArchsDefault(): + """Returns the |XcodeArchsDefault| object to use to expand ARCHS for the + installed version of Xcode. The default values used by Xcode for ARCHS + and the expansion of the variables depends on the version of Xcode used. + + For all version anterior to Xcode 5.0 or posterior to Xcode 5.1 included + uses $(ARCHS_STANDARD) if ARCHS is unset, while Xcode 5.0 to 5.0.2 uses + $(ARCHS_STANDARD_INCLUDING_64_BIT). This variable was added to Xcode 5.0 + and deprecated with Xcode 5.1. + + For "macosx" SDKROOT, all version starting with Xcode 5.0 includes 64-bit + architecture as part of $(ARCHS_STANDARD) and default to only building it. + + For "iphoneos" and "iphonesimulator" SDKROOT, 64-bit architectures are part + of $(ARCHS_STANDARD_INCLUDING_64_BIT) from Xcode 5.0. From Xcode 5.1, they + are also part of $(ARCHS_STANDARD). + + All thoses rules are coded in the construction of the |XcodeArchsDefault| + object to use depending on the version of Xcode detected. The object is + for performance reason.""" + global XCODE_ARCHS_DEFAULT_CACHE + if XCODE_ARCHS_DEFAULT_CACHE: + return XCODE_ARCHS_DEFAULT_CACHE + xcode_version, _ = XcodeVersion() + if xcode_version < '0500': + XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( + '$(ARCHS_STANDARD)', + XcodeArchsVariableMapping(['i386']), + XcodeArchsVariableMapping(['i386']), + XcodeArchsVariableMapping(['armv7'])) + elif xcode_version < '0510': + XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( + '$(ARCHS_STANDARD_INCLUDING_64_BIT)', + XcodeArchsVariableMapping(['x86_64'], ['x86_64']), + XcodeArchsVariableMapping(['i386'], ['i386', 'x86_64']), + XcodeArchsVariableMapping( + ['armv7', 'armv7s'], + ['armv7', 'armv7s', 'arm64'])) + else: + XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( + '$(ARCHS_STANDARD)', + XcodeArchsVariableMapping(['x86_64'], ['x86_64']), + XcodeArchsVariableMapping(['i386', 'x86_64'], ['i386', 'x86_64']), + XcodeArchsVariableMapping( + ['armv7', 'armv7s', 'arm64'], + ['armv7', 'armv7s', 'arm64'])) + return XCODE_ARCHS_DEFAULT_CACHE + + class XcodeSettings(object): """A class that understands the gyp 'xcode_settings' object.""" # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached # at class-level for efficiency. _sdk_path_cache = {} + _sdk_root_cache = {} + + # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so + # cached at class-level for efficiency. + _plist_cache = {} + + # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so + # cached at class-level for efficiency. + _codesigning_key_cache = {} def __init__(self, spec): self.spec = spec @@ -35,25 +170,34 @@ configs = spec['configurations'] for configname, config in configs.iteritems(): self.xcode_settings[configname] = config.get('xcode_settings', {}) + self._ConvertConditionalKeys(configname) if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', None): self.isIOS = True - # If you need this, speak up at http://crbug.com/122592 - conditional_keys = [key for key in self.xcode_settings[configname] - if key.endswith(']')] - if conditional_keys: - print 'Warning: Conditional keys not implemented, ignoring:', \ - ' '.join(conditional_keys) - for key in conditional_keys: - del self.xcode_settings[configname][key] - # This is only non-None temporarily during the execution of some methods. self.configname = None # Used by _AdjustLibrary to match .a and .dylib entries in libraries. self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') + def _ConvertConditionalKeys(self, configname): + """Converts or warns on conditional keys. Xcode supports conditional keys, + such as CODE_SIGN_IDENTITY[sdk=iphoneos*]. This is a partial implementation + with some keys converted while the rest force a warning.""" + settings = self.xcode_settings[configname] + conditional_keys = [key for key in settings if key.endswith(']')] + for key in conditional_keys: + # If you need more, speak up at http://crbug.com/122592 + if key.endswith("[sdk=iphoneos*]"): + if configname.endswith("iphoneos"): + new_key = key.split("[")[0] + settings[new_key] = settings[key] + else: + print 'Warning: Conditional keys not implemented, ignoring:', \ + ' '.join(conditional_keys) + del settings[key] + def _Settings(self): assert self.configname return self.xcode_settings[self.configname] @@ -71,9 +215,24 @@ if test_key in self._Settings(): print 'Warning: Ignoring not yet implemented key "%s".' % test_key + def IsBinaryOutputFormat(self, configname): + default = "binary" if self.isIOS else "xml" + format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', + default) + return format == "binary" + def _IsBundle(self): return int(self.spec.get('mac_bundle', 0)) != 0 + def _IsIosAppExtension(self): + return int(self.spec.get('ios_app_extension', 0)) != 0 + + def _IsIosWatchKitExtension(self): + return int(self.spec.get('ios_watchkit_extension', 0)) != 0 + + def _IsIosWatchApp(self): + return int(self.spec.get('ios_watch_app', 0)) != 0 + def GetFrameworkVersion(self): """Returns the framework version of the current target. Only valid for bundles.""" @@ -93,7 +252,10 @@ 'WRAPPER_EXTENSION', default=default_wrapper_extension) return '.' + self.spec.get('product_extension', wrapper_extension) elif self.spec['type'] == 'executable': - return '.' + self.spec.get('product_extension', 'app') + if self._IsIosAppExtension() or self._IsIosWatchKitExtension(): + return '.' + self.spec.get('product_extension', 'appex') + else: + return '.' + self.spec.get('product_extension', 'app') else: assert False, "Don't know extension for '%s', target '%s'" % ( self.spec['type'], self.spec['target_name']) @@ -148,6 +310,18 @@ def GetProductType(self): """Returns the PRODUCT_TYPE of this target.""" + if self._IsIosAppExtension(): + assert self._IsBundle(), ('ios_app_extension flag requires mac_bundle ' + '(target %s)' % self.spec['target_name']) + return 'com.apple.product-type.app-extension' + if self._IsIosWatchKitExtension(): + assert self._IsBundle(), ('ios_watchkit_extension flag requires ' + 'mac_bundle (target %s)' % self.spec['target_name']) + return 'com.apple.product-type.watchkit-extension' + if self._IsIosWatchApp(): + assert self._IsBundle(), ('ios_watch_app flag requires mac_bundle ' + '(target %s)' % self.spec['target_name']) + return 'com.apple.product-type.application.watchapp' if self._IsBundle(): return { 'executable': 'com.apple.product-type.application', @@ -242,26 +416,40 @@ def GetActiveArchs(self, configname): """Returns the architectures this target should be built for.""" - # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set - # CURRENT_ARCH / NATIVE_ARCH env vars? - return self.xcode_settings[configname].get('ARCHS', ['i386']) + config_settings = self.xcode_settings[configname] + xcode_archs_default = GetXcodeArchsDefault() + return xcode_archs_default.ActiveArchs( + config_settings.get('ARCHS'), + config_settings.get('VALID_ARCHS'), + config_settings.get('SDKROOT')) def _GetSdkVersionInfoItem(self, sdk, infoitem): - job = subprocess.Popen(['xcodebuild', '-version', '-sdk', sdk, infoitem], - stdout=subprocess.PIPE) - out = job.communicate()[0] - if job.returncode != 0: - sys.stderr.write(out + '\n') - raise GypError('Error %d running xcodebuild' % job.returncode) - return out.rstrip('\n') + # xcodebuild requires Xcode and can't run on Command Line Tools-only + # systems from 10.7 onward. + # Since the CLT has no SDK paths anyway, returning None is the + # most sensible route and should still do the right thing. + try: + return GetStdout(['xcodebuild', '-version', '-sdk', sdk, infoitem]) + except: + pass - def _SdkPath(self): - sdk_root = self.GetPerTargetSetting('SDKROOT', default='macosx') + def _SdkRoot(self, configname): + if configname is None: + configname = self.configname + return self.GetPerConfigSetting('SDKROOT', configname, default='') + + def _SdkPath(self, configname=None): + sdk_root = self._SdkRoot(configname) if sdk_root.startswith('/'): return sdk_root + return self._XcodeSdkPath(sdk_root) + + def _XcodeSdkPath(self, sdk_root): if sdk_root not in XcodeSettings._sdk_path_cache: - XcodeSettings._sdk_path_cache[sdk_root] = self._GetSdkVersionInfoItem( - sdk_root, 'Path') + sdk_path = self._GetSdkVersionInfoItem(sdk_root, 'Path') + XcodeSettings._sdk_path_cache[sdk_root] = sdk_path + if sdk_root: + XcodeSettings._sdk_root_cache[sdk_path] = sdk_root return XcodeSettings._sdk_path_cache[sdk_root] def _AppendPlatformVersionMinFlags(self, lst): @@ -286,7 +474,7 @@ cflags = [] sdk_root = self._SdkPath() - if 'SDKROOT' in self._Settings(): + if 'SDKROOT' in self._Settings() and sdk_root: cflags.append('-isysroot %s' % sdk_root) if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'): @@ -337,6 +525,13 @@ if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'): cflags.append('-Wnewline-eof') + # In Xcode, this is only activated when GCC_COMPILER_VERSION is clang or + # llvm-gcc. It also requires a fairly recent libtool, and + # if the system clang isn't used, DYLD_LIBRARY_PATH needs to contain the + # path to the libLTO.dylib that matches the used clang. + if self._Test('LLVM_LTO', 'YES', default='NO'): + cflags.append('-flto') + self._AppendPlatformVersionMinFlags(cflags) # TODO: @@ -352,7 +547,8 @@ if arch is not None: archs = [arch] else: - archs = self._Settings().get('ARCHS', ['i386']) + assert self.configname + archs = self.GetActiveArchs(self.configname) if len(archs) != 1: # TODO: Supporting fat binaries will be annoying. self._WarnUnimplemented('ARCHS') @@ -372,10 +568,14 @@ cflags += self._Settings().get('WARNING_CFLAGS', []) + if sdk_root: + framework_root = sdk_root + else: + framework_root = '' config = self.spec['configurations'][self.configname] framework_dirs = config.get('mac_framework_dirs', []) for directory in framework_dirs: - cflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) + cflags.append('-F' + directory.replace('$(SDKROOT)', framework_root)) self.configname = None return cflags @@ -444,12 +644,18 @@ if self._Test('CLANG_ENABLE_OBJC_ARC', 'YES', default='NO'): flags.append('-fobjc-arc') + def _AddObjectiveCMissingPropertySynthesisFlags(self, flags): + if self._Test('CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS', + 'YES', default='NO'): + flags.append('-Wobjc-missing-property-synthesis') + def GetCflagsObjC(self, configname): """Returns flags that need to be added to .m compilations.""" self.configname = configname cflags_objc = [] self._AddObjectiveCGarbageCollectionFlags(cflags_objc) self._AddObjectiveCARCFlags(cflags_objc) + self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objc) self.configname = None return cflags_objc @@ -459,6 +665,7 @@ cflags_objcc = [] self._AddObjectiveCGarbageCollectionFlags(cflags_objcc) self._AddObjectiveCARCFlags(cflags_objcc) + self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objcc) if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'): cflags_objcc.append('-fobjc-call-cxx-cdtors') self.configname = None @@ -533,8 +740,8 @@ # -exported_symbols_list file # -Wl,exported_symbols_list file # -Wl,exported_symbols_list,file - LINKER_FILE = '(\S+)' - WORD = '\S+' + LINKER_FILE = r'(\S+)' + WORD = r'\S+' linker_flags = [ ['-exported_symbols_list', LINKER_FILE], # Needed for NaCl. ['-unexported_symbols_list', LINKER_FILE], @@ -584,7 +791,7 @@ self._AppendPlatformVersionMinFlags(ldflags) - if 'SDKROOT' in self._Settings(): + if 'SDKROOT' in self._Settings() and self._SdkPath(): ldflags.append('-isysroot ' + self._SdkPath()) for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): @@ -598,7 +805,8 @@ if arch is not None: archs = [arch] else: - archs = self._Settings().get('ARCHS', ['i386']) + assert self.configname + archs = self.GetActiveArchs(self.configname) if len(archs) != 1: # TODO: Supporting fat binaries will be annoying. self._WarnUnimplemented('ARCHS') @@ -615,10 +823,29 @@ for rpath in self._Settings().get('LD_RUNPATH_SEARCH_PATHS', []): ldflags.append('-Wl,-rpath,' + rpath) + sdk_root = self._SdkPath() + if not sdk_root: + sdk_root = '' config = self.spec['configurations'][self.configname] framework_dirs = config.get('mac_framework_dirs', []) for directory in framework_dirs: - ldflags.append('-F' + directory.replace('$(SDKROOT)', self._SdkPath())) + ldflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) + + is_extension = self._IsIosAppExtension() or self._IsIosWatchKitExtension() + if sdk_root and is_extension: + # Adds the link flags for extensions. These flags are common for all + # extensions and provide loader and main function. + # These flags reflect the compilation options used by xcode to compile + # extensions. + ldflags.append('-lpkstart') + if XcodeVersion() < '0900': + ldflags.append(sdk_root + + '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') + ldflags.append('-fapplication-extension') + ldflags.append('-Xlinker -rpath ' + '-Xlinker @executable_path/../../Frameworks') + + self._Appendf(ldflags, 'CLANG_CXX_LIBRARY', '-stdlib=%s') self.configname = None return ldflags @@ -656,19 +883,25 @@ del result[key] return result + def GetPerConfigSetting(self, setting, configname, default=None): + if configname in self.xcode_settings: + return self.xcode_settings[configname].get(setting, default) + else: + return self.GetPerTargetSetting(setting, default) + def GetPerTargetSetting(self, setting, default=None): """Tries to get xcode_settings.setting from spec. Assumes that the setting has the same value in all configurations and throws otherwise.""" - first_pass = True + is_first_pass = True result = None for configname in sorted(self.xcode_settings.keys()): - if first_pass: + if is_first_pass: result = self.xcode_settings[configname].get(setting, None) - first_pass = False + is_first_pass = False else: assert result == self.xcode_settings[configname].get(setting, None), ( "Expected per-target setting for '%s', got per-config setting " - "(target %s)" % (setting, spec['target_name'])) + "(target %s)" % (setting, self.spec['target_name'])) if result is None: return default return result @@ -684,7 +917,7 @@ self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): default_strip_style = 'debugging' - if self._IsBundle(): + if self.spec['type'] == 'loadable_module' and self._IsBundle(): default_strip_style = 'non-global' elif self.spec['type'] == 'executable': default_strip_style = 'all' @@ -726,7 +959,8 @@ self.configname = None return result - def GetTargetPostbuilds(self, configname, output, output_binary, quiet=False): + def _GetTargetPostbuilds(self, configname, output, output_binary, + quiet=False): """Returns a list of shell commands that contain the shell commands to run as postbuilds for this target, before the actual postbuilds.""" # dSYMs need to build before stripping happens. @@ -734,7 +968,58 @@ self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + self._GetStripPostbuilds(configname, output_binary, quiet)) - def _AdjustLibrary(self, library): + def _GetIOSPostbuilds(self, configname, output_binary): + """Return a shell command to codesign the iOS output binary so it can + be deployed to a device. This should be run as the very last step of the + build.""" + if not (self.isIOS and self.spec['type'] == 'executable'): + return [] + + settings = self.xcode_settings[configname] + key = self._GetIOSCodeSignIdentityKey(settings) + if not key: + return [] + + # Warn for any unimplemented signing xcode keys. + unimpl = ['OTHER_CODE_SIGN_FLAGS'] + unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) + if unimpl: + print 'Warning: Some codesign keys not implemented, ignoring: %s' % ( + ', '.join(sorted(unimpl))) + + return ['%s code-sign-bundle "%s" "%s" "%s" "%s"' % ( + os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, + settings.get('CODE_SIGN_RESOURCE_RULES_PATH', ''), + settings.get('CODE_SIGN_ENTITLEMENTS', ''), + settings.get('PROVISIONING_PROFILE', '')) + ] + + def _GetIOSCodeSignIdentityKey(self, settings): + identity = settings.get('CODE_SIGN_IDENTITY') + if not identity: + return None + if identity not in XcodeSettings._codesigning_key_cache: + output = subprocess.check_output( + ['security', 'find-identity', '-p', 'codesigning', '-v']) + for line in output.splitlines(): + if identity in line: + fingerprint = line.split()[1] + cache = XcodeSettings._codesigning_key_cache + assert identity not in cache or fingerprint == cache[identity], ( + "Multiple codesigning fingerprints for identity: %s" % identity) + XcodeSettings._codesigning_key_cache[identity] = fingerprint + return XcodeSettings._codesigning_key_cache.get(identity, '') + + def AddImplicitPostbuilds(self, configname, output, output_binary, + postbuilds=[], quiet=False): + """Returns a list of shell commands that should run before and after + |postbuilds|.""" + assert output_binary is not None + pre = self._GetTargetPostbuilds(configname, output, output_binary, quiet) + post = self._GetIOSPostbuilds(configname, output_binary) + return pre + postbuilds + post + + def _AdjustLibrary(self, library, config_name=None): if library.endswith('.framework'): l = '-framework ' + os.path.splitext(os.path.basename(library))[0] else: @@ -743,15 +1028,92 @@ l = '-l' + m.group(1) else: l = library - return l.replace('$(SDKROOT)', self._SdkPath()) - def AdjustLibraries(self, libraries): + sdk_root = self._SdkPath(config_name) + if not sdk_root: + sdk_root = '' + return l.replace('$(SDKROOT)', sdk_root) + + def AdjustLibraries(self, libraries, config_name=None): """Transforms entries like 'Cocoa.framework' in libraries into entries like '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. """ - libraries = [ self._AdjustLibrary(library) for library in libraries] + libraries = [self._AdjustLibrary(library, config_name) + for library in libraries] return libraries + def _BuildMachineOSBuild(self): + return GetStdout(['sw_vers', '-buildVersion']) + + def _XcodeIOSDeviceFamily(self, configname): + family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') + return [int(x) for x in family.split(',')] + + def GetExtraPlistItems(self, configname=None): + """Returns a dictionary with extra items to insert into Info.plist.""" + if configname not in XcodeSettings._plist_cache: + cache = {} + cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() + + xcode, xcode_build = XcodeVersion() + cache['DTXcode'] = xcode + cache['DTXcodeBuild'] = xcode_build + + sdk_root = self._SdkRoot(configname) + if not sdk_root: + sdk_root = self._DefaultSdkRoot() + cache['DTSDKName'] = sdk_root + if xcode >= '0430': + cache['DTSDKBuild'] = self._GetSdkVersionInfoItem( + sdk_root, 'ProductBuildVersion') + else: + cache['DTSDKBuild'] = cache['BuildMachineOSBuild'] + + if self.isIOS: + cache['DTPlatformName'] = cache['DTSDKName'] + if configname.endswith("iphoneos"): + cache['DTPlatformVersion'] = self._GetSdkVersionInfoItem( + sdk_root, 'ProductVersion') + cache['CFBundleSupportedPlatforms'] = ['iPhoneOS'] + else: + cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] + XcodeSettings._plist_cache[configname] = cache + + # Include extra plist items that are per-target, not per global + # XcodeSettings. + items = dict(XcodeSettings._plist_cache[configname]) + if self.isIOS: + items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) + return items + + def _DefaultSdkRoot(self): + """Returns the default SDKROOT to use. + + Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode + project, then the environment variable was empty. Starting with this + version, Xcode uses the name of the newest SDK installed. + """ + xcode_version, xcode_build = XcodeVersion() + if xcode_version < '0500': + return '' + default_sdk_path = self._XcodeSdkPath('') + default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path) + if default_sdk_root: + return default_sdk_root + try: + all_sdks = GetStdout(['xcodebuild', '-showsdks']) + except: + # If xcodebuild fails, there will be no valid SDKs + return '' + for line in all_sdks.splitlines(): + items = line.split() + if len(items) >= 3 and items[-2] == '-sdk': + sdk_root = items[-1] + sdk_path = self._XcodeSdkPath(sdk_root) + if sdk_path == default_sdk_path: + return sdk_root + return '' + class MacPrefixHeader(object): """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. @@ -859,6 +1221,81 @@ ] +def XcodeVersion(): + """Returns a tuple of version and build version of installed Xcode.""" + # `xcodebuild -version` output looks like + # Xcode 4.6.3 + # Build version 4H1503 + # or like + # Xcode 3.2.6 + # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 + # BuildVersion: 10M2518 + # Convert that to '0463', '4H1503'. + global XCODE_VERSION_CACHE + if XCODE_VERSION_CACHE: + return XCODE_VERSION_CACHE + try: + version_list = GetStdout(['xcodebuild', '-version']).splitlines() + # In some circumstances xcodebuild exits 0 but doesn't return + # the right results; for example, a user on 10.7 or 10.8 with + # a bogus path set via xcode-select + # In that case this may be a CLT-only install so fall back to + # checking that version. + if len(version_list) < 2: + raise GypError("xcodebuild returned unexpected results") + except: + version = CLTVersion() + if version: + version = re.match(r'(\d\.\d\.?\d*)', version).groups()[0] + else: + raise GypError("No Xcode or CLT version detected!") + # The CLT has no build information, so we return an empty string. + version_list = [version, ''] + version = version_list[0] + build = version_list[-1] + # Be careful to convert "4.2" to "0420": + version = version.split()[-1].replace('.', '') + version = (version + '0' * (3 - len(version))).zfill(4) + if build: + build = build.split()[-1] + XCODE_VERSION_CACHE = (version, build) + return XCODE_VERSION_CACHE + + +# This function ported from the logic in Homebrew's CLT version check +def CLTVersion(): + """Returns the version of command-line tools from pkgutil.""" + # pkgutil output looks like + # package-id: com.apple.pkg.CLTools_Executables + # version: 5.0.1.0.1.1382131676 + # volume: / + # location: / + # install-time: 1382544035 + # groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-group com.apple.DevToolsNonRelocatableShared.pkg-group + STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo" + FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" + MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables" + + regex = re.compile('version: (?P.+)') + for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]: + try: + output = GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key]) + return re.search(regex, output).groupdict()['version'] + except: + continue + + +def GetStdout(cmdlist): + """Returns the content of standard output returned by invoking |cmdlist|. + Raises |GypError| if the command return with a non-zero return code.""" + job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) + out = job.communicate()[0] + if job.returncode != 0: + sys.stderr.write(out + '\n') + raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) + return out.rstrip('\n') + + def MergeGlobalXcodeSettingsToSpec(global_dict, spec): """Merges the global xcode_settings dictionary into each configuration of the target represented by spec. For keys that are both in the global and the local @@ -921,7 +1358,10 @@ output = os.path.join(output, res_parts[1]) # Compiled XIB files are referred to by .nib. if output.endswith('.xib'): - output = output[0:-3] + 'nib' + output = os.path.splitext(output)[0] + '.nib' + # Compiled storyboard files are referred to by .storyboardc. + if output.endswith('.storyboard'): + output = os.path.splitext(output)[0] + '.storyboardc' yield output, res @@ -1007,8 +1447,8 @@ 'TARGET_BUILD_DIR' : built_products_dir, 'TEMP_DIR' : '${TMPDIR}', } - if xcode_settings.GetPerTargetSetting('SDKROOT'): - env['SDKROOT'] = xcode_settings._SdkPath() + if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): + env['SDKROOT'] = xcode_settings._SdkPath(configuration) else: env['SDKROOT'] = '' @@ -1035,6 +1475,11 @@ install_name_base = xcode_settings.GetInstallNameBase() if install_name_base: env['DYLIB_INSTALL_NAME_BASE'] = install_name_base + if XcodeVersion() >= '0500' and not env.get('SDKROOT'): + sdk_root = xcode_settings._SdkRoot(configuration) + if not sdk_root: + sdk_root = xcode_settings._XcodeSdkPath('') + env['SDKROOT'] = sdk_root if not additional_settings: additional_settings = {} @@ -1131,3 +1576,35 @@ spec['target_name'], postbuild['postbuild_name'])) postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action'])) return postbuilds + + +def _HasIOSTarget(targets): + """Returns true if any target contains the iOS specific key + IPHONEOS_DEPLOYMENT_TARGET.""" + for target_dict in targets.values(): + for config in target_dict['configurations'].values(): + if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'): + return True + return False + + +def _AddIOSDeviceConfigurations(targets): + """Clone all targets and append -iphoneos to the name. Configure these targets + to build for iOS devices and use correct architectures for those builds.""" + for target_dict in targets.itervalues(): + toolset = target_dict['toolset'] + configs = target_dict['configurations'] + for config_name, config_dict in dict(configs).iteritems(): + iphoneos_config_dict = copy.deepcopy(config_dict) + configs[config_name + '-iphoneos'] = iphoneos_config_dict + configs[config_name + '-iphonesimulator'] = config_dict + if toolset == 'target': + iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' + return targets + +def CloneConfigurationForDeviceAndEmulator(target_dicts): + """If |target_dicts| contains any iOS targets, automatically create -iphoneos + targets for iOS device builds.""" + if _HasIOSTarget(target_dicts): + return _AddIOSDeviceConfigurations(target_dicts) + return target_dicts diff -Nru gyp-0.1~svn1729/pylib/gyp/xcode_ninja.py gyp-0.1+20150913git1f374df9/pylib/gyp/xcode_ninja.py --- gyp-0.1~svn1729/pylib/gyp/xcode_ninja.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/xcode_ninja.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,270 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Xcode-ninja wrapper project file generator. + +This updates the data structures passed to the Xcode gyp generator to build +with ninja instead. The Xcode project itself is transformed into a list of +executable targets, each with a build step to build with ninja, and a target +with every source and resource file. This appears to sidestep some of the +major performance headaches experienced using complex projects and large number +of targets within Xcode. +""" + +import errno +import gyp.generator.ninja +import os +import re +import xml.sax.saxutils + + +def _WriteWorkspace(main_gyp, sources_gyp, params): + """ Create a workspace to wrap main and sources gyp paths. """ + (build_file_root, build_file_ext) = os.path.splitext(main_gyp) + workspace_path = build_file_root + '.xcworkspace' + options = params['options'] + if options.generator_output: + workspace_path = os.path.join(options.generator_output, workspace_path) + try: + os.makedirs(workspace_path) + except OSError, e: + if e.errno != errno.EEXIST: + raise + output_string = '\n' + \ + '\n' + for gyp_name in [main_gyp, sources_gyp]: + name = os.path.splitext(os.path.basename(gyp_name))[0] + '.xcodeproj' + name = xml.sax.saxutils.quoteattr("group:" + name) + output_string += ' \n' % name + output_string += '\n' + + workspace_file = os.path.join(workspace_path, "contents.xcworkspacedata") + + try: + with open(workspace_file, 'r') as input_file: + input_string = input_file.read() + if input_string == output_string: + return + except IOError: + # Ignore errors if the file doesn't exist. + pass + + with open(workspace_file, 'w') as output_file: + output_file.write(output_string) + +def _TargetFromSpec(old_spec, params): + """ Create fake target for xcode-ninja wrapper. """ + # Determine ninja top level build dir (e.g. /path/to/out). + ninja_toplevel = None + jobs = 0 + if params: + options = params['options'] + ninja_toplevel = \ + os.path.join(options.toplevel_dir, + gyp.generator.ninja.ComputeOutputDir(params)) + jobs = params.get('generator_flags', {}).get('xcode_ninja_jobs', 0) + + target_name = old_spec.get('target_name') + product_name = old_spec.get('product_name', target_name) + product_extension = old_spec.get('product_extension') + + ninja_target = {} + ninja_target['target_name'] = target_name + ninja_target['product_name'] = product_name + if product_extension: + ninja_target['product_extension'] = product_extension + ninja_target['toolset'] = old_spec.get('toolset') + ninja_target['default_configuration'] = old_spec.get('default_configuration') + ninja_target['configurations'] = {} + + # Tell Xcode to look in |ninja_toplevel| for build products. + new_xcode_settings = {} + if ninja_toplevel: + new_xcode_settings['CONFIGURATION_BUILD_DIR'] = \ + "%s/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" % ninja_toplevel + + if 'configurations' in old_spec: + for config in old_spec['configurations'].iterkeys(): + old_xcode_settings = \ + old_spec['configurations'][config].get('xcode_settings', {}) + if 'IPHONEOS_DEPLOYMENT_TARGET' in old_xcode_settings: + new_xcode_settings['CODE_SIGNING_REQUIRED'] = "NO" + new_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] = \ + old_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] + ninja_target['configurations'][config] = {} + ninja_target['configurations'][config]['xcode_settings'] = \ + new_xcode_settings + + ninja_target['mac_bundle'] = old_spec.get('mac_bundle', 0) + ninja_target['ios_app_extension'] = old_spec.get('ios_app_extension', 0) + ninja_target['ios_watchkit_extension'] = \ + old_spec.get('ios_watchkit_extension', 0) + ninja_target['ios_watchkit_app'] = old_spec.get('ios_watchkit_app', 0) + ninja_target['type'] = old_spec['type'] + if ninja_toplevel: + ninja_target['actions'] = [ + { + 'action_name': 'Compile and copy %s via ninja' % target_name, + 'inputs': [], + 'outputs': [], + 'action': [ + 'env', + 'PATH=%s' % os.environ['PATH'], + 'ninja', + '-C', + new_xcode_settings['CONFIGURATION_BUILD_DIR'], + target_name, + ], + 'message': 'Compile and copy %s via ninja' % target_name, + }, + ] + if jobs > 0: + ninja_target['actions'][0]['action'].extend(('-j', jobs)) + return ninja_target + +def IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): + """Limit targets for Xcode wrapper. + + Xcode sometimes performs poorly with too many targets, so only include + proper executable targets, with filters to customize. + Arguments: + target_extras: Regular expression to always add, matching any target. + executable_target_pattern: Regular expression limiting executable targets. + spec: Specifications for target. + """ + target_name = spec.get('target_name') + # Always include targets matching target_extras. + if target_extras is not None and re.search(target_extras, target_name): + return True + + # Otherwise just show executable targets. + if spec.get('type', '') == 'executable' and \ + spec.get('product_extension', '') != 'bundle': + + # If there is a filter and the target does not match, exclude the target. + if executable_target_pattern is not None: + if not re.search(executable_target_pattern, target_name): + return False + return True + return False + +def CreateWrapper(target_list, target_dicts, data, params): + """Initialize targets for the ninja wrapper. + + This sets up the necessary variables in the targets to generate Xcode projects + that use ninja as an external builder. + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + data: Dict of flattened build files keyed on gyp path. + params: Dict of global options for gyp. + """ + orig_gyp = params['build_files'][0] + for gyp_name, gyp_dict in data.iteritems(): + if gyp_name == orig_gyp: + depth = gyp_dict['_DEPTH'] + + # Check for custom main gyp name, otherwise use the default CHROMIUM_GYP_FILE + # and prepend .ninja before the .gyp extension. + generator_flags = params.get('generator_flags', {}) + main_gyp = generator_flags.get('xcode_ninja_main_gyp', None) + if main_gyp is None: + (build_file_root, build_file_ext) = os.path.splitext(orig_gyp) + main_gyp = build_file_root + ".ninja" + build_file_ext + + # Create new |target_list|, |target_dicts| and |data| data structures. + new_target_list = [] + new_target_dicts = {} + new_data = {} + + # Set base keys needed for |data|. + new_data[main_gyp] = {} + new_data[main_gyp]['included_files'] = [] + new_data[main_gyp]['targets'] = [] + new_data[main_gyp]['xcode_settings'] = \ + data[orig_gyp].get('xcode_settings', {}) + + # Normally the xcode-ninja generator includes only valid executable targets. + # If |xcode_ninja_executable_target_pattern| is set, that list is reduced to + # executable targets that match the pattern. (Default all) + executable_target_pattern = \ + generator_flags.get('xcode_ninja_executable_target_pattern', None) + + # For including other non-executable targets, add the matching target name + # to the |xcode_ninja_target_pattern| regular expression. (Default none) + target_extras = generator_flags.get('xcode_ninja_target_pattern', None) + + for old_qualified_target in target_list: + spec = target_dicts[old_qualified_target] + if IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): + # Add to new_target_list. + target_name = spec.get('target_name') + new_target_name = '%s:%s#target' % (main_gyp, target_name) + new_target_list.append(new_target_name) + + # Add to new_target_dicts. + new_target_dicts[new_target_name] = _TargetFromSpec(spec, params) + + # Add to new_data. + for old_target in data[old_qualified_target.split(':')[0]]['targets']: + if old_target['target_name'] == target_name: + new_data_target = {} + new_data_target['target_name'] = old_target['target_name'] + new_data_target['toolset'] = old_target['toolset'] + new_data[main_gyp]['targets'].append(new_data_target) + + # Create sources target. + sources_target_name = 'sources_for_indexing' + sources_target = _TargetFromSpec( + { 'target_name' : sources_target_name, + 'toolset': 'target', + 'default_configuration': 'Default', + 'mac_bundle': '0', + 'type': 'executable' + }, None) + + # Tell Xcode to look everywhere for headers. + sources_target['configurations'] = {'Default': { 'include_dirs': [ depth ] } } + + sources = [] + for target, target_dict in target_dicts.iteritems(): + base = os.path.dirname(target) + files = target_dict.get('sources', []) + \ + target_dict.get('mac_bundle_resources', []) + for action in target_dict.get('actions', []): + files.extend(action.get('inputs', [])) + # Remove files starting with $. These are mostly intermediate files for the + # build system. + files = [ file for file in files if not file.startswith('$')] + + # Make sources relative to root build file. + relative_path = os.path.dirname(main_gyp) + sources += [ os.path.relpath(os.path.join(base, file), relative_path) + for file in files ] + + sources_target['sources'] = sorted(set(sources)) + + # Put sources_to_index in it's own gyp. + sources_gyp = \ + os.path.join(os.path.dirname(main_gyp), sources_target_name + ".gyp") + fully_qualified_target_name = \ + '%s:%s#target' % (sources_gyp, sources_target_name) + + # Add to new_target_list, new_target_dicts and new_data. + new_target_list.append(fully_qualified_target_name) + new_target_dicts[fully_qualified_target_name] = sources_target + new_data_target = {} + new_data_target['target_name'] = sources_target['target_name'] + new_data_target['_DEPTH'] = depth + new_data_target['toolset'] = "target" + new_data[sources_gyp] = {} + new_data[sources_gyp]['targets'] = [] + new_data[sources_gyp]['included_files'] = [] + new_data[sources_gyp]['xcode_settings'] = \ + data[orig_gyp].get('xcode_settings', {}) + new_data[sources_gyp]['targets'].append(new_data_target) + + # Write workspace to file. + _WriteWorkspace(main_gyp, sources_gyp, params) + return (new_target_list, new_target_dicts, new_data) diff -Nru gyp-0.1~svn1729/pylib/gyp/xcodeproj_file.py gyp-0.1+20150913git1f374df9/pylib/gyp/xcodeproj_file.py --- gyp-0.1~svn1729/pylib/gyp/xcodeproj_file.py 2013-09-13 15:28:41.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylib/gyp/xcodeproj_file.py 2015-09-13 13:41:20.000000000 +0000 @@ -173,7 +173,7 @@ # Used by SourceTreeAndPathFromPath -_path_leading_variable = re.compile('^\$\((.*?)\)(/(.*))?$') +_path_leading_variable = re.compile(r'^\$\((.*?)\)(/(.*))?$') def SourceTreeAndPathFromPath(input_path): """Given input_path, returns a tuple with sourceTree and path values. @@ -196,7 +196,7 @@ return (source_tree, output_path) def ConvertVariablesToShellSyntax(input_string): - return re.sub('\$\((.*?)\)', '${\\1}', input_string) + return re.sub(r'\$\((.*?)\)', '${\\1}', input_string) class XCObject(object): """The abstract base of all class types used in Xcode project files. @@ -341,13 +341,13 @@ elif isinstance(value, dict): # dicts are never strong. if is_strong: - raise TypeError, 'Strong dict for key ' + key + ' in ' + \ - self.__class__.__name__ + raise TypeError('Strong dict for key ' + key + ' in ' + \ + self.__class__.__name__) else: that._properties[key] = value.copy() else: - raise TypeError, 'Unexpected type ' + value.__class__.__name__ + \ - ' for key ' + key + ' in ' + self.__class__.__name__ + raise TypeError('Unexpected type ' + value.__class__.__name__ + \ + ' for key ' + key + ' in ' + self.__class__.__name__) return that @@ -366,8 +366,7 @@ ('name' in self._schema and self._schema['name'][3]): return self._properties['name'] - raise NotImplementedError, \ - self.__class__.__name__ + ' must implement Name' + raise NotImplementedError(self.__class__.__name__ + ' must implement Name') def Comment(self): """Return a comment string for the object. @@ -466,10 +465,10 @@ for descendant in descendants: if descendant.id in ids: other = ids[descendant.id] - raise KeyError, \ + raise KeyError( 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \ (descendant.id, str(descendant._properties), - str(other._properties), self._properties['rootObject'].Name()) + str(other._properties), self._properties['rootObject'].Name())) ids[descendant.id] = descendant def Children(self): @@ -630,7 +629,7 @@ sep printable += end_tabs + '}' else: - raise TypeError, "Can't make " + value.__class__.__name__ + ' printable' + raise TypeError("Can't make " + value.__class__.__name__ + ' printable') if comment != None: printable += ' ' + self._EncodeComment(comment) @@ -756,31 +755,31 @@ for property, value in properties.iteritems(): # Make sure the property is in the schema. if not property in self._schema: - raise KeyError, property + ' not in ' + self.__class__.__name__ + raise KeyError(property + ' not in ' + self.__class__.__name__) # Make sure the property conforms to the schema. (is_list, property_type, is_strong) = self._schema[property][0:3] if is_list: if value.__class__ != list: - raise TypeError, \ + raise TypeError( property + ' of ' + self.__class__.__name__ + \ - ' must be list, not ' + value.__class__.__name__ + ' must be list, not ' + value.__class__.__name__) for item in value: if not isinstance(item, property_type) and \ not (item.__class__ == unicode and property_type == str): # Accept unicode where str is specified. str is treated as # UTF-8-encoded. - raise TypeError, \ + raise TypeError( 'item of ' + property + ' of ' + self.__class__.__name__ + \ ' must be ' + property_type.__name__ + ', not ' + \ - item.__class__.__name__ + item.__class__.__name__) elif not isinstance(value, property_type) and \ not (value.__class__ == unicode and property_type == str): # Accept unicode where str is specified. str is treated as # UTF-8-encoded. - raise TypeError, \ + raise TypeError( property + ' of ' + self.__class__.__name__ + ' must be ' + \ - property_type.__name__ + ', not ' + value.__class__.__name__ + property_type.__name__ + ', not ' + value.__class__.__name__) # Checks passed, perform the assignment. if do_copy: @@ -804,9 +803,9 @@ elif isinstance(value, dict): self._properties[property] = value.copy() else: - raise TypeError, "Don't know how to copy a " + \ - value.__class__.__name__ + ' object for ' + \ - property + ' in ' + self.__class__.__name__ + raise TypeError("Don't know how to copy a " + \ + value.__class__.__name__ + ' object for ' + \ + property + ' in ' + self.__class__.__name__) else: self._properties[property] = value @@ -837,15 +836,15 @@ # Schema validation. if not key in self._schema: - raise KeyError, key + ' not in ' + self.__class__.__name__ + raise KeyError(key + ' not in ' + self.__class__.__name__) (is_list, property_type, is_strong) = self._schema[key][0:3] if not is_list: - raise TypeError, key + ' of ' + self.__class__.__name__ + ' must be list' + raise TypeError(key + ' of ' + self.__class__.__name__ + ' must be list') if not isinstance(value, property_type): - raise TypeError, 'item of ' + key + ' of ' + self.__class__.__name__ + \ - ' must be ' + property_type.__name__ + ', not ' + \ - value.__class__.__name__ + raise TypeError('item of ' + key + ' of ' + self.__class__.__name__ + \ + ' must be ' + property_type.__name__ + ', not ' + \ + value.__class__.__name__) # If the property doesn't exist yet, create a new empty list to receive the # item. @@ -869,7 +868,7 @@ for property, attributes in self._schema.iteritems(): (is_list, property_type, is_strong, is_required) = attributes[0:4] if is_required and not property in self._properties: - raise KeyError, self.__class__.__name__ + ' requires ' + property + raise KeyError(self.__class__.__name__ + ' requires ' + property) def _SetDefaultsFromSchema(self): """Assign object default values according to the schema. This will not @@ -1143,16 +1142,16 @@ child_path = child.PathFromSourceTreeAndPath() if child_path: if child_path in self._children_by_path: - raise ValueError, 'Found multiple children with path ' + child_path + raise ValueError('Found multiple children with path ' + child_path) self._children_by_path[child_path] = child if isinstance(child, PBXVariantGroup): child_name = child._properties.get('name', None) key = (child_name, child_path) if key in self._variant_children_by_name_and_path: - raise ValueError, 'Found multiple PBXVariantGroup children with ' + \ - 'name ' + str(child_name) + ' and path ' + \ - str(child_path) + raise ValueError('Found multiple PBXVariantGroup children with ' + \ + 'name ' + str(child_name) + ' and path ' + \ + str(child_path)) self._variant_children_by_name_and_path[key] = child def AppendChild(self, child): @@ -1483,8 +1482,11 @@ 'cpp': 'sourcecode.cpp.cpp', 'css': 'text.css', 'cxx': 'sourcecode.cpp.cpp', + 'dart': 'sourcecode', 'dylib': 'compiled.mach-o.dylib', 'framework': 'wrapper.framework', + 'gyp': 'sourcecode', + 'gypi': 'sourcecode', 'h': 'sourcecode.c.h', 'hxx': 'sourcecode.cpp.h', 'icns': 'image.icns', @@ -1505,15 +1507,25 @@ 's': 'sourcecode.asm', 'storyboard': 'file.storyboard', 'strings': 'text.plist.strings', + 'swift': 'sourcecode.swift', 'ttf': 'file', + 'xcassets': 'folder.assetcatalog', 'xcconfig': 'text.xcconfig', 'xcdatamodel': 'wrapper.xcdatamodel', + 'xcdatamodeld':'wrapper.xcdatamodeld', 'xib': 'file.xib', 'y': 'sourcecode.yacc', } + prop_map = { + 'dart': 'explicitFileType', + 'gyp': 'explicitFileType', + 'gypi': 'explicitFileType', + } + if is_dir: file_type = 'folder' + prop_name = 'lastKnownFileType' else: basename = posixpath.basename(self._properties['path']) (root, ext) = posixpath.splitext(basename) @@ -1528,8 +1540,9 @@ # for unrecognized files not containing text. Xcode seems to choose # based on content. file_type = extension_map.get(ext, 'text') + prop_name = prop_map.get(ext, 'lastKnownFileType') - self._properties['lastKnownFileType'] = file_type + self._properties[prop_name] = file_type class PBXVariantGroup(PBXGroup, XCFileLikeElement): @@ -1594,7 +1607,7 @@ if configuration._properties['name'] == name: return configuration - raise KeyError, name + raise KeyError(name) def DefaultConfiguration(self): """Convenience accessor to obtain the default XCBuildConfiguration.""" @@ -1651,7 +1664,7 @@ value = configuration_value else: if value != configuration_value: - raise ValueError, 'Variant values for ' + key + raise ValueError('Variant values for ' + key) return value @@ -1758,8 +1771,8 @@ # added, either as a child or deeper descendant. The second item should # be a boolean indicating whether files should be added into hierarchical # groups or one single flat group. - raise NotImplementedError, \ - self.__class__.__name__ + ' must implement FileGroup' + raise NotImplementedError( + self.__class__.__name__ + ' must implement FileGroup') def _AddPathToDict(self, pbxbuildfile, path): """Adds path to the dict tracking paths belonging to this build phase. @@ -1768,7 +1781,7 @@ """ if path in self._files_by_path: - raise ValueError, 'Found multiple build files with path ' + path + raise ValueError('Found multiple build files with path ' + path) self._files_by_path[path] = pbxbuildfile def _AddBuildFileToDicts(self, pbxbuildfile, path=None): @@ -1823,8 +1836,8 @@ # problem. if xcfilelikeelement in self._files_by_xcfilelikeelement and \ self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile: - raise ValueError, 'Found multiple build files for ' + \ - xcfilelikeelement.Name() + raise ValueError('Found multiple build files for ' + \ + xcfilelikeelement.Name()) self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile def AppendBuildFile(self, pbxbuildfile, path=None): @@ -1988,8 +2001,8 @@ subfolder = 0 relative_path = path[1:] else: - raise ValueError, 'Can\'t use path %s in a %s' % \ - (path, self.__class__.__name__) + raise ValueError('Can\'t use path %s in a %s' % \ + (path, self.__class__.__name__)) self._properties['dstPath'] = relative_path self._properties['dstSubfolderSpec'] = subfolder @@ -2225,22 +2238,30 @@ # Mapping from Xcode product-types to settings. The settings are: # filetype : used for explicitFileType in the project file # prefix : the prefix for the file name - # suffix : the suffix for the filen ame + # suffix : the suffix for the file name _product_filetypes = { - 'com.apple.product-type.application': ['wrapper.application', - '', '.app'], - 'com.apple.product-type.bundle': ['wrapper.cfbundle', - '', '.bundle'], - 'com.apple.product-type.framework': ['wrapper.framework', - '', '.framework'], - 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib', - 'lib', '.dylib'], - 'com.apple.product-type.library.static': ['archive.ar', - 'lib', '.a'], - 'com.apple.product-type.tool': ['compiled.mach-o.executable', - '', ''], - 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib', - '', '.so'], + 'com.apple.product-type.application': ['wrapper.application', + '', '.app'], + 'com.apple.product-type.application.watchapp': ['wrapper.application', + '', '.app'], + 'com.apple.product-type.watchkit-extension': ['wrapper.app-extension', + '', '.appex'], + 'com.apple.product-type.app-extension': ['wrapper.app-extension', + '', '.appex'], + 'com.apple.product-type.bundle': ['wrapper.cfbundle', + '', '.bundle'], + 'com.apple.product-type.framework': ['wrapper.framework', + '', '.framework'], + 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib', + 'lib', '.dylib'], + 'com.apple.product-type.library.static': ['archive.ar', + 'lib', '.a'], + 'com.apple.product-type.tool': ['compiled.mach-o.executable', + '', ''], + 'com.apple.product-type.bundle.unit-test': ['wrapper.cfbundle', + '', '.xctest'], + 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib', + '', '.so'], } def __init__(self, properties=None, id=None, parent=None, @@ -2292,13 +2313,18 @@ if force_extension is None: force_extension = suffix[1:] + if self._properties['productType'] == \ + 'com.apple.product-type-bundle.unit.test': + if force_extension is None: + force_extension = suffix[1:] + if force_extension is not None: # If it's a wrapper (bundle), set WRAPPER_EXTENSION. + # Extension override. + suffix = '.' + force_extension if filetype.startswith('wrapper.'): self.SetBuildSetting('WRAPPER_EXTENSION', force_extension) else: - # Extension override. - suffix = '.' + force_extension self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension) if filetype.startswith('compiled.mach-o.executable'): @@ -2714,8 +2740,53 @@ self._SetUpProductReferences(other_pbxproject, product_group, project_ref) + inherit_unique_symroot = self._AllSymrootsUnique(other_pbxproject, False) + targets = other_pbxproject.GetProperty('targets') + if all(self._AllSymrootsUnique(t, inherit_unique_symroot) for t in targets): + dir_path = project_ref._properties['path'] + product_group._hashables.extend(dir_path) + return [product_group, project_ref] + def _AllSymrootsUnique(self, target, inherit_unique_symroot): + # Returns True if all configurations have a unique 'SYMROOT' attribute. + # The value of inherit_unique_symroot decides, if a configuration is assumed + # to inherit a unique 'SYMROOT' attribute from its parent, if it doesn't + # define an explicit value for 'SYMROOT'. + symroots = self._DefinedSymroots(target) + for s in self._DefinedSymroots(target): + if (s is not None and not self._IsUniqueSymrootForTarget(s) or + s is None and not inherit_unique_symroot): + return False + return True if symroots else inherit_unique_symroot + + def _DefinedSymroots(self, target): + # Returns all values for the 'SYMROOT' attribute defined in all + # configurations for this target. If any configuration doesn't define the + # 'SYMROOT' attribute, None is added to the returned set. If all + # configurations don't define the 'SYMROOT' attribute, an empty set is + # returned. + config_list = target.GetProperty('buildConfigurationList') + symroots = set() + for config in config_list.GetProperty('buildConfigurations'): + setting = config.GetProperty('buildSettings') + if 'SYMROOT' in setting: + symroots.add(setting['SYMROOT']) + else: + symroots.add(None) + if len(symroots) == 1 and None in symroots: + return set() + return symroots + + def _IsUniqueSymrootForTarget(self, symroot): + # This method returns True if all configurations in target contain a + # 'SYMROOT' attribute that is unique for the given target. A value is + # unique, if the Xcode macro '$SRCROOT' appears in it in any form. + uniquifier = ['$SRCROOT', '$(SRCROOT)'] + if any(x in symroot for x in uniquifier): + return True + return False + def _SetUpProductReferences(self, other_pbxproject, product_group, project_ref): # TODO(mark): This only adds references to products in other_pbxproject @@ -2784,7 +2855,7 @@ product_group = ref_dict['ProductGroup'] product_group._properties['children'] = sorted( product_group._properties['children'], - cmp=lambda x, y: CompareProducts(x, y, remote_products)) + cmp=lambda x, y, rp=remote_products: CompareProducts(x, y, rp)) class XCProjectFile(XCObject): @@ -2792,27 +2863,10 @@ _schema.update({ 'archiveVersion': [0, int, 0, 1, 1], 'classes': [0, dict, 0, 1, {}], - 'objectVersion': [0, int, 0, 1, 45], + 'objectVersion': [0, int, 0, 1, 46], 'rootObject': [0, PBXProject, 1, 1], }) - def SetXcodeVersion(self, version): - version_to_object_version = { - '2.4': 45, - '3.0': 45, - '3.1': 45, - '3.2': 46, - } - if not version in version_to_object_version: - supported_str = ', '.join(sorted(version_to_object_version.keys())) - raise Exception( - 'Unsupported Xcode version %s (supported: %s)' % - ( version, supported_str ) ) - compatibility_version = 'Xcode %s' % version - self._properties['rootObject'].SetProperty('compatibilityVersion', - compatibility_version) - self.SetProperty('objectVersion', version_to_object_version[version]); - def ComputeIDs(self, recursive=True, overwrite=True, hash=None): # Although XCProjectFile is implemented here as an XCObject, it's not a # proper object in the Xcode sense, and it certainly doesn't have its own diff -Nru gyp-0.1~svn1729/pylintrc gyp-0.1+20150913git1f374df9/pylintrc --- gyp-0.1~svn1729/pylintrc 2011-11-28 16:31:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/pylintrc 1970-01-01 00:00:00.000000000 +0000 @@ -1,307 +0,0 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). -# C0103: Invalid name "NN" (should match [a-z_][a-z0-9_]{2,30}$) -# C0111: Missing docstring -# C0302: Too many lines in module (NN) -# R0902: Too many instance attributes (N/7) -# R0903: Too few public methods (N/2) -# R0904: Too many public methods (NN/20) -# R0912: Too many branches (NN/12) -# R0913: Too many arguments (N/5) -# R0914: Too many local variables (NN/15) -# R0915: Too many statements (NN/50) -# W0141: Used builtin function 'map' -# W0142: Used * or ** magic -# W0232: Class has no __init__ method -# W0511: TODO -# W0603: Using the global statement -# -# These should be enabled eventually: -# C0112: Empty docstring -# C0301: Line too long (NN/80) -# C0321: More than one statement on single line -# C0322: Operator not preceded by a space -# C0323: Operator not followed by a space -# C0324: Comma not followed by a space -# E0101: Explicit return in __init__ -# E0102: function already defined line NN -# E1002: Use of super on an old style class -# E1101: Instance of 'XX' has no 'YY' member -# E1103: Instance of 'XX' has no 'XX' member (but some types could not be inferred) -# E0602: Undefined variable 'XX' -# F0401: Unable to import 'XX' -# R0201: Method could be a function -# R0801: Similar lines in N files -# W0102: Dangerous default value {} as argument -# W0104: Statement seems to have no effect -# W0105: String statement has no effect -# W0108: Lambda may not be necessary -# W0201: Attribute 'XX' defined outside __init__ -# W0212: Access to a protected member XX of a client class -# W0221: Arguments number differs from overridden method -# W0223: Method 'XX' is abstract in class 'YY' but is not overridden -# W0231: __init__ method from base class 'XX' is not called -# W0301: Unnecessary semicolon -# W0311: Bad indentation. Found NN spaces, expected NN -# W0401: Wildcard import XX -# W0402: Uses of a deprecated module 'string' -# W0403: Relative import 'XX', should be 'YY.XX' -# W0404: Reimport 'XX' (imported line NN) -# W0601: Global variable 'XX' undefined at the module level -# W0602: Using global for 'XX' but no assignment is done -# W0611: Unused import pprint -# W0612: Unused variable 'XX' -# W0613: Unused argument 'XX' -# W0614: Unused import XX from wildcard import -# W0621: Redefining name 'XX' from outer scope (line NN) -# W0622: Redefining built-in 'NN' -# W0631: Using possibly undefined loop variable 'XX' -# W0701: Raising a string exception -# W0702: No exception type(s) specified -disable=C0103,C0111,C0302,R0902,R0903,R0904,R0912,R0913,R0914,R0915,W0141,W0142,W0232,W0511,W0603,C0112,C0301,C0321,C0322,C0323,C0324,E0101,E0102,E1002,E1101,E1103,E0602,F0401,R0201,R0801,W0102,W0104,W0105,W0108,W0201,W0212,W0221,W0223,W0231,W0301,W0311,W0401,W0402,W0403,W0404,W0601,W0602,W0611,W0612,W0613,W0614,W0621,W0622,W0631,W0701,W0702 - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html -output-format=text - -# Include message's id in output -include-ids=yes - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=no - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (RP0004). -comment=no - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching the beginning of the name of dummy variables -# (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=80 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff -Nru gyp-0.1~svn1729/README.md gyp-0.1+20150913git1f374df9/README.md --- gyp-0.1~svn1729/README.md 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/README.md 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +GYP can Generate Your Projects. + +Mailing list: http://groups.google.com/group/gyp-developer + +* [User documentation](/docs/UserDocumentation.md) +* [Input Format Reference](/docs/InputFormatReference.md) +* [Language specification](/docs/LanguageSpecification.md) +* [GYP Hacking](/docs/Hacking.md) +* [GYP Testing](/docs/Testing.md) +* [GYP vs. CMake](/docs/GypVsCMake.md) +* [Source](/docs/Source.md) +* [Buildbot](/docs/Buildbot.md) diff -Nru gyp-0.1~svn1729/setup.py gyp-0.1+20150913git1f374df9/setup.py --- gyp-0.1~svn1729/setup.py 2013-09-04 17:51:09.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/setup.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,8 +4,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from ez_setup import use_setuptools -use_setuptools() from setuptools import setup setup( diff -Nru gyp-0.1~svn1729/test/actions/gyptest-all.py gyp-0.1+20150913git1f374df9/test/actions/gyptest-all.py --- gyp-0.1~svn1729/test/actions/gyptest-all.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -22,8 +22,7 @@ # writes it as a means to making the action run on every build. That # doesn't mesh well with ninja's semantics. TODO(evan): figure out # how to work always-run actions in to ninja. -# Android also can't do this as it doesn't have order-only dependencies. -if test.format in ['ninja', 'android']: +if test.format in ['ninja', 'xcode-ninja']: test.build('actions.gyp', test.ALL, chdir='relocate/src') else: # Test that an "always run" action increases a counter on multiple diff -Nru gyp-0.1~svn1729/test/actions/gyptest-default.py gyp-0.1+20150913git1f374df9/test/actions/gyptest-default.py --- gyp-0.1~svn1729/test/actions/gyptest-default.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions/gyptest-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -20,8 +20,7 @@ # writes it as a means to making the action run on every build. That # doesn't mesh well with ninja's semantics. TODO(evan): figure out # how to work always-run actions in to ninja. -# Android also can't do this as it doesn't have order-only dependencies. -if test.format in ['ninja', 'android']: +if test.format in ['ninja', 'xcode-ninja']: test.build('actions.gyp', test.ALL, chdir='relocate/src') else: # Test that an "always run" action increases a counter on multiple diff -Nru gyp-0.1~svn1729/test/actions/src/subdir1/program.c gyp-0.1+20150913git1f374df9/test/actions/src/subdir1/program.c --- gyp-0.1~svn1729/test/actions/src/subdir1/program.c 2009-09-10 20:42:24.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions/src/subdir1/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -3,7 +3,7 @@ extern void prog1(void); extern void prog2(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from program.c\n"); prog1(); diff -Nru gyp-0.1~svn1729/test/actions/src/subdir3/generate_main.py gyp-0.1+20150913git1f374df9/test/actions/src/subdir3/generate_main.py --- gyp-0.1~svn1729/test/actions/src/subdir3/generate_main.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions/src/subdir3/generate_main.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,7 +9,7 @@ contents = """ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from generate_main.py\\n"); return 0; diff -Nru gyp-0.1~svn1729/test/actions-bare/gyptest-bare.py gyp-0.1+20150913git1f374df9/test/actions-bare/gyptest-bare.py --- gyp-0.1~svn1729/test/actions-bare/gyptest-bare.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-bare/gyptest-bare.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,7 @@ test = TestGyp.TestGyp() test.run_gyp('bare.gyp', chdir='src') + test.relocate('src', 'relocate/src') test.build('bare.gyp', chdir='relocate/src') diff -Nru gyp-0.1~svn1729/test/actions-depfile/depfile.gyp gyp-0.1+20150913git1f374df9/test/actions-depfile/depfile.gyp --- gyp-0.1~svn1729/test/actions-depfile/depfile.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-depfile/depfile.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'depfile_target', + 'type': 'none', + 'actions': [ + { + 'action_name': 'depfile_action', + 'inputs': [ + 'input.txt', + ], + 'outputs': [ + 'output.txt', + ], + 'depfile': 'depfile.d', + 'action': [ ] + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/actions-depfile/gyptest-all.py gyp-0.1+20150913git1f374df9/test/actions-depfile/gyptest-all.py --- gyp-0.1~svn1729/test/actions-depfile/gyptest-all.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-depfile/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Verifies that depfile fields are output in ninja rules.""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'ninja': + test.run_gyp('depfile.gyp') + contents = open(test.built_file_path('obj/depfile_target.ninja')).read() + + expected = 'depfile = depfile.d' + if expected not in contents: + test.fail_test() + test.pass_test() diff -Nru gyp-0.1~svn1729/test/actions-depfile/input.txt gyp-0.1+20150913git1f374df9/test/actions-depfile/input.txt --- gyp-0.1~svn1729/test/actions-depfile/input.txt 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-depfile/input.txt 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +input diff -Nru gyp-0.1~svn1729/test/actions-multiple-outputs/gyptest-multiple-outputs.py gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs/gyptest-multiple-outputs.py --- gyp-0.1~svn1729/test/actions-multiple-outputs/gyptest-multiple-outputs.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs/gyptest-multiple-outputs.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies actions with multiple outputs will correctly rebuild. +""" + +import TestGyp +import os +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + +test = TestGyp.TestGyp() + +test.run_gyp('multiple-outputs.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +def build_and_check(): + # Build + check that both outputs exist. + test.build('multiple-outputs.gyp', chdir=chdir) + test.built_file_must_exist('out1.txt', chdir=chdir) + test.built_file_must_exist('out2.txt', chdir=chdir) + +# Plain build. +build_and_check() + +# Remove either + rebuild. Both should exist (again). +os.remove(test.built_file_path('out1.txt', chdir=chdir)) +build_and_check(); + +# Remove the other + rebuild. Both should exist (again). +os.remove(test.built_file_path('out2.txt', chdir=chdir)) +build_and_check(); + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/actions-multiple-outputs/src/multiple-outputs.gyp gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs/src/multiple-outputs.gyp --- gyp-0.1~svn1729/test/actions-multiple-outputs/src/multiple-outputs.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs/src/multiple-outputs.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'multiple-outputs', + 'type': 'none', + 'actions': [ + { + 'action_name': 'action1', + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/out1.txt', + '<(PRODUCT_DIR)/out2.txt', + ], + 'action': ['python', 'touch.py', '<@(_outputs)'], + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/actions-multiple-outputs/src/touch.py gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs/src/touch.py --- gyp-0.1~svn1729/test/actions-multiple-outputs/src/touch.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs/src/touch.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import sys + +"""Cross-platform touch.""" + +for fname in sys.argv[1:]: + if os.path.exists(fname): + os.utime(fname, None) + else: + open(fname, 'w').close() diff -Nru gyp-0.1~svn1729/test/actions-multiple-outputs-with-dependencies/gyptest-action.py gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs-with-dependencies/gyptest-action.py --- gyp-0.1~svn1729/test/actions-multiple-outputs-with-dependencies/gyptest-action.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs-with-dependencies/gyptest-action.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies actions with multiple outputs & dependncies will correctly rebuild. + +This is a regression test for crrev.com/1177163002. +""" + +import TestGyp +import os +import sys +import time + +if sys.platform in ('darwin', 'win32'): + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + +test = TestGyp.TestGyp() + +TESTDIR='relocate/src' +test.run_gyp('action.gyp', chdir='src') +test.relocate('src', TESTDIR) + +def build_and_check(content): + test.write(TESTDIR + '/input.txt', content) + test.build('action.gyp', 'upper', chdir=TESTDIR) + test.built_file_must_match('result.txt', content, chdir=TESTDIR) + +build_and_check('Content for first build.') + +# Ninja works with timestamps and the test above is fast enough that the +# 'updated' file may end up with the same timestamp as the original, meaning +# that ninja may not always recognize the input file has changed. +if test.format == 'ninja': + time.sleep(1) + +build_and_check('An updated input file.') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/actions-multiple-outputs-with-dependencies/src/action.gyp gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs-with-dependencies/src/action.gyp --- gyp-0.1~svn1729/test/actions-multiple-outputs-with-dependencies/src/action.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs-with-dependencies/src/action.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,28 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'upper', + 'type': 'none', + 'actions': [{ + 'action_name': 'upper_action', + 'inputs': ['<(PRODUCT_DIR)/out2.txt'], + 'outputs': ['<(PRODUCT_DIR)/result.txt'], + 'action': ['python', 'rcopy.py', '<@(_inputs)', '<@(_outputs)'], + }], + }, + { + 'target_name': 'lower', + 'type': 'none', + 'actions': [{ + 'action_name': 'lower_action', + 'inputs': ['input.txt'], + 'outputs': ['<(PRODUCT_DIR)/out1.txt', '<(PRODUCT_DIR)/out2.txt'], + 'action': ['python', 'rcopy.py', '<@(_inputs)', '<@(_outputs)'], + }], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/actions-multiple-outputs-with-dependencies/src/rcopy.py gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs-with-dependencies/src/rcopy.py --- gyp-0.1~svn1729/test/actions-multiple-outputs-with-dependencies/src/rcopy.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-multiple-outputs-with-dependencies/src/rcopy.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import sys + +"""A slightly odd 'cp' implementation for this test. + +This 'cp' can have many targets, but only one source. 'cp src dest1 dest2' +will copy the file 'src' to both 'dest1' and 'dest2'.""" + +with open(sys.argv[1], 'r') as f: + src = f.read() +for dest in sys.argv[2:]: + with open(dest, 'w') as f: + f.write(src) + diff -Nru gyp-0.1~svn1729/test/actions-none/gyptest-none.py gyp-0.1+20150913git1f374df9/test/actions-none/gyptest-none.py --- gyp-0.1~svn1729/test/actions-none/gyptest-none.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/actions-none/gyptest-none.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,7 @@ test = TestGyp.TestGyp() test.run_gyp('none_with_source_files.gyp', chdir='src') + test.relocate('src', 'relocate/src') test.build('none_with_source_files.gyp', chdir='relocate/src') diff -Nru gyp-0.1~svn1729/test/additional-targets/gyptest-additional.py gyp-0.1+20150913git1f374df9/test/additional-targets/gyptest-additional.py --- gyp-0.1~svn1729/test/additional-targets/gyptest-additional.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/additional-targets/gyptest-additional.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,7 +12,10 @@ test = TestGyp.TestGyp() -test.run_gyp('all.gyp', chdir='src') +test.run_gyp('all.gyp', + '-G', 'xcode_ninja_target_pattern=^all_targets$', + chdir='src') + test.relocate('src', 'relocate/src') # Build all. @@ -32,8 +35,12 @@ type=test.SHARED_LIB, chdir=chdir) +# xcode-ninja doesn't generate separate workspaces for sub-gyps by design +if test.format == 'xcode-ninja': + test.pass_test() + # TODO(mmoss) Make consistent with msvs, with 'dir1' before 'out/Default'? -if test.format in ('make', 'ninja', 'android'): +if test.format in ('make', 'ninja', 'cmake'): chdir='relocate/src' else: chdir='relocate/src/dir1' diff -Nru gyp-0.1~svn1729/test/analyzer/common.gypi gyp-0.1+20150913git1f374df9/test/analyzer/common.gypi --- gyp-0.1~svn1729/test/analyzer/common.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/common.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ +} diff -Nru gyp-0.1~svn1729/test/analyzer/gyptest-analyzer.py gyp-0.1+20150913git1f374df9/test/analyzer/gyptest-analyzer.py --- gyp-0.1~svn1729/test/analyzer/gyptest-analyzer.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/gyptest-analyzer.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,369 @@ +#!/usr/bin/env python +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Tests for analyzer +""" + +import json +import TestGyp + +found = 'Found dependency' +found_all = 'Found dependency (all)' +not_found = 'No dependencies' + + +def _CreateConfigFile(files, targets): + """Creates the analyzer config file, which is used as the input to analyzer. + See description of analyzer.py for description of the arguments.""" + f = open('test_file', 'w') + to_write = {'files': files, 'targets': targets } + json.dump(to_write, f) + f.close() + + +def _CreateBogusConfigFile(): + f = open('test_file','w') + f.write('bogus') + f.close() + + +def _ReadOutputFileContents(): + f = open('analyzer_output', 'r') + result = json.load(f) + f.close() + return result + + +# NOTE: this would be clearer if it subclassed TestGypCustom, but that trips +# over a bug in pylint (E1002). +test = TestGyp.TestGypCustom(format='analyzer') + +def CommonArgs(): + return ('-Gconfig_path=test_file', + '-Ganalyzer_output_path=analyzer_output') + + +def run_analyzer(*args, **kw): + """Runs the test specifying a particular config and output path.""" + args += CommonArgs() + test.run_gyp('test.gyp', *args, **kw) + + +def run_analyzer2(*args, **kw): + """Same as run_analyzer(), but passes in test2.gyp instead of test.gyp.""" + args += CommonArgs() + test.run_gyp('test2.gyp', *args, **kw) + + +def run_analyzer3(*args, **kw): + """Same as run_analyzer(), but passes in test3.gyp instead of test.gyp.""" + args += CommonArgs() + test.run_gyp('test3.gyp', *args, **kw) + + +def run_analyzer4(*args, **kw): + """Same as run_analyzer(), but passes in test3.gyp instead of test.gyp.""" + args += CommonArgs() + test.run_gyp('test4.gyp', *args, **kw) + + +def EnsureContains(targets=set(), matched=False, build_targets=set()): + """Verifies output contains |targets|.""" + result = _ReadOutputFileContents() + if result.get('error', None): + print 'unexpected error', result.get('error') + test.fail_test() + + if result.get('invalid_targets', None): + print 'unexpected invalid_targets', result.get('invalid_targets') + test.fail_test() + + actual_targets = set(result['targets']) + if actual_targets != targets: + print 'actual targets:', actual_targets, '\nexpected targets:', targets + test.fail_test() + + actual_build_targets = set(result['build_targets']) + if actual_build_targets != build_targets: + print 'actual build_targets:', actual_build_targets, \ + '\nexpected build_targets:', build_targets + test.fail_test() + + if matched and result['status'] != found: + print 'expected', found, 'got', result['status'] + test.fail_test() + elif not matched and result['status'] != not_found: + print 'expected', not_found, 'got', result['status'] + test.fail_test() + + +def EnsureMatchedAll(targets): + result = _ReadOutputFileContents() + if result.get('error', None): + print 'unexpected error', result.get('error') + test.fail_test() + + if result.get('invalid_targets', None): + print 'unexpected invalid_targets', result.get('invalid_targets') + test.fail_test() + + if result['status'] != found_all: + print 'expected', found_all, 'got', result['status'] + test.fail_test() + + actual_targets = set(result['targets']) + if actual_targets != targets: + print 'actual targets:', actual_targets, '\nexpected targets:', targets + test.fail_test() + + +def EnsureError(expected_error_string): + """Verifies output contains the error string.""" + result = _ReadOutputFileContents() + if result.get('error', '').find(expected_error_string) == -1: + print 'actual error:', result.get('error', ''), '\nexpected error:', \ + expected_error_string + test.fail_test() + + +def EnsureStdoutContains(expected_error_string): + if test.stdout().find(expected_error_string) == -1: + print 'actual stdout:', test.stdout(), '\nexpected stdout:', \ + expected_error_string + test.fail_test() + + +def EnsureInvalidTargets(expected_invalid_targets): + """Verifies output contains invalid_targets.""" + result = _ReadOutputFileContents() + actual_invalid_targets = set(result['invalid_targets']) + if actual_invalid_targets != expected_invalid_targets: + print 'actual invalid_targets:', actual_invalid_targets, \ + '\nexpected :', expected_invalid_targets + test.fail_test() + + +# Two targets, A and B (both static_libraries) and A depends upon B. If a file +# in B changes, then both A and B are output. It is not strictly necessary that +# A is compiled in this case, only B. +_CreateConfigFile(['b.c'], []) +test.run_gyp('static_library_test.gyp', *CommonArgs()) +EnsureContains(matched=True, build_targets={'a' ,'b'}) + +# Verifies config_path must be specified. +test.run_gyp('test.gyp') +EnsureStdoutContains('Must specify files to analyze via config_path') + +# Verifies config_path must point to a valid file. +test.run_gyp('test.gyp', '-Gconfig_path=bogus_file', + '-Ganalyzer_output_path=analyzer_output') +EnsureError('Unable to open file bogus_file') + +# Verify 'invalid_targets' is present when bad target is specified. +_CreateConfigFile(['exe2.c'], ['bad_target']) +run_analyzer() +EnsureInvalidTargets({'bad_target'}) + +# Verifies config_path must point to a valid json file. +_CreateBogusConfigFile() +run_analyzer() +EnsureError('Unable to parse config file test_file') + +# Trivial test of a source. +_CreateConfigFile(['foo.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Conditional source that is excluded. +_CreateConfigFile(['conditional_source.c'], []) +run_analyzer() +EnsureContains(matched=False) + +# Conditional source that is included by way of argument. +_CreateConfigFile(['conditional_source.c'], []) +run_analyzer('-Dtest_variable=1') +EnsureContains(matched=True, build_targets={'exe'}) + +# Two unknown files. +_CreateConfigFile(['unknown1.c', 'unoknow2.cc'], []) +run_analyzer() +EnsureContains() + +# Two unknown files. +_CreateConfigFile(['unknown1.c', 'subdir/subdir_sourcex.c'], []) +run_analyzer() +EnsureContains() + +# Included dependency +_CreateConfigFile(['unknown1.c', 'subdir/subdir_source.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe', 'exe3'}) + +# Included inputs to actions. +_CreateConfigFile(['action_input.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Don't consider outputs. +_CreateConfigFile(['action_output.c'], []) +run_analyzer() +EnsureContains(matched=False) + +# Rule inputs. +_CreateConfigFile(['rule_input.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Ignore path specified with PRODUCT_DIR. +_CreateConfigFile(['product_dir_input.c'], []) +run_analyzer() +EnsureContains(matched=False) + +# Path specified via a variable. +_CreateConfigFile(['subdir/subdir_source2.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Verifies paths with // are fixed up correctly. +_CreateConfigFile(['parent_source.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe', 'exe3'}) + +# Verifies relative paths are resolved correctly. +_CreateConfigFile(['subdir/subdir_source.h'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Verifies relative paths in inputs are resolved correctly. +_CreateConfigFile(['rel_path1.h'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Various permutations when passing in targets. +_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['exe', 'exe3']) +run_analyzer() +EnsureContains(matched=True, targets={'exe3'}, build_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['exe']) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe2', 'exe3'}) + +# Verifies duplicates are ignored. +_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['exe', 'exe']) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['exe2.c'], ['exe']) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe2'}) + +_CreateConfigFile(['exe2.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe2'}) + +_CreateConfigFile(['subdir/subdir2b_source.c', 'exe2.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe2', 'exe3'}) + +_CreateConfigFile(['subdir/subdir2b_source.c'], ['exe3']) +run_analyzer() +EnsureContains(matched=True, targets={'exe3'}, build_targets={'exe3'}) + +_CreateConfigFile(['exe2.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe2'}) + +_CreateConfigFile(['foo.c'], []) +run_analyzer() +EnsureContains(matched=True, build_targets={'exe'}) + +# Assertions when modifying build (gyp/gypi) files, especially when said files +# are included. +_CreateConfigFile(['subdir2/d.cc'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, targets={'exe', 'foo'}, build_targets={'exe'}) + +_CreateConfigFile(['subdir2/subdir.includes.gypi'], + ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, targets={'exe', 'foo'}, build_targets={'exe'}) + +_CreateConfigFile(['subdir2/subdir.gyp'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, targets={'exe', 'foo'}, build_targets={'exe'}) + +_CreateConfigFile(['test2.includes.gypi'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2() +EnsureContains(matched=True, targets={'exe', 'exe2', 'exe3'}, + build_targets={'exe', 'exe2', 'exe3'}) + +# Verify modifying a file included makes all targets dirty. +_CreateConfigFile(['common.gypi'], ['exe', 'exe2', 'foo', 'exe3']) +run_analyzer2('-Icommon.gypi') +EnsureMatchedAll({'exe', 'exe2', 'foo', 'exe3'}) + +# Assertions from test3.gyp. +_CreateConfigFile(['d.c', 'f.c'], ['a']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a', 'b'}) + +_CreateConfigFile(['f.c'], ['a']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a', 'b'}) + +_CreateConfigFile(['f.c'], []) +run_analyzer3() +EnsureContains(matched=True, build_targets={'a', 'b'}) + +_CreateConfigFile(['c.c', 'e.c'], []) +run_analyzer3() +EnsureContains(matched=True, build_targets={'a', 'b', 'c', 'e'}) + +_CreateConfigFile(['d.c'], ['a']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a', 'b'}) + +_CreateConfigFile(['a.c'], ['a', 'b']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a'}) + +_CreateConfigFile(['a.c'], ['a', 'b']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a'}) + +_CreateConfigFile(['d.c'], ['a', 'b']) +run_analyzer3() +EnsureContains(matched=True, targets={'a', 'b'}, build_targets={'a', 'b'}) + +_CreateConfigFile(['f.c'], ['a']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a', 'b'}) + +_CreateConfigFile(['a.c'], ['a']) +run_analyzer3() +EnsureContains(matched=True, targets={'a'}, build_targets={'a'}) + +_CreateConfigFile(['a.c'], []) +run_analyzer3() +EnsureContains(matched=True, build_targets={'a'}) + +_CreateConfigFile(['d.c'], []) +run_analyzer3() +EnsureContains(matched=True, build_targets={'a', 'b'}) + +# Assertions around test4.gyp. +_CreateConfigFile(['f.c'], []) +run_analyzer4() +EnsureContains(matched=True, build_targets={'e', 'f'}) + +_CreateConfigFile(['d.c'], []) +run_analyzer4() +EnsureContains(matched=True, build_targets={'a', 'b', 'c', 'd'}) + +_CreateConfigFile(['i.c'], []) +run_analyzer4() +EnsureContains(matched=True, build_targets={'h', 'i'}) + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/analyzer/static_library_test.gyp gyp-0.1+20150913git1f374df9/test/analyzer/static_library_test.gyp --- gyp-0.1~svn1729/test/analyzer/static_library_test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/static_library_test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,34 @@ +# Copyright 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# These gyp files create the following dependencies: +# +# test.gyp: +# #a -> b +# a.c +# #b +# b.c +# a and b are static libraries. + +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + 'dependencies': [ + 'b', + ], + }, + { + 'target_name': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/subdir/subdir2/subdir2.gyp gyp-0.1+20150913git1f374df9/test/analyzer/subdir/subdir2/subdir2.gyp --- gyp-0.1~svn1729/test/analyzer/subdir/subdir2/subdir2.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/subdir/subdir2/subdir2.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,15 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'subdir2', + 'type': 'static_library', + 'sources': [ + '../subdir_source.h', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/subdir/subdir.gyp gyp-0.1+20150913git1f374df9/test/analyzer/subdir/subdir.gyp --- gyp-0.1~svn1729/test/analyzer/subdir/subdir.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/subdir/subdir.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,36 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'trailing_dir_path': '../', + }, + 'targets': [ + { + 'target_name': 'foo', + 'type': 'static_library', + 'sources': [ + 'subdir_source.c', + '<(trailing_dir_path)/parent_source.c', + ], + }, + { + 'target_name': 'subdir2a', + 'type': 'static_library', + 'sources': [ + 'subdir2_source.c', + ], + 'dependencies': [ + 'subdir2b', + ], + }, + { + 'target_name': 'subdir2b', + 'type': 'static_library', + 'sources': [ + 'subdir2b_source.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/subdir2/subdir.gyp gyp-0.1+20150913git1f374df9/test/analyzer/subdir2/subdir.gyp --- gyp-0.1~svn1729/test/analyzer/subdir2/subdir.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/subdir2/subdir.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,18 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'foo', + 'type': 'static_library', + 'sources': [ + 'subdir_source.c', + ], + 'includes': [ + 'subdir.includes.gypi', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/subdir2/subdir.includes.gypi gyp-0.1+20150913git1f374df9/test/analyzer/subdir2/subdir.includes.gypi --- gyp-0.1~svn1729/test/analyzer/subdir2/subdir.includes.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/subdir2/subdir.includes.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'sources': [ + 'd.cc' + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test2.gyp gyp-0.1+20150913git1f374df9/test/analyzer/test2.gyp --- gyp-0.1~svn1729/test/analyzer/test2.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test2.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'exe', + 'type': 'executable', + 'dependencies': [ + 'subdir2/subdir.gyp:foo', + ], + }, + { + 'target_name': 'exe2', + 'type': 'executable', + 'includes': [ + 'test2.includes.gypi', + ], + }, + ], + 'includes': [ + 'test2.toplevel_includes.gypi', + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test2.includes.gypi gyp-0.1+20150913git1f374df9/test/analyzer/test2.includes.gypi --- gyp-0.1~svn1729/test/analyzer/test2.includes.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test2.includes.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'sources': [ + 'a.cc', + 'b.cc' + ], + 'includes': [ + 'test2.includes.includes.gypi', + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test2.includes.includes.gypi gyp-0.1+20150913git1f374df9/test/analyzer/test2.includes.includes.gypi --- gyp-0.1~svn1729/test/analyzer/test2.includes.includes.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test2.includes.includes.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'sources': [ + 'c.cc' + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test2.toplevel_includes.gypi gyp-0.1+20150913git1f374df9/test/analyzer/test2.toplevel_includes.gypi --- gyp-0.1~svn1729/test/analyzer/test2.toplevel_includes.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test2.toplevel_includes.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,15 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'exe3', + 'type': 'executable', + 'sources': [ + 'e.cc', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test3.gyp gyp-0.1+20150913git1f374df9/test/analyzer/test3.gyp --- gyp-0.1~svn1729/test/analyzer/test3.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test3.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,77 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'all', + 'type': 'none', + 'dependencies': [ + 'a', + 'b', + ], + }, + { + 'target_name': 'a', + 'type': 'executable', + 'sources': [ + 'a.c', + ], + 'dependencies': [ + 'c', + 'd', + ], + }, + { + 'target_name': 'b', + 'type': 'executable', + 'sources': [ + 'b.c', + ], + 'dependencies': [ + 'd', + 'e', + ], + }, + { + 'target_name': 'c', + 'type': 'executable', + 'sources': [ + 'c.c', + ], + }, + { + 'target_name': 'd', + 'type': 'none', + 'sources': [ + 'd.c', + ], + 'dependencies': [ + 'f', + 'g', + ], + }, + { + 'target_name': 'e', + 'type': 'executable', + 'sources': [ + 'e.c', + ], + }, + { + 'target_name': 'f', + 'type': 'static_library', + 'sources': [ + 'f.c', + ], + }, + { + 'target_name': 'g', + 'type': 'executable', + 'sources': [ + 'g.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test4.gyp gyp-0.1+20150913git1f374df9/test/analyzer/test4.gyp --- gyp-0.1~svn1729/test/analyzer/test4.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test4.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,80 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'executable', + 'sources': [ + 'a.c', + ], + 'dependencies': [ + 'b', + 'c', + ], + }, + { + 'target_name': 'b', + 'type': 'executable', + 'sources': [ + 'b.c', + ], + 'dependencies': [ + 'd', + ], + }, + { + 'target_name': 'c', + 'type': 'executable', + 'sources': [ + 'c.c', + ], + 'dependencies': [ + 'b', + 'd', + ], + }, + { + 'target_name': 'd', + 'type': 'executable', + 'sources': [ + 'd.c', + ], + }, + { + 'target_name': 'e', + 'type': 'executable', + 'dependencies': [ + 'test5.gyp:f', + ], + }, + { + 'target_name': 'h', + 'type': 'none', + 'dependencies': [ + 'i', + ], + 'rules': [ + { + 'rule_name': 'rule', + 'extension': 'pdf', + 'inputs': [ + 'rule_input.c', + ], + 'outputs': [ + 'rule_output.pdf', + ], + }, + ], + }, + { + 'target_name': 'i', + 'type': 'static_library', + 'sources': [ + 'i.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test5.gyp gyp-0.1+20150913git1f374df9/test/analyzer/test5.gyp --- gyp-0.1~svn1729/test/analyzer/test5.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test5.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'f', + 'type': 'executable', + 'sources': [ + 'f.c', + ], + }, + { + 'target_name': 'g', + 'type': 'executable', + 'sources': [ + 'g.c', + ], + 'dependencies': [ + 'f', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/analyzer/test.gyp gyp-0.1+20150913git1f374df9/test/analyzer/test.gyp --- gyp-0.1~svn1729/test/analyzer/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/analyzer/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,114 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# These gyp files create the following dependencies: +# +# test.gyp: +# #exe -> subdir/subdir.gyp#foo, subdir/subdir2/subdir2.gyp#subdir2 +# foo.c +# subdir/subdir_source2.c +# conditional_source.c (if test_variable==1) +# action_input.c +# action_output.c +# rule_input.c +# rule_output.pdf +# #exe2 +# exe2.c +# #exe3 -> subdir/subdir.gyp#foo, subdir/subdir.gyp#subdir2a +# exe3.c +# #all (type none) -> exe, exe3 +# +# subdir/subdir.gyp +# #foo +# subdir/subdir_source.c +# parent_source.c +# #subdir2a -> subdir2b +# subdir/subdir2_source.c +# #subdir2b +# subdir/subdir2b_source.c +# +# subdir/subdir2/subdir2.gyp +# #subdir2 +# subdir/subdir_source.h + +{ + 'variables': { + 'test_variable%': 0, + 'variable_path': 'subdir', + }, + 'targets': [ + { + 'target_name': 'exe', + 'type': 'executable', + 'dependencies': [ + 'subdir/subdir.gyp:foo', + 'subdir/subdir2/subdir2.gyp:subdir2', + ], + 'sources': [ + 'foo.c', + '<(variable_path)/subdir_source2.c', + ], + 'conditions': [ + ['test_variable==1', { + 'sources': [ + 'conditional_source.c', + ], + }], + ], + 'actions': [ + { + 'action_name': 'action', + 'inputs': [ + '<(PRODUCT_DIR)/product_dir_input.c', + 'action_input.c', + '../bad_path1.h', + '../../bad_path2.h', + './rel_path1.h', + ], + 'outputs': [ + 'action_output.c', + ], + }, + ], + 'rules': [ + { + 'rule_name': 'rule', + 'extension': 'pdf', + 'inputs': [ + 'rule_input.c', + ], + 'outputs': [ + 'rule_output.pdf', + ], + }, + ], + }, + { + 'target_name': 'exe2', + 'type': 'executable', + 'sources': [ + 'exe2.c', + ], + }, + { + 'target_name': 'exe3', + 'type': 'executable', + 'dependencies': [ + 'subdir/subdir.gyp:foo', + 'subdir/subdir.gyp:subdir2a', + ], + 'sources': [ + 'exe3.c', + ], + }, + { + 'target_name': 'all', + 'type': 'none', + 'dependencies': [ + 'exe', + 'exe3', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/arflags/gyptest-arflags.py gyp-0.1+20150913git1f374df9/test/arflags/gyptest-arflags.py --- gyp-0.1~svn1729/test/arflags/gyptest-arflags.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/arflags/gyptest-arflags.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that building a target with invalid arflags fails. +""" + +import os +import sys +import TestGyp + +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + +test = TestGyp.TestGyp(formats=['ninja']) +test.run_gyp('test.gyp') +expected_status = 0 if sys.platform in ['darwin', 'win32'] else 1 +test.build('test.gyp', target='lib', status=expected_status) +test.pass_test() diff -Nru gyp-0.1~svn1729/test/arflags/test.gyp gyp-0.1+20150913git1f374df9/test/arflags/test.gyp --- gyp-0.1~svn1729/test/arflags/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/arflags/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +{ + 'targets': [ + { + 'target_name': 'lib', + 'type': 'static_library', + 'sources': ['lib.cc'], + 'arflags': ['--nonexistent'], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/assembly/src/program.c gyp-0.1+20150913git1f374df9/test/assembly/src/program.c --- gyp-0.1~svn1729/test/assembly/src/program.c 2009-09-29 22:36:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/assembly/src/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern int lib1_function(void); -int main(int argc, char *argv[]) +int main(void) { fprintf(stdout, "Hello from program.c\n"); fflush(stdout); diff -Nru gyp-0.1~svn1729/test/builddir/gyptest-all.py gyp-0.1+20150913git1f374df9/test/builddir/gyptest-all.py --- gyp-0.1~svn1729/test/builddir/gyptest-all.py 2012-12-26 16:49:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -23,9 +23,8 @@ # its sources. I'm not sure if make is wrong for writing outside the current # directory, or if the test is wrong for assuming everything generated is under # the current directory. -# Android does not support setting the build directory. -# Ninja does not support relocation. -test = TestGyp.TestGyp(formats=['!make', '!ninja', '!android']) +# Ninja and CMake do not support setting the build directory. +test = TestGyp.TestGyp(formats=['!make', '!ninja', '!cmake']) test.run_gyp('prog1.gyp', '--depth=..', chdir='src') if test.format == 'msvs': diff -Nru gyp-0.1~svn1729/test/builddir/gyptest-default.py gyp-0.1+20150913git1f374df9/test/builddir/gyptest-default.py --- gyp-0.1~svn1729/test/builddir/gyptest-default.py 2012-12-26 16:49:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/gyptest-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -23,9 +23,8 @@ # its sources. I'm not sure if make is wrong for writing outside the current # directory, or if the test is wrong for assuming everything generated is under # the current directory. -# Android does not support setting the build directory. -# Ninja does not support relocation. -test = TestGyp.TestGyp(formats=['!make', '!ninja', '!android']) +# Ninja and CMake do not support setting the build directory. +test = TestGyp.TestGyp(formats=['!make', '!ninja', '!cmake']) test.run_gyp('prog1.gyp', '--depth=..', chdir='src') if test.format == 'msvs': diff -Nru gyp-0.1~svn1729/test/builddir/src/prog1.c gyp-0.1+20150913git1f374df9/test/builddir/src/prog1.c --- gyp-0.1~svn1729/test/builddir/src/prog1.c 2009-09-11 18:20:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/src/prog1.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func1(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog1.c\n"); func1(); diff -Nru gyp-0.1~svn1729/test/builddir/src/subdir2/prog2.c gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/prog2.c --- gyp-0.1~svn1729/test/builddir/src/subdir2/prog2.c 2009-09-11 18:20:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func2(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from subdir2/prog2.c\n"); func2(); diff -Nru gyp-0.1~svn1729/test/builddir/src/subdir2/subdir3/prog3.c gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/subdir3/prog3.c --- gyp-0.1~svn1729/test/builddir/src/subdir2/subdir3/prog3.c 2009-09-11 18:20:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/subdir3/prog3.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func3(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from subdir2/subdir3/prog3.c\n"); func3(); diff -Nru gyp-0.1~svn1729/test/builddir/src/subdir2/subdir3/subdir4/prog4.c gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/subdir3/subdir4/prog4.c --- gyp-0.1~svn1729/test/builddir/src/subdir2/subdir3/subdir4/prog4.c 2009-09-11 18:20:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/subdir3/subdir4/prog4.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func4(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from subdir2/subdir3/subdir4/prog4.c\n"); func4(); diff -Nru gyp-0.1~svn1729/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c --- gyp-0.1~svn1729/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c 2009-09-11 18:20:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func5(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from subdir2/subdir3/subdir4/subdir5/prog5.c\n"); func5(); diff -Nru gyp-0.1~svn1729/test/build-option/gyptest-build.py gyp-0.1+20150913git1f374df9/test/build-option/gyptest-build.py --- gyp-0.1~svn1729/test/build-option/gyptest-build.py 2012-09-18 18:05:05.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/build-option/gyptest-build.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,11 @@ test = TestGyp.TestGyp(workdir='workarea_default') +if test.format == 'xcode-ninja': + # The xcode-ninja generator doesn't support --build + # cf. https://code.google.com/p/gyp/issues/detail?id=453 + test.skip_test() + test.run_gyp('hello.gyp', '--build=Default') test.run_built_executable('hello', stdout="Hello, world!\n") diff -Nru gyp-0.1~svn1729/test/build-option/hello.c gyp-0.1+20150913git1f374df9/test/build-option/hello.c --- gyp-0.1~svn1729/test/build-option/hello.c 2012-09-18 18:05:05.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/build-option/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello, world!\n"); return 0; diff -Nru gyp-0.1~svn1729/test/cflags/cflags.c gyp-0.1+20150913git1f374df9/test/cflags/cflags.c --- gyp-0.1~svn1729/test/cflags/cflags.c 2013-08-19 23:12:57.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/cflags/cflags.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { #ifdef FOO printf("FOO defined\n"); diff -Nru gyp-0.1~svn1729/test/cflags/gyptest-cflags.py gyp-0.1+20150913git1f374df9/test/cflags/gyptest-cflags.py --- gyp-0.1~svn1729/test/cflags/gyptest-cflags.py 2013-08-20 00:47:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/cflags/gyptest-cflags.py 2015-09-13 13:41:20.000000000 +0000 @@ -5,41 +5,25 @@ # found in the LICENSE file. """ -Verifies build of an executable with C++ define specified by a gyp define, and -the use of the environment during regeneration when the gyp file changes. +Verifies the use of the environment during regeneration when the gyp file +changes, specifically via build of an executable with C preprocessor +definition specified by CFLAGS. + +In this test, gyp and build both run in same local environment. """ -import os -import sys import TestGyp -env_stack = [] - - -def PushEnv(): - env_copy = os.environ.copy() - env_stack.append(env_copy) - -def PopEnv(): - os.environ.clear() - os.environ.update(env_stack.pop()) - -formats = ['make', 'ninja'] +# CPPFLAGS works in ninja but not make; CFLAGS works in both +FORMATS = ('make', 'ninja') -test = TestGyp.TestGyp(formats=formats) +test = TestGyp.TestGyp(formats=FORMATS) -try: - PushEnv() - os.environ['CFLAGS'] = '' - os.environ['GYP_CROSSCOMPILE'] = '1' +# First set CFLAGS to blank in case the platform doesn't support unsetenv. +with TestGyp.LocalEnv({'CFLAGS': '', + 'GYP_CROSSCOMPILE': '1'}): test.run_gyp('cflags.gyp') test.build('cflags.gyp') -finally: - # We clear the environ after calling gyp. When the auto-regeneration happens, - # the same define should be reused anyway. Reset to empty string first in - # case the platform doesn't support unsetenv. - PopEnv() - expect = """FOO not defined\n""" test.run_built_executable('cflags', stdout=expect) @@ -47,18 +31,10 @@ test.sleep() -try: - PushEnv() - os.environ['CFLAGS'] = '-DFOO=1' - os.environ['GYP_CROSSCOMPILE'] = '1' +with TestGyp.LocalEnv({'CFLAGS': '-DFOO=1', + 'GYP_CROSSCOMPILE': '1'}): test.run_gyp('cflags.gyp') test.build('cflags.gyp') -finally: - # We clear the environ after calling gyp. When the auto-regeneration happens, - # the same define should be reused anyway. Reset to empty string first in - # case the platform doesn't support unsetenv. - PopEnv() - expect = """FOO defined\n""" test.run_built_executable('cflags', stdout=expect) @@ -69,34 +45,18 @@ test.sleep() -try: - PushEnv() - os.environ['CFLAGS'] = '' +with TestGyp.LocalEnv({'CFLAGS': ''}): test.run_gyp('cflags.gyp') test.build('cflags.gyp') -finally: - # We clear the environ after calling gyp. When the auto-regeneration happens, - # the same define should be reused anyway. Reset to empty string first in - # case the platform doesn't support unsetenv. - PopEnv() - expect = """FOO not defined\n""" test.run_built_executable('cflags', stdout=expect) test.sleep() -try: - PushEnv() - os.environ['CFLAGS'] = '-DFOO=1' +with TestGyp.LocalEnv({'CFLAGS': '-DFOO=1'}): test.run_gyp('cflags.gyp') test.build('cflags.gyp') -finally: - # We clear the environ after calling gyp. When the auto-regeneration happens, - # the same define should be reused anyway. Reset to empty string first in - # case the platform doesn't support unsetenv. - PopEnv() - expect = """FOO defined\n""" test.run_built_executable('cflags', stdout=expect) diff -Nru gyp-0.1~svn1729/test/compilable/src/program.cpp gyp-0.1+20150913git1f374df9/test/compilable/src/program.cpp --- gyp-0.1~svn1729/test/compilable/src/program.cpp 2009-09-29 22:36:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compilable/src/program.cpp 2015-09-13 13:41:20.000000000 +0000 @@ -1,7 +1,7 @@ #include #include "lib1.hpp" -int main(int argc, char *argv[]) { +int main(void) { fprintf(stdout, "Hello from program.c\n"); fflush(stdout); lib1_function(); diff -Nru gyp-0.1~svn1729/test/compiler-override/compiler-exe.gyp gyp-0.1+20150913git1f374df9/test/compiler-override/compiler-exe.gyp --- gyp-0.1~svn1729/test/compiler-override/compiler-exe.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/compiler-exe.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,16 @@ +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'hello', + 'type': 'executable', + 'sources': [ + 'test.c', + 'cxxtest.cc', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/compiler-override/compiler.gyp gyp-0.1+20150913git1f374df9/test/compiler-override/compiler.gyp --- gyp-0.1~svn1729/test/compiler-override/compiler.gyp 2012-08-15 17:11:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/compiler.gyp 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -# Copyright (c) 2012 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'hello', - 'type': 'executable', - 'sources': [ - 'test.c', - 'cxxtest.cc', - ], - }, - ], -} diff -Nru gyp-0.1~svn1729/test/compiler-override/compiler-host.gyp gyp-0.1+20150913git1f374df9/test/compiler-override/compiler-host.gyp --- gyp-0.1~svn1729/test/compiler-override/compiler-host.gyp 2012-08-15 17:11:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/compiler-host.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -5,7 +5,7 @@ { 'targets': [ { - 'toolset': 'host', + 'toolset': 'host', 'target_name': 'hello', 'type': 'executable', 'sources': [ diff -Nru gyp-0.1~svn1729/test/compiler-override/compiler-shared-lib.gyp gyp-0.1+20150913git1f374df9/test/compiler-override/compiler-shared-lib.gyp --- gyp-0.1~svn1729/test/compiler-override/compiler-shared-lib.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/compiler-shared-lib.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,16 @@ +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'hello-lib', + 'type': 'shared_library', + 'sources': [ + 'test.c', + 'cxxtest.cc', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/compiler-override/gyptest-compiler-env.py gyp-0.1+20150913git1f374df9/test/compiler-override/gyptest-compiler-env.py --- gyp-0.1~svn1729/test/compiler-override/gyptest-compiler-env.py 2013-09-10 22:45:33.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/gyptest-compiler-env.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,7 +15,7 @@ here = os.path.dirname(os.path.abspath(__file__)) if sys.platform == 'win32': - # cross compiling not support by ninja on windows + # cross compiling not supported by ninja on windows # and make not supported on windows at all. sys.exit(0) @@ -30,8 +30,6 @@ test.run_gyp(gypfile) test.build(gypfile) - # We can't test to presence of my_ld.py in the output since - # ninja will use CXX_target as the linker regardless test.must_contain_all_lines(test.stdout(), check_for) @@ -39,7 +37,9 @@ def TestTargetOveride(): expected = ['my_cc.py', 'my_cxx.py', 'FOO' ] - if test.format != 'ninja': # ninja just uses $CC / $CXX as linker. + + # ninja just uses $CC / $CXX as linker. + if test.format not in ['ninja', 'xcode-ninja']: expected.append('FOO_LINK') # Check that CC, CXX and LD set target compiler @@ -49,8 +49,7 @@ os.environ['CXX'] = 'python %s/my_cxx.py FOO' % here os.environ['LINK'] = 'python %s/my_ld.py FOO_LINK' % here - CheckCompiler(test, 'compiler.gyp', expected, - True) + CheckCompiler(test, 'compiler-exe.gyp', expected, True) finally: os.environ.clear() os.environ.update(oldenv) @@ -58,8 +57,8 @@ # Run the same tests once the eviron has been restored. The # generated should have embedded all the settings in the # project files so the results should be the same. - CheckCompiler(test, 'compiler.gyp', expected, - False) + CheckCompiler(test, 'compiler-exe.gyp', expected, False) + def TestTargetOverideCompilerOnly(): # Same test again but with that CC, CXX and not LD @@ -68,7 +67,7 @@ os.environ['CC'] = 'python %s/my_cc.py FOO' % here os.environ['CXX'] = 'python %s/my_cxx.py FOO' % here - CheckCompiler(test, 'compiler.gyp', + CheckCompiler(test, 'compiler-exe.gyp', ['my_cc.py', 'my_cxx.py', 'FOO'], True) finally: @@ -78,7 +77,7 @@ # Run the same tests once the eviron has been restored. The # generated should have embedded all the settings in the # project files so the results should be the same. - CheckCompiler(test, 'compiler.gyp', + CheckCompiler(test, 'compiler-exe.gyp', ['my_cc.py', 'my_cxx.py', 'FOO'], False) @@ -107,6 +106,5 @@ TestTargetOveride() TestTargetOverideCompilerOnly() -TestHostOveride() test.pass_test() diff -Nru gyp-0.1~svn1729/test/compiler-override/gyptest-compiler-env-toolchain.py gyp-0.1+20150913git1f374df9/test/compiler-override/gyptest-compiler-env-toolchain.py --- gyp-0.1~svn1729/test/compiler-override/gyptest-compiler-env-toolchain.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/gyptest-compiler-env-toolchain.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +""" +Verifies that the user can override the compiler and linker using +CC/CXX/NM/READELF environment variables. +""" + +import TestGyp +import os +import copy +import sys + +here = os.path.dirname(os.path.abspath(__file__)) + +if sys.platform == 'win32': + # cross compiling not supported by ninja on windows + # and make not supported on windows at all. + sys.exit(0) + +# Clear any existing compiler related env vars. +for key in ['CC', 'CXX', 'LINK', 'CC_host', 'CXX_host', 'LINK_host', + 'NM_target', 'READELF_target']: + if key in os.environ: + del os.environ[key] + + +def CheckCompiler(test, gypfile, check_for, run_gyp): + if run_gyp: + test.run_gyp(gypfile) + test.build(gypfile) + + test.must_contain_all_lines(test.stdout(), check_for) + + +test = TestGyp.TestGyp(formats=['ninja']) +# Must set the test format to something with a flavor (the part after the '-') +# in order to test the desired behavior. Since we want to run a non-host +# toolchain, we have to set the flavor to something that the ninja generator +# doesn't know about, so it doesn't default to the host-specific tools (e.g., +# 'otool' on mac to generate the .TOC). +# +# Note that we can't just pass format=['ninja-some_toolchain'] to the +# constructor above, because then this test wouldn't be recognized as a ninja +# format test. +test.formats = ['ninja-my_flavor' if f == 'ninja' else f for f in test.formats] + + +def TestTargetOverideSharedLib(): + # The std output from nm and readelf is redirected to files, so we can't + # expect their output to appear. Instead, check for the files they create to + # see if they actually ran. + expected = ['my_cc.py', 'my_cxx.py', 'FOO'] + + # Check that CC, CXX, NM, READELF, set target compiler + env = {'CC': 'python %s/my_cc.py FOO' % here, + 'CXX': 'python %s/my_cxx.py FOO' % here, + 'NM': 'python %s/my_nm.py' % here, + 'READELF': 'python %s/my_readelf.py' % here} + + with TestGyp.LocalEnv(env): + CheckCompiler(test, 'compiler-shared-lib.gyp', expected, True) + test.must_contain(test.built_file_path('RAN_MY_NM'), 'RAN_MY_NM') + test.must_contain(test.built_file_path('RAN_MY_READELF'), 'RAN_MY_READELF') + test.unlink(test.built_file_path('RAN_MY_NM')) + test.unlink(test.built_file_path('RAN_MY_READELF')) + + # Run the same tests once the eviron has been restored. The generated + # projects should have embedded all the settings in the project files so the + # results should be the same. + CheckCompiler(test, 'compiler-shared-lib.gyp', expected, False) + test.must_contain(test.built_file_path('RAN_MY_NM'), 'RAN_MY_NM') + test.must_contain(test.built_file_path('RAN_MY_READELF'), 'RAN_MY_READELF') + + +TestTargetOverideSharedLib() +test.pass_test() diff -Nru gyp-0.1~svn1729/test/compiler-override/gyptest-compiler-global-settings.py gyp-0.1+20150913git1f374df9/test/compiler-override/gyptest-compiler-global-settings.py --- gyp-0.1~svn1729/test/compiler-override/gyptest-compiler-global-settings.py 2013-07-08 18:18:12.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/gyptest-compiler-global-settings.py 2015-09-13 13:41:20.000000000 +0000 @@ -43,6 +43,11 @@ test.build(gypfile) test.must_contain_all_lines(test.stdout(), ['my_cc.py', 'my_cxx.py', 'FOO']) +# The xcode generator chokes on the 'host' toolset. Skip the rest of +# this test (cf. https://code.google.com/p/gyp/issues/detail?id=454). +if test.format == 'xcode-ninja': + test.pass_test() + # Same again but with the host toolset. replacements['TOOLSET'] = 'host' s = Template(open(gypfile + '.in').read()) @@ -59,4 +64,15 @@ test.build(gypfile) test.must_contain_all_lines(test.stdout(), ['my_cc.py', 'my_cxx.py', 'BAR']) +# Check that CC_host overrides make_global_settings +old_env = dict(os.environ) +os.environ['CC_host'] = '%s %s/my_cc.py SECRET' % (replacements['PYTHON'], + replacements['PWD']) +test.run_gyp(gypfile) +os.environ.clear() +os.environ.update(old_env) + +test.build(gypfile) +test.must_contain_all_lines(test.stdout(), ['SECRET', 'my_cxx.py', 'BAR']) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/compiler-override/my_nm.py gyp-0.1+20150913git1f374df9/test/compiler-override/my_nm.py --- gyp-0.1~svn1729/test/compiler-override/my_nm.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/my_nm.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import sys +print sys.argv +with open('RAN_MY_NM', 'w') as f: + f.write('RAN_MY_NM') diff -Nru gyp-0.1~svn1729/test/compiler-override/my_readelf.py gyp-0.1+20150913git1f374df9/test/compiler-override/my_readelf.py --- gyp-0.1~svn1729/test/compiler-override/my_readelf.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/compiler-override/my_readelf.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import sys +print sys.argv +with open('RAN_MY_READELF', 'w') as f: + f.write('RAN_MY_READELF') diff -Nru gyp-0.1~svn1729/test/conditions/elseif/elseif_bad1.gyp gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_bad1.gyp --- gyp-0.1~svn1729/test/conditions/elseif/elseif_bad1.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_bad1.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,20 @@ +# Copyright (c) 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Trigger an error because of two consecutive string conditions. + +{ + 'targets': [ + { + 'variables': { 'test_var': 0 }, + 'target_name': 'program', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'conditions': [ + ['test_var==0', 'test_var==1', { + }], + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/conditions/elseif/elseif_bad2.gyp gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_bad2.gyp --- gyp-0.1~svn1729/test/conditions/elseif/elseif_bad2.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_bad2.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +# Copyright (c) 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Trigger an error because of two consecutive string conditions, even if the +# conditions are not actually evaluated. + +{ + 'targets': [ + { + 'variables': { 'test_var': 0 }, + 'target_name': 'program', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'conditions': [ + ['test_var==0', { + }, 'test_var==1', 'test_var==2', { + }], + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/conditions/elseif/elseif_bad3.gyp gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_bad3.gyp --- gyp-0.1~svn1729/test/conditions/elseif/elseif_bad3.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_bad3.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +# Copyright (c) 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Trigger an error because there are unexpected trailing items in a condition. + +{ + 'targets': [ + { + 'variables': { 'test_var': 0 }, + 'target_name': 'program', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'conditions': [ + ['test_var==0' { + }, 'test_var==1', { + }, { + }, 'test_var==2', { + }], + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/conditions/elseif/elseif_conditions.gypi gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_conditions.gypi --- gyp-0.1~svn1729/test/conditions/elseif/elseif_conditions.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif_conditions.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,15 @@ +{ + 'conditions': [ + ['test_var==0', { + 'defines': ['FOO="first_if"'], + }, 'test_var==1', { + 'defines': ['FOO="first_else_if"'], + }, 'test_var==2', { + 'defines': ['FOO="second_else_if"'], + }, 'test_var==3', { + 'defines': ['FOO="third_else_if"'], + }, { + 'defines': ['FOO="last_else"'], + }], + ], +} diff -Nru gyp-0.1~svn1729/test/conditions/elseif/elseif.gyp gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif.gyp --- gyp-0.1~svn1729/test/conditions/elseif/elseif.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/elseif.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,43 @@ +# Copyright (c) 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'variables': { 'test_var': 0 }, + 'target_name': 'program0', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'includes': [ 'elseif_conditions.gypi' ], + }, + { + 'variables': { 'test_var': 1 }, + 'target_name': 'program1', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'includes': [ 'elseif_conditions.gypi' ], + }, + { + 'variables': { 'test_var': 2 }, + 'target_name': 'program2', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'includes': [ 'elseif_conditions.gypi' ], + }, + { + 'variables': { 'test_var': 3 }, + 'target_name': 'program3', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'includes': [ 'elseif_conditions.gypi' ], + }, + { + 'variables': { 'test_var': 4 }, + 'target_name': 'program4', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'includes': [ 'elseif_conditions.gypi' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/conditions/elseif/gyptest_elseif.py gyp-0.1+20150913git1f374df9/test/conditions/elseif/gyptest_elseif.py --- gyp-0.1~svn1729/test/conditions/elseif/gyptest_elseif.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/gyptest_elseif.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verify that "else-if" conditions work. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('elseif.gyp') +test.build('elseif.gyp', test.ALL) +test.run_built_executable( + 'program0', stdout='first_if\n') +test.run_built_executable( + 'program1', stdout='first_else_if\n') +test.run_built_executable( + 'program2', stdout='second_else_if\n') +test.run_built_executable( + 'program3', stdout='third_else_if\n') +test.run_built_executable( + 'program4', stdout='last_else\n') + +# Verify that bad condition blocks fail at gyp time. +test.run_gyp('elseif_bad1.gyp', status=1, stderr=None) +test.run_gyp('elseif_bad2.gyp', status=1, stderr=None) +test.run_gyp('elseif_bad3.gyp', status=1, stderr=None) + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/conditions/elseif/program.cc gyp-0.1+20150913git1f374df9/test/conditions/elseif/program.cc --- gyp-0.1~svn1729/test/conditions/elseif/program.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/conditions/elseif/program.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +int main() { + printf("%s\n", FOO); + return 0; +} diff -Nru gyp-0.1~svn1729/test/configurations/basics/configurations.c gyp-0.1+20150913git1f374df9/test/configurations/basics/configurations.c --- gyp-0.1~svn1729/test/configurations/basics/configurations.c 2009-10-29 18:28:44.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/basics/configurations.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { #ifdef FOO printf("Foo configuration\n"); diff -Nru gyp-0.1~svn1729/test/configurations/inheritance/configurations.c gyp-0.1+20150913git1f374df9/test/configurations/inheritance/configurations.c --- gyp-0.1~svn1729/test/configurations/inheritance/configurations.c 2009-10-29 18:28:44.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/inheritance/configurations.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { #ifdef BASE printf("Base configuration\n"); diff -Nru gyp-0.1~svn1729/test/configurations/inheritance/duplicates.gyp gyp-0.1+20150913git1f374df9/test/configurations/inheritance/duplicates.gyp --- gyp-0.1~svn1729/test/configurations/inheritance/duplicates.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/inheritance/duplicates.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,27 @@ +# Copyright 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'target_defaults': { + 'default_configuration': 'A', + 'configurations': { + 'A': { + 'defines': ['SOMETHING'], + }, + 'B': { + 'inherit_from': ['A'], + }, + }, + 'cflags': ['-g'], + }, + 'targets': [ + { + 'target_name': 'configurations', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/configurations/inheritance/duplicates.gypd.golden gyp-0.1+20150913git1f374df9/test/configurations/inheritance/duplicates.gypd.golden --- gyp-0.1~svn1729/test/configurations/inheritance/duplicates.gypd.golden 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/inheritance/duplicates.gypd.golden 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +{'_DEPTH': '.', + 'included_files': ['duplicates.gyp'], + 'targets': [{'configurations': {'A': {'cflags': ['-g'], + 'defines': ['SOMETHING']}, + 'B': {'cflags': ['-g'], + 'defines': ['SOMETHING'], + 'inherit_from': ['A']}}, + 'default_configuration': 'A', + 'sources': ['configurations.c'], + 'target_name': 'configurations', + 'toolset': 'target', + 'type': 'executable'}]} diff -Nru gyp-0.1~svn1729/test/configurations/inheritance/gyptest-duplicates.py gyp-0.1+20150913git1f374df9/test/configurations/inheritance/gyptest-duplicates.py --- gyp-0.1~svn1729/test/configurations/inheritance/gyptest-duplicates.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/inheritance/gyptest-duplicates.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +# Copyright 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that configurations do not duplicate other settings. +""" + +import TestGyp + +test = TestGyp.TestGyp(format='gypd') + +test.run_gyp('duplicates.gyp') + +# Verify the duplicates.gypd against the checked-in expected contents. +# +# Normally, we should canonicalize line endings in the expected +# contents file setting the Subversion svn:eol-style to native, +# but that would still fail if multiple systems are sharing a single +# workspace on a network-mounted file system. Consequently, we +# massage the Windows line endings ('\r\n') in the output to the +# checked-in UNIX endings ('\n'). + +contents = test.read('duplicates.gypd').replace( + '\r', '').replace('\\\\', '/') +expect = test.read('duplicates.gypd.golden').replace('\r', '') +if not test.match(contents, expect): + print "Unexpected contents of `duplicates.gypd'" + test.diff(expect, contents, 'duplicates.gypd ') + test.fail_test() + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/configurations/target_platform/front.c gyp-0.1+20150913git1f374df9/test/configurations/target_platform/front.c --- gyp-0.1~svn1729/test/configurations/target_platform/front.c 2009-11-17 02:04:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/target_platform/front.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ const char *message(void); -int main(int argc, char *argv[]) { +int main(void) { printf("%s\n", message()); return 0; } diff -Nru gyp-0.1~svn1729/test/configurations/x64/configurations.c gyp-0.1+20150913git1f374df9/test/configurations/x64/configurations.c --- gyp-0.1~svn1729/test/configurations/x64/configurations.c 2009-10-30 21:33:16.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/configurations/x64/configurations.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) { +int main(void) { if (sizeof(void*) == 4) { printf("Running Win32\n"); } else if (sizeof(void*) == 8) { diff -Nru gyp-0.1~svn1729/test/copies/gyptest-all.py gyp-0.1+20150913git1f374df9/test/copies/gyptest-all.py --- gyp-0.1~svn1729/test/copies/gyptest-all.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,7 +12,9 @@ test = TestGyp.TestGyp() -test.run_gyp('copies.gyp', chdir='src') +test.run_gyp('copies.gyp', + '-G', 'xcode_ninja_target_pattern=^(?!copies_null)', + chdir='src') test.relocate('src', 'relocate/src') diff -Nru gyp-0.1~svn1729/test/copies/gyptest-attribs.py gyp-0.1+20150913git1f374df9/test/copies/gyptest-attribs.py --- gyp-0.1~svn1729/test/copies/gyptest-attribs.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/gyptest-attribs.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that copying files preserves file attributes. +""" + +import TestGyp + +import os +import stat +import sys + + +def check_attribs(path, expected_exec_bit): + out_path = test.built_file_path(path, chdir='src') + + in_stat = os.stat(os.path.join('src', path)) + out_stat = os.stat(out_path) + if out_stat.st_mode & stat.S_IXUSR != expected_exec_bit: + test.fail_test() + + +test = TestGyp.TestGyp() + +test.run_gyp('copies-attribs.gyp', chdir='src') + +test.build('copies-attribs.gyp', chdir='src') + +if sys.platform != 'win32': + out_path = test.built_file_path('executable-file.sh', chdir='src') + test.must_contain(out_path, + '#!/bin/bash\n' + '\n' + 'echo echo echo echo cho ho o o\n') + check_attribs('executable-file.sh', expected_exec_bit=stat.S_IXUSR) + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/copies/gyptest-default.py gyp-0.1+20150913git1f374df9/test/copies/gyptest-default.py --- gyp-0.1~svn1729/test/copies/gyptest-default.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/gyptest-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,7 +12,9 @@ test = TestGyp.TestGyp() -test.run_gyp('copies.gyp', chdir='src') +test.run_gyp('copies.gyp', + '-G', 'xcode_ninja_target_pattern=^(?!copies_null)', + chdir='src') test.relocate('src', 'relocate/src') diff -Nru gyp-0.1~svn1729/test/copies/gyptest-samedir.py gyp-0.1+20150913git1f374df9/test/copies/gyptest-samedir.py --- gyp-0.1~svn1729/test/copies/gyptest-samedir.py 2013-02-03 16:48:10.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/gyptest-samedir.py 2015-09-13 13:41:20.000000000 +0000 @@ -11,9 +11,9 @@ import TestGyp -# The Android build system doesn't allow output to go to arbitrary places. -test = TestGyp.TestGyp(formats=['!android']) +test = TestGyp.TestGyp() test.run_gyp('copies-samedir.gyp', chdir='src') + test.relocate('src', 'relocate/src') test.build('copies-samedir.gyp', 'copies_samedir', chdir='relocate/src') diff -Nru gyp-0.1~svn1729/test/copies/gyptest-slash.py gyp-0.1+20150913git1f374df9/test/copies/gyptest-slash.py --- gyp-0.1~svn1729/test/copies/gyptest-slash.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/gyptest-slash.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,6 +12,7 @@ test = TestGyp.TestGyp() test.run_gyp('copies-slash.gyp', chdir='src') + test.relocate('src', 'relocate/src') test.build('copies-slash.gyp', chdir='relocate/src') diff -Nru gyp-0.1~svn1729/test/copies/gyptest-updir.py gyp-0.1+20150913git1f374df9/test/copies/gyptest-updir.py --- gyp-0.1~svn1729/test/copies/gyptest-updir.py 2012-12-12 16:24:59.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/gyptest-updir.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,11 +9,17 @@ yields a make variable. """ +import sys + import TestGyp -# The Android build system doesn't allow output to go to arbitrary places. -test = TestGyp.TestGyp(formats=['!android']) +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + +test = TestGyp.TestGyp() test.run_gyp('copies-updir.gyp', chdir='src') + test.relocate('src', 'relocate/src') test.build('copies-updir.gyp', 'copies_up', chdir='relocate/src') diff -Nru gyp-0.1~svn1729/test/copies/src/copies-attribs.gyp gyp-0.1+20150913git1f374df9/test/copies/src/copies-attribs.gyp --- gyp-0.1~svn1729/test/copies/src/copies-attribs.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/src/copies-attribs.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,20 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'copies1', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + 'executable-file.sh', + ], + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/copies/src/executable-file.sh gyp-0.1+20150913git1f374df9/test/copies/src/executable-file.sh --- gyp-0.1~svn1729/test/copies/src/executable-file.sh 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/copies/src/executable-file.sh 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo echo echo echo cho ho o o diff -Nru gyp-0.1~svn1729/test/cxxflags/cxxflags.cc gyp-0.1+20150913git1f374df9/test/cxxflags/cxxflags.cc --- gyp-0.1~svn1729/test/cxxflags/cxxflags.cc 2010-12-18 00:14:31.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/cxxflags/cxxflags.cc 2015-09-13 13:41:20.000000000 +0000 @@ -4,12 +4,12 @@ #include -int main(int argc, char *argv[]) +int main(void) { -#ifdef __OPTIMIZE__ - printf("Using an optimization flag\n"); +#ifdef ABC + printf("With define\n"); #else - printf("Using no optimization flag\n"); + printf("No define\n"); #endif return 0; } diff -Nru gyp-0.1~svn1729/test/cxxflags/cxxflags.gyp gyp-0.1+20150913git1f374df9/test/cxxflags/cxxflags.gyp --- gyp-0.1~svn1729/test/cxxflags/cxxflags.gyp 2010-12-18 00:14:31.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/cxxflags/cxxflags.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -7,7 +7,6 @@ { 'target_name': 'cxxflags', 'type': 'executable', - 'opt': '-Os', 'sources': [ 'cxxflags.cc', ], diff -Nru gyp-0.1~svn1729/test/cxxflags/gyptest-cxxflags.py gyp-0.1+20150913git1f374df9/test/cxxflags/gyptest-cxxflags.py --- gyp-0.1~svn1729/test/cxxflags/gyptest-cxxflags.py 2012-12-10 11:20:44.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/cxxflags/gyptest-cxxflags.py 2015-09-13 13:41:20.000000000 +0000 @@ -5,60 +5,40 @@ # found in the LICENSE file. """ -Verifies build of an executable with C++ define specified by a gyp define, and -the use of the environment during regeneration when the gyp file changes. +Verifies the use of the environment during regeneration when the gyp file +changes, specifically via build of an executable with C++ flags specified by +CXXFLAGS. + +In this test, gyp happens within a local environment, but build outside of it. """ -import os import TestGyp -env_stack = [] - - -def PushEnv(): - env_copy = os.environ.copy() - env_stack.append(env_copy) - -def PopEnv(): - os.eniron=env_stack.pop() +FORMATS = ('ninja',) -# Regenerating build files when a gyp file changes is currently only supported -# by the make generator. -test = TestGyp.TestGyp(formats=['make']) +test = TestGyp.TestGyp(formats=FORMATS) -try: - PushEnv() - os.environ['CXXFLAGS'] = '-O0' +# We reset the environ after calling gyp. When the auto-regeneration happens, +# the same define should be reused anyway. +with TestGyp.LocalEnv({'CXXFLAGS': ''}): test.run_gyp('cxxflags.gyp') -finally: - # We clear the environ after calling gyp. When the auto-regeneration happens, - # the same define should be reused anyway. Reset to empty string first in - # case the platform doesn't support unsetenv. - PopEnv() test.build('cxxflags.gyp') expect = """\ -Using no optimization flag +No define """ test.run_built_executable('cxxflags', stdout=expect) test.sleep() -try: - PushEnv() - os.environ['CXXFLAGS'] = '-O2' +with TestGyp.LocalEnv({'CXXFLAGS': '-DABC'}): test.run_gyp('cxxflags.gyp') -finally: - # We clear the environ after calling gyp. When the auto-regeneration happens, - # the same define should be reused anyway. Reset to empty string first in - # case the platform doesn't support unsetenv. - PopEnv() test.build('cxxflags.gyp') expect = """\ -Using an optimization flag +With define """ test.run_built_executable('cxxflags', stdout=expect) diff -Nru gyp-0.1~svn1729/test/defines/defines.c gyp-0.1+20150913git1f374df9/test/defines/defines.c --- gyp-0.1~svn1729/test/defines/defines.c 2012-05-18 13:47:21.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/defines/defines.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { #ifdef FOO printf("FOO is defined\n"); diff -Nru gyp-0.1~svn1729/test/defines/gyptest-define-override.py gyp-0.1+20150913git1f374df9/test/defines/gyptest-define-override.py --- gyp-0.1~svn1729/test/defines/gyptest-define-override.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/defines/gyptest-define-override.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,22 +13,31 @@ test = TestGyp.TestGyp() +# CMake loudly warns about passing '#' to the compiler and drops the define. +expect_stderr = '' +if test.format == 'cmake': + expect_stderr = ( +"""WARNING: Preprocessor definitions containing '#' may not be passed on the""" +""" compiler command line because many compilers do not support it.\n""" +"""CMake is dropping a preprocessor definition: HASH_VALUE="a#1"\n""" +"""Consider defining the macro in a (configured) header file.\n\n""") + # Command-line define test.run_gyp('defines.gyp', '-D', 'OS=fakeos') -test.build('defines.gyp') +test.build('defines.gyp', stderr=expect_stderr) test.built_file_must_exist('fakeosprogram', type=test.EXECUTABLE) # Clean up the exe so subsequent tests don't find an old exe. os.remove(test.built_file_path('fakeosprogram', type=test.EXECUTABLE)) # Without "OS" override, fokeosprogram shouldn't be built. test.run_gyp('defines.gyp') -test.build('defines.gyp') +test.build('defines.gyp', stderr=expect_stderr) test.built_file_must_not_exist('fakeosprogram', type=test.EXECUTABLE) # Environment define os.environ['GYP_DEFINES'] = 'OS=fakeos' test.run_gyp('defines.gyp') -test.build('defines.gyp') +test.build('defines.gyp', stderr=expect_stderr) test.built_file_must_exist('fakeosprogram', type=test.EXECUTABLE) test.pass_test() diff -Nru gyp-0.1~svn1729/test/defines/gyptest-defines.py gyp-0.1+20150913git1f374df9/test/defines/gyptest-defines.py --- gyp-0.1~svn1729/test/defines/gyptest-defines.py 2012-05-18 16:05:04.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/defines/gyptest-defines.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,14 +14,26 @@ test.run_gyp('defines.gyp') -test.build('defines.gyp') - expect = """\ FOO is defined VALUE is 1 2*PAREN_VALUE is 12 -HASH_VALUE is a#1 """ + +#CMake loudly warns about passing '#' to the compiler and drops the define. +expect_stderr = '' +if test.format == 'cmake': + expect_stderr = ( +"""WARNING: Preprocessor definitions containing '#' may not be passed on the""" +""" compiler command line because many compilers do not support it.\n""" +"""CMake is dropping a preprocessor definition: HASH_VALUE="a#1"\n""" +"""Consider defining the macro in a (configured) header file.\n\n""") +else: + expect += """HASH_VALUE is a#1 +""" + +test.build('defines.gyp', stderr=expect_stderr) + test.run_built_executable('defines', stdout=expect) test.pass_test() diff -Nru gyp-0.1~svn1729/test/defines-escaping/defines-escaping.c gyp-0.1+20150913git1f374df9/test/defines-escaping/defines-escaping.c --- gyp-0.1~svn1729/test/defines-escaping/defines-escaping.c 2010-03-20 00:07:12.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/defines-escaping/defines-escaping.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf(TEST_FORMAT, TEST_ARGS); return 0; diff -Nru gyp-0.1~svn1729/test/dependencies/adso/all_dependent_settings_order.gyp gyp-0.1+20150913git1f374df9/test/dependencies/adso/all_dependent_settings_order.gyp --- gyp-0.1~svn1729/test/dependencies/adso/all_dependent_settings_order.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependencies/adso/all_dependent_settings_order.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,45 @@ +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'none', + 'sources': ['a.cc'], + 'all_dependent_settings': {'sources': ['a.cc']}, + }, + { + 'target_name': 'b', + 'type': 'none', + 'sources': ['b.cc'], + 'all_dependent_settings': {'sources': ['b.cc']}, + 'dependencies': ['a'], + }, + + { + 'target_name': 'c', + 'type': 'none', + 'sources': ['c.cc'], + 'all_dependent_settings': {'sources': ['c.cc']}, + 'dependencies': ['b', 'a'], + }, + { + 'target_name': 'd', + 'type': 'none', + 'sources': ['d.cc'], + 'dependencies': ['c', 'a', 'b'], + 'actions': [ + { + 'action_name': 'write_sources', + 'inputs': ['write_args.py'], + 'outputs': ['<(PRODUCT_DIR)/out.txt'], + 'action': [ + 'python', + 'write_args.py', + '<(PRODUCT_DIR)/out.txt', + '>@(_sources)' + ], + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/dependencies/adso/write_args.py gyp-0.1+20150913git1f374df9/test/dependencies/adso/write_args.py --- gyp-0.1~svn1729/test/dependencies/adso/write_args.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependencies/adso/write_args.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +# Copyright 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys + +f = open(sys.argv[1], 'wb') +f.write(' '.join(sys.argv[2:])) +f.close() diff -Nru gyp-0.1~svn1729/test/dependencies/gyptest-all-dependent-settings-order.py gyp-0.1+20150913git1f374df9/test/dependencies/gyptest-all-dependent-settings-order.py --- gyp-0.1~svn1729/test/dependencies/gyptest-all-dependent-settings-order.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependencies/gyptest-all-dependent-settings-order.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +# Copyright 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Tests that all_dependent_settings are processed in topological order. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all_dependent_settings_order.gyp', chdir='adso') +test.build('all_dependent_settings_order.gyp', chdir='adso') +test.built_file_must_match('out.txt', 'd.cc a.cc b.cc c.cc', + chdir='adso') +test.pass_test() diff -Nru gyp-0.1~svn1729/test/dependencies/gyptest-extra-targets.py gyp-0.1+20150913git1f374df9/test/dependencies/gyptest-extra-targets.py --- gyp-0.1~svn1729/test/dependencies/gyptest-extra-targets.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependencies/gyptest-extra-targets.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,7 +12,8 @@ test = TestGyp.TestGyp() -test.run_gyp('extra_targets.gyp') +test.run_gyp('extra_targets.gyp', + '-G', 'xcode_ninja_target_pattern=^a$') # This should fail if it tries to build 'c_unused' since 'c/c.c' has a syntax # error and won't compile. diff -Nru gyp-0.1~svn1729/test/dependencies/gyptest-lib-only.py gyp-0.1+20150913git1f374df9/test/dependencies/gyptest-lib-only.py --- gyp-0.1~svn1729/test/dependencies/gyptest-lib-only.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependencies/gyptest-lib-only.py 2015-09-13 13:41:20.000000000 +0000 @@ -29,7 +29,7 @@ if test.format == 'xcode': test.built_file_must_not_exist('b', type=test.STATIC_LIB) else: - assert test.format in ('make', 'ninja') + assert test.format in ('make', 'ninja', 'xcode-ninja') test.built_file_must_exist('b', type=test.STATIC_LIB) else: # Make puts the resulting library in a directory matching the input gyp file; diff -Nru gyp-0.1~svn1729/test/dependency-copy/src/file1.c gyp-0.1+20150913git1f374df9/test/dependency-copy/src/file1.c --- gyp-0.1~svn1729/test/dependency-copy/src/file1.c 2009-09-09 21:32:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependency-copy/src/file1.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from file1.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/dependency-copy/src/file2.c gyp-0.1+20150913git1f374df9/test/dependency-copy/src/file2.c --- gyp-0.1~svn1729/test/dependency-copy/src/file2.c 2009-09-09 21:32:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/dependency-copy/src/file2.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from file2.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/empty-target/empty-target.gyp gyp-0.1+20150913git1f374df9/test/empty-target/empty-target.gyp --- gyp-0.1~svn1729/test/empty-target/empty-target.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/empty-target/empty-target.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'empty_target', + 'type': 'none', + }, + ], +} diff -Nru gyp-0.1~svn1729/test/empty-target/gyptest-empty-target.py gyp-0.1+20150913git1f374df9/test/empty-target/gyptest-empty-target.py --- gyp-0.1~svn1729/test/empty-target/gyptest-empty-target.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/empty-target/gyptest-empty-target.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies building a target with nothing succeeds. +""" + +import os +import sys +import TestGyp + +test = TestGyp.TestGyp() +test.run_gyp('empty-target.gyp') +test.build('empty-target.gyp', target='empty_target') +test.pass_test() diff -Nru gyp-0.1~svn1729/test/errors/dependency_cycle.gyp gyp-0.1+20150913git1f374df9/test/errors/dependency_cycle.gyp --- gyp-0.1~svn1729/test/errors/dependency_cycle.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/errors/dependency_cycle.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +# Copyright 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'target0', + 'type': 'none', + 'dependencies': [ 'target1' ], + }, + { + 'target_name': 'target1', + 'type': 'none', + 'dependencies': [ 'target2' ], + }, + { + 'target_name': 'target2', + 'type': 'none', + 'dependencies': [ 'target0' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/errors/error_command.gyp gyp-0.1+20150913git1f374df9/test/errors/error_command.gyp --- gyp-0.1~svn1729/test/errors/error_command.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/errors/error_command.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'foo', + 'type': ' -int main(int argc, char *argv[]) +int main(void) { printf("Hello from deeper.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/generator-output/src/subdir2/prog2.c gyp-0.1+20150913git1f374df9/test/generator-output/src/subdir2/prog2.c --- gyp-0.1~svn1729/test/generator-output/src/subdir2/prog2.c 2009-09-04 17:57:42.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/generator-output/src/subdir2/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ #include "include3.h" #include "deeper.h" -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog2.c\n"); printf("Hello from %s\n", INC_STRING); diff -Nru gyp-0.1~svn1729/test/generator-output/src/subdir3/prog3.c gyp-0.1+20150913git1f374df9/test/generator-output/src/subdir3/prog3.c --- gyp-0.1~svn1729/test/generator-output/src/subdir3/prog3.c 2009-09-04 17:57:42.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/generator-output/src/subdir3/prog3.c 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ #include "include3.h" #include "deeper.h" -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog3.c\n"); printf("Hello from %s\n", INC_STRING); diff -Nru gyp-0.1~svn1729/test/gyp-defines/gyptest-multiple-values.py gyp-0.1+20150913git1f374df9/test/gyp-defines/gyptest-multiple-values.py --- gyp-0.1~svn1729/test/gyp-defines/gyptest-multiple-values.py 2012-12-12 16:24:59.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/gyp-defines/gyptest-multiple-values.py 2015-09-13 13:41:20.000000000 +0000 @@ -16,6 +16,7 @@ os.environ['GYP_DEFINES'] = 'key=value1 key=value2 key=value3' test.run_gyp('defines.gyp') + test.build('defines.gyp') test.must_contain('action.txt', 'value3') @@ -23,16 +24,11 @@ # values. os.environ['GYP_DEFINES'] = 'key=repeated_value key=value1 key=repeated_value' test.run_gyp('defines.gyp') + if test.format == 'msvs' and not test.uses_msbuild: # msvs versions before 2010 don't detect build rule changes not reflected # in file system timestamps. Rebuild to see differences. test.build('defines.gyp', rebuild=True) -elif test.format == 'android': - # The Android build system doesn't currently have a way to get files whose - # build rules have changed (but whose timestamps haven't) to be rebuilt. - # See bug http://code.google.com/p/gyp/issues/detail?id=308 - test.unlink('action.txt') - test.build('defines.gyp') else: test.build('defines.gyp') test.must_contain('action.txt', 'repeated_value') diff -Nru gyp-0.1~svn1729/test/hello/gyptest-regyp-output.py gyp-0.1+20150913git1f374df9/test/hello/gyptest-regyp-output.py --- gyp-0.1~svn1729/test/hello/gyptest-regyp-output.py 2013-06-28 13:58:56.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/hello/gyptest-regyp-output.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,8 +12,8 @@ import TestGyp # Regenerating build files when a gyp file changes is currently only supported -# by the make and Android generators, and --generator-output is not supported -# by Android and ninja, so we can only test for make. +# by the make generator, and --generator-output is not supported by ninja, so we +# can only test for make. test = TestGyp.TestGyp(formats=['make']) CHDIR='generator-output' diff -Nru gyp-0.1~svn1729/test/hello/hello2.c gyp-0.1+20150913git1f374df9/test/hello/hello2.c --- gyp-0.1~svn1729/test/hello/hello2.c 2010-01-08 14:58:07.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/hello/hello2.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello, two!\n"); return 0; diff -Nru gyp-0.1~svn1729/test/hello/hello.c gyp-0.1+20150913git1f374df9/test/hello/hello.c --- gyp-0.1~svn1729/test/hello/hello.c 2010-01-08 14:58:07.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/hello/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello, world!\n"); return 0; diff -Nru gyp-0.1~svn1729/test/home_dot_gyp/src/printfoo.c gyp-0.1+20150913git1f374df9/test/home_dot_gyp/src/printfoo.c --- gyp-0.1~svn1729/test/home_dot_gyp/src/printfoo.c 2009-11-10 17:01:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/home_dot_gyp/src/printfoo.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("FOO is %s\n", FOO); return 0; diff -Nru gyp-0.1~svn1729/test/include_dirs/src/includes.c gyp-0.1+20150913git1f374df9/test/include_dirs/src/includes.c --- gyp-0.1~svn1729/test/include_dirs/src/includes.c 2010-09-14 20:40:20.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/include_dirs/src/includes.c 2015-09-13 13:41:20.000000000 +0000 @@ -5,7 +5,7 @@ #include "include2.h" #include "shadow.h" -int main(int argc, char *argv[]) +int main(void) { printf("Hello from includes.c\n"); printf("Hello from %s\n", INC_STRING); diff -Nru gyp-0.1~svn1729/test/include_dirs/src/subdir/subdir_includes.c gyp-0.1+20150913git1f374df9/test/include_dirs/src/subdir/subdir_includes.c --- gyp-0.1~svn1729/test/include_dirs/src/subdir/subdir_includes.c 2009-09-01 23:46:21.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/include_dirs/src/subdir/subdir_includes.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include "include1.h" #include "include2.h" -int main(int argc, char *argv[]) +int main(void) { printf("Hello from subdir/subdir_includes.c\n"); printf("Hello from %s\n", INC_STRING); diff -Nru gyp-0.1~svn1729/test/intermediate_dir/gyptest-intermediate-dir.py gyp-0.1+20150913git1f374df9/test/intermediate_dir/gyptest-intermediate-dir.py --- gyp-0.1~svn1729/test/intermediate_dir/gyptest-intermediate-dir.py 2012-08-09 21:33:12.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/intermediate_dir/gyptest-intermediate-dir.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,7 @@ test = TestGyp.TestGyp() test.run_gyp('test.gyp', chdir='src') + test.build('test.gyp', 'target1', chdir='src') # Check stuff exists. intermediate_file1 = test.read('src/outfile.txt') @@ -22,6 +23,7 @@ test.must_contain(shared_intermediate_file1, 'shared_target1') test.run_gyp('test2.gyp', chdir='src') + # Force the shared intermediate to be rebuilt. test.sleep() test.touch('src/shared_infile.txt') diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/TestApp/check_no_signature.py gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/check_no_signature.py --- gyp-0.1~svn1729/test/ios/app-bundle/TestApp/check_no_signature.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/check_no_signature.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/python + +import os +import subprocess +import sys + +p = os.path.join(os.environ['BUILT_PRODUCTS_DIR'],os.environ['EXECUTABLE_PATH']) +proc = subprocess.Popen(['codesign', '-v', p], + stderr=subprocess.STDOUT, stdout=subprocess.PIPE) +o = proc.communicate()[0].strip() +if "code object is not signed at all" not in o: + sys.stderr.write('File should not already be signed.') + sys.exit(1) diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard --- gyp-0.1~svn1729/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/English.lproj/Main_iPhone.storyboard 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json --- gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json --- gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "super_sylvain.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "super_sylvain@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "super_sylvain@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file Binary files /tmp/dvXclg8H0q/gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png and /tmp/5lRImkuIue/gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png differ Binary files /tmp/dvXclg8H0q/gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png and /tmp/5lRImkuIue/gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png differ Binary files /tmp/dvXclg8H0q/gyp-0.1~svn1729/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png and /tmp/5lRImkuIue/gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png differ diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m --- gyp-0.1~svn1729/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/only-compile-in-32-bits.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#if defined(__LP64__) +# error 64-bit build +#endif diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m --- gyp-0.1~svn1729/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/TestApp/only-compile-in-64-bits.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#if !defined(__LP64__) +# error 32-bit build +#endif diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/test-archs.gyp gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-archs.gyp --- gyp-0.1~svn1729/test/ios/app-bundle/test-archs.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-archs.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,110 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ], + 'target_defaults': { + 'product_extension': 'bundle', + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'CODE_SIGNING_REQUIRED': 'NO', + 'SDKROOT': 'iphonesimulator', # -isysroot + 'TARGETED_DEVICE_FAMILY': '1,2', + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + }, + 'targets': [ + { + 'target_name': 'TestNoArchs', + 'product_name': 'TestNoArchs', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + 'TestApp/only-compile-in-32-bits.m', + ], + 'xcode_settings': { + 'VALID_ARCHS': [ + 'i386', + 'x86_64', + 'arm64', + 'armv7', + ], + } + }, + { + 'target_name': 'TestArch32Bits', + 'product_name': 'TestArch32Bits', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + 'TestApp/only-compile-in-32-bits.m', + ], + 'xcode_settings': { + 'ARCHS': [ + '$(ARCHS_STANDARD)', + ], + 'VALID_ARCHS': [ + 'i386', + 'armv7', + ], + }, + }, + { + 'target_name': 'TestArch64Bits', + 'product_name': 'TestArch64Bits', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + 'TestApp/only-compile-in-64-bits.m', + ], + 'xcode_settings': { + 'ARCHS': [ + '$(ARCHS_STANDARD_INCLUDING_64_BIT)', + ], + 'VALID_ARCHS': [ + 'x86_64', + 'arm64', + ], + }, + }, + { + 'target_name': 'TestMultiArchs', + 'product_name': 'TestMultiArchs', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + ], + 'xcode_settings': { + 'ARCHS': [ + '$(ARCHS_STANDARD_INCLUDING_64_BIT)', + ], + 'VALID_ARCHS': [ + 'x86_64', + 'i386', + 'arm64', + 'armv7', + ], + } + }, + ], +} diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/test-assets-catalog.gyp gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-assets-catalog.gyp --- gyp-0.1~svn1729/test/ios/app-bundle/test-assets-catalog.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-assets-catalog.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,45 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'conditions': [ + ['"<(GENERATOR)"=="ninja"', { + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ['CXX', '/usr/bin/clang++'], + ], + }], + ], + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test App Assets Catalog Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + 'TestApp/English.lproj/Main_iPhone.storyboard', + 'TestApp/Images.xcassets', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'SDKROOT': 'iphonesimulator', # -isysroot + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/test-crosscompile.gyp gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-crosscompile.gyp --- gyp-0.1~svn1729/test/ios/app-bundle/test-crosscompile.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-crosscompile.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,47 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ], + 'targets': [ + # This target will not be built, but is here so that ninja Xcode emulation + # understand this is a multi-platform (ios + mac) build. + { + 'target_name': 'TestDummy', + 'product_name': 'TestDummy', + 'toolsets': ['target'], + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'tool_main.cc', + ], + 'xcode_settings': { + 'SDKROOT': 'iphonesimulator', # -isysroot + 'TARGETED_DEVICE_FAMILY': '1,2', + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', + }, + }, + { + 'target_name': 'TestHost', + 'product_name': 'TestHost', + 'toolsets': ['host'], + 'type': 'executable', + 'mac_bundle': 0, + 'sources': [ + 'tool_main.cc', + ], + 'xcode_settings': { + 'SDKROOT': 'macosx', + 'ARCHS': [ + '$(ARCHS_STANDARD)', + 'x86_64', + ], + 'VALID_ARCHS': [ + 'x86_64', + ], + } + } + ], +} diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/test-device.gyp gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-device.gyp --- gyp-0.1~svn1729/test/ios/app-bundle/test-device.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test-device.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,79 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ], + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test App Gyp', + 'type': 'executable', + 'product_extension': 'bundle', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'SDKROOT': 'iphonesimulator', # -isysroot + 'TARGETED_DEVICE_FAMILY': '1,2', + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'IPHONEOS_DEPLOYMENT_TARGET': '4.2', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + }, + { + 'target_name': 'sig_test', + 'product_name': 'sig_test', + 'type': 'executable', + 'product_extension': 'bundle', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'postbuilds': [ + { + 'postbuild_name': 'Verify no signature', + 'action': [ + 'python', + 'TestApp/check_no_signature.py' + ], + }, + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'SDKROOT': 'iphonesimulator', # -isysroot + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'IPHONEOS_DEPLOYMENT_TARGET': '4.2', + 'CONFIGURATION_BUILD_DIR':'buildsig/Default', + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/test.gyp gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test.gyp --- gyp-0.1~svn1729/test/ios/app-bundle/test.gyp 2013-05-13 18:33:58.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -15,7 +15,6 @@ 'target_name': 'test_app', 'product_name': 'Test App Gyp', 'type': 'executable', - 'product_extension': 'bundle', 'mac_bundle': 1, 'sources': [ 'TestApp/main.m', @@ -23,6 +22,7 @@ 'mac_bundle_resources': [ 'TestApp/English.lproj/InfoPlist.strings', 'TestApp/English.lproj/MainMenu.xib', + 'TestApp/English.lproj/Main_iPhone.storyboard', ], 'link_settings': { 'libraries': [ @@ -36,7 +36,37 @@ ], 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', 'SDKROOT': 'iphonesimulator', # -isysroot - 'IPHONEOS_DEPLOYMENT_TARGET': '4.2', + 'IPHONEOS_DEPLOYMENT_TARGET': '5.0', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + }, + { + 'target_name': 'test_app_xml', + 'product_name': 'Test App Gyp XML', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'TestApp/main.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + 'TestApp/English.lproj/Main_iPhone.storyboard', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'INFOPLIST_OUTPUT_FORMAT':'xml', + 'SDKROOT': 'iphonesimulator', # -isysroot + 'IPHONEOS_DEPLOYMENT_TARGET': '5.0', 'CONFIGURATION_BUILD_DIR':'build/Default', }, }, diff -Nru gyp-0.1~svn1729/test/ios/app-bundle/tool_main.cc gyp-0.1+20150913git1f374df9/test/ios/app-bundle/tool_main.cc --- gyp-0.1~svn1729/test/ios/app-bundle/tool_main.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/app-bundle/tool_main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/ios/extension/ActionExtension/ActionViewController.h gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/ActionViewController.h --- gyp-0.1~svn1729/test/ios/extension/ActionExtension/ActionViewController.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/ActionViewController.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface ActionViewController : UIViewController + +@end diff -Nru gyp-0.1~svn1729/test/ios/extension/ActionExtension/ActionViewController.m gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/ActionViewController.m --- gyp-0.1~svn1729/test/ios/extension/ActionExtension/ActionViewController.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/ActionViewController.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,31 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ActionViewController.h" +#import + +@interface ActionViewController () + +@end + +@implementation ActionViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (IBAction)done { + // Return any edited content to the host app. + // This template doesn't do anything, so we just echo the passed in items. + [self.extensionContext + completeRequestReturningItems:self.extensionContext.inputItems + completionHandler:nil]; +} + +@end diff -Nru gyp-0.1~svn1729/test/ios/extension/ActionExtension/Info.plist gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/Info.plist --- gyp-0.1~svn1729/test/ios/extension/ActionExtension/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ActionExtension + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.gyptest.extension.ActionExtension + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSExtension + + NSExtensionAttributes + + NSExtensionActivationRule + TRUEPREDICATE + NSExtensionPointName + com.apple.ui-services + NSExtensionPointVersion + 1.0 + + NSExtensionMainStoryboard + MainInterface + NSExtensionPointIdentifier + com.apple.ui-services + + + diff -Nru gyp-0.1~svn1729/test/ios/extension/ActionExtension/MainInterface.storyboard gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/MainInterface.storyboard --- gyp-0.1~svn1729/test/ios/extension/ActionExtension/MainInterface.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ActionExtension/MainInterface.storyboard 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/AppDelegate.h gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/AppDelegate.h --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/AppDelegate.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/AppDelegate.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end + diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/AppDelegate.m gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/AppDelegate.m --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/AppDelegate.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/AppDelegate.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication*)application + didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + // Override point for customization after application launch. + return YES; +} + +@end diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Base.lproj/Main.storyboard 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Images.xcassets/AppIcon.appiconset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Images.xcassets/LaunchImage.launchimage/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,51 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "subtype" : "retina4", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Info.plist gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Info.plist --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ExtensionContainer + CFBundleIdentifier + com.google.gyptest.extension + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + + diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/main.m gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/main.m --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/main.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/main.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, + NSStringFromClass([AppDelegate class])); + } +} diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/ViewController.h gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/ViewController.h --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/ViewController.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/ViewController.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface ViewController : UIViewController + + +@end + diff -Nru gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/ViewController.m gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/ViewController.m --- gyp-0.1~svn1729/test/ios/extension/ExtensionContainer/ViewController.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/ExtensionContainer/ViewController.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ViewController.h" + +@interface ViewController () + + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff -Nru gyp-0.1~svn1729/test/ios/extension/extension.gyp gyp-0.1+20150913git1f374df9/test/ios/extension/extension.gyp --- gyp-0.1~svn1729/test/ios/extension/extension.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/extension/extension.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,85 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ['CXX', '/usr/bin/clang++'], + ], + 'targets': [ + { + 'target_name': 'ExtensionContainer', + 'product_name': 'ExtensionContainer', + 'type': 'executable', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + 'ExtensionContainer/Base.lproj/Main.storyboard', + ], + 'sources': [ + 'ExtensionContainer/AppDelegate.h', + 'ExtensionContainer/AppDelegate.m', + 'ExtensionContainer/ViewController.h', + 'ExtensionContainer/ViewController.m', + 'ExtensionContainer/main.m', + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/ExtensionContainer.app/PlugIns', + 'files': [ + '<(PRODUCT_DIR)/ActionExtension.appex', + ]}], + 'dependencies': [ + 'ActionExtension' + ], + + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'INFOPLIST_FILE': 'ExtensionContainer/Info.plist', + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'ARCHS': [ 'armv7' ], + 'SDKROOT': 'iphoneos', + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + }, + }, + { + 'target_name': 'ActionExtension', + 'product_name': 'ActionExtension', + 'type': 'executable', + 'mac_bundle': 1, + 'ios_app_extension': 1, + 'sources': [ + 'ActionExtension/ActionViewController.h', + 'ActionExtension/ActionViewController.m', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + '$(SDKROOT)/System/Library/Frameworks/MobileCoreServices.framework', + ], + }, + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'INFOPLIST_FILE': 'ActionExtension/Info.plist', + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'ARCHS': [ 'armv7' ], + 'SDKROOT': 'iphoneos', + 'IPHONEOS_DEPLOYMENT_TARGET': '7.0', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + }, + }, + ], +} + diff -Nru gyp-0.1~svn1729/test/ios/gyptest-app-ios-assets-catalog.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-app-ios-assets-catalog.py --- gyp-0.1~svn1729/test/ios/gyptest-app-ios-assets-catalog.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-app-ios-assets-catalog.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that ios app bundles are built correctly. +""" + +import TestGyp +import TestMac + +import os.path +import sys + +# Xcode supports for assets catalog was introduced in Xcode 6.0 +if sys.platform == 'darwin' and TestMac.Xcode.Version() >= '0600': + test_gyp_path = 'test-assets-catalog.gyp' + test_app_path = 'Test App Assets Catalog Gyp.app' + + test = TestGyp.TestGyp(formats=['xcode', 'ninja']) + test.run_gyp(test_gyp_path, chdir='app-bundle') + test.build(test_gyp_path, test.ALL, chdir='app-bundle') + + # Test that the extension is .bundle + test.built_file_must_exist( + os.path.join(test_app_path, 'Test App Assets Catalog Gyp'), + chdir='app-bundle') + + # Info.plist + info_plist = test.built_file_path( + os.path.join(test_app_path, 'Info.plist'), + chdir='app-bundle') + # Resources + test.built_file_must_exist( + os.path.join(test_app_path, 'English.lproj/InfoPlist.strings'), + chdir='app-bundle') + test.built_file_must_exist( + os.path.join(test_app_path, 'English.lproj/MainMenu.nib'), + chdir='app-bundle') + test.built_file_must_exist( + os.path.join(test_app_path, 'English.lproj/Main_iPhone.storyboardc'), + chdir='app-bundle') + test.built_file_must_exist( + os.path.join(test_app_path, 'Assets.car'), + chdir='app-bundle') + + # Packaging + test.built_file_must_exist( + os.path.join(test_app_path, 'PkgInfo'), + chdir='app-bundle') + test.built_file_must_match( + os.path.join(test_app_path, 'PkgInfo'), 'APPLause', + chdir='app-bundle') + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/ios/gyptest-app-ios.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-app-ios.py --- gyp-0.1~svn1729/test/ios/gyptest-app-ios.py 2013-05-09 00:10:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-app-ios.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,8 +10,22 @@ import TestGyp +import subprocess import sys +def CheckFileXMLPropertyList(file): + output = subprocess.check_output(['file', file]) + # The double space after XML is intentional. + if not 'XML document text' in output: + print 'File: Expected XML document text, got %s' % output + test.fail_test() + +def CheckFileBinaryPropertyList(file): + output = subprocess.check_output(['file', file]) + if not 'Apple binary property list' in output: + print 'File: Expected Apple binary property list, got %s' % output + test.fail_test() + if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['xcode', 'ninja']) @@ -20,24 +34,38 @@ test.build('test.gyp', test.ALL, chdir='app-bundle') # Test that the extension is .bundle - test.built_file_must_exist('Test App Gyp.bundle/Test App Gyp', + test.built_file_must_exist('Test App Gyp.app/Test App Gyp', chdir='app-bundle') # Info.plist - info_plist = test.built_file_path('Test App Gyp.bundle/Info.plist', + info_plist = test.built_file_path('Test App Gyp.app/Info.plist', + chdir='app-bundle') + test.built_file_must_exist(info_plist) + CheckFileBinaryPropertyList(info_plist) + + # XML Info.plist + info_plist = test.built_file_path('Test App Gyp XML.app/Info.plist', chdir='app-bundle') + CheckFileXMLPropertyList(info_plist) + # Resources + strings_file = test.built_file_path( + 'Test App Gyp.app/English.lproj/InfoPlist.strings', + chdir='app-bundle') + test.built_file_must_exist(strings_file) + CheckFileBinaryPropertyList(strings_file) + test.built_file_must_exist( - 'Test App Gyp.bundle/English.lproj/InfoPlist.strings', + 'Test App Gyp.app/English.lproj/MainMenu.nib', chdir='app-bundle') test.built_file_must_exist( - 'Test App Gyp.bundle/English.lproj/MainMenu.nib', + 'Test App Gyp.app/English.lproj/Main_iPhone.storyboardc', chdir='app-bundle') # Packaging - test.built_file_must_exist('Test App Gyp.bundle/PkgInfo', + test.built_file_must_exist('Test App Gyp.app/PkgInfo', chdir='app-bundle') - test.built_file_must_match('Test App Gyp.bundle/PkgInfo', 'APPLause', + test.built_file_must_match('Test App Gyp.app/PkgInfo', 'APPLause', chdir='app-bundle') test.pass_test() diff -Nru gyp-0.1~svn1729/test/ios/gyptest-archs.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-archs.py --- gyp-0.1~svn1729/test/ios/gyptest-archs.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-archs.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that device and simulator bundles are built correctly. +""" + +import TestGyp +import TestMac + +import collections +import sys + + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + + test_cases = [ + ('Default', 'TestArch32Bits', ['i386']), + ('Default-iphoneos', 'TestArch32Bits', ['armv7']), + ] + + if TestMac.Xcode.Version() < '0510': + test_cases.extend([ + ('Default', 'TestNoArchs', ['i386']), + ('Default-iphoneos', 'TestNoArchs', ['armv7'])]) + + if TestMac.Xcode.Version() >= '0500': + test_cases.extend([ + ('Default', 'TestArch64Bits', ['x86_64']), + ('Default', 'TestMultiArchs', ['i386', 'x86_64']), + ('Default-iphoneos', 'TestArch64Bits', ['arm64']), + ('Default-iphoneos', 'TestMultiArchs', ['armv7', 'arm64'])]) + + test.run_gyp('test-archs.gyp', chdir='app-bundle') + for configuration, target, archs in test_cases: + is_device_build = configuration.endswith('-iphoneos') + + kwds = collections.defaultdict(list) + if test.format == 'xcode': + if is_device_build: + configuration, sdk = configuration.split('-') + kwds['arguments'].extend(['-sdk', sdk]) + if TestMac.Xcode.Version() < '0500': + kwds['arguments'].extend(['-arch', archs[0]]) + + test.set_configuration(configuration) + filename = '%s.bundle/%s' % (target, target) + test.build('test-archs.gyp', target, chdir='app-bundle', **kwds) + result_file = test.built_file_path(filename, chdir='app-bundle') + + test.must_exist(result_file) + TestMac.CheckFileType(test, result_file, archs) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/ios/gyptest-crosscompile.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-crosscompile.py --- gyp-0.1~svn1729/test/ios/gyptest-crosscompile.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-crosscompile.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that tools are built correctly. +""" + +import TestGyp +import TestMac + +import sys +import os + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + + oldenv = os.environ.copy() + try: + os.environ['GYP_CROSSCOMPILE'] = '1' + test.run_gyp('test-crosscompile.gyp', chdir='app-bundle') + finally: + os.environ.clear() + os.environ.update(oldenv) + + test.set_configuration('Default') + test.build('test-crosscompile.gyp', 'TestHost', chdir='app-bundle') + result_file = test.built_file_path('TestHost', chdir='app-bundle') + test.must_exist(result_file) + TestMac.CheckFileType(test, result_file, ['x86_64']) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/ios/gyptest-extension.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-extension.py --- gyp-0.1~svn1729/test/ios/gyptest-extension.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-extension.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that ios app extensions are built correctly. +""" + +import TestGyp +import TestMac + +import sys +if sys.platform == 'darwin' and TestMac.Xcode.Version()>="0600": + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + + test.run_gyp('extension.gyp', chdir='extension') + + test.build('extension.gyp', 'ExtensionContainer', chdir='extension') + + # Test that the extension is .appex + test.built_file_must_exist( + 'ExtensionContainer.app/PlugIns/ActionExtension.appex', + chdir='extension') + + test.pass_test() + diff -Nru gyp-0.1~svn1729/test/ios/gyptest-per-config-settings.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-per-config-settings.py --- gyp-0.1~svn1729/test/ios/gyptest-per-config-settings.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-per-config-settings.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,151 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that device and simulator bundles are built correctly. +""" + +import plistlib +import TestGyp +import os +import struct +import subprocess +import sys +import tempfile + +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + +def CheckFileType(file, expected): + proc = subprocess.Popen(['lipo', '-info', file], stdout=subprocess.PIPE) + o = proc.communicate()[0].strip() + assert not proc.returncode + if not expected in o: + print 'File: Expected %s, got %s' % (expected, o) + test.fail_test() + +def HasCerts(): + # Because the bots do not have certs, don't check them if there are no + # certs available. + proc = subprocess.Popen(['security','find-identity','-p', 'codesigning', + '-v'], stdout=subprocess.PIPE) + return "0 valid identities found" not in proc.communicate()[0].strip() + +def CheckSignature(file): + proc = subprocess.Popen(['codesign', '-v', file], stdout=subprocess.PIPE) + o = proc.communicate()[0].strip() + assert not proc.returncode + if "code object is not signed at all" in o: + print 'File %s not properly signed.' % (file) + test.fail_test() + +def CheckEntitlements(file, expected_entitlements): + with tempfile.NamedTemporaryFile() as temp: + proc = subprocess.Popen(['codesign', '--display', '--entitlements', + temp.name, file], stdout=subprocess.PIPE) + o = proc.communicate()[0].strip() + assert not proc.returncode + data = temp.read() + entitlements = ParseEntitlements(data) + if not entitlements: + print 'No valid entitlements found in %s.' % (file) + test.fail_test() + if entitlements != expected_entitlements: + print 'Unexpected entitlements found in %s.' % (file) + test.fail_test() + +def ParseEntitlements(data): + if len(data) < 8: + return None + magic, length = struct.unpack('>II', data[:8]) + if magic != 0xfade7171 or length != len(data): + return None + return data[8:] + +def GetProductVersion(): + args = ['xcodebuild','-version','-sdk','iphoneos','ProductVersion'] + job = subprocess.Popen(args, stdout=subprocess.PIPE) + return job.communicate()[0].strip() + +def CheckPlistvalue(plist, key, expected): + if key not in plist: + print '%s not set in plist' % key + test.fail_test() + return + actual = plist[key] + if actual != expected: + print 'File: Expected %s, got %s for %s' % (expected, actual, key) + test.fail_test() + +def CheckPlistNotSet(plist, key): + if key in plist: + print '%s should not be set in plist' % key + test.fail_test() + return + +def ConvertBinaryPlistToXML(path): + proc = subprocess.call(['plutil', '-convert', 'xml1', path], + stdout=subprocess.PIPE) + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + + test.run_gyp('test-device.gyp', chdir='app-bundle') + + test_configs = ['Default-iphoneos', 'Default'] + # TODO(justincohen): Disabling 'Default-iphoneos' for xcode until bots are + # configured with signing certs. + if test.format == 'xcode': + test_configs.remove('Default-iphoneos') + + for configuration in test_configs: + test.set_configuration(configuration) + test.build('test-device.gyp', 'test_app', chdir='app-bundle') + result_file = test.built_file_path('Test App Gyp.bundle/Test App Gyp', + chdir='app-bundle') + test.must_exist(result_file) + + info_plist = test.built_file_path('Test App Gyp.bundle/Info.plist', + chdir='app-bundle') + + # plistlib doesn't support binary plists, but that's what Xcode creates. + if test.format == 'xcode': + ConvertBinaryPlistToXML(info_plist) + plist = plistlib.readPlist(info_plist) + + CheckPlistvalue(plist, 'UIDeviceFamily', [1, 2]) + + if configuration == 'Default-iphoneos': + CheckFileType(result_file, 'armv7') + CheckPlistvalue(plist, 'DTPlatformVersion', GetProductVersion()) + CheckPlistvalue(plist, 'CFBundleSupportedPlatforms', ['iPhoneOS']) + CheckPlistvalue(plist, 'DTPlatformName', 'iphoneos') + else: + CheckFileType(result_file, 'i386') + CheckPlistNotSet(plist, 'DTPlatformVersion') + CheckPlistvalue(plist, 'CFBundleSupportedPlatforms', ['iPhoneSimulator']) + CheckPlistvalue(plist, 'DTPlatformName', 'iphonesimulator') + + if HasCerts() and configuration == 'Default-iphoneos': + test.build('test-device.gyp', 'sig_test', chdir='app-bundle') + result_file = test.built_file_path('sig_test.bundle/sig_test', + chdir='app-bundle') + CheckSignature(result_file) + info_plist = test.built_file_path('sig_test.bundle/Info.plist', + chdir='app-bundle') + + plist = plistlib.readPlist(info_plist) + CheckPlistvalue(plist, 'UIDeviceFamily', [1]) + + entitlements_file = test.built_file_path('sig_test.xcent', + chdir='app-bundle') + if os.path.isfile(entitlements_file): + expected_entitlements = open(entitlements_file).read() + CheckEntitlements(result_file, expected_entitlements) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/ios/gyptest-watch.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-watch.py --- gyp-0.1~svn1729/test/ios/gyptest-watch.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-watch.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that ios watch extensions and apps are built correctly. +""" + +import TestGyp +import TestMac + +import sys + +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + +if sys.platform == 'darwin' and TestMac.Xcode.Version() >= "0620": + test = TestGyp.TestGyp(formats=['ninja', 'xcode']) + + test.run_gyp('watch.gyp', chdir='watch') + + test.build( + 'watch.gyp', + 'WatchContainer', + chdir='watch') + + # Test that the extension exists + test.built_file_must_exist( + 'WatchContainer.app/PlugIns/WatchKitExtension.appex', + chdir='watch') + + # Test that the watch app exists + test.built_file_must_exist( + 'WatchContainer.app/PlugIns/WatchKitExtension.appex/WatchApp.app', + chdir='watch') + + test.pass_test() + diff -Nru gyp-0.1~svn1729/test/ios/gyptest-xcode-ninja.py gyp-0.1+20150913git1f374df9/test/ios/gyptest-xcode-ninja.py --- gyp-0.1~svn1729/test/ios/gyptest-xcode-ninja.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/gyptest-xcode-ninja.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verify that the xcode-ninja GYP_GENERATOR runs and builds correctly. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['xcode']) + + # Run ninja and xcode-ninja + test.formats = ['ninja', 'xcode-ninja'] + test.run_gyp('test.gyp', chdir='app-bundle') + + # If it builds the target, it works. + test.build('test.ninja.gyp', chdir='app-bundle') + test.pass_test() diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json --- gyp-0.1~svn1729/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Images.xcassets/AppIcon.appiconset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,62 @@ +{ + "images" : [ + { + "size" : "14.5x14.5", + "idiom" : "watch", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "38mm" + }, + { + "size" : "18x18", + "idiom" : "watch", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "42mm" + }, + { + "size" : "29x29", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "2x" + }, + { + "size" : "29.3x29.3", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "38mm" + }, + { + "size" : "44x44", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "42mm" + }, + { + "size" : "86x86", + "idiom" : "watch", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "38mm" + }, + { + "size" : "98x98", + "idiom" : "watch", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "42mm" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json --- gyp-0.1~svn1729/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Images.xcassets/LaunchImage.launchimage/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "watch", + "extent" : "full-screen", + "minimum-system-version" : "8.0", + "subtype" : "38mm", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "watch", + "extent" : "full-screen", + "minimum-system-version" : "8.0", + "subtype" : "42mm", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchApp/Info.plist gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Info.plist --- gyp-0.1~svn1729/test/ios/watch/WatchApp/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + WatchApp + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.google.gyptest.watch.watchapp + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + WKCompanionAppBundleIdentifier + com.google.gyptest.watch + WKWatchKitApp + + + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchApp/Interface.storyboard gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Interface.storyboard --- gyp-0.1~svn1729/test/ios/watch/WatchApp/Interface.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchApp/Interface.storyboard 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/AppDelegate.h gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/AppDelegate.h --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/AppDelegate.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/AppDelegate.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/AppDelegate.m gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/AppDelegate.m --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/AppDelegate.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/AppDelegate.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication*)application + didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + // Override point for customization after application launch. + return YES; +} + +@end diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Base.lproj/Main.storyboard 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Images.xcassets/AppIcon.appiconset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Images.xcassets/LaunchImage.launchimage/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,51 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "subtype" : "retina4", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/Info.plist gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Info.plist --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + WatchContainer + CFBundleIdentifier + com.google.gyptest.watch + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/main.m gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/main.m --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/main.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/main.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, + NSStringFromClass([AppDelegate class])); + } +} diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/ViewController.h gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/ViewController.h --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/ViewController.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/ViewController.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface ViewController : UIViewController + + +@end + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchContainer/ViewController.m gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/ViewController.m --- gyp-0.1~svn1729/test/ios/watch/WatchContainer/ViewController.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchContainer/ViewController.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ViewController.h" + +@interface ViewController () + + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff -Nru gyp-0.1~svn1729/test/ios/watch/watch.gyp gyp-0.1+20150913git1f374df9/test/ios/watch/watch.gyp --- gyp-0.1~svn1729/test/ios/watch/watch.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/watch.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,105 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ['CXX', '/usr/bin/clang++'], + ], + 'target_defaults': { + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fobjc-abi-version=2', + ], + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'SDKROOT': 'iphoneos', + 'IPHONEOS_DEPLOYMENT_TARGET': '8.2', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + } + }, + 'targets': [ + { + 'target_name': 'WatchContainer', + 'product_name': 'WatchContainer', + 'type': 'executable', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + 'WatchContainer/Base.lproj/Main.storyboard', + ], + 'sources': [ + 'WatchContainer/AppDelegate.h', + 'WatchContainer/AppDelegate.m', + 'WatchContainer/ViewController.h', + 'WatchContainer/ViewController.m', + 'WatchContainer/main.m', + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/WatchContainer.app/PlugIns', + 'files': [ + '<(PRODUCT_DIR)/WatchKitExtension.appex', + ]}], + 'dependencies': [ + 'WatchKitExtension' + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'WatchContainer/Info.plist', + }, + }, + { + 'target_name': 'WatchKitExtension', + 'product_name': 'WatchKitExtension', + 'type': 'executable', + 'mac_bundle': 1, + 'ios_watchkit_extension': 1, + 'sources': [ + 'WatchKitExtension/InterfaceController.h', + 'WatchKitExtension/InterfaceController.m', + ], + 'mac_bundle_resources': [ + 'WatchKitExtension/Images.xcassets', + '<(PRODUCT_DIR)/WatchApp.app', + ], + 'dependencies': [ + 'WatchApp' + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/WatchKit.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'WatchKitExtension/Info.plist', + 'SKIP_INSTALL': 'YES', + 'COPY_PHASE_STRIP': 'NO', + }, + }, + { + 'target_name': 'WatchApp', + 'product_name': 'WatchApp', + 'type': 'executable', + 'mac_bundle': 1, + 'ios_watch_app': 1, + 'mac_bundle_resources': [ + 'WatchApp/Images.xcassets', + 'WatchApp/Interface.storyboard', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'WatchApp/Info.plist', + 'SKIP_INSTALL': 'YES', + 'COPY_PHASE_STRIP': 'NO', + 'TARGETED_DEVICE_FAMILY': '4', + 'TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*]': '1,4', + }, + }, + ], +} + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json --- gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/Images.xcassets/MyImage.imageset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/Info.plist gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/Info.plist --- gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + WatchContainer WatchKit Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.google.gyptest.watch.watchkitextension + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSExtension + + NSExtensionAttributes + + WKAppBundleIdentifier + com.google.gyptest.watch.watchapp + + NSExtensionPointIdentifier + com.apple.watchkit + + RemoteInterfacePrincipalClass + InterfaceController + + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/InterfaceController.h gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/InterfaceController.h --- gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/InterfaceController.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/InterfaceController.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import + +@interface InterfaceController : WKInterfaceController +@end + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/InterfaceController.m gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/InterfaceController.m --- gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/InterfaceController.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/InterfaceController.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "InterfaceController.h" + +@implementation InterfaceController + +- (instancetype)initWithContext:(id)context { + if ((self = [super initWithContext:context])) { + // -initWithContext: + } + return self; +} + +- (void)willActivate { + // -willActivate +} + +- (void)didDeactivate { + // -didDeactivate +} + +@end + diff -Nru gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/MainInterface.storyboard gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/MainInterface.storyboard --- gyp-0.1~svn1729/test/ios/watch/WatchKitExtension/MainInterface.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ios/watch/WatchKitExtension/MainInterface.storyboard 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/lib/TestGyp.py gyp-0.1+20150913git1f374df9/test/lib/TestGyp.py --- gyp-0.1~svn1729/test/lib/TestGyp.py 2013-05-22 10:13:07.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/lib/TestGyp.py 2015-09-13 13:41:20.000000000 +0000 @@ -6,10 +6,12 @@ TestGyp.py: a testing framework for GYP integration tests. """ +import collections +from contextlib import contextmanager +import itertools import os import re import shutil -import stat import subprocess import sys import tempfile @@ -22,9 +24,10 @@ 'TestGyp', ]) + def remove_debug_line_numbers(contents): """Function to remove the line numbers from the debug output - of gyp and thus remove the exremem fragility of the stdout + of gyp and thus reduce the extreme fragility of the stdout comparison tests. """ lines = contents.splitlines() @@ -35,12 +38,26 @@ lines = [len(l) > 3 and ":".join(l[3:]) or l for l in lines] return "\n".join(lines) + def match_modulo_line_numbers(contents_a, contents_b): """File contents matcher that ignores line numbers.""" contents_a = remove_debug_line_numbers(contents_a) contents_b = remove_debug_line_numbers(contents_b) return TestCommon.match_exact(contents_a, contents_b) + +@contextmanager +def LocalEnv(local_env): + """Context manager to provide a local OS environment.""" + old_env = os.environ.copy() + os.environ.update(local_env) + try: + yield + finally: + os.environ.clear() + os.environ.update(old_env) + + class TestGypBase(TestCommon.TestCommon): """ Class for controlling end-to-end tests of gyp generators. @@ -60,6 +77,7 @@ configuration and to run executables generated by those builds. """ + formats = [] build_tool = None build_tool_list = [] @@ -93,6 +111,9 @@ else: gyp = 'gyp' self.gyp = os.path.abspath(gyp) + self.no_parallel = False + + self.formats = [self.format] self.initialize_build_tool() @@ -111,10 +132,11 @@ super(TestGypBase, self).__init__(*args, **kw) + real_format = self.format.split('-')[-1] excluded_formats = set([f for f in formats if f[0] == '!']) included_formats = set(formats) - excluded_formats - if ('!'+self.format in excluded_formats or - included_formats and self.format not in included_formats): + if ('!'+real_format in excluded_formats or + included_formats and real_format not in included_formats): msg = 'Invalid test for %r format; skipping test.\n' self.skip_test(msg % self.format) @@ -128,6 +150,9 @@ # Clear $GYP_DEFINES for the same reason. if 'GYP_DEFINES' in os.environ: del os.environ['GYP_DEFINES'] + # Override the user's language settings, which could + # otherwise make the output vary from what is expected. + os.environ['LC_ALL'] = 'C' def built_file_must_exist(self, name, type=None, **kw): """ @@ -155,6 +180,13 @@ """ return self.must_not_match(self.built_file_path(name, **kw), contents) + def built_file_must_not_contain(self, name, contents, **kw): + """ + Fails the test if the specified built file name contains the specified + contents. + """ + return self.must_not_contain(self.built_file_path(name, **kw), contents) + def copy_test_configuration(self, source_dir, dest_dir): """ Copies the test configuration from the specified source_dir @@ -246,8 +278,18 @@ # TODO: --depth=. works around Chromium-specific tree climbing. depth = kw.pop('depth', '.') - run_args = ['--depth='+depth, '--format='+self.format, gyp_file] + run_args = ['--depth='+depth] + run_args.extend(['--format='+f for f in self.formats]); + run_args.append(gyp_file) + if self.no_parallel: + run_args += ['--no-parallel'] + # TODO: if extra_args contains a '--build' flag + # we really want that to only apply to the last format (self.format). run_args.extend(self.extra_args) + # Default xcode_ninja_target_pattern to ^.*$ to fix xcode-ninja tests + xcode_ninja_target_pattern = kw.pop('xcode_ninja_target_pattern', '.*') + run_args.extend( + ['-G', 'xcode_ninja_target_pattern=%s' % xcode_ninja_target_pattern]) run_args.extend(args) return self.run(program=self.gyp, arguments=run_args, **kw) @@ -349,6 +391,11 @@ internal data structure as pretty-printed Python). """ format = 'gypd' + def __init__(self, gyp=None, *args, **kw): + super(TestGypGypd, self).__init__(*args, **kw) + # gypd implies the use of 'golden' files, so parallelizing conflicts as it + # causes ordering changes. + self.no_parallel = True class TestGypCustom(TestGypBase): @@ -361,161 +408,106 @@ super(TestGypCustom, self).__init__(*args, **kw) -class TestGypAndroid(TestGypBase): +class TestGypCMake(TestGypBase): """ - Subclass for testing the GYP Android makefile generator. Note that - build/envsetup.sh and lunch must have been run before running tests. - - TODO: This is currently an incomplete implementation. We do not support - run_built_executable(), so we pass only tests which do not use this. As a - result, support for host targets is not properly tested. + Subclass for testing the GYP CMake generator, using cmake's ninja backend. """ - format = 'android' + format = 'cmake' + build_tool_list = ['cmake'] + ALL = 'all' - # Note that we can't use mmm as the build tool because ... - # - it builds all targets, whereas we need to pass a target - # - it is a function, whereas the test runner assumes the build tool is a file - # Instead we use make and duplicate the logic from mmm. - build_tool_list = ['make'] + def cmake_build(self, gyp_file, target=None, **kw): + arguments = kw.get('arguments', [])[:] - # We use our custom target 'gyp_all_modules', as opposed to the 'all_modules' - # target used by mmm, to build only those targets which are part of the gyp - # target 'all'. - ALL = 'gyp_all_modules' + self.build_tool_list = ['cmake'] + self.initialize_build_tool() - def __init__(self, gyp=None, *args, **kw): - # Android requires build and test output to be inside its source tree. - # We use the following working directory for the test's source, but the - # test's build output still goes to $ANDROID_PRODUCT_OUT. - # Note that some tests explicitly set format='gypd' to invoke the gypd - # backend. This writes to the source tree, but there's no way around this. - kw['workdir'] = os.path.join('/tmp', 'gyptest', - kw.get('workdir', 'testworkarea')) - # We need to remove all gyp outputs from out/. Ths is because some tests - # don't have rules to regenerate output, so they will simply re-use stale - # output if present. Since the test working directory gets regenerated for - # each test run, this can confuse things. - # We don't have a list of build outputs because we don't know which - # dependent targets were built. Instead we delete all gyp-generated output. - # This may be excessive, but should be safe. - out_dir = os.environ['ANDROID_PRODUCT_OUT'] - obj_dir = os.path.join(out_dir, 'obj') - shutil.rmtree(os.path.join(obj_dir, 'GYP'), ignore_errors = True) - for x in ['EXECUTABLES', 'STATIC_LIBRARIES', 'SHARED_LIBRARIES']: - for d in os.listdir(os.path.join(obj_dir, x)): - if d.endswith('_gyp_intermediates'): - shutil.rmtree(os.path.join(obj_dir, x, d), ignore_errors = True) - for x in [os.path.join('obj', 'lib'), os.path.join('system', 'lib')]: - for d in os.listdir(os.path.join(out_dir, x)): - if d.endswith('_gyp.so'): - os.remove(os.path.join(out_dir, x, d)) + chdir = os.path.join(kw.get('chdir', '.'), + 'out', + self.configuration_dirname()) + kw['chdir'] = chdir - super(TestGypAndroid, self).__init__(*args, **kw) + arguments.append('-G') + arguments.append('Ninja') - def target_name(self, target): - if target == self.ALL: - return self.ALL - # The default target is 'droid'. However, we want to use our special target - # to build only the gyp target 'all'. - if target in (None, self.DEFAULT): - return self.ALL - return target + kw['arguments'] = arguments - def build(self, gyp_file, target=None, **kw): - """ - Runs a build using the Android makefiles generated from the specified - gyp_file. This logic is taken from Android's mmm. - """ + stderr = kw.get('stderr', None) + if stderr: + kw['stderr'] = stderr.split('$$$')[0] + + self.run(program=self.build_tool, **kw) + + def ninja_build(self, gyp_file, target=None, **kw): arguments = kw.get('arguments', [])[:] - arguments.append(self.target_name(target)) + + self.build_tool_list = ['ninja'] + self.initialize_build_tool() + + # Add a -C output/path to the command line. arguments.append('-C') - arguments.append(os.environ['ANDROID_BUILD_TOP']) + arguments.append(os.path.join('out', self.configuration_dirname())) + + if target not in (None, self.DEFAULT): + arguments.append(target) + kw['arguments'] = arguments - chdir = kw.get('chdir', '') - makefile = os.path.join(self.workdir, chdir, 'GypAndroid.mk') - os.environ['ONE_SHOT_MAKEFILE'] = makefile - result = self.run(program=self.build_tool, **kw) - del os.environ['ONE_SHOT_MAKEFILE'] - return result - def android_module(self, group, name, subdir): - if subdir: - name = '%s_%s' % (subdir, name) - if group == 'SHARED_LIBRARIES': - name = 'lib_%s' % name - return '%s_gyp' % name - - def intermediates_dir(self, group, module_name): - return os.path.join(os.environ['ANDROID_PRODUCT_OUT'], 'obj', group, - '%s_intermediates' % module_name) + stderr = kw.get('stderr', None) + if stderr: + stderrs = stderr.split('$$$') + kw['stderr'] = stderrs[1] if len(stderrs) > 1 else '' - def built_file_path(self, name, type=None, **kw): - """ - Returns a path to the specified file name, of the specified type, - as built by Android. Note that we don't support the configuration - parameter. - """ - # Built files are in $ANDROID_PRODUCT_OUT. This requires copying logic from - # the Android build system. - if type == None: - return os.path.join(os.environ['ANDROID_PRODUCT_OUT'], 'obj', 'GYP', - 'shared_intermediates', name) - subdir = kw.get('subdir') - if type == self.EXECUTABLE: - # We don't install executables - group = 'EXECUTABLES' - module_name = self.android_module(group, name, subdir) - return os.path.join(self.intermediates_dir(group, module_name), name) - if type == self.STATIC_LIB: - group = 'STATIC_LIBRARIES' - module_name = self.android_module(group, name, subdir) - return os.path.join(self.intermediates_dir(group, module_name), - '%s.a' % module_name) - if type == self.SHARED_LIB: - group = 'SHARED_LIBRARIES' - module_name = self.android_module(group, name, subdir) - return os.path.join(self.intermediates_dir(group, module_name), 'LINKED', - '%s.so' % module_name) - assert False, 'Unhandled type' + return self.run(program=self.build_tool, **kw) - def run_built_executable(self, name, *args, **kw): - """ - Runs an executable program built from a gyp-generated configuration. + def build(self, gyp_file, target=None, status=0, **kw): + # Two tools must be run to build, cmake and the ninja. + # Allow cmake to succeed when the overall expectation is to fail. + if status is None: + kw['status'] = None + else: + if not isinstance(status, collections.Iterable): status = (status,) + kw['status'] = list(itertools.chain((0,), status)) + self.cmake_build(gyp_file, target, **kw) + kw['status'] = status + self.ninja_build(gyp_file, target, **kw) - This is not correctly implemented for Android. For now, we simply check - that the executable file exists. - """ - # Running executables requires a device. Even if we build for target x86, - # the binary is not built with the correct toolchain options to actually - # run on the host. + def run_built_executable(self, name, *args, **kw): + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + if sys.platform == 'darwin': + configuration = self.configuration_dirname() + os.environ['DYLD_LIBRARY_PATH'] = os.path.join('out', configuration) + return self.run(program=program, *args, **kw) - # Copied from TestCommon.run() - match = kw.pop('match', self.match) - status = None - if os.path.exists(self.built_file_path(name)): - status = 1 - self._complete(None, None, None, None, status, match) - - def match_single_line(self, lines = None, expected_line = None): - """ - Checks that specified line appears in the text. - """ - for line in lines.split('\n'): - if line == expected_line: - return 1 - return + def built_file_path(self, name, type=None, **kw): + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + result.append('out') + result.append(self.configuration_dirname()) + if type == self.STATIC_LIB: + if sys.platform != 'darwin': + result.append('obj.target') + elif type == self.SHARED_LIB: + if sys.platform != 'darwin' and sys.platform != 'win32': + result.append('lib.target') + subdir = kw.get('subdir') + if subdir and type != self.SHARED_LIB: + result.append(subdir) + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) def up_to_date(self, gyp_file, target=None, **kw): - """ - Verifies that a build of the specified target is up to date. - """ - kw['stdout'] = ("make: Nothing to be done for `%s'." % - self.target_name(target)) + result = self.ninja_build(gyp_file, target, **kw) + if not result: + stdout = self.stdout() + if 'ninja: no work to do' not in stdout: + self.report_not_up_to_date() + self.fail_test() + return result - # We need to supply a custom matcher, since we don't want to depend on the - # exact stdout string. - kw['match'] = self.match_single_line - return self.build(gyp_file, target, **kw) class TestGypMake(TestGypBase): """ @@ -612,6 +604,53 @@ return path +def FindMSBuildInstallation(msvs_version = 'auto'): + """Returns path to MSBuild for msvs_version or latest available. + + Looks in the registry to find install location of MSBuild. + MSBuild before v4.0 will not build c++ projects, so only use newer versions. + """ + import TestWin + registry = TestWin.Registry() + + msvs_to_msbuild = { + '2013': r'12.0', + '2012': r'4.0', # Really v4.0.30319 which comes with .NET 4.5. + '2010': r'4.0'} + + msbuild_basekey = r'HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions' + if not registry.KeyExists(msbuild_basekey): + print 'Error: could not find MSBuild base registry entry' + return None + + msbuild_version = None + if msvs_version in msvs_to_msbuild: + msbuild_test_version = msvs_to_msbuild[msvs_version] + if registry.KeyExists(msbuild_basekey + '\\' + msbuild_test_version): + msbuild_version = msbuild_test_version + else: + print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" ' + 'but corresponding MSBuild "%s" was not found.' % + (msvs_version, msbuild_version)) + if not msbuild_version: + for msvs_version in sorted(msvs_to_msbuild, reverse=True): + msbuild_test_version = msvs_to_msbuild[msvs_version] + if registry.KeyExists(msbuild_basekey + '\\' + msbuild_test_version): + msbuild_version = msbuild_test_version + break + if not msbuild_version: + print 'Error: could not find MSBuild registry entry' + return None + + msbuild_path = registry.GetValue(msbuild_basekey + '\\' + msbuild_version, + 'MSBuildToolsPath') + if not msbuild_path: + print 'Error: could not get MSBuild registry entry value' + return None + + return os.path.join(msbuild_path, 'MSBuild.exe') + + def FindVisualStudioInstallation(): """Returns appropriate values for .build_tool and .uses_msbuild fields of TestGypBase for Visual Studio. @@ -624,6 +663,7 @@ for drive in range(ord('C'), ord('Z') + 1) for suffix in ['', ' (x86)']] possible_paths = { + '2013': r'Microsoft Visual Studio 12.0\Common7\IDE\devenv.com', '2012': r'Microsoft Visual Studio 11.0\Common7\IDE\devenv.com', '2010': r'Microsoft Visual Studio 10.0\Common7\IDE\devenv.com', '2008': r'Microsoft Visual Studio 9.0\Common7\IDE\devenv.com', @@ -636,39 +676,28 @@ msvs_version = flag.split('=')[-1] msvs_version = os.environ.get('GYP_MSVS_VERSION', msvs_version) - build_tool = None if msvs_version in possible_paths: # Check that the path to the specified GYP_MSVS_VERSION exists. path = possible_paths[msvs_version] for r in possible_roots: - bt = os.path.join(r, path) - if os.path.exists(bt): - build_tool = bt + build_tool = os.path.join(r, path) + if os.path.exists(build_tool): uses_msbuild = msvs_version >= '2010' - return build_tool, uses_msbuild + msbuild_path = FindMSBuildInstallation(msvs_version) + return build_tool, uses_msbuild, msbuild_path else: print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" ' 'but corresponding "%s" was not found.' % (msvs_version, path)) - if build_tool: - # We found 'devenv' on the path, use that and try to guess the version. - for version, path in possible_paths.iteritems(): - if build_tool.find(path) >= 0: - uses_msbuild = version >= '2010' - return build_tool, uses_msbuild - else: - # If not, assume not MSBuild. - uses_msbuild = False - return build_tool, uses_msbuild # Neither GYP_MSVS_VERSION nor the path help us out. Iterate through # the choices looking for a match. for version in sorted(possible_paths, reverse=True): path = possible_paths[version] for r in possible_roots: - bt = os.path.join(r, path) - if os.path.exists(bt): - build_tool = bt + build_tool = os.path.join(r, path) + if os.path.exists(build_tool): uses_msbuild = msvs_version >= '2010' - return build_tool, uses_msbuild + msbuild_path = FindMSBuildInstallation(msvs_version) + return build_tool, uses_msbuild, msbuild_path print 'Error: could not find devenv' sys.exit(1) @@ -686,7 +715,8 @@ def initialize_build_tool(self): super(TestGypOnMSToolchain, self).initialize_build_tool() if sys.platform in ('win32', 'cygwin'): - self.devenv_path, self.uses_msbuild = FindVisualStudioInstallation() + build_tools = FindVisualStudioInstallation() + self.devenv_path, self.uses_msbuild, self.msbuild_path = build_tools self.vsvars_path = TestGypOnMSToolchain._ComputeVsvarsPath( self.devenv_path) @@ -866,6 +896,56 @@ return self.workpath(*result) +class TestGypMSVSNinja(TestGypNinja): + """ + Subclass for testing the GYP Visual Studio Ninja generator. + """ + format = 'msvs-ninja' + + def initialize_build_tool(self): + super(TestGypMSVSNinja, self).initialize_build_tool() + # When using '--build', make sure ninja is first in the format list. + self.formats.insert(0, 'ninja') + + def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw): + """ + Runs a Visual Studio build using the configuration generated + from the specified gyp_file. + """ + arguments = kw.get('arguments', [])[:] + if target in (None, self.ALL, self.DEFAULT): + # Note: the Visual Studio generator doesn't add an explicit 'all' target. + # This will build each project. This will work if projects are hermetic, + # but may fail if they are not (a project may run more than once). + # It would be nice to supply an all.metaproj for MSBuild. + arguments.extend([gyp_file.replace('.gyp', '.sln')]) + else: + # MSBuild documentation claims that one can specify a sln but then build a + # project target like 'msbuild a.sln /t:proj:target' but this format only + # supports 'Clean', 'Rebuild', and 'Publish' (with none meaning Default). + # This limitation is due to the .sln -> .sln.metaproj conversion. + # The ':' is not special, 'proj:target' is a target in the metaproj. + arguments.extend([target+'.vcxproj']) + + if clean: + build = 'Clean' + elif rebuild: + build = 'Rebuild' + else: + build = 'Build' + arguments.extend(['/target:'+build]) + configuration = self.configuration_buildname() + config = configuration.split('|') + arguments.extend(['/property:Configuration='+config[0]]) + if len(config) > 1: + arguments.extend(['/property:Platform='+config[1]]) + arguments.extend(['/property:BuildInParallel=false']) + arguments.extend(['/verbosity:minimal']) + + kw['arguments'] = arguments + return self.run(program=self.msbuild_path, **kw) + + class TestGypXcode(TestGypBase): """ Subclass for testing the GYP Xcode generator. @@ -893,6 +973,7 @@ 'Checking Dependencies...\n** BUILD SUCCEEDED **\n', # Xcode 3.0/3.1 'Check dependencies\n** BUILD SUCCEEDED **\n\n', # Xcode 3.2 'Check dependencies\n\n\n** BUILD SUCCEEDED **\n\n', # Xcode 4.2 + 'Check dependencies\n\n** BUILD SUCCEEDED **\n\n', # Xcode 5.0 ) def build(self, gyp_file, target=None, **kw): @@ -975,13 +1056,83 @@ return self.workpath(*result) +class TestGypXcodeNinja(TestGypXcode): + """ + Subclass for testing the GYP Xcode Ninja generator. + """ + format = 'xcode-ninja' + + def initialize_build_tool(self): + super(TestGypXcodeNinja, self).initialize_build_tool() + # When using '--build', make sure ninja is first in the format list. + self.formats.insert(0, 'ninja') + + def build(self, gyp_file, target=None, **kw): + """ + Runs an xcodebuild using the .xcodeproj generated from the specified + gyp_file. + """ + build_config = self.configuration + if build_config and build_config.endswith(('-iphoneos', + '-iphonesimulator')): + build_config, sdk = self.configuration.split('-') + kw['arguments'] = kw.get('arguments', []) + ['-sdk', sdk] + + with self._build_configuration(build_config): + return super(TestGypXcodeNinja, self).build( + gyp_file.replace('.gyp', '.ninja.gyp'), target, **kw) + + @contextmanager + def _build_configuration(self, build_config): + config = self.configuration + self.configuration = build_config + try: + yield + finally: + self.configuration = config + + def built_file_path(self, name, type=None, **kw): + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + result.append('out') + result.append(self.configuration_dirname()) + subdir = kw.get('subdir') + if subdir and type != self.SHARED_LIB: + result.append(subdir) + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) + + def up_to_date(self, gyp_file, target=None, **kw): + result = self.build(gyp_file, target, **kw) + if not result: + stdout = self.stdout() + if 'ninja: no work to do' not in stdout: + self.report_not_up_to_date() + self.fail_test() + return result + + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable built by xcodebuild + ninja. + """ + configuration = self.configuration_dirname() + os.environ['DYLD_LIBRARY_PATH'] = os.path.join('out', configuration) + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + return self.run(program=program, *args, **kw) + + format_class_list = [ TestGypGypd, - TestGypAndroid, + TestGypCMake, TestGypMake, TestGypMSVS, + TestGypMSVSNinja, TestGypNinja, TestGypXcode, + TestGypXcodeNinja, ] def TestGyp(*args, **kw): diff -Nru gyp-0.1~svn1729/test/lib/TestMac.py gyp-0.1+20150913git1f374df9/test/lib/TestMac.py --- gyp-0.1~svn1729/test/lib/TestMac.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/lib/TestMac.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,73 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +TestMac.py: a collection of helper function shared between test on Mac OS X. +""" + +import re +import subprocess + +__all__ = ['Xcode', 'CheckFileType'] + + +def CheckFileType(test, file, archs): + """Check that |file| contains exactly |archs| or fails |test|.""" + proc = subprocess.Popen(['lipo', '-info', file], stdout=subprocess.PIPE) + o = proc.communicate()[0].strip() + assert not proc.returncode + if len(archs) == 1: + pattern = re.compile('^Non-fat file: (.*) is architecture: (.*)$') + else: + pattern = re.compile('^Architectures in the fat file: (.*) are: (.*)$') + match = pattern.match(o) + if match is None: + print 'Ouput does not match expected pattern: %s' % (pattern.pattern) + test.fail_test() + else: + found_file, found_archs = match.groups() + if found_file != file or set(found_archs.split()) != set(archs): + print 'Expected file %s with arch %s, got %s with arch %s' % ( + file, ' '.join(archs), found_file, found_archs) + test.fail_test() + + +class XcodeInfo(object): + """Simplify access to Xcode informations.""" + + def __init__(self): + self._cache = {} + + def _XcodeVersion(self): + lines = subprocess.check_output(['xcodebuild', '-version']).splitlines() + version = ''.join(lines[0].split()[-1].split('.')) + version = (version + '0' * (3 - len(version))).zfill(4) + return version, lines[-1].split()[-1] + + def Version(self): + if 'Version' not in self._cache: + self._cache['Version'], self._cache['Build'] = self._XcodeVersion() + return self._cache['Version'] + + def Build(self): + if 'Build' not in self._cache: + self._cache['Version'], self._cache['Build'] = self._XcodeVersion() + return self._cache['Build'] + + def SDKBuild(self): + if 'SDKBuild' not in self._cache: + self._cache['SDKBuild'] = subprocess.check_output( + ['xcodebuild', '-version', '-sdk', '', 'ProductBuildVersion']) + self._cache['SDKBuild'] = self._cache['SDKBuild'].rstrip('\n') + return self._cache['SDKBuild'] + + def SDKVersion(self): + if 'SDKVersion' not in self._cache: + self._cache['SDKVersion'] = subprocess.check_output( + ['xcodebuild', '-version', '-sdk', '', 'SDKVersion']) + self._cache['SDKVersion'] = self._cache['SDKVersion'].rstrip('\n') + return self._cache['SDKVersion'] + + +Xcode = XcodeInfo() diff -Nru gyp-0.1~svn1729/test/lib/TestWin.py gyp-0.1+20150913git1f374df9/test/lib/TestWin.py --- gyp-0.1~svn1729/test/lib/TestWin.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/lib/TestWin.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,101 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +TestWin.py: a collection of helpers for testing on Windows. +""" + +import errno +import os +import re +import sys +import subprocess + +class Registry(object): + def _QueryBase(self, sysdir, key, value): + """Use reg.exe to read a particular key. + + While ideally we might use the win32 module, we would like gyp to be + python neutral, so for instance cygwin python lacks this module. + + Arguments: + sysdir: The system subdirectory to attempt to launch reg.exe from. + key: The registry key to read from. + value: The particular value to read. + Return: + stdout from reg.exe, or None for failure. + """ + # Skip if not on Windows or Python Win32 setup issue + if sys.platform not in ('win32', 'cygwin'): + return None + # Setup params to pass to and attempt to launch reg.exe + cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'), + 'query', key] + if value: + cmd.extend(['/v', value]) + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # Get the stdout from reg.exe, reading to the end so p.returncode is valid + # Note that the error text may be in [1] in some cases + text = p.communicate()[0] + # Check return code from reg.exe; officially 0==success and 1==error + if p.returncode: + return None + return text + + def Query(self, key, value=None): + r"""Use reg.exe to read a particular key through _QueryBase. + + First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If + that fails, it falls back to System32. Sysnative is available on Vista and + up and available on Windows Server 2003 and XP through KB patch 942589. Note + that Sysnative will always fail if using 64-bit python due to it being a + virtual directory and System32 will work correctly in the first place. + + KB 942589 - http://support.microsoft.com/kb/942589/en-us. + + Arguments: + key: The registry key. + value: The particular registry value to read (optional). + Return: + stdout from reg.exe, or None for failure. + """ + text = None + try: + text = self._QueryBase('Sysnative', key, value) + except OSError, e: + if e.errno == errno.ENOENT: + text = self._QueryBase('System32', key, value) + else: + raise + return text + + def GetValue(self, key, value): + """Use reg.exe to obtain the value of a registry key. + + Args: + key: The registry key. + value: The particular registry value to read. + Return: + contents of the registry key's value, or None on failure. + """ + text = self.Query(key, value) + if not text: + return None + # Extract value. + match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text) + if not match: + return None + return match.group(1) + + def KeyExists(self, key): + """Use reg.exe to see if a key exists. + + Args: + key: The registry key to check. + Return: + True if the key exists + """ + if not self.Query(key): + return False + return True diff -Nru gyp-0.1~svn1729/test/library/gyptest-shared-obj-install-path.py gyp-0.1+20150913git1f374df9/test/library/gyptest-shared-obj-install-path.py --- gyp-0.1~svn1729/test/library/gyptest-shared-obj-install-path.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/library/gyptest-shared-obj-install-path.py 2015-09-13 13:41:20.000000000 +0000 @@ -23,10 +23,7 @@ test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src') -if test.format=='android': - makefile_path = 'relocate/src/GypAndroid.mk' -else: - makefile_path = 'relocate/src/Makefile' +makefile_path = 'relocate/src/Makefile' with open(makefile_path) as makefile: make_contents = makefile.read() diff -Nru gyp-0.1~svn1729/test/library/src/program.c gyp-0.1+20150913git1f374df9/test/library/src/program.c --- gyp-0.1~svn1729/test/library/src/program.c 2009-09-19 15:25:51.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/library/src/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ extern void lib2_function(void); extern void moveable_function(void); -int main(int argc, char *argv[]) +int main(void) { fprintf(stdout, "Hello from program.c\n"); fflush(stdout); diff -Nru gyp-0.1~svn1729/test/library_dirs/gyptest-library-dirs.py gyp-0.1+20150913git1f374df9/test/library_dirs/gyptest-library-dirs.py --- gyp-0.1~svn1729/test/library_dirs/gyptest-library-dirs.py 2013-07-02 00:49:07.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/library_dirs/gyptest-library-dirs.py 2015-09-13 13:41:20.000000000 +0000 @@ -8,9 +8,11 @@ Verifies library_dirs (in link_settings) are properly found. """ +import sys + import TestGyp -test = TestGyp.TestGyp(formats=['!android']) +test = TestGyp.TestGyp() lib_dir = test.tempdir('secret_location') @@ -29,5 +31,20 @@ test.run_built_executable( 'libraries-search-path-test', chdir='subdir', stdout=expect) +if sys.platform in ('win32', 'cygwin'): + test.run_gyp('test-win.gyp', + '-D', + 'abs_path_to_secret_library_location={0}'.format(lib_dir), + chdir='subdir') + + test.build('test.gyp', 'mylib', chdir='subdir') + test.build('test-win.gyp', + 'libraries-search-path-test-lib-suffix', + chdir='subdir') + + test.run_built_executable( + 'libraries-search-path-test-lib-suffix', chdir='subdir', stdout=expect) + + test.pass_test() test.cleanup() diff -Nru gyp-0.1~svn1729/test/library_dirs/subdir/test-win.gyp gyp-0.1+20150913git1f374df9/test/library_dirs/subdir/test-win.gyp --- gyp-0.1~svn1729/test/library_dirs/subdir/test-win.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/library_dirs/subdir/test-win.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,60 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + # This creates a static library and puts it in a nonstandard location for + # libraries-search-path-test. + 'target_name': 'mylib', + 'type': 'static_library', + 'standalone_static_library': 1, + # This directory is NOT in the default library search locations. It also + # MUST be passed in on the gyp command line: + # + # -D abs_path_to_secret_library_location=/some_absolute_path + # + # The gyptest itself (../gyptest-library-dirs.py) provides this. + 'product_dir': '<(abs_path_to_secret_library_location)', + 'sources': [ + 'mylib.cc', + ], + }, + { + 'target_name': 'libraries-search-path-test-lib-suffix', + 'type': 'executable', + 'dependencies': [ + # It is important to NOT list the mylib as a dependency here, because + # some build systems will track it down based on its product_dir, + # such that the link succeeds even without the library_dirs below. + # + # The point of this weird structuring is to ensure that 'library_dirs' + # works as advertised, such that just '-lmylib' (or its equivalent) + # works based on the directories that library_dirs puts in the library + # link path. + # + # If 'mylib' was listed as a proper dependency here, the build system + # would find it and link with its path on disk. + # + # Note that this implies 'mylib' must already be built when building + # 'libraries-search-path-test' (see ../gyptest-library-dirs.py). + # + #'mylib', + ], + 'sources': [ + 'hello.cc', + ], + # Note that without this, the mylib library would not be found and + # successfully linked. + 'library_dirs': [ + '<(abs_path_to_secret_library_location)', + ], + 'link_settings': { + 'libraries': [ + '-lmylib.lib', + ], + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/link-dependency/gyptest-link-dependency.py gyp-0.1+20150913git1f374df9/test/link-dependency/gyptest-link-dependency.py --- gyp-0.1~svn1729/test/link-dependency/gyptest-link-dependency.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/link-dependency/gyptest-link-dependency.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verify that a target marked as 'link_dependency==1' isn't being pulled into +the 'none' target's dependency (which would otherwise lead to a dependency +cycle in ninja). +""" + +import TestGyp + +# See https://codereview.chromium.org/177043010/#msg15 for why this doesn't +# work with cmake. +test = TestGyp.TestGyp(formats=['!cmake']) + +test.run_gyp('test.gyp') +test.build('test.gyp', 'main') + +# If running gyp worked, all is well. +test.pass_test() diff -Nru gyp-0.1~svn1729/test/link-dependency/main.c gyp-0.1+20150913git1f374df9/test/link-dependency/main.c --- gyp-0.1~svn1729/test/link-dependency/main.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/link-dependency/main.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +#include +#include +int main() { + void *p = malloc(1); + printf("p: %p\n", p); + return 0; +} diff -Nru gyp-0.1~svn1729/test/link-dependency/mymalloc.c gyp-0.1+20150913git1f374df9/test/link-dependency/mymalloc.c --- gyp-0.1~svn1729/test/link-dependency/mymalloc.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/link-dependency/mymalloc.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +#include + +// The windows ninja generator is expecting an import library to get generated, +// but it doesn't if there are no exports. +#ifdef _MSC_VER +__declspec(dllexport) void foo() {} +#endif + +void *malloc(size_t size) { + (void)size; + return (void*)0xdeadbeef; +} diff -Nru gyp-0.1~svn1729/test/link-dependency/test.gyp gyp-0.1+20150913git1f374df9/test/link-dependency/test.gyp --- gyp-0.1~svn1729/test/link-dependency/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/link-dependency/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,37 @@ +{ + 'variables': { + 'custom_malloc%' : 1, + }, + 'target_defaults': { + 'conditions': [ + ['custom_malloc==1', { + 'dependencies': [ + 'malloc', + ], + }], + ], + }, + 'targets': [ + { + 'target_name': 'main', + 'type': 'none', + 'dependencies': [ 'main_initial',], + }, + { + 'target_name': 'main_initial', + 'type': 'executable', + 'product_name': 'main', + 'sources': [ 'main.c' ], + }, + { + 'target_name': 'malloc', + 'type': 'shared_library', + 'variables': { + 'prune_self_dependency': 1, + # Targets with type 'none' won't depend on this target. + 'link_dependency': 1, + }, + 'sources': [ 'mymalloc.c' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/link-objects/base.c gyp-0.1+20150913git1f374df9/test/link-objects/base.c --- gyp-0.1~svn1729/test/link-objects/base.c 2011-01-04 19:28:59.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/link-objects/base.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ void extra(); -int main(int argc, char** argv) { +int main(void) { extra(); return 0; } diff -Nru gyp-0.1~svn1729/test/linux/gyptest-ldflags-duplicates.py gyp-0.1+20150913git1f374df9/test/linux/gyptest-ldflags-duplicates.py --- gyp-0.1~svn1729/test/linux/gyptest-ldflags-duplicates.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/linux/gyptest-ldflags-duplicates.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies duplicate ldflags are not removed. +""" + +import TestGyp + +import sys + +if sys.platform.startswith('linux'): + test = TestGyp.TestGyp() + + CHDIR = 'ldflags-duplicates' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/linux/ldflags-duplicates/check-ldflags.py gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/check-ldflags.py --- gyp-0.1~svn1729/test/linux/ldflags-duplicates/check-ldflags.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/check-ldflags.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies duplicate ldflags are not removed. +""" + +import sys + +def CheckContainsFlags(args, substring): + if args.find(substring) is -1: + print 'ERROR: Linker arguments "%s" are missing in "%s"' % (substring, args) + return False; + return True; + +if __name__ == '__main__': + args = " ".join(sys.argv) + print "args = " +args + if not CheckContainsFlags(args, 'lib1.a -Wl,--no-whole-archive') \ + or not CheckContainsFlags(args, 'lib2.a -Wl,--no-whole-archive'): + sys.exit(1); + sys.exit(0) diff -Nru gyp-0.1~svn1729/test/linux/ldflags-duplicates/lib1.c gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/lib1.c --- gyp-0.1~svn1729/test/linux/ldflags-duplicates/lib1.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/lib1.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void foo() { +} diff -Nru gyp-0.1~svn1729/test/linux/ldflags-duplicates/lib2.c gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/lib2.c --- gyp-0.1~svn1729/test/linux/ldflags-duplicates/lib2.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/lib2.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void bar() { +} diff -Nru gyp-0.1~svn1729/test/linux/ldflags-duplicates/main.c gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/main.c --- gyp-0.1~svn1729/test/linux/ldflags-duplicates/main.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/main.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/linux/ldflags-duplicates/test.gyp gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/test.gyp --- gyp-0.1~svn1729/test/linux/ldflags-duplicates/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/linux/ldflags-duplicates/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,45 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'make_global_settings': [ + ['LINK_wrapper', './check-ldflags.py'], + ], + 'targets': [ + { + 'target_name': 'test', + 'type': 'executable', + 'ldflags': [ + '-Wl,--whole-archive <(PRODUCT_DIR)/lib1.a', + '-Wl,--no-whole-archive', + + '-Wl,--whole-archive <(PRODUCT_DIR)/lib2.a', + '-Wl,--no-whole-archive', + ], + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'sources': [ + 'main.c', + ], + }, + { + 'target_name': 'lib1', + 'type': 'static_library', + 'standalone_static_library': 1, + 'sources': [ + 'lib1.c', + ], + }, + { + 'target_name': 'lib2', + 'type': 'static_library', + 'standalone_static_library': 1, + 'sources': [ + 'lib2.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json --- gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff -Nru gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json --- gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "super_sylvain.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "super_sylvain@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "super_sylvain@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file Binary files /tmp/dvXclg8H0q/gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png and /tmp/5lRImkuIue/gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png differ Binary files /tmp/dvXclg8H0q/gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png and /tmp/5lRImkuIue/gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png differ Binary files /tmp/dvXclg8H0q/gyp-0.1~svn1729/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png and /tmp/5lRImkuIue/gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png differ diff -Nru gyp-0.1~svn1729/test/mac/app-bundle/TestApp/TestApp-Info.plist gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/TestApp-Info.plist --- gyp-0.1~svn1729/test/mac/app-bundle/TestApp/TestApp-Info.plist 2012-03-09 17:45:45.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/app-bundle/TestApp/TestApp-Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -2,6 +2,8 @@ + BuildMachineOSBuild + Doesn't matter, will be overwritten CFBundleDevelopmentRegion English CFBundleExecutable @@ -9,7 +11,7 @@ CFBundleIconFile CFBundleIdentifier - com.google.${PRODUCT_NAME} + com.google.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName diff -Nru gyp-0.1~svn1729/test/mac/app-bundle/test-assets-catalog.gyp gyp-0.1+20150913git1f374df9/test/mac/app-bundle/test-assets-catalog.gyp --- gyp-0.1~svn1729/test/mac/app-bundle/test-assets-catalog.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/app-bundle/test-assets-catalog.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,43 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'dep_framework', + 'product_name': 'Dependency Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'empty.c', ], + }, + { + 'target_name': 'test_app', + 'product_name': 'Test App Assets Catalog Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'dependencies': [ 'dep_framework', ], + 'sources': [ + 'TestApp/main.m', + 'TestApp/TestApp_Prefix.pch', + 'TestApp/TestAppAppDelegate.h', + 'TestApp/TestAppAppDelegate.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', # UTF-8 + 'TestApp/English.lproj/utf-16be.strings', + 'TestApp/English.lproj/utf-16le.strings', + 'TestApp/English.lproj/MainMenu.xib', + 'TestApp/Images.xcassets', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + 'MACOSX_DEPLOYMENT_TARGET': '10.9', + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/archs/file_a.cc gyp-0.1+20150913git1f374df9/test/mac/archs/file_a.cc --- gyp-0.1~svn1729/test/mac/archs/file_a.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/file_a.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "file_a.h" + +void DependentFunctionA() { +} diff -Nru gyp-0.1~svn1729/test/mac/archs/file_a.h gyp-0.1+20150913git1f374df9/test/mac/archs/file_a.h --- gyp-0.1~svn1729/test/mac/archs/file_a.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/file_a.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef _INCLUDED_TEST_MAC_DEPENDENCIES_FILE_A_H_ +#define _INCLUDED_TEST_MAC_DEPENDENCIES_FILE_A_H_ + +void DependentFunctionA(); + +#endif // _INCLUDED_TEST_MAC_DEPENDENCIES_FILE_A_H_ diff -Nru gyp-0.1~svn1729/test/mac/archs/file_b.cc gyp-0.1+20150913git1f374df9/test/mac/archs/file_b.cc --- gyp-0.1~svn1729/test/mac/archs/file_b.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/file_b.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "file_b.h" + +void DependentFunctionB() { +} diff -Nru gyp-0.1~svn1729/test/mac/archs/file_b.h gyp-0.1+20150913git1f374df9/test/mac/archs/file_b.h --- gyp-0.1~svn1729/test/mac/archs/file_b.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/file_b.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef _INCLUDED_TEST_MAC_DEPENDENCIES_FILE_B_H_ +#define _INCLUDED_TEST_MAC_DEPENDENCIES_FILE_B_H_ + +void DependentFunctionB(); + +#endif // _INCLUDED_TEST_MAC_DEPENDENCIES_FILE_B_H_ diff -Nru gyp-0.1~svn1729/test/mac/archs/file_c.cc gyp-0.1+20150913git1f374df9/test/mac/archs/file_c.cc --- gyp-0.1~svn1729/test/mac/archs/file_c.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/file_c.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "file_a.h" +#include "file_b.h" + +void PublicFunctionC() { + DependentFunctionA(); + DependentFunctionB(); +} diff -Nru gyp-0.1~svn1729/test/mac/archs/file_d.cc gyp-0.1+20150913git1f374df9/test/mac/archs/file_d.cc --- gyp-0.1~svn1729/test/mac/archs/file_d.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/file_d.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "file_a.h" +#include "file_b.h" + +void PublicFunctionD() { + DependentFunctionA(); + DependentFunctionB(); +} diff -Nru gyp-0.1~svn1729/test/mac/archs/test-archs-multiarch.gyp gyp-0.1+20150913git1f374df9/test/mac/archs/test-archs-multiarch.gyp --- gyp-0.1~svn1729/test/mac/archs/test-archs-multiarch.gyp 2013-08-12 13:39:13.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/test-archs-multiarch.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -21,6 +21,16 @@ }, }, { + 'target_name': 'shared_32_64_bundle', + 'product_name': 'My Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'my_file.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + { 'target_name': 'module_32_64', 'type': 'loadable_module', 'sources': [ 'my_file.cc' ], @@ -29,6 +39,16 @@ }, }, { + 'target_name': 'module_32_64_bundle', + 'product_name': 'My Bundle', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'my_file.cc' ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + { 'target_name': 'exe_32_64', 'type': 'executable', 'sources': [ 'empty_main.cc' ], @@ -56,5 +76,17 @@ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', }, }, + # This does not compile but should not cause generation errors. + { + 'target_name': 'exe_32_64_no_sources', + 'type': 'executable', + 'dependencies': [ + 'static_32_64', + ], + 'sources': [], + 'xcode_settings': { + 'ARCHS': ['i386', 'x86_64'], + }, + }, ] } diff -Nru gyp-0.1~svn1729/test/mac/archs/test-dependencies.gyp gyp-0.1+20150913git1f374df9/test/mac/archs/test-dependencies.gyp --- gyp-0.1~svn1729/test/mac/archs/test-dependencies.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/test-dependencies.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,92 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'target_defaults': { + 'xcode_settings': { + 'ARCHS': ['i386', 'x86_64'], + }, + }, + 'targets': [ + { + 'target_name': 'target_a', + 'type': 'static_library', + 'sources': [ + 'file_a.cc', + 'file_a.h', + ], + }, + { + 'target_name': 'target_b', + 'type': 'static_library', + 'sources': [ + 'file_b.cc', + 'file_b.h', + ], + }, + { + 'target_name': 'target_c_standalone_helper', + 'type': 'loadable_module', + 'hard_dependency': 1, + 'dependencies': [ + 'target_a', + 'target_b', + ], + 'sources': [ + 'file_c.cc', + ], + }, + { + 'target_name': 'target_c_standalone', + 'type': 'none', + 'dependencies': [ + 'target_c_standalone_helper', + ], + 'actions': [ + { + 'action_name': 'Package C', + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/libc_standalone.a', + ], + 'action': [ + 'touch', + '<@(_outputs)', + ], + }, + ], + }, + { + 'target_name': 'target_d_standalone_helper', + 'type': 'shared_library', + 'dependencies': [ + 'target_a', + 'target_b', + ], + 'sources': [ + 'file_d.cc', + ], + }, + { + 'target_name': 'target_d_standalone', + 'type': 'none', + 'dependencies': [ + 'target_d_standalone_helper', + ], + 'actions': [ + { + 'action_name': 'Package D', + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/libd_standalone.a', + ], + 'action': [ + 'touch', + '<@(_outputs)', + ], + }, + ], + } + ], +} diff -Nru gyp-0.1~svn1729/test/mac/archs/test-valid-archs.gyp gyp-0.1+20150913git1f374df9/test/mac/archs/test-valid-archs.gyp --- gyp-0.1~svn1729/test/mac/archs/test-valid-archs.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/archs/test-valid-archs.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,28 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'lib', + 'product_name': 'Test', + 'type': 'static_library', + 'sources': [ 'my_file.cc' ], + 'xcode_settings': { + 'ARCHS': ['i386', 'x86_64', 'unknown-arch'], + 'VALID_ARCHS': ['x86_64'], + }, + }, + { + 'target_name': 'exe', + 'product_name': 'Test', + 'type': 'executable', + 'dependencies': [ 'lib' ], + 'sources': [ 'my_main_file.cc' ], + 'xcode_settings': { + 'ARCHS': ['i386', 'x86_64', 'unknown-arch'], + 'VALID_ARCHS': ['x86_64'], + }, + }] +} diff -Nru gyp-0.1~svn1729/test/mac/bundle-resources/executable-file.sh gyp-0.1+20150913git1f374df9/test/mac/bundle-resources/executable-file.sh --- gyp-0.1~svn1729/test/mac/bundle-resources/executable-file.sh 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/bundle-resources/executable-file.sh 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo echo echo echo cho ho o o diff -Nru gyp-0.1~svn1729/test/mac/bundle-resources/test.gyp gyp-0.1+20150913git1f374df9/test/mac/bundle-resources/test.gyp --- gyp-0.1~svn1729/test/mac/bundle-resources/test.gyp 2013-09-04 21:42:14.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/bundle-resources/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,7 @@ 'mac_bundle': 1, 'mac_bundle_resources': [ 'secret.txt', + 'executable-file.sh', ], }, # A rule with process_outputs_as_mac_bundle_resources should copy files diff -Nru gyp-0.1~svn1729/test/mac/clang-cxx-library/libc++.cc gyp-0.1+20150913git1f374df9/test/mac/clang-cxx-library/libc++.cc --- gyp-0.1~svn1729/test/mac/clang-cxx-library/libc++.cc 2013-03-14 20:50:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/clang-cxx-library/libc++.cc 2015-09-13 13:41:20.000000000 +0000 @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include +#include #ifndef _LIBCPP_VERSION #error expected std library: libc++ #endif -int main() { return 0; } +int main() { std::string x; return x.size(); } diff -Nru gyp-0.1~svn1729/test/mac/clang-cxx-library/libstdc++.cc gyp-0.1+20150913git1f374df9/test/mac/clang-cxx-library/libstdc++.cc --- gyp-0.1~svn1729/test/mac/clang-cxx-library/libstdc++.cc 2013-03-14 20:50:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/clang-cxx-library/libstdc++.cc 2015-09-13 13:41:20.000000000 +0000 @@ -7,5 +7,5 @@ #error expected std library: libstdc++ #endif -int main() { return 0; } +int main() { std::string x; return x.size(); } diff -Nru gyp-0.1~svn1729/test/mac/framework/framework.gyp gyp-0.1+20150913git1f374df9/test/mac/framework/framework.gyp --- gyp-0.1~svn1729/test/mac/framework/framework.gyp 2013-08-27 23:35:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/framework/framework.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -67,5 +67,28 @@ }, ], }, + { + 'target_name': 'copy_target_code_sign', + 'type': 'none', + 'dependencies': [ 'test_framework', 'dep_framework', ], + 'copies': [ + # Test copying directories with spaces in src and dest paths. + { + 'destination': '<(PRODUCT_DIR)/Test Framework.framework/foo', + 'files': [ + '<(PRODUCT_DIR)/Dependency Bundle.framework', + ], + 'xcode_code_sign': 1, + }, + ], + 'actions': [ + { + 'action_name': 'aektschn', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/touched_file'], + 'action': ['touch', '${BUILT_PRODUCTS_DIR}/action_file'], + }, + ], + }, ], } diff -Nru gyp-0.1~svn1729/test/mac/framework/TestFramework/Info.plist gyp-0.1+20150913git1f374df9/test/mac/framework/TestFramework/Info.plist --- gyp-0.1~svn1729/test/mac/framework/TestFramework/Info.plist 2011-07-18 22:04:39.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/framework/TestFramework/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME} + com.yourcompany.${PRODUCT_NAME:identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName diff -Nru gyp-0.1~svn1729/test/mac/gyptest-action-envvars.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-action-envvars.py --- gyp-0.1~svn1729/test/mac/gyptest-action-envvars.py 2012-01-14 01:13:04.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-action-envvars.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,6 +15,12 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + # The xcode-ninja generator handles gypfiles which are not at the + # project root incorrectly. + # cf. https://code.google.com/p/gyp/issues/detail?id=460 + if test.format == 'xcode-ninja': + test.skip_test() + CHDIR = 'action-envvars' test.run_gyp('action/action.gyp', chdir=CHDIR) test.build('action/action.gyp', 'action', chdir=CHDIR, SYMROOT='../build') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-app-assets-catalog.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-app-assets-catalog.py --- gyp-0.1~svn1729/test/mac/gyptest-app-assets-catalog.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-app-assets-catalog.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that app bundles are built correctly. +""" + +import TestGyp +import TestMac + +import os +import plistlib +import subprocess +import sys + +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + +def ExpectEq(expected, actual): + if expected != actual: + print >>sys.stderr, 'Expected "%s", got "%s"' % (expected, actual) + test.fail_test() + +def ls(path): + '''Returns a list of all files in a directory, relative to the directory.''' + result = [] + for dirpath, _, files in os.walk(path): + for f in files: + result.append(os.path.join(dirpath, f)[len(path) + 1:]) + return result + +# Xcode supports for assets catalog was introduced in Xcode 6.0 +if sys.platform == 'darwin' and TestMac.Xcode.Version() >= '0600': + test_gyp_path = 'test-assets-catalog.gyp' + test_app_path = 'Test App Assets Catalog Gyp.app' + + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + test.run_gyp(test_gyp_path, chdir='app-bundle') + test.build(test_gyp_path, test.ALL, chdir='app-bundle') + + # Binary + test.built_file_must_exist( + os.path.join(test_app_path, 'Contents/MacOS/Test App Assets Catalog Gyp'), + chdir='app-bundle') + + # Info.plist + info_plist = test.built_file_path( + os.path.join(test_app_path, 'Contents/Info.plist'), + chdir='app-bundle') + test.must_exist(info_plist) + test.must_contain( + info_plist, + 'com.google.Test-App-Assets-Catalog-Gyp') # Variable expansion + test.must_not_contain(info_plist, '${MACOSX_DEPLOYMENT_TARGET}'); + + if test.format != 'make': + # TODO: Synthesized plist entries aren't hooked up in the make generator. + machine = subprocess.check_output(['sw_vers', '-buildVersion']).rstrip('\n') + plist = plistlib.readPlist(info_plist) + ExpectEq(machine, plist['BuildMachineOSBuild']) + + expected = '' + version = TestMac.Xcode.SDKVersion() + expected = 'macosx' + version + ExpectEq(expected, plist['DTSDKName']) + sdkbuild = TestMac.Xcode.SDKBuild() + if not sdkbuild: + # Above command doesn't work in Xcode 4.2. + sdkbuild = plist['BuildMachineOSBuild'] + ExpectEq(sdkbuild, plist['DTSDKBuild']) + ExpectEq(TestMac.Xcode.Version(), plist['DTXcode']) + ExpectEq(TestMac.Xcode.Build(), plist['DTXcodeBuild']) + + # Resources + strings_files = ['InfoPlist.strings', 'utf-16be.strings', 'utf-16le.strings'] + for f in strings_files: + strings = test.built_file_path( + os.path.join(test_app_path, 'Contents/Resources/English.lproj', f), + chdir='app-bundle') + test.must_exist(strings) + # Xcodes writes UTF-16LE with BOM. + contents = open(strings, 'rb').read() + if not contents.startswith('\xff\xfe' + '/* Localized'.encode('utf-16le')): + test.fail_test() + + test.built_file_must_exist( + os.path.join( + test_app_path, 'Contents/Resources/English.lproj/MainMenu.nib'), + chdir='app-bundle') + + # make does not supports .xcassets files + extra_content_files = [] + if test.format != 'make': + extra_content_files = ['Contents/Resources/Assets.car'] + for f in extra_content_files: + test.built_file_must_exist( + os.path.join(test_app_path, f), + chdir='app-bundle') + + # Packaging + test.built_file_must_exist( + os.path.join(test_app_path, 'Contents/PkgInfo'), + chdir='app-bundle') + test.built_file_must_match( + os.path.join(test_app_path, 'Contents/PkgInfo'), 'APPLause', + chdir='app-bundle') + + # Check that no other files get added to the bundle. + if set(ls(test.built_file_path(test_app_path, chdir='app-bundle'))) != \ + set(['Contents/MacOS/Test App Assets Catalog Gyp', + 'Contents/Info.plist', + 'Contents/Resources/English.lproj/MainMenu.nib', + 'Contents/PkgInfo', + ] + extra_content_files + + [os.path.join('Contents/Resources/English.lproj', f) + for f in strings_files]): + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-app-error.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-app-error.py --- gyp-0.1~svn1729/test/mac/gyptest-app-error.py 2013-03-28 19:56:08.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-app-error.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,6 +14,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + expected_error = 'Old-style plist parser: missing semicolon in dictionary' saw_expected_error = [False] # Python2 has no "nonlocal" keyword. def match(a, b): @@ -34,7 +37,8 @@ test.build('test-error.gyp', test.ALL, chdir='app-bundle') # Ninja pipes stderr of subprocesses to stdout. - if test.format == 'ninja' and expected_error in test.stdout(): + if test.format in ['ninja', 'xcode-ninja'] \ + and expected_error in test.stdout(): saw_expected_error[0] = True if saw_expected_error[0]: diff -Nru gyp-0.1~svn1729/test/mac/gyptest-app.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-app.py --- gyp-0.1~svn1729/test/mac/gyptest-app.py 2013-09-06 15:17:23.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-app.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,11 +9,31 @@ """ import TestGyp +import TestMac import os +import plistlib +import subprocess import sys +if sys.platform in ('darwin', 'win32'): + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + +def CheckFileXMLPropertyList(file): + output = subprocess.check_output(['file', file]) + # The double space after XML is intentional. + if not 'XML document text' in output: + print 'File: Expected XML document text, got %s' % output + test.fail_test() + +def ExpectEq(expected, actual): + if expected != actual: + print >>sys.stderr, 'Expected "%s", got "%s"' % (expected, actual) + test.fail_test() + def ls(path): '''Returns a list of all files in a directory, relative to the directory.''' result = [] @@ -38,8 +58,31 @@ info_plist = test.built_file_path('Test App Gyp.app/Contents/Info.plist', chdir='app-bundle') test.must_exist(info_plist) - test.must_contain(info_plist, 'com.google.Test App Gyp') # Variable expansion + test.must_contain(info_plist, 'com.google.Test-App-Gyp') # Variable expansion test.must_not_contain(info_plist, '${MACOSX_DEPLOYMENT_TARGET}'); + CheckFileXMLPropertyList(info_plist) + + if test.format != 'make': + # TODO: Synthesized plist entries aren't hooked up in the make generator. + machine = subprocess.check_output(['sw_vers', '-buildVersion']).rstrip('\n') + plist = plistlib.readPlist(info_plist) + ExpectEq(machine, plist['BuildMachineOSBuild']) + + # Prior to Xcode 5.0.0, SDKROOT (and thus DTSDKName) was only defined if + # set in the Xcode project file. Starting with that version, it is always + # defined. + expected = '' + if TestMac.Xcode.Version() >= '0500': + version = TestMac.Xcode.SDKVersion() + expected = 'macosx' + version + ExpectEq(expected, plist['DTSDKName']) + sdkbuild = TestMac.Xcode.SDKBuild() + if not sdkbuild: + # Above command doesn't work in Xcode 4.2. + sdkbuild = plist['BuildMachineOSBuild'] + ExpectEq(sdkbuild, plist['DTSDKBuild']) + ExpectEq(TestMac.Xcode.Version(), plist['DTXcode']) + ExpectEq(TestMac.Xcode.Build(), plist['DTXcodeBuild']) # Resources strings_files = ['InfoPlist.strings', 'utf-16be.strings', 'utf-16le.strings'] diff -Nru gyp-0.1~svn1729/test/mac/gyptest-archs.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-archs.py --- gyp-0.1~svn1729/test/mac/gyptest-archs.py 2013-08-12 13:39:13.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-archs.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,7 @@ """ import TestGyp +import TestMac import re import subprocess @@ -17,51 +18,78 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) - def CheckFileType(file, expected): - proc = subprocess.Popen(['file', '-b', file], stdout=subprocess.PIPE) - o = proc.communicate()[0].strip() - assert not proc.returncode - if not re.match(expected, o, re.DOTALL): - print 'File: Expected %s, got %s' % (expected, o) - test.fail_test() - test.run_gyp('test-no-archs.gyp', chdir='archs') test.build('test-no-archs.gyp', test.ALL, chdir='archs') result_file = test.built_file_path('Test', chdir='archs') test.must_exist(result_file) - # FIXME: The default setting changed from i386 to x86_64 in Xcode 5. - #CheckFileType(result_file, '^Mach-O executable i386') + + if TestMac.Xcode.Version() >= '0500': + expected_type = ['x86_64'] + else: + expected_type = ['i386'] + TestMac.CheckFileType(test, result_file, expected_type) + + test.run_gyp('test-valid-archs.gyp', chdir='archs') + test.build('test-valid-archs.gyp', test.ALL, chdir='archs') + result_file = test.built_file_path('Test', chdir='archs') + test.must_exist(result_file) + TestMac.CheckFileType(test, result_file, ['x86_64']) test.run_gyp('test-archs-x86_64.gyp', chdir='archs') test.build('test-archs-x86_64.gyp', test.ALL, chdir='archs') result_file = test.built_file_path('Test64', chdir='archs') test.must_exist(result_file) - CheckFileType(result_file, '^Mach-O 64-bit executable x86_64$') + TestMac.CheckFileType(test, result_file, ['x86_64']) + + test.run_gyp('test-dependencies.gyp', chdir='archs') + test.build('test-dependencies.gyp', target=test.ALL, chdir='archs') + products = ['c_standalone', 'd_standalone'] + for product in products: + result_file = test.built_file_path( + product, chdir='archs', type=test.STATIC_LIB) + test.must_exist(result_file) if test.format != 'make': + # Build all targets except 'exe_32_64_no_sources' that does build + # but should not cause error when generating ninja files + targets = [ + 'static_32_64', 'shared_32_64', 'shared_32_64_bundle', + 'module_32_64', 'module_32_64_bundle', + 'exe_32_64', 'exe_32_64_bundle', 'precompiled_prefix_header_mm_32_64', + ] + test.run_gyp('test-archs-multiarch.gyp', chdir='archs') - test.build('test-archs-multiarch.gyp', test.ALL, chdir='archs') + + for target in targets: + test.build('test-archs-multiarch.gyp', target=target, chdir='archs') result_file = test.built_file_path( 'static_32_64', chdir='archs', type=test.STATIC_LIB) test.must_exist(result_file) - CheckFileType(result_file, 'Mach-O universal binary with 2 architectures' - '.*architecture i386.*architecture x86_64') + TestMac.CheckFileType(test, result_file, ['i386', 'x86_64']) result_file = test.built_file_path( 'shared_32_64', chdir='archs', type=test.SHARED_LIB) test.must_exist(result_file) - CheckFileType(result_file, 'Mach-O universal binary with 2 architectures' - '.*architecture i386.*architecture x86_64') + TestMac.CheckFileType(test, result_file, ['i386', 'x86_64']) + + result_file = test.built_file_path('My Framework.framework/My Framework', + chdir='archs') + test.must_exist(result_file) + TestMac.CheckFileType(test, result_file, ['i386', 'x86_64']) + # Check that symbol "_x" made it into both versions of the binary: + if not all(['D _x' in subprocess.check_output( + ['nm', '-arch', arch, result_file]) for arch in ['i386', 'x86_64']]): + # This can only flakily fail, due to process ordering issues. If this + # does fail flakily, then something's broken, it's not the test at fault. + test.fail_test() result_file = test.built_file_path( 'exe_32_64', chdir='archs', type=test.EXECUTABLE) test.must_exist(result_file) - CheckFileType(result_file, 'Mach-O universal binary with 2 architectures' - '.*architecture i386.*architecture x86_64') + TestMac.CheckFileType(test, result_file, ['i386', 'x86_64']) result_file = test.built_file_path('Test App.app/Contents/MacOS/Test App', chdir='archs') test.must_exist(result_file) - CheckFileType(result_file, 'Mach-O universal binary with 2 architectures' - '.*architecture i386.*architecture x86_64') + TestMac.CheckFileType(test, result_file, ['i386', 'x86_64']) diff -Nru gyp-0.1~svn1729/test/mac/gyptest-bundle-resources.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-bundle-resources.py --- gyp-0.1~svn1729/test/mac/gyptest-bundle-resources.py 2013-09-04 21:42:14.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-bundle-resources.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,8 +10,27 @@ import TestGyp +import os +import stat import sys +if sys.platform in ('darwin'): + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + +def check_attribs(path, expected_exec_bit): + out_path = test.built_file_path( + os.path.join('resource.app/Contents/Resources', path), chdir=CHDIR) + + in_stat = os.stat(os.path.join(CHDIR, path)) + out_stat = os.stat(out_path) + if in_stat.st_mtime == out_stat.st_mtime: + test.fail_test() + if out_stat.st_mode & stat.S_IXUSR != expected_exec_bit: + test.fail_test() + + if sys.platform == 'darwin': # set |match| to ignore build stderr output. test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) @@ -26,6 +45,15 @@ test.built_file_must_match('source_rule.app/Contents/Resources/secret.txt', 'ABC\n', chdir=CHDIR) + test.built_file_must_match( + 'resource.app/Contents/Resources/executable-file.sh', + '#!/bin/bash\n' + '\n' + 'echo echo echo echo cho ho o o\n', chdir=CHDIR) + + check_attribs('executable-file.sh', expected_exec_bit=stat.S_IXUSR) + check_attribs('secret.txt', expected_exec_bit=0) + # TODO(thakis): This currently fails with make. if test.format != 'make': test.built_file_must_match( diff -Nru gyp-0.1~svn1729/test/mac/gyptest-cflags.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-cflags.py --- gyp-0.1~svn1729/test/mac/gyptest-cflags.py 2012-04-16 16:26:22.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-cflags.py 2015-09-13 13:41:20.000000000 +0000 @@ -1,4 +1,3 @@ - #!/usr/bin/env python # Copyright (c) 2012 Google Inc. All rights reserved. @@ -17,5 +16,6 @@ test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'cflags' test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-clang-cxx-library.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-clang-cxx-library.py --- gyp-0.1~svn1729/test/mac/gyptest-clang-cxx-library.py 2013-03-18 15:38:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-clang-cxx-library.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,20 +9,19 @@ """ import TestGyp +import TestMac import os import sys if sys.platform == 'darwin': - test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) - # Xcode 4.2 on OS X 10.6 doesn't install the libc++ headers, don't run this # test there. - if not os.path.isdir('/usr/lib/c++'): + if TestMac.Xcode.Version() <= '0420': sys.exit(0) + test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) test.run_gyp('clang-cxx-library.gyp', chdir='clang-cxx-library') - test.build('clang-cxx-library.gyp', test.ALL, chdir='clang-cxx-library') test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-copies.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-copies.py --- gyp-0.1~svn1729/test/mac/gyptest-copies.py 2012-01-13 22:26:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-copies.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,6 +15,9 @@ import time if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) test.run_gyp('framework.gyp', chdir='framework') @@ -46,4 +49,7 @@ # Check that actions ran. test.built_file_must_exist('action_file', chdir='framework') + # Test that a copy with the "Code Sign on Copy" flag on succeeds. + test.build('framework.gyp', 'copy_target_code_sign', chdir='framework') + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-depend-on-bundle.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-depend-on-bundle.py --- gyp-0.1~svn1729/test/mac/gyptest-depend-on-bundle.py 2012-01-10 19:31:54.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-depend-on-bundle.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) test.run_gyp('test.gyp', chdir='depend-on-bundle') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-framework.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-framework.py --- gyp-0.1~svn1729/test/mac/gyptest-framework.py 2013-08-27 21:46:32.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-framework.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,10 @@ import os import sys +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + def ls(path): '''Returns a list of all files in a directory, relative to the directory.''' @@ -36,9 +40,11 @@ chdir='framework') # Info.plist - test.built_file_must_exist( + info_plist = test.built_file_path( 'Test Framework.framework/Versions/A/Resources/Info.plist', chdir='framework') + test.must_exist(info_plist) + test.must_contain(info_plist, 'com.yourcompany.Test_Framework') # Resources test.built_file_must_exist( diff -Nru gyp-0.1~svn1729/test/mac/gyptest-global-settings.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-global-settings.py --- gyp-0.1~svn1729/test/mac/gyptest-global-settings.py 2012-01-19 17:23:22.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-global-settings.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,6 +15,13 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + # The xcode-ninja generator handles gypfiles which are not at the + # project root incorrectly. + # cf. https://code.google.com/p/gyp/issues/detail?id=460 + if test.format == 'xcode-ninja': + test.skip_test() + test.run_gyp('src/dir2/dir2.gyp', chdir='global-settings', depth='src') # run_gyp shouldn't throw. diff -Nru gyp-0.1~svn1729/test/mac/gyptest-identical-name.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-identical-name.py --- gyp-0.1~svn1729/test/mac/gyptest-identical-name.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-identical-name.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies libraries (in identical-names) are properly handeled by xcode. + +The names for all libraries participating in this build are: +libtestlib.a - identical-name/testlib +libtestlib.a - identical-name/proxy/testlib +libproxy.a - identical-name/proxy +The first two libs produce a hash collision in Xcode when Gyp is executed, +because they have the same name and would be copied to the same directory with +Xcode default settings. +For this scenario to work one needs to change the Xcode variables SYMROOT and +CONFIGURATION_BUILD_DIR. Setting these to per-lib-unique directories, avoids +copying the libs into the same directory. + +The test consists of two steps. The first one verifies that by setting both +vars, there is no hash collision anymore during Gyp execution and that the libs +can actually be be built. The second one verifies that there is still a hash +collision if the vars are not set and thus the current behavior is preserved. +""" + +import TestGyp + +import sys + +def IgnoreOutput(string, expected_string): + return True + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['xcode']) + + + test.run_gyp('test.gyp', chdir='identical-name') + test.build('test.gyp', test.ALL, chdir='identical-name') + + test.run_gyp('test-should-fail.gyp', chdir='identical-name') + test.built_file_must_not_exist('test-should-fail.xcodeproj') + + test.pass_test() + diff -Nru gyp-0.1~svn1729/test/mac/gyptest-infoplist-process.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-infoplist-process.py --- gyp-0.1~svn1729/test/mac/gyptest-infoplist-process.py 2012-01-13 22:26:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-infoplist-process.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'infoplist-process' diff -Nru gyp-0.1~svn1729/test/mac/gyptest-installname.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-installname.py --- gyp-0.1~svn1729/test/mac/gyptest-installname.py 2012-04-05 18:03:01.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-installname.py 2015-09-13 13:41:20.000000000 +0000 @@ -16,10 +16,14 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'installname' test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) def GetInstallname(p): diff -Nru gyp-0.1~svn1729/test/mac/gyptest-ldflags-passed-to-libtool.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-ldflags-passed-to-libtool.py --- gyp-0.1~svn1729/test/mac/gyptest-ldflags-passed-to-libtool.py 2013-02-13 17:23:58.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-ldflags-passed-to-libtool.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match = lambda a, b: True) @@ -20,6 +23,7 @@ 'xcode': [1, 65], # 1 for xcode 3, 65 for xcode 4 (see `man sysexits`) 'make': 2, 'ninja': 1, + 'xcode-ninja': [1, 65], }[test.format] CHDIR = 'ldflags-libtool' diff -Nru gyp-0.1~svn1729/test/mac/gyptest-ldflags.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-ldflags.py --- gyp-0.1~svn1729/test/mac/gyptest-ldflags.py 2012-04-11 22:13:29.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-ldflags.py 2015-09-13 13:41:20.000000000 +0000 @@ -16,6 +16,12 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + # The xcode-ninja generator handles gypfiles which are not at the + # project root incorrectly. + # cf. https://code.google.com/p/gyp/issues/detail?id=460 + if test.format == 'xcode-ninja': + test.skip_test() + CHDIR = 'ldflags' test.run_gyp('subdirectory/test.gyp', chdir=CHDIR) diff -Nru gyp-0.1~svn1729/test/mac/gyptest-libraries.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-libraries.py --- gyp-0.1~svn1729/test/mac/gyptest-libraries.py 2012-01-26 03:58:23.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-libraries.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,6 +15,12 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + # The xcode-ninja generator handles gypfiles which are not at the + # project root incorrectly. + # cf. https://code.google.com/p/gyp/issues/detail?id=460 + if test.format == 'xcode-ninja': + test.skip_test() + test.run_gyp('subdir/test.gyp', chdir='libraries') test.build('subdir/test.gyp', test.ALL, chdir='libraries') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-libtool-zero.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-libtool-zero.py --- gyp-0.1~svn1729/test/mac/gyptest-libtool-zero.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-libtool-zero.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies libraries have proper mtime. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR = 'libtool-zero' + + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', 'mylib', chdir=CHDIR) + + test.up_to_date('test.gyp', 'mylib', chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-loadable-module-bundle-product-extension.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-loadable-module-bundle-product-extension.py --- gyp-0.1~svn1729/test/mac/gyptest-loadable-module-bundle-product-extension.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-loadable-module-bundle-product-extension.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Tests that loadable_modules don't collide when using the same name with +different file extensions. +""" + +import TestGyp + +import os +import struct +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR = 'loadable-module-bundle-product-extension' + test.run_gyp('test.gyp', + '-G', 'xcode_ninja_target_pattern=^.*$', + chdir=CHDIR) + + test.build('test.gyp', test.ALL, chdir=CHDIR) + + test.must_exist(test.built_file_path('Collide.foo', chdir=CHDIR)) + test.must_exist(test.built_file_path('Collide.bar', chdir=CHDIR)) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-loadable-module.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-loadable-module.py --- gyp-0.1~svn1729/test/mac/gyptest-loadable-module.py 2013-09-05 15:38:18.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-loadable-module.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,10 +15,14 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'loadable-module' test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) # Binary. diff -Nru gyp-0.1~svn1729/test/mac/gyptest-lto.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-lto.py --- gyp-0.1~svn1729/test/mac/gyptest-lto.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-lto.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that LTO flags work. +""" + +import TestGyp + +import os +import re +import subprocess +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + CHDIR = 'lto' + test.run_gyp('test.gyp', chdir=CHDIR) + + test.build('test.gyp', test.ALL, chdir=CHDIR) + + def ObjPath(srcpath, target): + # TODO: Move this into TestGyp if it's needed elsewhere. + if test.format == 'xcode': + return os.path.join(CHDIR, 'build', 'test.build', 'Default', + target + '.build', 'Objects-normal', 'x86_64', + srcpath + '.o') + elif 'ninja' in test.format: # ninja, xcode-ninja + return os.path.join(CHDIR, 'out', 'Default', 'obj', + target + '.' + srcpath + '.o') + elif test.format == 'make': + return os.path.join(CHDIR, 'out', 'Default', 'obj.target', + target, srcpath + '.o') + + def ObjType(p, t_expected): + r = re.compile(r'nsyms\s+(\d+)') + o = subprocess.check_output(['file', p]) + objtype = 'unknown' + if ': Mach-O ' in o: + objtype = 'mach-o' + elif ': LLVM bit-code ' in o: + objtype = 'llvm' + if objtype != t_expected: + print 'Expected %s, got %s' % (t_expected, objtype) + test.fail_test() + + ObjType(ObjPath('cfile', 'lto'), 'llvm') + ObjType(ObjPath('ccfile', 'lto'), 'llvm') + ObjType(ObjPath('mfile', 'lto'), 'llvm') + ObjType(ObjPath('mmfile', 'lto'), 'llvm') + ObjType(ObjPath('asmfile', 'lto'), 'mach-o') + + ObjType(ObjPath('cfile', 'lto_static'), 'llvm') + ObjType(ObjPath('ccfile', 'lto_static'), 'llvm') + ObjType(ObjPath('mfile', 'lto_static'), 'llvm') + ObjType(ObjPath('mmfile', 'lto_static'), 'llvm') + ObjType(ObjPath('asmfile', 'lto_static'), 'mach-o') + + test.pass_test() + + # TODO: Probably test for -object_path_lto too, else dsymutil won't be + # useful maybe? diff -Nru gyp-0.1~svn1729/test/mac/gyptest-missing-cfbundlesignature.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-missing-cfbundlesignature.py --- gyp-0.1~svn1729/test/mac/gyptest-missing-cfbundlesignature.py 2012-03-09 17:43:32.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-missing-cfbundlesignature.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) test.run_gyp('test.gyp', chdir='missing-cfbundlesignature') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-non-strs-flattened-to-env.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-non-strs-flattened-to-env.py --- gyp-0.1~svn1729/test/mac/gyptest-non-strs-flattened-to-env.py 2012-01-13 22:26:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-non-strs-flattened-to-env.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,6 +14,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'non-strs-flattened-to-env' diff -Nru gyp-0.1~svn1729/test/mac/gyptest-objc-gc.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-objc-gc.py --- gyp-0.1~svn1729/test/mac/gyptest-objc-gc.py 2013-07-19 19:09:46.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-objc-gc.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,7 @@ """ import TestGyp +import TestMac import sys @@ -17,29 +18,34 @@ test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'], match = lambda a, b: True) - CHDIR = 'objc-gc' - test.run_gyp('test.gyp', chdir=CHDIR) + # Xcode 5.1 removed support for garbage-collection: + # error: garbage collection is no longer supported + if TestMac.Xcode.Version() < '0510': + + CHDIR = 'objc-gc' + test.run_gyp('test.gyp', chdir=CHDIR) + + build_error_code = { + 'xcode': [1, 65], # 1 for xcode 3, 65 for xcode 4 (see `man sysexits`) + 'make': 2, + 'ninja': 1, + }[test.format] + + test.build('test.gyp', 'gc_exe_fails', chdir=CHDIR, status=build_error_code) + test.build( + 'test.gyp', 'gc_off_exe_req_lib', chdir=CHDIR, status=build_error_code) + + test.build('test.gyp', 'gc_req_exe', chdir=CHDIR) + test.run_built_executable('gc_req_exe', chdir=CHDIR, stdout="gc on: 1\n") + + test.build('test.gyp', 'gc_exe_req_lib', chdir=CHDIR) + test.run_built_executable( + 'gc_exe_req_lib', chdir=CHDIR, stdout="gc on: 1\n") - build_error_code = { - 'xcode': [1, 65], # 1 for xcode 3, 65 for xcode 4 (see `man sysexits`) - 'make': 2, - 'ninja': 1, - }[test.format] - - test.build('test.gyp', 'gc_exe_fails', chdir=CHDIR, status=build_error_code) - test.build( - 'test.gyp', 'gc_off_exe_req_lib', chdir=CHDIR, status=build_error_code) - - test.build('test.gyp', 'gc_req_exe', chdir=CHDIR) - test.run_built_executable('gc_req_exe', chdir=CHDIR, stdout="gc on: 1\n") + test.build('test.gyp', 'gc_exe', chdir=CHDIR) + test.run_built_executable('gc_exe', chdir=CHDIR, stdout="gc on: 1\n") - test.build('test.gyp', 'gc_exe_req_lib', chdir=CHDIR) - test.run_built_executable('gc_exe_req_lib', chdir=CHDIR, stdout="gc on: 1\n") - - test.build('test.gyp', 'gc_exe', chdir=CHDIR) - test.run_built_executable('gc_exe', chdir=CHDIR, stdout="gc on: 1\n") - - test.build('test.gyp', 'gc_off_exe', chdir=CHDIR) - test.run_built_executable('gc_off_exe', chdir=CHDIR, stdout="gc on: 0\n") + test.build('test.gyp', 'gc_off_exe', chdir=CHDIR) + test.run_built_executable('gc_off_exe', chdir=CHDIR, stdout="gc on: 0\n") test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-postbuild-copy-bundle.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-postbuild-copy-bundle.py --- gyp-0.1~svn1729/test/mac/gyptest-postbuild-copy-bundle.py 2012-11-07 20:04:09.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-postbuild-copy-bundle.py 2015-09-13 13:41:20.000000000 +0000 @@ -21,7 +21,7 @@ CHDIR = 'postbuild-copy-bundle' test.run_gyp('test.gyp', chdir=CHDIR) - app_bundle_dir = test.built_file_path('Test app.app', chdir=CHDIR) + app_bundle_dir = test.built_file_path('Test App.app', chdir=CHDIR) bundled_framework_dir = os.path.join( app_bundle_dir, 'Contents', 'My Framework.framework', 'Resources') final_plist_path = os.path.join(bundled_framework_dir, 'Info.plist') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-postbuild-defaults.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-postbuild-defaults.py --- gyp-0.1~svn1729/test/mac/gyptest-postbuild-defaults.py 2012-01-26 01:18:54.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-postbuild-defaults.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'postbuild-defaults' diff -Nru gyp-0.1~svn1729/test/mac/gyptest-postbuild-fail.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-postbuild-fail.py --- gyp-0.1~svn1729/test/mac/gyptest-postbuild-fail.py 2013-02-13 22:26:48.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-postbuild-fail.py 2015-09-13 13:41:20.000000000 +0000 @@ -23,6 +23,7 @@ 'xcode': [1, 65], # 1 for xcode 3, 65 for xcode 4 (see `man sysexits`) 'make': 2, 'ninja': 1, + 'xcode-ninja': [1, 65], }[test.format] diff -Nru gyp-0.1~svn1729/test/mac/gyptest-prefixheader.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-prefixheader.py --- gyp-0.1~svn1729/test/mac/gyptest-prefixheader.py 2012-01-04 01:43:37.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-prefixheader.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,5 +15,6 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) test.run_gyp('test.gyp', chdir='prefixheader') + test.build('test.gyp', test.ALL, chdir='prefixheader') test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-rebuild.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-rebuild.py --- gyp-0.1~svn1729/test/mac/gyptest-rebuild.py 2012-05-22 21:06:31.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-rebuild.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'rebuild' diff -Nru gyp-0.1~svn1729/test/mac/gyptest-rpath.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-rpath.py --- gyp-0.1~svn1729/test/mac/gyptest-rpath.py 2012-05-10 22:34:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-rpath.py 2015-09-13 13:41:20.000000000 +0000 @@ -20,6 +20,7 @@ CHDIR = 'rpath' test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) def GetRpaths(p): @@ -30,20 +31,20 @@ assert not proc.returncode return r.findall(o) - if (GetRpaths('libdefault_rpath.dylib') != []): + if GetRpaths('libdefault_rpath.dylib') != []: test.fail_test() - if (GetRpaths('libexplicit_rpath.dylib') != ['@executable_path/.']): + if GetRpaths('libexplicit_rpath.dylib') != ['@executable_path/.']: test.fail_test() if (GetRpaths('libexplicit_rpaths_escaped.dylib') != ['First rpath', 'Second rpath']): test.fail_test() - if (GetRpaths('My Framework.framework/My Framework') != ['@loader_path/.']): + if GetRpaths('My Framework.framework/My Framework') != ['@loader_path/.']: test.fail_test() - if (GetRpaths('executable') != ['@executable_path/.']): + if GetRpaths('executable') != ['@executable_path/.']: test.fail_test() test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-sdkroot.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-sdkroot.py --- gyp-0.1~svn1729/test/mac/gyptest-sdkroot.py 2013-04-09 19:11:48.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-sdkroot.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,25 +14,36 @@ import subprocess import sys + if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + def GetSDKPath(sdk): + """Return SDKROOT if the SDK version |sdk| is installed or empty string.""" + DEVNULL = open(os.devnull, 'wb') + try: + proc = subprocess.Popen( + ['xcodebuild', '-version', '-sdk', 'macosx' + sdk, 'Path'], + stdout=subprocess.PIPE, stderr=DEVNULL) + return proc.communicate()[0].rstrip('\n') + finally: + DEVNULL.close() + + def SelectSDK(): + """Select the oldest SDK installed (greater than 10.6).""" + for sdk in ['10.6', '10.7', '10.8', '10.9']: + path = GetSDKPath(sdk) + if path: + return True, sdk, path + return False, '', '' + # Make sure this works on the bots, which only have the 10.6 sdk, and on - # dev machines, who usually don't have the 10.6 sdk. - sdk = '10.6' - DEVNULL = open(os.devnull, 'wb') - proc = subprocess.Popen(['xcodebuild', '-version', '-sdk', 'macosx' + sdk], - stdout=DEVNULL, stderr=DEVNULL) - proc.communicate() - DEVNULL.close() - if proc.returncode: - sdk = '10.7' - - proc = subprocess.Popen(['xcodebuild', '-version', - '-sdk', 'macosx' + sdk, 'Path'], - stdout=subprocess.PIPE) - sdk_path = proc.communicate()[0].rstrip('\n') - if proc.returncode != 0: + # dev machines which usually don't have the 10.6 sdk. + sdk_found, sdk, sdk_path = SelectSDK() + if not sdk_found: test.fail_test() test.write('sdkroot/test.gyp', test.read('sdkroot/test.gyp') % sdk) diff -Nru gyp-0.1~svn1729/test/mac/gyptest-sourceless-module.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-sourceless-module.py --- gyp-0.1~svn1729/test/mac/gyptest-sourceless-module.py 2013-09-13 16:47:45.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-sourceless-module.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) test.run_gyp('test.gyp', chdir='sourceless-module') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-strip-default.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-strip-default.py --- gyp-0.1~svn1729/test/mac/gyptest-strip-default.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-strip-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that the default STRIP_STYLEs match between different generators. +""" + +import TestGyp + +import re +import subprocess +import sys +import time + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) + + CHDIR='strip' + test.run_gyp('test-defaults.gyp', chdir=CHDIR) + + test.build('test-defaults.gyp', test.ALL, chdir=CHDIR) + + # Lightweight check if stripping was done. + def OutPath(s): + return test.built_file_path(s, chdir=CHDIR) + + def CheckNsyms(p, o_expected): + proc = subprocess.Popen(['nm', '-aU', p], stdout=subprocess.PIPE) + o = proc.communicate()[0] + + # Filter out mysterious "00 0000 OPT radr://5614542" symbol which + # is apparently only printed on the bots (older toolchain?). + # Yes, "radr", not "rdar". + o = ''.join(filter(lambda s: 'radr://5614542' not in s, o.splitlines(True))) + + o = o.replace('A', 'T') + o = re.sub(r'^[a-fA-F0-9]+', 'XXXXXXXX', o, flags=re.MULTILINE) + assert not proc.returncode + if o != o_expected: + print 'Stripping: Expected symbols """\n%s""", got """\n%s"""' % ( + o_expected, o) + test.fail_test() + + CheckNsyms(OutPath('libsingle_dylib.dylib'), +"""\ +XXXXXXXX S _ci +XXXXXXXX S _i +XXXXXXXX T _the_function +XXXXXXXX t _the_hidden_function +XXXXXXXX T _the_used_function +XXXXXXXX T _the_visible_function +""") + CheckNsyms(OutPath('single_so.so'), +"""\ +XXXXXXXX S _ci +XXXXXXXX S _i +XXXXXXXX T _the_function +XXXXXXXX t _the_hidden_function +XXXXXXXX T _the_used_function +XXXXXXXX T _the_visible_function +""") + CheckNsyms(OutPath('single_exe'), +"""\ +XXXXXXXX T __mh_execute_header +""") + + CheckNsyms(test.built_file_path( + 'bundle_dylib.framework/Versions/A/bundle_dylib', chdir=CHDIR), +"""\ +XXXXXXXX S _ci +XXXXXXXX S _i +XXXXXXXX T _the_function +XXXXXXXX t _the_hidden_function +XXXXXXXX T _the_used_function +XXXXXXXX T _the_visible_function +""") + CheckNsyms(test.built_file_path( + 'bundle_so.bundle/Contents/MacOS/bundle_so', chdir=CHDIR), +"""\ +XXXXXXXX S _ci +XXXXXXXX S _i +XXXXXXXX T _the_function +XXXXXXXX T _the_used_function +XXXXXXXX T _the_visible_function +""") + CheckNsyms(test.built_file_path( + 'bundle_exe.app/Contents/MacOS/bundle_exe', chdir=CHDIR), +"""\ +XXXXXXXX T __mh_execute_header +""") + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-strip.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-strip.py --- gyp-0.1~svn1729/test/mac/gyptest-strip.py 2013-02-12 23:46:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-strip.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,7 @@ """ import TestGyp +import TestMac import re import subprocess @@ -28,26 +29,33 @@ def CheckNsyms(p, n_expected): r = re.compile(r'nsyms\s+(\d+)') - proc = subprocess.Popen(['otool', '-l', p], stdout=subprocess.PIPE) - o = proc.communicate()[0] - assert not proc.returncode + o = subprocess.check_output(['otool', '-l', p]) m = r.search(o) n = int(m.group(1)) if n != n_expected: print 'Stripping: Expected %d symbols, got %d' % (n_expected, n) test.fail_test() + # Starting with Xcode 5.0, clang adds an additional symbols to the compiled + # file when using a relative path to the input file. So when using ninja + # with Xcode 5.0 or higher, take this additional symbol into consideration + # for unstripped builds (it is stripped by all strip commands). + expected_extra_symbol_count = 0 + if test.format in ['ninja', 'xcode-ninja'] \ + and TestMac.Xcode.Version() >= '0500': + expected_extra_symbol_count = 1 + # The actual numbers here are not interesting, they just need to be the same # in both the xcode and the make build. - CheckNsyms(OutPath('no_postprocess'), 10) - CheckNsyms(OutPath('no_strip'), 10) + CheckNsyms(OutPath('no_postprocess'), 29 + expected_extra_symbol_count) + CheckNsyms(OutPath('no_strip'), 29 + expected_extra_symbol_count) CheckNsyms(OutPath('strip_all'), 0) - CheckNsyms(OutPath('strip_nonglobal'), 2) - CheckNsyms(OutPath('strip_debugging'), 2) + CheckNsyms(OutPath('strip_nonglobal'), 6) + CheckNsyms(OutPath('strip_debugging'), 7) CheckNsyms(OutPath('strip_all_custom_flags'), 0) CheckNsyms(test.built_file_path( 'strip_all_bundle.framework/Versions/A/strip_all_bundle', chdir='strip'), 0) - CheckNsyms(OutPath('strip_save'), 2) + CheckNsyms(OutPath('strip_save'), 7) test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-swift-library.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-swift-library.py --- gyp-0.1~svn1729/test/mac/gyptest-swift-library.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-swift-library.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that a swift framework builds correctly. +""" + +import TestGyp +import TestMac + +import collections +import sys +import subprocess + +if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + test = TestGyp.TestGyp(formats=['xcode']) + + # Ensures that the given symbol is present in the given file, by running nm. + def CheckHasSymbolName(path, symbol): + output = subprocess.check_output(['nm', '-j', path]) + idx = output.find(symbol) + if idx == -1: + print 'Swift: Could not find symobl: %s' % symbol + test.fail_test() + + test_cases = [] + + # Run this for iOS on XCode 6.0 or greater + if TestMac.Xcode.Version() >= '0600': + test_cases.append(('Default', 'iphoneos')) + test_cases.append(('Default', 'iphonesimulator')) + + # Run it for Mac on XCode 6.1 or greater + if TestMac.Xcode.Version() >= '0610': + test_cases.append(('Default', None)) + + # Generate the project. + test.run_gyp('test.gyp', chdir='swift-library') + + # Build and verify for each configuration. + for configuration, sdk in test_cases: + kwds = collections.defaultdict(list) + if test.format == 'xcode': + if sdk is not None: + kwds['arguments'].extend(['-sdk', sdk]) + + test.set_configuration(configuration) + test.build('test.gyp', 'SwiftFramework', chdir='swift-library', **kwds) + + filename = 'SwiftFramework.framework/SwiftFramework' + result_file = test.built_file_path(filename, chdir='swift-library') + + test.must_exist(result_file) + + # Check to make sure that our swift class (GypSwiftTest) is present in the + # built binary + CheckHasSymbolName(result_file, "C14SwiftFramework12GypSwiftTest") + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-type-envvars.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-type-envvars.py --- gyp-0.1~svn1729/test/mac/gyptest-type-envvars.py 2012-01-13 22:26:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-type-envvars.py 2015-09-13 13:41:20.000000000 +0000 @@ -15,7 +15,9 @@ if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) - test.run_gyp('test.gyp', chdir='type_envvars') + test.run_gyp('test.gyp', + '-G', 'xcode_ninja_target_pattern=^(?!nonbundle_none).*$', + chdir='type_envvars') test.build('test.gyp', test.ALL, chdir='type_envvars') diff -Nru gyp-0.1~svn1729/test/mac/gyptest-xcode-env-order.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-xcode-env-order.py --- gyp-0.1~svn1729/test/mac/gyptest-xcode-env-order.py 2012-08-31 21:37:04.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-xcode-env-order.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,10 +9,15 @@ """ import TestGyp +import TestMac +import subprocess import sys if sys.platform == 'darwin': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) CHDIR = 'xcode-env-order' @@ -71,10 +76,15 @@ # if it's not right at the start of the string (e.g. ':$PRODUCT_TYPE'), so # this looks like an Xcode bug. This bug isn't emulated (yet?), so check this # only for Xcode. - if test.format == 'xcode': + if test.format == 'xcode' and TestMac.Xcode.Version() < '0500': test.must_contain(info_plist, '''\ \tBareProcessedKey3 \t$PRODUCT_TYPE:D:/Source/Project/Test''') + else: + # The bug has been fixed by Xcode version 5.0.0. + test.must_contain(info_plist, '''\ +\tBareProcessedKey3 +\tcom.apple.product-type.application:D:/Source/Project/Test''') test.must_contain(info_plist, '''\ \tMixedProcessedKey diff -Nru gyp-0.1~svn1729/test/mac/gyptest-xcode-gcc.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-xcode-gcc.py --- gyp-0.1~svn1729/test/mac/gyptest-xcode-gcc.py 2013-03-14 20:21:59.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-xcode-gcc.py 2015-09-13 13:41:20.000000000 +0000 @@ -11,11 +11,23 @@ import TestGyp import os +import subprocess import sys def IgnoreOutput(string, expected_string): return True +def CompilerVersion(compiler): + stdout = subprocess.check_output([compiler, '-v'], stderr=subprocess.STDOUT) + return stdout.rstrip('\n') + +def CompilerSupportsWarnAboutInvalidOffsetOfMacro(test): + # "clang" does not support the "-Winvalid-offsetof" flag, and silently + # ignore it. Starting with Xcode 5.0.0, "gcc" is just a "clang" binary with + # some hard-coded include path hack, so use the output of "-v" to detect if + # the compiler supports the flag or not. + return 'clang' not in CompilerVersion('/usr/bin/cc') + if sys.platform == 'darwin': test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) @@ -30,10 +42,7 @@ # clang doesn't warn on invalid offsetofs, it silently ignores # -Wno-invalid-offsetof. - # TODO(thakis): This isn't really the right way to detect the compiler, - # `which cc` detects what make ends up using, and Xcode has some embedded - # compiler, but it's a reliable proxy at least on the bots. - if os.readlink('/usr/bin/cc') != 'clang': + if CompilerSupportsWarnAboutInvalidOffsetOfMacro(test): targets.append('warn_about_invalid_offsetof_macro') for target in targets: diff -Nru gyp-0.1~svn1729/test/mac/gyptest-xcode-support-actions.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-xcode-support-actions.py --- gyp-0.1~svn1729/test/mac/gyptest-xcode-support-actions.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-xcode-support-actions.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that support actions are properly created. +""" + +import TestGyp + +import os +import subprocess +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['xcode']) + + CHDIR = 'xcode-support-actions' + + test.run_gyp('test.gyp', '-Gsupport_target_suffix=_customsuffix', chdir=CHDIR) + test.build('test.gyp', target='target_customsuffix', chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/gyptest-xctest.py gyp-0.1+20150913git1f374df9/test/mac/gyptest-xctest.py --- gyp-0.1~svn1729/test/mac/gyptest-xctest.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/gyptest-xctest.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that xctest targets are correctly configured. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['xcode']) + + # Ignore this test if Xcode 5 is not installed + import subprocess + job = subprocess.Popen(['xcodebuild', '-version'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, err = job.communicate() + if job.returncode != 0: + raise Exception('Error %d running xcodebuild' % job.returncode) + xcode_version, build_number = out.splitlines() + # Convert the version string from 'Xcode 5.0' to ['5','0']. + xcode_version = xcode_version.split()[-1].split('.') + if xcode_version < ['5']: + test.pass_test() + + CHDIR = 'xctest' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', chdir=CHDIR, arguments=['-scheme', 'classes', 'test']) + + test.built_file_must_match('tests.xctest/Contents/Resources/resource.txt', + 'foo\n', chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/mac/identical-name/proxy/proxy.cc gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/proxy.cc --- gyp-0.1~svn1729/test/mac/identical-name/proxy/proxy.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/proxy.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,2 @@ +// Empty file + diff -Nru gyp-0.1~svn1729/test/mac/identical-name/proxy/proxy.gyp gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/proxy.gyp --- gyp-0.1~svn1729/test/mac/identical-name/proxy/proxy.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/proxy.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +{ + 'includes': ['../test.gypi'], + 'targets': [{ + 'target_name': 'testlib', + 'type': 'none', + 'dependencies': ['testlib/testlib.gyp:testlib'], + 'sources': ['proxy.cc'], + }], +} diff -Nru gyp-0.1~svn1729/test/mac/identical-name/proxy/testlib/testlib.cc gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/testlib/testlib.cc --- gyp-0.1~svn1729/test/mac/identical-name/proxy/testlib/testlib.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/testlib/testlib.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,2 @@ +// Empty file + diff -Nru gyp-0.1~svn1729/test/mac/identical-name/proxy/testlib/testlib.gyp gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/testlib/testlib.gyp --- gyp-0.1~svn1729/test/mac/identical-name/proxy/testlib/testlib.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/proxy/testlib/testlib.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +{ + 'includes': ['../../test.gypi'], + 'targets': [{ + 'target_name': 'testlib', + 'type': 'static_library', + 'sources': ['testlib.cc'], + }], +} diff -Nru gyp-0.1~svn1729/test/mac/identical-name/test.gyp gyp-0.1+20150913git1f374df9/test/mac/identical-name/test.gyp --- gyp-0.1~svn1729/test/mac/identical-name/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +{ + 'includes': ['test.gypi'], + 'targets': [{ + 'target_name': 'test', + 'type': 'executable', + 'dependencies': [ + 'testlib/testlib.gyp:proxy', + 'proxy/proxy.gyp:testlib', + ], + }], +} \ No newline at end of file diff -Nru gyp-0.1~svn1729/test/mac/identical-name/test.gypi gyp-0.1+20150913git1f374df9/test/mac/identical-name/test.gypi --- gyp-0.1~svn1729/test/mac/identical-name/test.gypi 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/test.gypi 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +{ + 'target_defaults': { + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/$SRCROOT/', + }, + }, +} diff -Nru gyp-0.1~svn1729/test/mac/identical-name/testlib/main.cc gyp-0.1+20150913git1f374df9/test/mac/identical-name/testlib/main.cc --- gyp-0.1~svn1729/test/mac/identical-name/testlib/main.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/testlib/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,3 @@ +int main(int argc, char **argv) { + return 0; +} diff -Nru gyp-0.1~svn1729/test/mac/identical-name/testlib/testlib.gyp gyp-0.1+20150913git1f374df9/test/mac/identical-name/testlib/testlib.gyp --- gyp-0.1~svn1729/test/mac/identical-name/testlib/testlib.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/testlib/testlib.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,14 @@ +{ + 'includes': ['../test.gypi'], + 'targets': [{ + 'target_name': 'proxy', + 'type': 'static_library', + 'sources': ['void.cc'], + 'dependencies': ['testlib'], + 'export_dependent_settings': ['testlib'], + }, { + 'target_name': 'testlib', + 'type': 'static_library', + 'sources': ['main.cc'], + }], +} diff -Nru gyp-0.1~svn1729/test/mac/identical-name/testlib/void.cc gyp-0.1+20150913git1f374df9/test/mac/identical-name/testlib/void.cc --- gyp-0.1~svn1729/test/mac/identical-name/testlib/void.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/testlib/void.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,2 @@ +// Empty file + diff -Nru gyp-0.1~svn1729/test/mac/identical-name/test-should-fail.gyp gyp-0.1+20150913git1f374df9/test/mac/identical-name/test-should-fail.gyp --- gyp-0.1~svn1729/test/mac/identical-name/test-should-fail.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/identical-name/test-should-fail.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +{ + 'targets': [{ + 'target_name': 'test', + 'type': 'executable', + 'dependencies': [ + 'testlib/testlib.gyp:proxy', + 'proxy/proxy.gyp:testlib', + ], + }], +} diff -Nru gyp-0.1~svn1729/test/mac/libtool-zero/mylib.c gyp-0.1+20150913git1f374df9/test/mac/libtool-zero/mylib.c --- gyp-0.1~svn1729/test/mac/libtool-zero/mylib.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/libtool-zero/mylib.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int my_foo(int x) { + return x + 1; +} diff -Nru gyp-0.1~svn1729/test/mac/libtool-zero/test.gyp gyp-0.1+20150913git1f374df9/test/mac/libtool-zero/test.gyp --- gyp-0.1~svn1729/test/mac/libtool-zero/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/libtool-zero/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,18 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'mylib', + 'type': 'static_library', + 'sources': [ + 'mylib.c', + ], + 'xcode_settings': { + 'ARCHS': [ 'i386', 'x86_64' ], + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/loadable-module-bundle-product-extension/src.cc gyp-0.1+20150913git1f374df9/test/mac/loadable-module-bundle-product-extension/src.cc --- gyp-0.1~svn1729/test/mac/loadable-module-bundle-product-extension/src.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/loadable-module-bundle-product-extension/src.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int test() { + return 1337; +} diff -Nru gyp-0.1~svn1729/test/mac/loadable-module-bundle-product-extension/test.gyp gyp-0.1+20150913git1f374df9/test/mac/loadable-module-bundle-product-extension/test.gyp --- gyp-0.1~svn1729/test/mac/loadable-module-bundle-product-extension/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/loadable-module-bundle-product-extension/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [{ + 'target_name': 'test', + 'type': 'none', + 'dependencies': ['child_one', 'child_two'], + }, { + 'target_name': 'child_one', + 'product_name': 'Collide', + 'product_extension': 'bar', + 'sources': ['src.cc'], + 'type': 'loadable_module', + 'mac_bundle': 1, + }, { + 'target_name': 'child_two', + 'product_name': 'Collide', + 'product_extension': 'foo', + 'sources': ['src.cc'], + 'type': 'loadable_module', + 'mac_bundle': 1, + }], +} diff -Nru gyp-0.1~svn1729/test/mac/lto/asmfile.S gyp-0.1+20150913git1f374df9/test/mac/lto/asmfile.S --- gyp-0.1~svn1729/test/mac/lto/asmfile.S 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/lto/asmfile.S 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,2 @@ +.globl _asfun +ret diff -Nru gyp-0.1~svn1729/test/mac/lto/ccfile.cc gyp-0.1+20150913git1f374df9/test/mac/lto/ccfile.cc --- gyp-0.1~svn1729/test/mac/lto/ccfile.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/lto/ccfile.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +void ccfun() {} diff -Nru gyp-0.1~svn1729/test/mac/lto/cfile.c gyp-0.1+20150913git1f374df9/test/mac/lto/cfile.c --- gyp-0.1~svn1729/test/mac/lto/cfile.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/lto/cfile.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +void cfun() {} diff -Nru gyp-0.1~svn1729/test/mac/lto/mfile.m gyp-0.1+20150913git1f374df9/test/mac/lto/mfile.m --- gyp-0.1~svn1729/test/mac/lto/mfile.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/lto/mfile.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +void mfun() {} diff -Nru gyp-0.1~svn1729/test/mac/lto/mmfile.mm gyp-0.1+20150913git1f374df9/test/mac/lto/mmfile.mm --- gyp-0.1~svn1729/test/mac/lto/mmfile.mm 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/lto/mmfile.mm 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +void mmfun() {} diff -Nru gyp-0.1~svn1729/test/mac/lto/test.gyp gyp-0.1+20150913git1f374df9/test/mac/lto/test.gyp --- gyp-0.1~svn1729/test/mac/lto/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/lto/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,35 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'lto', + 'type': 'shared_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile.cc', + 'mmfile.mm', + 'asmfile.S', + ], + 'xcode_settings': { + 'LLVM_LTO': 'YES', + }, + }, + { + 'target_name': 'lto_static', + 'type': 'static_library', + 'sources': [ + 'cfile.c', + 'mfile.m', + 'ccfile.cc', + 'mmfile.mm', + 'asmfile.S', + ], + 'xcode_settings': { + 'LLVM_LTO': 'YES', + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/sdkroot/test_shorthand.sh gyp-0.1+20150913git1f374df9/test/mac/sdkroot/test_shorthand.sh --- gyp-0.1~svn1729/test/mac/sdkroot/test_shorthand.sh 2013-03-16 00:19:45.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/sdkroot/test_shorthand.sh 2015-09-13 13:41:20.000000000 +0000 @@ -5,8 +5,16 @@ set -e -if ! expected=$(xcodebuild -version -sdk macosx10.6 Path 2>/dev/null) ; then - expected=$(xcodebuild -version -sdk macosx10.7 Path) +found=false +for sdk in 10.6 10.7 10.8 10.9 ; do + if expected=$(xcodebuild -version -sdk macosx$sdk Path 2>/dev/null) ; then + found=true + break + fi +done +if ! $found ; then + echo >&2 "cannot find installed SDK" + exit 1 fi test $SDKROOT = $expected diff -Nru gyp-0.1~svn1729/test/mac/strip/file.c gyp-0.1+20150913git1f374df9/test/mac/strip/file.c --- gyp-0.1~svn1729/test/mac/strip/file.c 2011-09-19 15:08:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/strip/file.c 2015-09-13 13:41:20.000000000 +0000 @@ -3,7 +3,20 @@ // found in the LICENSE file. static void the_static_function() {} +__attribute__((used)) void the_used_function() {} + +__attribute__((visibility("hidden"))) __attribute__((used)) + void the_hidden_function() {} +__attribute__((visibility("default"))) __attribute__((used)) + void the_visible_function() {} + +extern const int eci; +__attribute__((used)) int i; +__attribute__((used)) const int ci = 34623; void the_function() { the_static_function(); + the_used_function(); + the_hidden_function(); + the_visible_function(); } diff -Nru gyp-0.1~svn1729/test/mac/strip/main.c gyp-0.1+20150913git1f374df9/test/mac/strip/main.c --- gyp-0.1~svn1729/test/mac/strip/main.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/strip/main.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +static void the_static_function() {} +__attribute__((used)) void the_used_function() {} + +__attribute__((visibility("hidden"))) __attribute__((used)) +void the_hidden_function() {} +__attribute__((visibility("default"))) __attribute__((used)) +void the_visible_function() {} + +void the_function() {} + +extern const int eci; +__attribute__((used)) int i; +__attribute__((used)) const int ci = 34623; + +int main() { + the_function(); + the_static_function(); + the_used_function(); + the_hidden_function(); + the_visible_function(); +} diff -Nru gyp-0.1~svn1729/test/mac/strip/test-defaults.gyp gyp-0.1+20150913git1f374df9/test/mac/strip/test-defaults.gyp --- gyp-0.1~svn1729/test/mac/strip/test-defaults.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/strip/test-defaults.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,51 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'make_global_settings': [ + ['CC', '/usr/bin/clang'], + ], + 'target_defaults': { + 'xcode_settings': { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + 'targets': [ + { + 'target_name': 'single_dylib', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + }, + { + 'target_name': 'single_so', + 'type': 'loadable_module', + 'sources': [ 'file.c', ], + }, + { + 'target_name': 'single_exe', + 'type': 'executable', + 'sources': [ 'main.c', ], + }, + + { + 'target_name': 'bundle_dylib', + 'type': 'shared_library', + 'mac_bundle': '1', + 'sources': [ 'file.c', ], + }, + { + 'target_name': 'bundle_so', + 'type': 'loadable_module', + 'mac_bundle': '1', + 'sources': [ 'file.c', ], + }, + { + 'target_name': 'bundle_exe', + 'type': 'executable', + 'mac_bundle': '1', + 'sources': [ 'main.c', ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/swift-library/file.swift gyp-0.1+20150913git1f374df9/test/mac/swift-library/file.swift --- gyp-0.1~svn1729/test/mac/swift-library/file.swift 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/swift-library/file.swift 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +import Foundation + +public class GypSwiftTest { + let myProperty = false + + init() { + self.myProperty = true + } +} \ No newline at end of file diff -Nru gyp-0.1~svn1729/test/mac/swift-library/Info.plist gyp-0.1+20150913git1f374df9/test/mac/swift-library/Info.plist --- gyp-0.1~svn1729/test/mac/swift-library/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/swift-library/Info.plist 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff -Nru gyp-0.1~svn1729/test/mac/swift-library/test.gyp gyp-0.1+20150913git1f374df9/test/mac/swift-library/test.gyp --- gyp-0.1~svn1729/test/mac/swift-library/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/swift-library/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,21 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'SwiftFramework', + 'product_name': 'SwiftFramework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'CODE_SIGNING_REQUIRED': 'NO', + 'CONFIGURATION_BUILD_DIR':'build/Default', + }, + 'sources': [ + 'file.swift', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_bundle_executable.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_bundle_executable.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_bundle_executable.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_bundle_executable.sh 2015-09-13 13:41:20.000000000 +0000 @@ -17,5 +17,4 @@ [[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] [[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_bundle_loadable_module.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_bundle_loadable_module.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_bundle_loadable_module.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_bundle_loadable_module.sh 2015-09-13 13:41:20.000000000 +0000 @@ -18,5 +18,4 @@ [[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] [[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_bundle_shared_library.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_bundle_shared_library.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_bundle_shared_library.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_bundle_shared_library.sh 2015-09-13 13:41:20.000000000 +0000 @@ -19,5 +19,4 @@ test $LD_DYLIB_INSTALL_NAME = \ "/Library/Frameworks/bundle_shared_library.framework/Versions/A/bundle_shared_library" -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_check_sdkroot.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_check_sdkroot.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_check_sdkroot.sh 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_check_sdkroot.sh 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,47 @@ +#!/bin/bash +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -e + +# `xcodebuild -version` output looks like +# Xcode 4.6.3 +# Build version 4H1503 +# or like +# Xcode 4.2 +# Build version 4C199 +# or like +# Xcode 3.2.6 +# Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 +# BuildVersion: 10M2518 +# Convert that to '0463', '0420' and '0326' respectively. +function xcodeversion() { + xcodebuild -version | awk '/Xcode ([0-9]+\.[0-9]+(\.[0-9]+)?)/ { + version = $2 + gsub(/\./, "", version) + if (length(version) < 3) { + version = version "0" + } + if (length(version) < 4) { + version = "0" version + } + } + END { print version }' +} + +# Returns true if |string1| is smaller than |string2|. +# This function assumes that both strings represent Xcode version numbers +# as returned by |xcodeversion|. +function smaller() { + local min="$(echo -ne "${1}\n${2}\n" | sort -n | head -n1)" + test "${min}" != "${2}" +} + +if [[ "$(xcodeversion)" < "0500" ]]; then + # Xcode version is older than 5.0, check that SDKROOT is set but empty. + [[ -z "${SDKROOT}" && -z "${SDKROOT-_}" ]] +else + # Xcode version is newer than 5.0, check that SDKROOT is set. + [[ "${SDKROOT}" == "$(xcodebuild -version -sdk '' Path)" ]] +fi diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_executable.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_executable.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_executable.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_executable.sh 2015-09-13 13:41:20.000000000 +0000 @@ -4,6 +4,7 @@ # found in the LICENSE file. set -e + # For some reason, Xcode doesn't set MACH_O_TYPE for non-bundle executables. # Check for "not set", not just "empty": [[ ! $MACH_O_TYPE && ${MACH_O_TYPE-_} ]] @@ -18,5 +19,4 @@ [[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] [[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_loadable_module.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_loadable_module.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_loadable_module.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_loadable_module.sh 2015-09-13 13:41:20.000000000 +0000 @@ -17,5 +17,4 @@ test $DYLIB_INSTALL_NAME_BASE = "/usr/local/lib" test $LD_DYLIB_INSTALL_NAME = "/usr/local/lib/nonbundle_loadable_module.so" -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_none.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_none.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_none.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_none.sh 2015-09-13 13:41:20.000000000 +0000 @@ -18,5 +18,4 @@ [[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] [[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_shared_library.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_shared_library.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_shared_library.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_shared_library.sh 2015-09-13 13:41:20.000000000 +0000 @@ -17,5 +17,4 @@ test $DYLIB_INSTALL_NAME_BASE = "/usr/local/lib" test $LD_DYLIB_INSTALL_NAME = "/usr/local/lib/libnonbundle_shared_library.dylib" -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_static_library.sh gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_static_library.sh --- gyp-0.1~svn1729/test/mac/type_envvars/test_nonbundle_static_library.sh 2012-08-29 03:31:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/type_envvars/test_nonbundle_static_library.sh 2015-09-13 13:41:20.000000000 +0000 @@ -17,5 +17,4 @@ [[ ! $DYLIB_INSTALL_NAME_BASE && ${DYLIB_INSTALL_NAME_BASE-_} ]] [[ ! $LD_DYLIB_INSTALL_NAME && ${LD_DYLIB_INSTALL_NAME-_} ]] -# Should be set, but empty. -[[ ! $SDKROOT && ! ${SDKROOT-_} ]] +"$(dirname "$0")/test_check_sdkroot.sh" diff -Nru gyp-0.1~svn1729/test/mac/xcode-support-actions/test.gyp gyp-0.1+20150913git1f374df9/test/mac/xcode-support-actions/test.gyp --- gyp-0.1~svn1729/test/mac/xcode-support-actions/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xcode-support-actions/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'target', + 'product_name': 'Product', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ + '<(PRODUCT_DIR)/copy.c', + ], + 'actions': [ + { + 'action_name': 'Helper', + 'description': 'Helps', + 'inputs': [ 'source.c' ], + 'outputs': [ '<(PRODUCT_DIR)/copy.c' ], + 'action': [ 'cp', '${SOURCE_ROOT}/source.c', + '<(PRODUCT_DIR)/copy.c' ], + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/mac/xctest/MyClass.h gyp-0.1+20150913git1f374df9/test/mac/xctest/MyClass.h --- gyp-0.1~svn1729/test/mac/xctest/MyClass.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xctest/MyClass.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface MyClass : NSObject +@end diff -Nru gyp-0.1~svn1729/test/mac/xctest/MyClass.m gyp-0.1+20150913git1f374df9/test/mac/xctest/MyClass.m --- gyp-0.1~svn1729/test/mac/xctest/MyClass.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xctest/MyClass.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "MyClass.h" + +@implementation MyClass +@end diff -Nru gyp-0.1~svn1729/test/mac/xctest/resource.txt gyp-0.1+20150913git1f374df9/test/mac/xctest/resource.txt --- gyp-0.1~svn1729/test/mac/xctest/resource.txt 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xctest/resource.txt 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +foo diff -Nru gyp-0.1~svn1729/test/mac/xctest/TestCase.m gyp-0.1+20150913git1f374df9/test/mac/xctest/TestCase.m --- gyp-0.1~svn1729/test/mac/xctest/TestCase.m 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xctest/TestCase.m 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,16 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#import "MyClass.h" + +@interface TestCase : XCTestCase +@end + +@implementation TestCase +- (void)testFoo { + MyClass *foo = [[MyClass alloc] init]; + XCTAssertNotNil(foo, @"expected non-nil object"); +} +@end diff -Nru gyp-0.1~svn1729/test/mac/xctest/test.gyp gyp-0.1+20150913git1f374df9/test/mac/xctest/test.gyp --- gyp-0.1~svn1729/test/mac/xctest/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xctest/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,47 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'classes', + 'type': 'static_library', + 'sources': [ + 'MyClass.h', + 'MyClass.m', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + ], + }, + }, + { + 'target_name': 'tests', + 'type': 'loadable_module', + 'mac_xctest_bundle': 1, + 'sources': [ + 'TestCase.m', + ], + 'dependencies': [ + 'classes', + ], + 'mac_bundle_resources': [ + 'resource.txt', + ], + 'xcode_settings': { + 'WRAPPER_EXTENSION': 'xctest', + 'FRAMEWORK_SEARCH_PATHS': [ + '$(inherited)', + '$(DEVELOPER_FRAMEWORKS_DIR)', + ], + 'OTHER_LDFLAGS': [ + '$(inherited)', + '-ObjC', + ], + }, + }, + ], +} + diff -Nru gyp-0.1~svn1729/test/mac/xctest/test.xcodeproj/xcshareddata/xcschemes/classes.xcscheme gyp-0.1+20150913git1f374df9/test/mac/xctest/test.xcodeproj/xcshareddata/xcschemes/classes.xcscheme --- gyp-0.1~svn1729/test/mac/xctest/test.xcodeproj/xcshareddata/xcschemes/classes.xcscheme 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/mac/xctest/test.xcodeproj/xcshareddata/xcschemes/classes.xcscheme 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru gyp-0.1~svn1729/test/make/main.cc gyp-0.1+20150913git1f374df9/test/make/main.cc --- gyp-0.1~svn1729/test/make/main.cc 2010-10-12 19:41:40.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ #include "main.h" -int main(int argc, char *argv[]) { +int main(void) { printf("hello world\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/make/noload/main.c gyp-0.1+20150913git1f374df9/test/make/noload/main.c --- gyp-0.1~svn1729/test/make/noload/main.c 2010-11-01 17:32:04.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make/noload/main.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ #include "lib/shared.h" -int main(int argc, char *argv[]) +int main(void) { printf("Hello from %s.\n", kSharedStr); return 0; diff -Nru gyp-0.1~svn1729/test/make_global_settings/ar/gyptest-make_global_settings_ar.py gyp-0.1+20150913git1f374df9/test/make_global_settings/ar/gyptest-make_global_settings_ar.py --- gyp-0.1~svn1729/test/make_global_settings/ar/gyptest-make_global_settings_ar.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/ar/gyptest-make_global_settings_ar.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies 'AR' in make_global_settings. +""" + +import os +import sys +import TestGyp + +def resolve_path(test, path): + if path is None: + return None + elif test.format == 'make': + return '$(abspath %s)' % path + elif test.format in ['ninja', 'xcode-ninja']: + return os.path.join('..', '..', path) + else: + test.fail_test() + + +def verify_ar_target(test, ar=None, rel_path=False): + if rel_path: + ar_expected = resolve_path(test, ar) + else: + ar_expected = ar + # Resolve default values + if ar_expected is None: + if test.format == 'make': + # Make generator hasn't set the default value for AR. + # You can remove the following assertion as long as it doesn't + # break existing projects. + test.must_not_contain('Makefile', 'AR ?= ') + return + elif test.format in ['ninja', 'xcode-ninja']: + if sys.platform == 'win32': + ar_expected = 'lib.exe' + else: + ar_expected = 'ar' + if test.format == 'make': + test.must_contain('Makefile', 'AR ?= %s' % ar_expected) + elif test.format in ['ninja', 'xcode-ninja']: + test.must_contain('out/Default/build.ninja', 'ar = %s' % ar_expected) + else: + test.fail_test() + + +def verify_ar_host(test, ar=None, rel_path=False): + if rel_path: + ar_expected = resolve_path(test, ar) + else: + ar_expected = ar + # Resolve default values + if ar_expected is None: + ar_expected = 'ar' + if test.format == 'make': + test.must_contain('Makefile', 'AR.host ?= %s' % ar_expected) + elif test.format in ['ninja', 'xcode-ninja']: + test.must_contain('out/Default/build.ninja', 'ar_host = %s' % ar_expected) + else: + test.fail_test() + + +test_format = ['ninja'] +if sys.platform in ('linux2', 'darwin'): + test_format += ['make'] + +test = TestGyp.TestGyp(formats=test_format) + +# Check default values +test.run_gyp('make_global_settings_ar.gyp') +verify_ar_target(test) + + +# Check default values with GYP_CROSSCOMPILE enabled. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ar.gyp') +verify_ar_target(test) +verify_ar_host(test) + + +# Test 'AR' in 'make_global_settings'. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ar.gyp', '-Dcustom_ar_target=my_ar') +verify_ar_target(test, ar='my_ar', rel_path=True) + + +# Test 'AR'/'AR.host' in 'make_global_settings'. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ar.gyp', + '-Dcustom_ar_target=my_ar_target1', + '-Dcustom_ar_host=my_ar_host1') +verify_ar_target(test, ar='my_ar_target1', rel_path=True) +verify_ar_host(test, ar='my_ar_host1', rel_path=True) + + +# Test $AR and $AR_host environment variables. +with TestGyp.LocalEnv({'AR': 'my_ar_target2', + 'AR_host': 'my_ar_host2'}): + test.run_gyp('make_global_settings_ar.gyp') +# Ninja generator resolves $AR in gyp phase. Make generator doesn't. +if test.format == 'ninja': + if sys.platform == 'win32': + # TODO(yukawa): Make sure if this is an expected result or not. + verify_ar_target(test, ar='lib.exe', rel_path=False) + else: + verify_ar_target(test, ar='my_ar_target2', rel_path=False) +verify_ar_host(test, ar='my_ar_host2', rel_path=False) + + +# Test 'AR' in 'make_global_settings' with $AR_host environment variable. +with TestGyp.LocalEnv({'AR_host': 'my_ar_host3'}): + test.run_gyp('make_global_settings_ar.gyp', + '-Dcustom_ar_target=my_ar_target3') +verify_ar_target(test, ar='my_ar_target3', rel_path=True) +verify_ar_host(test, ar='my_ar_host3', rel_path=False) + + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/make_global_settings/ar/make_global_settings_ar.gyp gyp-0.1+20150913git1f374df9/test/make_global_settings/ar/make_global_settings_ar.gyp --- gyp-0.1~svn1729/test/make_global_settings/ar/make_global_settings_ar.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/ar/make_global_settings_ar.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style licence that can be +# found in the LICENSE file. + +{ + 'variables': { + 'custom_ar_target%': '', + 'custom_ar_host%': '', + }, + 'conditions': [ + ['"<(custom_ar_target)"!=""', { + 'make_global_settings': [ + ['AR', '<(custom_ar_target)'], + ], + }], + ['"<(custom_ar_host)"!=""', { + 'make_global_settings': [ + ['AR.host', '<(custom_ar_host)'], + ], + }], + ], + 'targets': [ + { + 'target_name': 'make_global_settings_ar_test', + 'type': 'static_library', + 'sources': [ 'foo.c' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/make_global_settings/basics/gyptest-make_global_settings.py gyp-0.1+20150913git1f374df9/test/make_global_settings/basics/gyptest-make_global_settings.py --- gyp-0.1~svn1729/test/make_global_settings/basics/gyptest-make_global_settings.py 2013-09-10 22:45:33.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/basics/gyptest-make_global_settings.py 2015-09-13 13:41:20.000000000 +0000 @@ -27,11 +27,11 @@ """ if sys.platform == 'linux2': link_expected = """ -LINK ?= flock $(builddir)/linker.lock $(abspath clang) +LINK ?= $(abspath clang) """ elif sys.platform == 'darwin': link_expected = """ -LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(abspath clang) +LINK ?= $(abspath clang) """ test.must_contain('Makefile', cc_expected) test.must_contain('Makefile', link_expected) diff -Nru gyp-0.1~svn1729/test/make_global_settings/full-toolchain/bar.cc gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/bar.cc --- gyp-0.1~svn1729/test/make_global_settings/full-toolchain/bar.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/bar.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +#error Not a real source file diff -Nru gyp-0.1~svn1729/test/make_global_settings/full-toolchain/foo.c gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/foo.c --- gyp-0.1~svn1729/test/make_global_settings/full-toolchain/foo.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/foo.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1 @@ +#error Not a real source file diff -Nru gyp-0.1~svn1729/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py --- gyp-0.1~svn1729/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/gyptest-make_global_settings.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies make_global_settings works with the full toolchain. +""" + +import os +import sys +import TestGyp + +if sys.platform == 'win32': + # cross compiling not supported by ninja on windows + # and make not supported on windows at all. + sys.exit(0) + +test = TestGyp.TestGyp(formats=['ninja']) +# Must set the test format to something with a flavor (the part after the '-') +# in order to test the desired behavior. Since we want to run a non-host +# toolchain, we have to set the flavor to something that the ninja generator +# doesn't know about, so it doesn't default to the host-specific tools (e.g., +# 'otool' on mac to generate the .TOC). +# +# Note that we can't just pass format=['ninja-some_toolchain'] to the +# constructor above, because then this test wouldn't be recognized as a ninja +# format test. +test.formats = ['ninja-my_flavor' if f == 'ninja' else f for f in test.formats] + +gyp_file = 'make_global_settings.gyp' + +test.run_gyp(gyp_file, + # Teach the .gyp file about the location of my_nm.py and + # my_readelf.py, and the python executable. + '-Dworkdir=%s' % test.workdir, + '-Dpython=%s' % sys.executable) +test.build(gyp_file, + arguments=['-v'] if test.format == 'ninja-my_flavor' else []) + +expected = ['MY_CC', 'MY_CXX'] +test.must_contain_all_lines(test.stdout(), expected) + +test.must_contain(test.built_file_path('RAN_MY_NM'), 'RAN_MY_NM') +test.must_contain(test.built_file_path('RAN_MY_READELF'), 'RAN_MY_READELF') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/make_global_settings/full-toolchain/make_global_settings.gyp gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/make_global_settings.gyp --- gyp-0.1~svn1729/test/make_global_settings/full-toolchain/make_global_settings.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/make_global_settings.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style licence that can be +# found in the LICENSE file. + +{ + 'make_global_settings': [ + ['CC', '/bin/echo MY_CC'], + ['CXX', '/bin/echo MY_CXX'], + ['NM', '<(python) <(workdir)/my_nm.py'], + ['READELF', '<(python) <(workdir)/my_readelf.py'], + ], + 'targets': [ + { + 'target_name': 'test', + 'type': 'shared_library', + 'sources': [ + 'foo.c', + 'bar.cc', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/make_global_settings/full-toolchain/my_nm.py gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/my_nm.py --- gyp-0.1~svn1729/test/make_global_settings/full-toolchain/my_nm.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/my_nm.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import sys +print sys.argv +with open('RAN_MY_NM', 'w') as f: + f.write('RAN_MY_NM') diff -Nru gyp-0.1~svn1729/test/make_global_settings/full-toolchain/my_readelf.py gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/my_readelf.py --- gyp-0.1~svn1729/test/make_global_settings/full-toolchain/my_readelf.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/full-toolchain/my_readelf.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import sys +print sys.argv +with open('RAN_MY_READELF', 'w') as f: + f.write('RAN_MY_READELF') diff -Nru gyp-0.1~svn1729/test/make_global_settings/ld/gyptest-make_global_settings_ld.py gyp-0.1+20150913git1f374df9/test/make_global_settings/ld/gyptest-make_global_settings_ld.py --- gyp-0.1~svn1729/test/make_global_settings/ld/gyptest-make_global_settings_ld.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/ld/gyptest-make_global_settings_ld.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,130 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies 'LD' in make_global_settings. +""" + +import os +import sys +import TestGyp + +def resolve_path(test, path): + if path is None: + return None + elif test.format == 'make': + return '$(abspath %s)' % path + elif test.format in ['ninja', 'xcode-ninja']: + return os.path.join('..', '..', path) + else: + test.fail_test() + + +def verify_ld_target(test, ld=None, rel_path=False): + if rel_path: + ld_expected = resolve_path(test, ld) + else: + ld_expected = ld + # Resolve default values + if ld_expected is None: + if test.format == 'make': + # Make generator hasn't set the default value for LD. + # You can remove the following assertion as long as it doesn't + # break existing projects. + test.must_not_contain('Makefile', 'LD ?= ') + return + elif test.format in ['ninja', 'xcode-ninja']: + if sys.platform == 'win32': + ld_expected = 'link.exe' + else: + ld_expected = '$cc' + if test.format == 'make': + test.must_contain('Makefile', 'LD ?= %s' % ld_expected) + elif test.format in ['ninja', 'xcode-ninja']: + test.must_contain('out/Default/build.ninja', 'ld = %s' % ld_expected) + else: + test.fail_test() + + +def verify_ld_host(test, ld=None, rel_path=False): + if rel_path: + ld_expected = resolve_path(test, ld) + else: + ld_expected = ld + # Resolve default values + if ld_expected is None: + if test.format == 'make': + # Make generator hasn't set the default value for LD.host. + # You can remove the following assertion as long as it doesn't + # break existing projects. + test.must_not_contain('Makefile', 'LD.host ?= ') + return + elif test.format in ['ninja', 'xcode-ninja']: + if sys.platform == 'win32': + ld_expected = '$ld' + else: + ld_expected = '$cc_host' + if test.format == 'make': + test.must_contain('Makefile', 'LD.host ?= %s' % ld_expected) + elif test.format in ['ninja', 'xcode-ninja']: + test.must_contain('out/Default/build.ninja', 'ld_host = %s' % ld_expected) + else: + test.fail_test() + + +test_format = ['ninja'] +if sys.platform in ('linux2', 'darwin'): + test_format += ['make'] + +test = TestGyp.TestGyp(formats=test_format) + +# Check default values +test.run_gyp('make_global_settings_ld.gyp') +verify_ld_target(test) + + +# Check default values with GYP_CROSSCOMPILE enabled. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ld.gyp') +verify_ld_target(test) +verify_ld_host(test) + + +# Test 'LD' in 'make_global_settings'. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ld.gyp', '-Dcustom_ld_target=my_ld') +verify_ld_target(test, ld='my_ld', rel_path=True) + + +# Test 'LD'/'LD.host' in 'make_global_settings'. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1'}): + test.run_gyp('make_global_settings_ld.gyp', + '-Dcustom_ld_target=my_ld_target1', + '-Dcustom_ld_host=my_ld_host1') +verify_ld_target(test, ld='my_ld_target1', rel_path=True) +verify_ld_host(test, ld='my_ld_host1', rel_path=True) + + +# Unlike other environment variables such as $AR/$AR_host, $CC/$CC_host, +# and $CXX/$CXX_host, neither Make generator nor Ninja generator recognizes +# $LD/$LD_host environment variables as of r1935. This may or may not be +# intentional, but here we leave a test case to verify this behavior just for +# the record. +# If you want to support $LD/$LD_host, please revise the following test case as +# well as the generator. +with TestGyp.LocalEnv({'GYP_CROSSCOMPILE': '1', + 'LD': 'my_ld_target2', + 'LD_host': 'my_ld_host2'}): + test.run_gyp('make_global_settings_ld.gyp') +if test.format == 'make': + test.must_not_contain('Makefile', 'my_ld_target2') + test.must_not_contain('Makefile', 'my_ld_host2') +elif test.format == 'ninja': + test.must_not_contain('out/Default/build.ninja', 'my_ld_target2') + test.must_not_contain('out/Default/build.ninja', 'my_ld_host2') + + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/make_global_settings/ld/make_global_settings_ld.gyp gyp-0.1+20150913git1f374df9/test/make_global_settings/ld/make_global_settings_ld.gyp --- gyp-0.1~svn1729/test/make_global_settings/ld/make_global_settings_ld.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/make_global_settings/ld/make_global_settings_ld.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style licence that can be +# found in the LICENSE file. + +{ + 'variables': { + 'custom_ld_target%': '', + 'custom_ld_host%': '', + }, + 'conditions': [ + ['"<(custom_ld_target)"!=""', { + 'make_global_settings': [ + ['LD', '<(custom_ld_target)'], + ], + }], + ['"<(custom_ld_host)"!=""', { + 'make_global_settings': [ + ['LD.host', '<(custom_ld_host)'], + ], + }], + ], + 'targets': [ + { + 'target_name': 'make_global_settings_ld_test', + 'type': 'static_library', + 'sources': [ 'foo.c' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/many-actions/gyptest-many-actions.py gyp-0.1+20150913git1f374df9/test/many-actions/gyptest-many-actions.py --- gyp-0.1~svn1729/test/many-actions/gyptest-many-actions.py 2012-05-16 18:30:06.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/many-actions/gyptest-many-actions.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,13 @@ line length. """ +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + import TestGyp test = TestGyp.TestGyp() diff -Nru gyp-0.1~svn1729/test/many-actions/gyptest-many-actions-unsorted.py gyp-0.1+20150913git1f374df9/test/many-actions/gyptest-many-actions-unsorted.py --- gyp-0.1~svn1729/test/many-actions/gyptest-many-actions-unsorted.py 2012-05-16 23:17:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/many-actions/gyptest-many-actions-unsorted.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,11 +9,18 @@ line length. """ +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + import TestGyp test = TestGyp.TestGyp() test.run_gyp('many-actions-unsorted.gyp') + test.build('many-actions-unsorted.gyp', test.ALL) for i in range(15): test.built_file_must_exist('generated_%d.h' % i) diff -Nru gyp-0.1~svn1729/test/module/gyptest-default.py gyp-0.1+20150913git1f374df9/test/module/gyptest-default.py --- gyp-0.1~svn1729/test/module/gyptest-default.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/module/gyptest-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,8 +12,7 @@ import TestGyp -# Android doesn't support loadable modules -test = TestGyp.TestGyp(formats=['!android']) +test = TestGyp.TestGyp() test.run_gyp('module.gyp', chdir='src') diff -Nru gyp-0.1~svn1729/test/msvs/buildevents/buildevents.gyp gyp-0.1+20150913git1f374df9/test/msvs/buildevents/buildevents.gyp --- gyp-0.1~svn1729/test/msvs/buildevents/buildevents.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/buildevents/buildevents.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,14 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'main', + 'type': 'executable', + 'sources': [ 'main.cc', ], + 'msvs_prebuild': r'echo starting', + 'msvs_postbuild': r'echo finished', + }, + ], +} diff -Nru gyp-0.1~svn1729/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py gyp-0.1+20150913git1f374df9/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py --- gyp-0.1~svn1729/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/buildevents/gyptest-msbuild-supports-prepostbuild.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that msvs_prebuild and msvs_postbuild can be specified in both +VS 2008 and 2010. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs'], workdir='workarea_all') + +test.run_gyp('buildevents.gyp', '-G', 'msvs_version=2008') +test.must_contain('main.vcproj', 'Name="VCPreBuildEventTool"') +test.must_contain('main.vcproj', 'Name="VCPostBuildEventTool"') + +test.run_gyp('buildevents.gyp', '-G', 'msvs_version=2010') +test.must_contain('main.vcxproj', '') +test.must_contain('main.vcxproj', '') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/msvs/buildevents/gyptest-ninja-warnings.py gyp-0.1+20150913git1f374df9/test/msvs/buildevents/gyptest-ninja-warnings.py --- gyp-0.1~svn1729/test/msvs/buildevents/gyptest-ninja-warnings.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/buildevents/gyptest-ninja-warnings.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that ninja errors out when encountering msvs_prebuild/msvs_postbuild. +""" + +import sys +import TestCmd +import TestGyp + + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + test.run_gyp('buildevents.gyp', + status=1, + stderr=r'.*msvs_prebuild not supported \(target main\).*', + match=TestCmd.match_re_dotall) + + test.run_gyp('buildevents.gyp', + status=1, + stderr=r'.*msvs_postbuild not supported \(target main\).*', + match=TestCmd.match_re_dotall) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/msvs/buildevents/main.cc gyp-0.1+20150913git1f374df9/test/msvs/buildevents/main.cc --- gyp-0.1~svn1729/test/msvs/buildevents/main.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/buildevents/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,5 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() {} diff -Nru gyp-0.1~svn1729/test/msvs/config_attrs/gyptest-config_attrs.py gyp-0.1+20150913git1f374df9/test/msvs/config_attrs/gyptest-config_attrs.py --- gyp-0.1~svn1729/test/msvs/config_attrs/gyptest-config_attrs.py 2012-03-08 22:53:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/config_attrs/gyptest-config_attrs.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,14 @@ import TestGyp import os +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + + test = TestGyp.TestGyp(workdir='workarea_all',formats=['msvs']) vc_version = 'VC90' diff -Nru gyp-0.1~svn1729/test/msvs/config_attrs/hello.c gyp-0.1+20150913git1f374df9/test/msvs/config_attrs/hello.c --- gyp-0.1~svn1729/test/msvs/config_attrs/hello.c 2012-03-08 22:53:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/config_attrs/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,8 +4,8 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello, world!\n"); return 0; -} \ No newline at end of file +} diff -Nru gyp-0.1~svn1729/test/msvs/external_builder/hello.cpp gyp-0.1+20150913git1f374df9/test/msvs/external_builder/hello.cpp --- gyp-0.1~svn1729/test/msvs/external_builder/hello.cpp 2013-04-24 19:19:38.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/external_builder/hello.cpp 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/msvs/filters/filters.gyp gyp-0.1+20150913git1f374df9/test/msvs/filters/filters.gyp --- gyp-0.1~svn1729/test/msvs/filters/filters.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/filters/filters.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,47 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'no_source_files', + 'type': 'none', + 'sources': [ ], + }, + { + 'target_name': 'one_source_file', + 'type': 'executable', + 'sources': [ + '../folder/a.c', + ], + }, + { + 'target_name': 'two_source_files', + 'type': 'executable', + 'sources': [ + '../folder/a.c', + '../folder/b.c', + ], + }, + { + 'target_name': 'three_files_in_two_folders', + 'type': 'executable', + 'sources': [ + '../folder1/a.c', + '../folder1/b.c', + '../folder2/c.c', + ], + }, + { + 'target_name': 'nested_folders', + 'type': 'executable', + 'sources': [ + '../folder1/nested/a.c', + '../folder2/d.c', + '../folder1/nested/b.c', + '../folder1/other/c.c', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/msvs/filters/gyptest-filters-2008.py gyp-0.1+20150913git1f374df9/test/msvs/filters/gyptest-filters-2008.py --- gyp-0.1~svn1729/test/msvs/filters/gyptest-filters-2008.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/filters/gyptest-filters-2008.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,68 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that extra filters are pruned correctly for Visual Studio 2008. +""" + +import re +import TestGyp + + +def strip_ws(str): + return re.sub('^ +', '', str, flags=re.M).replace('\n', '') + + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('filters.gyp', '-G', 'standalone', '-G', 'msvs_version=2008') + +test.must_contain('no_source_files.vcproj', '') + +test.must_contain('one_source_file.vcproj', strip_ws('''\ + + + +''')) + +test.must_contain('two_source_files.vcproj', strip_ws('''\ + + + + +''')) + +test.must_contain('three_files_in_two_folders.vcproj', strip_ws('''\ + + + + + + + + + +''')) + +test.must_contain('nested_folders.vcproj', strip_ws('''\ + + + + + + + + + + + + + + +''')) + + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/msvs/filters/gyptest-filters-2010.py gyp-0.1+20150913git1f374df9/test/msvs/filters/gyptest-filters-2010.py --- gyp-0.1~svn1729/test/msvs/filters/gyptest-filters-2010.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/filters/gyptest-filters-2010.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that extra filters are pruned correctly for Visual Studio 2010 +and later. +""" + +import TestGyp + + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('filters.gyp', '-G', 'standalone', '-G', 'msvs_version=2010') + +test.must_not_exist('no_source_files.vcxproj.filters') + +test.must_not_exist('one_source_file.vcxproj.filters') + +test.must_not_exist('two_source_files.vcxproj.filters') + +test.must_contain('three_files_in_two_folders.vcxproj.filters', '''\ + + + folder1 + + + folder1 + + + folder2 + + +'''.replace('\n', '\r\n')) + +test.must_contain('nested_folders.vcxproj.filters', '''\ + + + folder1\\nested + + + folder2 + + + folder1\\nested + + + folder1\\other + + +'''.replace('\n', '\r\n')) + + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/msvs/list_excluded/hello.cpp gyp-0.1+20150913git1f374df9/test/msvs/list_excluded/hello.cpp --- gyp-0.1~svn1729/test/msvs/list_excluded/hello.cpp 2012-02-03 23:54:22.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/list_excluded/hello.cpp 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/action_fail.py gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/action_fail.py --- gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/action_fail.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/action_fail.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys + +sys.exit(1) diff -Nru gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/actions.gyp gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/actions.gyp --- gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/actions.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/actions.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,40 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'actions-test', + 'type': 'none', + 'actions': [ + { + 'action_name': 'first action (fails)', + 'inputs': [ + 'action_fail.py', + ], + 'outputs': [ + 'ALWAYS_OUT_OF_DATE', + ], + 'action': [ + 'python', '<@(_inputs)' + ], + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'second action (succeeds)', + 'inputs': [ + 'action_succeed.py', + ], + 'outputs': [ + 'ALWAYS_OUT_OF_DATE', + ], + 'action': [ + 'python', '<@(_inputs)' + ], + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/action_succeed.py gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/action_succeed.py --- gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/action_succeed.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/action_succeed.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys + +sys.exit(0) diff -Nru gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/gyptest.py gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/gyptest.py --- gyp-0.1~svn1729/test/msvs/multiple_actions_error_handling/gyptest.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/multiple_actions_error_handling/gyptest.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies that failing actions make the build fail reliably, even when there +are multiple actions in one project. +""" + +import os +import sys +import TestGyp +import TestCmd + +test = TestGyp.TestGyp(formats=['msvs'], workdir='workarea_all') + +test.run_gyp('actions.gyp') +test.build('actions.gyp', + target='actions-test', + status=1, + stdout=r'.*"cmd\.exe" exited with code 1\..*', + match=TestCmd.match_re_dotall) + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/msvs/props/hello.c gyp-0.1+20150913git1f374df9/test/msvs/props/hello.c --- gyp-0.1~svn1729/test/msvs/props/hello.c 2012-03-08 22:53:34.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/props/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello, world!\n"); return 0; diff -Nru gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/dummy.bar gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/dummy.bar --- gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/dummy.bar 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/dummy.bar 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,5 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +A dummy file with the .bar extension (used for stderr rule). diff -Nru gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/dummy.foo gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/dummy.foo --- gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/dummy.foo 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/dummy.foo 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,5 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +A dummy file with the .foo extension (used for stdout rule). diff -Nru gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py --- gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/gyptest-rules-stdout-stderr.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" Verifies that stdout and stderr from rules get logged in the build's +stdout.""" + +import sys +import TestGyp + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs']) + + test.run_gyp('rules-stdout-stderr.gyp') + test.build('rules-stdout-stderr.gyp', test.ALL) + + expected_stdout_lines = [ + 'testing stdout', + 'This will go to stdout', + + # Note: stderr output from rules will go to the build's stdout. + 'testing stderr', + 'This will go to stderr', + ] + test.must_contain_all_lines(test.stdout(), expected_stdout_lines) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp --- gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/rules-stdout-stderr.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,52 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test', + 'type': 'none', + 'sources': [ + 'dummy.foo', + 'dummy.bar', + ], + 'rules': [ + { + 'rule_name': 'test_stdout', + 'extension': 'foo', + 'message': 'testing stdout', + 'msvs_cygwin_shell': 0, + 'inputs': [ + 'rule_stdout.py', + ], + 'outputs': [ + 'dummy.foo_output', + ], + 'action': [ + 'python', + 'rule_stdout.py', + '<(RULE_INPUT_PATH)', + ], + }, + { + 'rule_name': 'test_stderr', + 'extension': 'bar', + 'message': 'testing stderr', + 'msvs_cygwin_shell': 0, + 'inputs': [ + 'rule_stderr.py', + ], + 'outputs': [ + 'dummy.bar_output', + ], + 'action': [ + 'python', + 'rule_stderr.py', + '<(RULE_INPUT_PATH)', + ], + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/rule_stderr.py gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/rule_stderr.py --- gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/rule_stderr.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/rule_stderr.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys +print >>sys.stderr, "This will go to stderr" diff -Nru gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/rule_stdout.py gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/rule_stdout.py --- gyp-0.1~svn1729/test/msvs/rules_stdout_stderr/rule_stdout.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/rules_stdout_stderr/rule_stdout.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +print "This will go to stdout" diff -Nru gyp-0.1~svn1729/test/msvs/shared_output/hello.c gyp-0.1+20150913git1f374df9/test/msvs/shared_output/hello.c --- gyp-0.1~svn1729/test/msvs/shared_output/hello.c 2012-05-11 20:34:38.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/shared_output/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ #include -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/msvs/shared_output/there/there.c gyp-0.1+20150913git1f374df9/test/msvs/shared_output/there/there.c --- gyp-0.1~svn1729/test/msvs/shared_output/there/there.c 2012-05-11 20:34:38.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/shared_output/there/there.c 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ #include -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/msvs/uldi2010/hello.c gyp-0.1+20150913git1f374df9/test/msvs/uldi2010/hello.c --- gyp-0.1~svn1729/test/msvs/uldi2010/hello.c 2012-01-26 23:51:06.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/msvs/uldi2010/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -6,7 +6,7 @@ extern int hello2(); -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); hello2(); return 0; diff -Nru gyp-0.1~svn1729/test/multiple-targets/gyptest-all.py gyp-0.1+20150913git1f374df9/test/multiple-targets/gyptest-all.py --- gyp-0.1~svn1729/test/multiple-targets/gyptest-all.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/multiple-targets/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,9 +4,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -""" -""" - import TestGyp test = TestGyp.TestGyp() diff -Nru gyp-0.1~svn1729/test/multiple-targets/gyptest-default.py gyp-0.1+20150913git1f374df9/test/multiple-targets/gyptest-default.py --- gyp-0.1~svn1729/test/multiple-targets/gyptest-default.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/multiple-targets/gyptest-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,9 +4,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -""" -""" - import TestGyp test = TestGyp.TestGyp() diff -Nru gyp-0.1~svn1729/test/multiple-targets/src/prog1.c gyp-0.1+20150913git1f374df9/test/multiple-targets/src/prog1.c --- gyp-0.1~svn1729/test/multiple-targets/src/prog1.c 2009-08-29 04:00:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/multiple-targets/src/prog1.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void common(void); -int main(int argc, char *argv[]) +int main(void) { printf("hello from prog1.c\n"); common(); diff -Nru gyp-0.1~svn1729/test/multiple-targets/src/prog2.c gyp-0.1+20150913git1f374df9/test/multiple-targets/src/prog2.c --- gyp-0.1~svn1729/test/multiple-targets/src/prog2.c 2009-08-29 04:00:50.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/multiple-targets/src/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void common(void); -int main(int argc, char *argv[]) +int main(void) { printf("hello from prog2.c\n"); common(); diff -Nru gyp-0.1~svn1729/test/ninja/action_dependencies/gyptest-action-dependencies.py gyp-0.1+20150913git1f374df9/test/ninja/action_dependencies/gyptest-action-dependencies.py --- gyp-0.1~svn1729/test/ninja/action_dependencies/gyptest-action-dependencies.py 2012-02-21 02:12:01.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/action_dependencies/gyptest-action-dependencies.py 2015-09-13 13:41:20.000000000 +0000 @@ -11,6 +11,12 @@ import os import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + import TestGyp # NOTE(piman): This test will not work with other generators because: @@ -21,6 +27,9 @@ # which I don't think is available on all generators. # TODO(piman): Extend to other generators when possible. test = TestGyp.TestGyp(formats=['ninja']) +# xcode-ninja doesn't support building single object files by design. +if test.format == 'xcode-ninja': + test.skip_test() test.run_gyp('action_dependencies.gyp', chdir='src') diff -Nru gyp-0.1~svn1729/test/ninja/action-rule-hash/gyptest-action-rule-hash.py gyp-0.1+20150913git1f374df9/test/ninja/action-rule-hash/gyptest-action-rule-hash.py --- gyp-0.1~svn1729/test/ninja/action-rule-hash/gyptest-action-rule-hash.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/action-rule-hash/gyptest-action-rule-hash.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verify that running gyp in a different directory does not cause actions and +rules to rerun. +""" + +import os +import sys +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja']) +# The xcode-ninja generator handles gypfiles which are not at the +# project root incorrectly. +# cf. https://code.google.com/p/gyp/issues/detail?id=460 +if test.format == 'xcode-ninja': + test.skip_test() + +test.run_gyp('subdir/action-rule-hash.gyp') +test.build('subdir/action-rule-hash.gyp', test.ALL) +test.up_to_date('subdir/action-rule-hash.gyp') + +# Verify that everything is still up-to-date when we re-invoke gyp from a +# different directory. +test.run_gyp('action-rule-hash.gyp', '--depth=../', chdir='subdir') +test.up_to_date('subdir/action-rule-hash.gyp') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp gyp-0.1+20150913git1f374df9/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp --- gyp-0.1~svn1729/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'sources': [ + '<(INTERMEDIATE_DIR)/main.cc', + ], + 'actions': [ + { + 'action_name': 'emit_main_cc', + 'inputs': ['emit.py'], + 'outputs': ['<(INTERMEDIATE_DIR)/main.cc'], + 'action': [ + 'python', + 'emit.py', + '<(INTERMEDIATE_DIR)/main.cc', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/ninja/action-rule-hash/subdir/emit.py gyp-0.1+20150913git1f374df9/test/ninja/action-rule-hash/subdir/emit.py --- gyp-0.1~svn1729/test/ninja/action-rule-hash/subdir/emit.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/action-rule-hash/subdir/emit.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys + +f = open(sys.argv[1], 'wb') +f.write('int main() {\n') +f.write(' return 0;\n') +f.write('}\n') +f.close() diff -Nru gyp-0.1~svn1729/test/ninja/chained-dependency/chained.c gyp-0.1+20150913git1f374df9/test/ninja/chained-dependency/chained.c --- gyp-0.1~svn1729/test/ninja/chained-dependency/chained.c 2012-02-07 19:41:40.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/chained-dependency/chained.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,5 +1,5 @@ #include "generated/header.h" -int main(int argc, char** argv) { +int main(void) { return 0; } diff -Nru gyp-0.1~svn1729/test/ninja/chained-dependency/gyptest-chained-dependency.py gyp-0.1+20150913git1f374df9/test/ninja/chained-dependency/gyptest-chained-dependency.py --- gyp-0.1~svn1729/test/ninja/chained-dependency/gyptest-chained-dependency.py 2012-02-21 18:17:13.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/chained-dependency/gyptest-chained-dependency.py 2015-09-13 13:41:20.000000000 +0000 @@ -18,6 +18,10 @@ # - it relies on a ninja-specific output file path. test = TestGyp.TestGyp(formats=['ninja']) +# xcode-ninja doesn't support building single object files by design. +if test.format == 'xcode-ninja': + test.skip_test() + test.run_gyp('chained-dependency.gyp') objext = '.obj' if sys.platform == 'win32' else '.o' test.build('chained-dependency.gyp', diff -Nru gyp-0.1~svn1729/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py gyp-0.1+20150913git1f374df9/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py --- gyp-0.1~svn1729/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/empty-and-non-empty-duplicate-name/gyptest-empty-and-non-empty-duplicate-name.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies a phony target isn't output if a target exists with the same name that +was output. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja']) + +# Reset xcode_ninja_target_pattern to its default for this test. +test.run_gyp('test.gyp', '-G', 'xcode_ninja_target_pattern=^$') + +# Check for both \r and \n to cover both windows and linux. +test.must_not_contain('out/Default/build.ninja', 'build empty_target: phony\r') +test.must_not_contain('out/Default/build.ninja', 'build empty_target: phony\n') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp gyp-0.1+20150913git1f374df9/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp --- gyp-0.1~svn1729/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/empty-and-non-empty-duplicate-name/subdir/included.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'empty_target', + 'type': 'executable', + 'sources': [ + 'test.cc', + ], + }, + { + 'target_name': 'included_empty_target', + 'type': 'none', + }, + ], +} diff -Nru gyp-0.1~svn1729/test/ninja/empty-and-non-empty-duplicate-name/test.gyp gyp-0.1+20150913git1f374df9/test/ninja/empty-and-non-empty-duplicate-name/test.gyp --- gyp-0.1~svn1729/test/ninja/empty-and-non-empty-duplicate-name/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/empty-and-non-empty-duplicate-name/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'All', + 'type': 'none', + 'dependencies': [ + 'subdir/included.gyp:included_empty_target' + ] + }, + { + 'target_name': 'empty_target', + 'type': 'none', + }, + ], +} diff -Nru gyp-0.1~svn1729/test/ninja/normalize-paths-win/gyptest-normalize-paths.py gyp-0.1+20150913git1f374df9/test/ninja/normalize-paths-win/gyptest-normalize-paths.py --- gyp-0.1~svn1729/test/ninja/normalize-paths-win/gyptest-normalize-paths.py 2012-04-27 23:07:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/normalize-paths-win/gyptest-normalize-paths.py 2015-09-13 13:41:20.000000000 +0000 @@ -31,6 +31,10 @@ 'AnotherName.exe' not in second): test.fail_test() + copytarget = open(test.built_file_path('obj/copy_target.ninja')).read() + if '$(VSInstallDir)' in copytarget: + test.fail_test() + action = open(test.built_file_path('obj/action.ninja')).read() if '..\\..\\out\\Default' in action: test.fail_test() diff -Nru gyp-0.1~svn1729/test/ninja/normalize-paths-win/normalize-paths.gyp gyp-0.1+20150913git1f374df9/test/ninja/normalize-paths-win/normalize-paths.gyp --- gyp-0.1~svn1729/test/ninja/normalize-paths-win/normalize-paths.gyp 2012-04-27 23:07:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/normalize-paths-win/normalize-paths.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -30,6 +30,18 @@ ], }, { + 'target_name': 'Copy_Target', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + '$(VSInstallDir)\\bin\\cl.exe', + ], + }, + ], + }, + { 'target_name': 'action', 'type': 'none', 'msvs_cygwin_shell': '0', diff -Nru gyp-0.1~svn1729/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py gyp-0.1+20150913git1f374df9/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py --- gyp-0.1~svn1729/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py 2012-07-16 19:07:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/solibs_avoid_relinking/gyptest-solibs-avoid-relinking.py 2015-09-13 13:41:20.000000000 +0000 @@ -22,6 +22,11 @@ # if this was extended to other generators). test = TestGyp.TestGyp(formats=['ninja']) +if not os.environ.get('ProgramFiles(x86)'): + # TODO(scottmg) + print 'Skipping test on x86, http://crbug.com/365833' + test.pass_test() + test.run_gyp('solibs_avoid_relinking.gyp') # Build the executable, grab its timestamp, touch the solib's source, rebuild diff -Nru gyp-0.1~svn1729/test/ninja/use-console/foo.bar gyp-0.1+20150913git1f374df9/test/ninja/use-console/foo.bar --- gyp-0.1~svn1729/test/ninja/use-console/foo.bar 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/use-console/foo.bar 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,5 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +This is a dummy file for rule/action input. diff -Nru gyp-0.1~svn1729/test/ninja/use-console/gyptest-use-console.py gyp-0.1+20150913git1f374df9/test/ninja/use-console/gyptest-use-console.py --- gyp-0.1~svn1729/test/ninja/use-console/gyptest-use-console.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/use-console/gyptest-use-console.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure 'ninja_use_console' is supported in actions and rules. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja']) + +test.run_gyp('use-console.gyp') + +no_pool = open(test.built_file_path('obj/no_pool.ninja')).read() +if 'pool =' in no_pool: + test.fail_test() + +action_pool = open(test.built_file_path('obj/action_pool.ninja')).read() +if 'pool = console' not in action_pool: + test.fail_test() + +rule_pool = open(test.built_file_path('obj/rule_pool.ninja')).read() +if 'pool = console' not in rule_pool: + test.fail_test() + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/ninja/use-console/use-console.gyp gyp-0.1+20150913git1f374df9/test/ninja/use-console/use-console.gyp --- gyp-0.1~svn1729/test/ninja/use-console/use-console.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/ninja/use-console/use-console.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,60 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'no_pool', + 'type': 'none', + 'actions': [ + { + 'action_name': 'some_action', + 'action': ['echo', 'hello'], + 'inputs': ['foo.bar'], + 'outputs': ['dummy'], + }, + ], + 'rules': [ + { + 'rule_name': 'some_rule', + 'extension': 'bar', + 'action': ['echo', 'hello'], + 'outputs': ['dummy'], + }, + ], + 'sources': [ + 'foo.bar', + ], + }, + { + 'target_name': 'action_pool', + 'type': 'none', + 'actions': [ + { + 'action_name': 'some_action', + 'action': ['echo', 'hello'], + 'inputs': ['foo.bar'], + 'outputs': ['dummy'], + 'ninja_use_console': 1, + }, + ], + }, + { + 'target_name': 'rule_pool', + 'type': 'none', + 'rules': [ + { + 'rule_name': 'some_rule', + 'extension': 'bar', + 'action': ['echo', 'hello'], + 'outputs': ['dummy'], + 'ninja_use_console': 1, + }, + ], + 'sources': [ + 'foo.bar', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/no-cpp/gyptest-no-cpp.py gyp-0.1+20150913git1f374df9/test/no-cpp/gyptest-no-cpp.py --- gyp-0.1~svn1729/test/no-cpp/gyptest-no-cpp.py 2013-09-10 22:45:33.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/no-cpp/gyptest-no-cpp.py 2015-09-13 13:41:20.000000000 +0000 @@ -16,9 +16,9 @@ # set |match| to ignore build stderr output. test = TestGyp.TestGyp(match = lambda a, b: True) -if sys.platform != 'win32' and test.format not in ('make', 'android'): +if sys.platform != 'win32' and test.format != 'make': # TODO: This doesn't pass with make. - # TODO: Does a test like this make sense with Windows? Android? + # TODO: Does a test like this make sense with Windows? CHDIR = 'src' test.run_gyp('test.gyp', chdir=CHDIR) @@ -41,6 +41,8 @@ 'xcode': [1, 65], # 1 for xcode 3, 65 for xcode 4 (see `man sysexits`) 'make': 2, 'ninja': 1, + 'cmake': 0, # CMake picks the compiler driver based on transitive checks. + 'xcode-ninja': [1, 65], }[test.format] test.build('test.gyp', 'no_cpp_dep_on_cc_lib', chdir=CHDIR, diff -Nru gyp-0.1~svn1729/test/product/gyptest-product.py gyp-0.1+20150913git1f374df9/test/product/gyptest-product.py --- gyp-0.1~svn1729/test/product/gyptest-product.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/product/gyptest-product.py 2015-09-13 13:41:20.000000000 +0000 @@ -11,8 +11,7 @@ import TestGyp -# Android does not support setting the build directory. -test = TestGyp.TestGyp(formats=['!android']) +test = TestGyp.TestGyp() test.run_gyp('product.gyp') test.build('product.gyp') diff -Nru gyp-0.1~svn1729/test/product/hello.c gyp-0.1+20150913git1f374df9/test/product/hello.c --- gyp-0.1~svn1729/test/product/hello.c 2010-01-25 22:04:11.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/product/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -8,7 +8,7 @@ return 42; } -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); printf("%d\n", func1()); return 0; diff -Nru gyp-0.1~svn1729/test/prune_targets/gyptest-prune-targets.py gyp-0.1+20150913git1f374df9/test/prune_targets/gyptest-prune-targets.py --- gyp-0.1~svn1729/test/prune_targets/gyptest-prune-targets.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/gyptest-prune-targets.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies --root-target removes the unnecessary targets. +""" + +import TestGyp + +test = TestGyp.TestGyp() +# The xcode-ninja generator has its own logic for which targets to include +if test.format == 'xcode-ninja': + test.skip_test() + +build_error_code = { + 'cmake': 1, + 'make': 2, + 'msvs': 1, + 'ninja': 1, + 'xcode': 65, +}[test.format] + +# By default, everything will be included. +test.run_gyp('test1.gyp') +test.build('test2.gyp', 'lib1') +test.build('test2.gyp', 'lib2') +test.build('test2.gyp', 'lib3') +test.build('test2.gyp', 'lib_indirect') +test.build('test1.gyp', 'program1') +test.build('test1.gyp', 'program2') +test.build('test1.gyp', 'program3') + +# With deep dependencies of program1 only. +test.run_gyp('test1.gyp', '--root-target=program1') +test.build('test2.gyp', 'lib1') +test.build('test2.gyp', 'lib2', status=build_error_code, stderr=None) +test.build('test2.gyp', 'lib3', status=build_error_code, stderr=None) +test.build('test2.gyp', 'lib_indirect') +test.build('test1.gyp', 'program1') +test.build('test1.gyp', 'program2', status=build_error_code, stderr=None) +test.build('test1.gyp', 'program3', status=build_error_code, stderr=None) + +# With deep dependencies of program2 only. +test.run_gyp('test1.gyp', '--root-target=program2') +test.build('test2.gyp', 'lib1', status=build_error_code, stderr=None) +test.build('test2.gyp', 'lib2') +test.build('test2.gyp', 'lib3', status=build_error_code, stderr=None) +test.build('test2.gyp', 'lib_indirect') +test.build('test1.gyp', 'program1', status=build_error_code, stderr=None) +test.build('test1.gyp', 'program2') +test.build('test1.gyp', 'program3', status=build_error_code, stderr=None) + +# With deep dependencies of program1 and program2. +test.run_gyp('test1.gyp', '--root-target=program1', '--root-target=program2') +test.build('test2.gyp', 'lib1') +test.build('test2.gyp', 'lib2') +test.build('test2.gyp', 'lib3', status=build_error_code, stderr=None) +test.build('test2.gyp', 'lib_indirect') +test.build('test1.gyp', 'program1') +test.build('test1.gyp', 'program2') +test.build('test1.gyp', 'program3', status=build_error_code, stderr=None) + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/prune_targets/lib1.cc gyp-0.1+20150913git1f374df9/test/prune_targets/lib1.cc --- gyp-0.1~svn1729/test/prune_targets/lib1.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/lib1.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void libfunc1() { +} diff -Nru gyp-0.1~svn1729/test/prune_targets/lib2.cc gyp-0.1+20150913git1f374df9/test/prune_targets/lib2.cc --- gyp-0.1~svn1729/test/prune_targets/lib2.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/lib2.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void libfunc2() { +} diff -Nru gyp-0.1~svn1729/test/prune_targets/lib3.cc gyp-0.1+20150913git1f374df9/test/prune_targets/lib3.cc --- gyp-0.1~svn1729/test/prune_targets/lib3.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/lib3.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void libfunc3() { +} diff -Nru gyp-0.1~svn1729/test/prune_targets/lib_indirect.cc gyp-0.1+20150913git1f374df9/test/prune_targets/lib_indirect.cc --- gyp-0.1~svn1729/test/prune_targets/lib_indirect.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/lib_indirect.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void libfunc_indirect() { +} diff -Nru gyp-0.1~svn1729/test/prune_targets/program.cc gyp-0.1+20150913git1f374df9/test/prune_targets/program.cc --- gyp-0.1~svn1729/test/prune_targets/program.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/program.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/prune_targets/test1.gyp gyp-0.1+20150913git1f374df9/test/prune_targets/test1.gyp --- gyp-0.1~svn1729/test/prune_targets/test1.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/test1.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'program1', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'dependencies': [ 'test2.gyp:lib1' ], + }, + { + 'target_name': 'program2', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'dependencies': [ 'test2.gyp:lib2' ], + }, + { + 'target_name': 'program3', + 'type': 'executable', + 'sources': [ 'program.cc' ], + 'dependencies': [ 'test2.gyp:lib3' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/prune_targets/test2.gyp gyp-0.1+20150913git1f374df9/test/prune_targets/test2.gyp --- gyp-0.1~svn1729/test/prune_targets/test2.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/prune_targets/test2.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,30 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'lib1', + 'type': 'static_library', + 'sources': [ 'lib1.cc' ], + 'dependencies': [ 'lib_indirect' ], + }, + { + 'target_name': 'lib2', + 'type': 'static_library', + 'sources': [ 'lib2.cc' ], + 'dependencies': [ 'lib_indirect' ], + }, + { + 'target_name': 'lib3', + 'type': 'static_library', + 'sources': [ 'lib3.cc' ], + }, + { + 'target_name': 'lib_indirect', + 'type': 'static_library', + 'sources': [ 'lib_indirect.cc' ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/rules/gyptest-all.py gyp-0.1+20150913git1f374df9/test/rules/gyptest-all.py --- gyp-0.1~svn1729/test/rules/gyptest-all.py 2012-05-31 23:07:56.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -8,6 +8,13 @@ Verifies simple rules when using an explicit build target of 'all'. """ +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + import TestGyp test = TestGyp.TestGyp() @@ -15,7 +22,9 @@ test.run_gyp('no_action_with_rules_fails.gyp', chdir='src/noaction', status=1, stderr=None) -test.run_gyp('actions.gyp', chdir='src') +test.run_gyp('actions.gyp', + '-G', 'xcode_ninja_target_pattern=^pull_in_all_actions$', + chdir='src') test.relocate('src', 'relocate/src') @@ -50,6 +59,10 @@ test.must_match('relocate/src/subdir2/file1.out2', 'Hello from file1.in\n') test.must_match('relocate/src/subdir2/file2.out2', 'Hello from file2.in\n') +test.must_match('relocate/src/subdir2/file1.out4', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out4', 'Hello from file2.in\n') +test.must_match('relocate/src/subdir2/file1.copy', 'Hello from file1.in\n') + test.must_match('relocate/src/external/file1.external_rules.out', 'Hello from file1.in\n') test.must_match('relocate/src/external/file2.external_rules.out', diff -Nru gyp-0.1~svn1729/test/rules/gyptest-default.py gyp-0.1+20150913git1f374df9/test/rules/gyptest-default.py --- gyp-0.1~svn1729/test/rules/gyptest-default.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/gyptest-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -8,11 +8,20 @@ Verifies simple rules when using an explicit build target of 'all'. """ +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + import TestGyp test = TestGyp.TestGyp() -test.run_gyp('actions.gyp', chdir='src') +test.run_gyp('actions.gyp', + '-G', 'xcode_ninja_target_pattern=^pull_in_all_actions$', + chdir='src') test.relocate('src', 'relocate/src') @@ -47,6 +56,10 @@ test.must_match('relocate/src/subdir2/file1.out2', 'Hello from file1.in\n') test.must_match('relocate/src/subdir2/file2.out2', 'Hello from file2.in\n') +test.must_match('relocate/src/subdir2/file1.out4', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out4', 'Hello from file2.in\n') +test.must_match('relocate/src/subdir2/file1.copy', 'Hello from file1.in\n') + test.must_match('relocate/src/external/file1.external_rules.out', 'Hello from file1.in\n') test.must_match('relocate/src/external/file2.external_rules.out', diff -Nru gyp-0.1~svn1729/test/rules/src/actions.gyp gyp-0.1+20150913git1f374df9/test/rules/src/actions.gyp --- gyp-0.1~svn1729/test/rules/src/actions.gyp 2012-05-31 23:07:56.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/actions.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -9,6 +9,7 @@ 'type': 'none', 'dependencies': [ 'subdir1/executable.gyp:*', + 'subdir2/both_rule_and_action_input.gyp:*', 'subdir2/never_used.gyp:*', 'subdir2/no_inputs.gyp:*', 'subdir2/no_action.gyp:*', diff -Nru gyp-0.1~svn1729/test/rules/src/special-variables.gyp gyp-0.1+20150913git1f374df9/test/rules/src/special-variables.gyp --- gyp-0.1~svn1729/test/rules/src/special-variables.gyp 2012-08-29 17:26:40.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/special-variables.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -13,7 +13,6 @@ 'extension': 'S', 'inputs': [ 'as.bat', - '$(InputPath)' ], 'outputs': [ '$(IntDir)/$(InputName).obj', diff -Nru gyp-0.1~svn1729/test/rules/src/subdir1/program.c gyp-0.1+20150913git1f374df9/test/rules/src/subdir1/program.c --- gyp-0.1~svn1729/test/rules/src/subdir1/program.c 2009-08-31 20:29:35.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/subdir1/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -3,7 +3,7 @@ extern void function1(void); extern void function2(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from program.c\n"); function1(); diff -Nru gyp-0.1~svn1729/test/rules/src/subdir2/both_rule_and_action_input.gyp gyp-0.1+20150913git1f374df9/test/rules/src/subdir2/both_rule_and_action_input.gyp --- gyp-0.1~svn1729/test/rules/src/subdir2/both_rule_and_action_input.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/subdir2/both_rule_and_action_input.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,50 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Tests that if a rule input is also an action input, both the rule and action +# are executed +{ + 'targets': [ + { + 'target_name': 'files_both_rule_and_action_input', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + '<(RULE_INPUT_ROOT).out4', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + }, + ], + 'actions': [ + { + 'action_name': 'copy_file1_in', + 'inputs': [ + '../copy-file.py', + 'file1.in', + ], + 'outputs': [ + 'file1.copy', + ], + 'action': [ + 'python', '<@(_inputs)', '<(_outputs)' + ], + }, + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/rules/src/subdir2/program.c gyp-0.1+20150913git1f374df9/test/rules/src/subdir2/program.c --- gyp-0.1~svn1729/test/rules/src/subdir2/program.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/subdir2/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +/* Copyright (c) 2014 Google Inc. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include + +int main(void) +{ + printf("Hello from program.c\n"); + return 0; +} diff -Nru gyp-0.1~svn1729/test/rules/src/subdir3/program.c gyp-0.1+20150913git1f374df9/test/rules/src/subdir3/program.c --- gyp-0.1~svn1729/test/rules/src/subdir3/program.c 2009-11-15 21:23:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/subdir3/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void function3(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from program.c\n"); function3(); diff -Nru gyp-0.1~svn1729/test/rules/src/subdir4/build-asm.gyp gyp-0.1+20150913git1f374df9/test/rules/src/subdir4/build-asm.gyp --- gyp-0.1~svn1729/test/rules/src/subdir4/build-asm.gyp 2012-11-14 00:07:29.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/subdir4/build-asm.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -37,7 +37,7 @@ '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).S', ], 'action': [ - 'bash', '-c', 'mv <(RULE_INPUT_PATH) <@(_outputs)', + 'bash', '-c', 'cp <(RULE_INPUT_PATH) <@(_outputs)', ], 'process_outputs_as_sources': 1, }, diff -Nru gyp-0.1~svn1729/test/rules/src/subdir4/program.c gyp-0.1+20150913git1f374df9/test/rules/src/subdir4/program.c --- gyp-0.1~svn1729/test/rules/src/subdir4/program.c 2011-08-10 21:58:43.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules/src/subdir4/program.c 2015-09-13 13:41:20.000000000 +0000 @@ -9,7 +9,7 @@ } #endif -int main(int argc, char *argv[]) +int main(void) { fprintf(stdout, "Hello from program.c\n"); fflush(stdout); diff -Nru gyp-0.1~svn1729/test/rules-dirname/gyptest-dirname.py gyp-0.1+20150913git1f374df9/test/rules-dirname/gyptest-dirname.py --- gyp-0.1~svn1729/test/rules-dirname/gyptest-dirname.py 2013-06-04 21:51:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-dirname/gyptest-dirname.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,8 +10,14 @@ import TestGyp import os +import sys -test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + +test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode', 'msvs']) test.run_gyp('actions.gyp', chdir='src') @@ -20,6 +26,7 @@ test.build('actions.gyp', chdir='relocate/src') expect = """\ +no dir here hi c hello baz """ @@ -28,9 +35,21 @@ else: chdir = 'relocate/src' test.run_built_executable('gencc_int_output', chdir=chdir, stdout=expect) +if test.format == 'msvs': + test.run_built_executable('gencc_int_output_external', chdir=chdir, + stdout=expect) -test.must_match('relocate/src/subdir/foo/bar/baz.printed', +test.must_match('relocate/src/subdir/foo/bar/baz.dirname', os.path.join('foo', 'bar')) -test.must_match('relocate/src/subdir/a/b/c.printed', os.path.join('a', 'b')) +test.must_match('relocate/src/subdir/a/b/c.dirname', + os.path.join('a', 'b')) + +# FIXME the xcode and make generators incorrectly convert RULE_INPUT_PATH +# to an absolute path, making the tests below fail! +if test.format != 'xcode' and test.format != 'make': + test.must_match('relocate/src/subdir/foo/bar/baz.path', + os.path.join('foo', 'bar', 'baz.printvars')) + test.must_match('relocate/src/subdir/a/b/c.path', + os.path.join('a', 'b', 'c.printvars')) test.pass_test() diff -Nru gyp-0.1~svn1729/test/rules-dirname/src/subdir/a/b/c.gencc gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/a/b/c.gencc --- gyp-0.1~svn1729/test/rules-dirname/src/subdir/a/b/c.gencc 2011-10-18 04:55:38.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/a/b/c.gencc 2015-09-13 13:41:20.000000000 +0000 @@ -1,11 +1,8 @@ // -*- mode: c++ -*- -#include - -using std::cout; -using std::endl; +#include namespace gen { void c() { - cout << "hi c" << endl; + printf("hi c\n"); } } diff -Nru gyp-0.1~svn1729/test/rules-dirname/src/subdir/foo/bar/baz.gencc gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/foo/bar/baz.gencc --- gyp-0.1~svn1729/test/rules-dirname/src/subdir/foo/bar/baz.gencc 2011-10-18 04:55:38.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/foo/bar/baz.gencc 2015-09-13 13:41:20.000000000 +0000 @@ -1,11 +1,8 @@ // -*- mode: c++ -*- -#include - -using std::cout; -using std::endl; +#include namespace gen { void baz() { - cout << "hello baz" << endl; + printf("hello baz\n"); } } diff -Nru gyp-0.1~svn1729/test/rules-dirname/src/subdir/input-rule-dirname.gyp gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/input-rule-dirname.gyp --- gyp-0.1~svn1729/test/rules-dirname/src/subdir/input-rule-dirname.gyp 2012-02-23 02:02:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/input-rule-dirname.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -5,7 +5,7 @@ { 'targets': [ { - 'target_name': 'print_rule_input_path', + 'target_name': 'print_rule_input_dirname', 'type': 'none', 'msvs_cygwin_shell': 0, 'sources': [ @@ -20,36 +20,52 @@ 'printvars.py', ], 'outputs': [ - '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).printed', + '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).dirname', ], 'action': [ 'python', '<@(_inputs)', '<(RULE_INPUT_DIRNAME)', '<@(_outputs)', ], }, - ], + ], + }, + { + 'target_name': 'print_rule_input_path', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'foo/bar/baz.printvars', + 'a/b/c.printvars', + ], + 'rules': [ + { + 'rule_name': 'printvars', + 'extension': 'printvars', + 'inputs': [ + 'printvars.py', + ], + 'outputs': [ + '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).path', + ], + 'action': [ + 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + }, + ], }, { 'target_name': 'gencc_int_output', 'type': 'executable', 'msvs_cygwin_shell': 0, - 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'], 'sources': [ + 'nodir.gencc', 'foo/bar/baz.gencc', 'a/b/c.gencc', - 'main.cc', - ], - 'conditions': [ - ['OS=="win"', { - 'dependencies': [ - 'cygwin', - ], - }], + 'main.cc', ], 'rules': [ { 'rule_name': 'gencc', 'extension': 'gencc', - 'msvs_external_rule': 1, 'inputs': [ '<(DEPTH)/copy-file.py', ], @@ -61,13 +77,45 @@ ], 'process_outputs_as_sources': 1, }, - ], + ], }, ], 'conditions': [ ['OS=="win"', { 'targets': [ { + 'target_name': 'gencc_int_output_external', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'], + 'sources': [ + 'nodir.gencc', + 'foo/bar/baz.gencc', + 'a/b/c.gencc', + 'main.cc', + ], + 'dependencies': [ + 'cygwin', + ], + 'rules': [ + { + 'rule_name': 'gencc', + 'extension': 'gencc', + 'msvs_external_rule': 1, + 'inputs': [ + '<(DEPTH)/copy-file.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).cc', + ], + 'action': [ + 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + { 'target_name': 'cygwin', 'type': 'none', 'actions': [ diff -Nru gyp-0.1~svn1729/test/rules-dirname/src/subdir/main.cc gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/main.cc --- gyp-0.1~svn1729/test/rules-dirname/src/subdir/main.cc 2011-10-18 04:55:38.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. namespace gen { + extern void nodir(); extern void c(); extern void baz(); } int main() { + gen::nodir(); gen::c(); gen::baz(); } diff -Nru gyp-0.1~svn1729/test/rules-dirname/src/subdir/nodir.gencc gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/nodir.gencc --- gyp-0.1~svn1729/test/rules-dirname/src/subdir/nodir.gencc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-dirname/src/subdir/nodir.gencc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +// -*- mode: c++ -*- +#include + +namespace gen { + void nodir() { + printf("no dir here\n"); + } +} diff -Nru gyp-0.1~svn1729/test/rules-rebuild/src/main.c gyp-0.1+20150913git1f374df9/test/rules-rebuild/src/main.c --- gyp-0.1~svn1729/test/rules-rebuild/src/main.c 2009-11-23 23:21:46.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-rebuild/src/main.c 2015-09-13 13:41:20.000000000 +0000 @@ -3,7 +3,7 @@ extern void prog1(void); extern void prog2(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from main.c\n"); prog1(); diff -Nru gyp-0.1~svn1729/test/rules-use-built-dependencies/gyptest-use-built-dependencies.py gyp-0.1+20150913git1f374df9/test/rules-use-built-dependencies/gyptest-use-built-dependencies.py --- gyp-0.1~svn1729/test/rules-use-built-dependencies/gyptest-use-built-dependencies.py 2013-06-04 21:51:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-use-built-dependencies/gyptest-use-built-dependencies.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,7 @@ test = TestGyp.TestGyp() test.run_gyp('use-built-dependencies-rule.gyp', chdir='src') + test.relocate('src', 'relocate/src') test.build('use-built-dependencies-rule.gyp', chdir='relocate/src') diff -Nru gyp-0.1~svn1729/test/rules-variables/gyptest-rules-variables.py gyp-0.1+20150913git1f374df9/test/rules-variables/gyptest-rules-variables.py --- gyp-0.1~svn1729/test/rules-variables/gyptest-rules-variables.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/rules-variables/gyptest-rules-variables.py 2015-09-13 13:41:20.000000000 +0000 @@ -8,6 +8,13 @@ Verifies rules related variables are expanded. """ +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + import TestGyp test = TestGyp.TestGyp(formats=['ninja']) diff -Nru gyp-0.1~svn1729/test/same-source-file-name/gyptest-fail-shared.py gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-fail-shared.py --- gyp-0.1~svn1729/test/same-source-file-name/gyptest-fail-shared.py 2012-11-28 12:02:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-fail-shared.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Checks that gyp fails on shared_library targets which have several files with -the same basename. -""" - -import TestGyp - -test = TestGyp.TestGyp() - -test.run_gyp('double-shared.gyp', chdir='src', status=1, stderr=None) - -test.pass_test() diff -Nru gyp-0.1~svn1729/test/same-source-file-name/gyptest-fail-static.py gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-fail-static.py --- gyp-0.1~svn1729/test/same-source-file-name/gyptest-fail-static.py 2012-11-28 12:02:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-fail-static.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Checks that gyp fails on static_library targets which have several files with -the same basename. -""" - -import TestGyp - -test = TestGyp.TestGyp() - -test.run_gyp('double-static.gyp', chdir='src', status=1, stderr=None) - -test.pass_test() diff -Nru gyp-0.1~svn1729/test/same-source-file-name/gyptest-pass-shared.py gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-pass-shared.py --- gyp-0.1~svn1729/test/same-source-file-name/gyptest-pass-shared.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-pass-shared.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Checks that gyp does not fail on shared_library targets which have several files +with the same basename. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('double-shared.gyp', chdir='src') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/same-source-file-name/gyptest-static.py gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-static.py --- gyp-0.1~svn1729/test/same-source-file-name/gyptest-static.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/gyptest-static.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Checks that gyp fails on static_library targets which have several files with +the same basename. +""" + +import os +import sys + +import TestGyp + +test = TestGyp.TestGyp() + +# Fails by default for the compatibility with legacy generators such as +# VCProj generator for Visual C++ 2008 and Makefile generator on Mac. +# TODO: Update expected behavior when these legacy generators are deprecated. +test.run_gyp('double-static.gyp', chdir='src', status=1, stderr=None) + +if ((test.format == 'make' and sys.platform == 'darwin') or + (test.format == 'msvs' and + int(os.environ.get('GYP_MSVS_VERSION', 2010)) < 2010)): + test.run_gyp('double-static.gyp', '--no-duplicate-basename-check', + chdir='src', status=1, stderr=None) +else: + test.run_gyp('double-static.gyp', '--no-duplicate-basename-check', + chdir='src') + test.build('double-static.gyp', test.ALL, chdir='src') + +test.pass_test() diff -Nru gyp-0.1~svn1729/test/same-source-file-name/src/double-shared.gyp gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/double-shared.gyp --- gyp-0.1~svn1729/test/same-source-file-name/src/double-shared.gyp 2012-11-28 12:02:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/double-shared.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -6,6 +6,7 @@ 'targets': [ { 'target_name': 'lib', + 'product_name': 'test_shared_lib', 'type': 'shared_library', 'sources': [ 'prog2.c', @@ -16,6 +17,11 @@ 'defines': [ 'PROG="prog2"', ], + 'conditions': [ + ['OS=="linux"', { + 'cflags': ['-fPIC'], + }], + ], }, ], } diff -Nru gyp-0.1~svn1729/test/same-source-file-name/src/double-static.gyp gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/double-static.gyp --- gyp-0.1~svn1729/test/same-source-file-name/src/double-static.gyp 2012-11-28 12:02:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/double-static.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -6,6 +6,7 @@ 'targets': [ { 'target_name': 'lib', + 'product_name': 'test_static_lib', 'type': 'static_library', 'sources': [ 'prog1.c', diff -Nru gyp-0.1~svn1729/test/same-source-file-name/src/prog1.c gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/prog1.c --- gyp-0.1~svn1729/test/same-source-file-name/src/prog1.c 2009-09-11 22:26:43.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/prog1.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog1.c\n"); func(); diff -Nru gyp-0.1~svn1729/test/same-source-file-name/src/prog2.c gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/prog2.c --- gyp-0.1~svn1729/test/same-source-file-name/src/prog2.c 2009-09-11 22:26:43.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -2,7 +2,7 @@ extern void func(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog2.c\n"); func(); diff -Nru gyp-0.1~svn1729/test/same-source-file-name/src/prog3.c gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/prog3.c --- gyp-0.1~svn1729/test/same-source-file-name/src/prog3.c 2012-11-28 12:02:52.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-source-file-name/src/prog3.c 2015-09-13 13:41:20.000000000 +0000 @@ -8,7 +8,7 @@ extern void subdir1_func(void); extern void subdir2_func(void); -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog3.c\n"); func(); diff -Nru gyp-0.1~svn1729/test/same-target-name-different-directory/gyptest-all.py gyp-0.1+20150913git1f374df9/test/same-target-name-different-directory/gyptest-all.py --- gyp-0.1~svn1729/test/same-target-name-different-directory/gyptest-all.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/same-target-name-different-directory/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -10,7 +10,12 @@ import TestGyp -test = TestGyp.TestGyp(formats=['android', 'ninja', 'make']) +test = TestGyp.TestGyp(formats=['ninja', 'make']) + +# xcode-ninja fails to generate a project due to id collisions +# cf. https://code.google.com/p/gyp/issues/detail?id=461 +if test.format == 'xcode-ninja': + test.skip_test() test.run_gyp('subdirs.gyp', chdir='src') diff -Nru gyp-0.1~svn1729/test/sibling/gyptest-all.py gyp-0.1+20150913git1f374df9/test/sibling/gyptest-all.py --- gyp-0.1~svn1729/test/sibling/gyptest-all.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/sibling/gyptest-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,13 +4,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -""" -""" - import TestGyp test = TestGyp.TestGyp() +# The xcode-ninja generator handles gypfiles which are not at the +# project root incorrectly. +# cf. https://code.google.com/p/gyp/issues/detail?id=460 +if test.format == 'xcode-ninja': + test.skip_test() + test.run_gyp('build/all.gyp', chdir='src') test.build('build/all.gyp', test.ALL, chdir='src') @@ -21,7 +24,7 @@ # TODO(mmoss) Should the Makefile go in the directory of the passed in .gyp # file? What about when passing in multiple .gyp files? Would sub-project # Makefiles (see http://codereview.chromium.org/340008 comments) solve this? -if test.format in ('make', 'ninja'): +if test.format in ('make', 'ninja', 'cmake'): chdir = 'src' if test.format == 'xcode': diff -Nru gyp-0.1~svn1729/test/sibling/gyptest-relocate.py gyp-0.1+20150913git1f374df9/test/sibling/gyptest-relocate.py --- gyp-0.1~svn1729/test/sibling/gyptest-relocate.py 2012-07-04 14:20:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/sibling/gyptest-relocate.py 2015-09-13 13:41:20.000000000 +0000 @@ -4,13 +4,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -""" -""" - import TestGyp test = TestGyp.TestGyp() +# The xcode-ninja generator handles gypfiles which are not at the +# project root incorrectly. +# cf. https://code.google.com/p/gyp/issues/detail?id=460 +if test.format == 'xcode-ninja': + test.skip_test() + test.run_gyp('build/all.gyp', chdir='src') test.relocate('src', 'relocate/src') @@ -23,7 +26,7 @@ # TODO(mmoss) Should the Makefile go in the directory of the passed in .gyp # file? What about when passing in multiple .gyp files? Would sub-project # Makefiles (see http://codereview.chromium.org/340008 comments) solve this? -if test.format in ('make', 'ninja'): +if test.format in ('make', 'ninja', 'cmake'): chdir = 'relocate/src' if test.format == 'xcode': diff -Nru gyp-0.1~svn1729/test/sibling/src/prog1/prog1.c gyp-0.1+20150913git1f374df9/test/sibling/src/prog1/prog1.c --- gyp-0.1~svn1729/test/sibling/src/prog1/prog1.c 2009-08-21 21:22:01.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/sibling/src/prog1/prog1.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog1.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/sibling/src/prog2/prog2.c gyp-0.1+20150913git1f374df9/test/sibling/src/prog2/prog2.c --- gyp-0.1~svn1729/test/sibling/src/prog2/prog2.c 2009-08-21 21:22:01.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/sibling/src/prog2/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog2.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/small/gyptest-small.py gyp-0.1+20150913git1f374df9/test/small/gyptest-small.py --- gyp-0.1~svn1729/test/small/gyptest-small.py 2013-08-20 13:28:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/small/gyptest-small.py 2015-09-13 13:41:20.000000000 +0000 @@ -20,7 +20,7 @@ # Add pylib to the import path (so tests can import their dependencies). # This is consistant with the path.append done in the top file "gyp". -sys.path.append(os.path.join(test._cwd, 'pylib')) +sys.path.insert(0, os.path.join(test._cwd, 'pylib')) # Add new test suites here. files_to_test = [ diff -Nru gyp-0.1~svn1729/test/standalone-static-library/gyptest-standalone-static-library.py gyp-0.1+20150913git1f374df9/test/standalone-static-library/gyptest-standalone-static-library.py --- gyp-0.1~svn1729/test/standalone-static-library/gyptest-standalone-static-library.py 2013-04-17 18:21:30.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/standalone-static-library/gyptest-standalone-static-library.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,10 +14,8 @@ import TestGyp # standalone_static_library currently means two things: a specific output -# location for the built target and non-thin archive files. The Android gyp -# generator leaves both decisions to the Android build system, so this test -# doesn't work for that format. -test = TestGyp.TestGyp(formats=['!android']) +# location for the built target and non-thin archive files. +test = TestGyp.TestGyp() # Verify that types other than static_library cause a failure. test.run_gyp('invalid.gyp', status=1, stderr=None) @@ -44,7 +42,8 @@ test.run_built_executable('prog', stdout=expect) # Verify that libmylib.a contains symbols. "ar -x" fails on a 'thin' archive. -if test.format in ('make', 'ninja') and sys.platform.startswith('linux'): +supports_thick = ('make', 'ninja', 'cmake') +if test.format in supports_thick and sys.platform.startswith('linux'): retcode = subprocess.call(['ar', '-x', path]) assert retcode == 0 diff -Nru gyp-0.1~svn1729/test/standalone-static-library/prog.c gyp-0.1+20150913git1f374df9/test/standalone-static-library/prog.c --- gyp-0.1~svn1729/test/standalone-static-library/prog.c 2012-10-05 02:02:24.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/standalone-static-library/prog.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ extern void print(void); -int main(int argc, char *argv[]) +int main(void) { print(); return 0; diff -Nru gyp-0.1~svn1729/test/subdirectory/gyptest-subdir-all.py gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-subdir-all.py --- gyp-0.1~svn1729/test/subdirectory/gyptest-subdir-all.py 2012-12-26 16:49:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-subdir-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -12,9 +12,9 @@ import TestGyp -# Android doesn't support running from subdirectories. # Ninja doesn't support relocation. -test = TestGyp.TestGyp(formats=['!ninja', '!android']) +# CMake produces a single CMakeLists.txt in the output directory. +test = TestGyp.TestGyp(formats=['!ninja', '!cmake']) test.run_gyp('prog1.gyp', chdir='src') diff -Nru gyp-0.1~svn1729/test/subdirectory/gyptest-subdir-default.py gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-subdir-default.py --- gyp-0.1~svn1729/test/subdirectory/gyptest-subdir-default.py 2012-12-26 16:49:26.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-subdir-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,9 +13,9 @@ import TestGyp import errno -# Android doesn't support running from subdirectories. # Ninja doesn't support relocation. -test = TestGyp.TestGyp(formats=['!ninja', '!android']) +# CMake produces a single CMakeLists.txt in the output directory. +test = TestGyp.TestGyp(formats=['!ninja', '!cmake']) test.run_gyp('prog1.gyp', chdir='src') diff -Nru gyp-0.1~svn1729/test/subdirectory/gyptest-SYMROOT-all.py gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-SYMROOT-all.py --- gyp-0.1~svn1729/test/subdirectory/gyptest-SYMROOT-all.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-SYMROOT-all.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,7 +9,7 @@ .gyp file in a subdirectory, without specifying an explicit output build directory, and using the generated solution or project file at the top of the tree as the entry point. - + The configuration sets the Xcode SYMROOT variable and uses --depth= to make Xcode behave like the other build tools--that is, put all built targets in a single output build directory at the top of the tree. diff -Nru gyp-0.1~svn1729/test/subdirectory/gyptest-SYMROOT-default.py gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-SYMROOT-default.py --- gyp-0.1~svn1729/test/subdirectory/gyptest-SYMROOT-default.py 2011-11-28 16:07:19.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/gyptest-SYMROOT-default.py 2015-09-13 13:41:20.000000000 +0000 @@ -9,7 +9,7 @@ .gyp file in a subdirectory, without specifying an explicit output build directory, and using the generated solution or project file at the top of the tree as the entry point. - + The configuration sets the Xcode SYMROOT variable and uses --depth= to make Xcode behave like the other build tools--that is, put all built targets in a single output build directory at the top of the tree. diff -Nru gyp-0.1~svn1729/test/subdirectory/src/prog1.c gyp-0.1+20150913git1f374df9/test/subdirectory/src/prog1.c --- gyp-0.1~svn1729/test/subdirectory/src/prog1.c 2009-08-28 18:36:45.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/src/prog1.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog1.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/subdirectory/src/subdir/prog2.c gyp-0.1+20150913git1f374df9/test/subdirectory/src/subdir/prog2.c --- gyp-0.1~svn1729/test/subdirectory/src/subdir/prog2.c 2009-08-13 19:29:24.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/src/subdir/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog2.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/subdirectory/src/subdir/subdir2/prog3.c gyp-0.1+20150913git1f374df9/test/subdirectory/src/subdir/subdir2/prog3.c --- gyp-0.1~svn1729/test/subdirectory/src/subdir/subdir2/prog3.c 2009-08-18 19:56:43.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/subdirectory/src/subdir/subdir2/prog3.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog3.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/target/gyptest-target.py gyp-0.1+20150913git1f374df9/test/target/gyptest-target.py --- gyp-0.1~svn1729/test/target/gyptest-target.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/target/gyptest-target.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +# Copyright (c) 2009 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verifies simplest-possible build of a "Hello, world!" program +using non-default extension. In particular, verifies how +target_extension is used to avoid MSB8012 for msvs. +""" + +import sys +import TestGyp + +if sys.platform in ('win32', 'cygwin'): + test = TestGyp.TestGyp() + + test.run_gyp('target.gyp') + test.build('target.gyp') + + # executables + test.built_file_must_exist('hello1.stuff', test.EXECUTABLE, bare=True) + test.built_file_must_exist('hello2.exe', test.EXECUTABLE, bare=True) + test.built_file_must_not_exist('hello2.stuff', test.EXECUTABLE, bare=True) + + # check msvs log for errors + if test.format == "msvs": + log_file = "obj\\hello1\\hello1.log" + test.built_file_must_exist(log_file) + test.built_file_must_not_contain(log_file, "MSB8012") + + log_file = "obj\\hello2\\hello2.log" + test.built_file_must_exist(log_file) + test.built_file_must_not_contain(log_file, "MSB8012") + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/target/hello.c gyp-0.1+20150913git1f374df9/test/target/hello.c --- gyp-0.1~svn1729/test/target/hello.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/target/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +/* Copyright (c) 2009 Google Inc. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +void main(void) { + printf("Hello, world!\n"); +} diff -Nru gyp-0.1~svn1729/test/target/target.gyp gyp-0.1+20150913git1f374df9/test/target/target.gyp --- gyp-0.1~svn1729/test/target/target.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/target/target.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +# Copyright (c) 2009 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'hello1', + 'product_extension': 'stuff', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello2', + 'target_extension': 'stuff', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + } + ] +} diff -Nru gyp-0.1~svn1729/test/toolsets/main.cc gyp-0.1+20150913git1f374df9/test/toolsets/main.cc --- gyp-0.1~svn1729/test/toolsets/main.cc 2013-04-11 18:28:51.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/toolsets/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -7,7 +7,7 @@ const char *GetToolset(); const char *GetToolsetShared(); -int main(int argc, char *argv[]) { +int main(void) { printf("%s\n", GetToolset()); printf("Shared: %s\n", GetToolsetShared()); } diff -Nru gyp-0.1~svn1729/test/toplevel-dir/gyptest-toplevel-dir.py gyp-0.1+20150913git1f374df9/test/toplevel-dir/gyptest-toplevel-dir.py --- gyp-0.1~svn1729/test/toplevel-dir/gyptest-toplevel-dir.py 2012-01-28 03:08:58.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/toplevel-dir/gyptest-toplevel-dir.py 2015-09-13 13:41:20.000000000 +0000 @@ -20,7 +20,7 @@ toplevel_dir = 'src' -test.build('all', chdir=toplevel_dir) +test.build('sub1/main.gyp', test.ALL, chdir=toplevel_dir) test.built_file_must_exist('prog1', type=test.EXECUTABLE, chdir=toplevel_dir) diff -Nru gyp-0.1~svn1729/test/toplevel-dir/src/sub1/prog1.c gyp-0.1+20150913git1f374df9/test/toplevel-dir/src/sub1/prog1.c --- gyp-0.1~svn1729/test/toplevel-dir/src/sub1/prog1.c 2010-05-20 14:40:37.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/toplevel-dir/src/sub1/prog1.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog1.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/toplevel-dir/src/sub2/prog2.c gyp-0.1+20150913git1f374df9/test/toplevel-dir/src/sub2/prog2.c --- gyp-0.1~svn1729/test/toplevel-dir/src/sub2/prog2.c 2010-05-20 14:40:37.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/toplevel-dir/src/sub2/prog2.c 2015-09-13 13:41:20.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char *argv[]) +int main(void) { printf("Hello from prog2.c\n"); return 0; diff -Nru gyp-0.1~svn1729/test/variables/commands/gyptest-commands-repeated-multidir.py gyp-0.1+20150913git1f374df9/test/variables/commands/gyptest-commands-repeated-multidir.py --- gyp-0.1~svn1729/test/variables/commands/gyptest-commands-repeated-multidir.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/variables/commands/gyptest-commands-repeated-multidir.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +# Copyright 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Test variable expansion of ' -int main(int argc, char *argv[]) { +int main(void) { printf(FOO "\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/win/command-quote/command-quote.gyp gyp-0.1+20150913git1f374df9/test/win/command-quote/command-quote.gyp --- gyp-0.1~svn1729/test/win/command-quote/command-quote.gyp 2012-07-18 23:57:01.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/command-quote/command-quote.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -15,7 +15,6 @@ 'rule_name': 'build_with_batch', 'msvs_cygwin_shell': 0, 'extension': 'S', - 'inputs': ['<(RULE_INPUT_PATH)'], 'outputs': ['output.obj'], 'action': ['call go.bat', '<(RULE_INPUT_PATH)', 'output.obj'], },], @@ -29,7 +28,6 @@ 'rule_name': 'build_with_batch2', 'msvs_cygwin_shell': 0, 'extension': 'S', - 'inputs': ['<(RULE_INPUT_PATH)'], 'outputs': ['output2.obj'], 'action': ['call', 'go.bat', '<(RULE_INPUT_PATH)', 'output2.obj'], },], @@ -43,7 +41,6 @@ 'rule_name': 'build_with_batch3', 'msvs_cygwin_shell': 0, 'extension': 'S', - 'inputs': ['<(RULE_INPUT_PATH)'], 'outputs': ['output3.obj'], 'action': ['bat with spaces.bat', '<(RULE_INPUT_PATH)', 'output3.obj'], },], @@ -57,7 +54,6 @@ 'rule_name': 'build_with_batch3', 'msvs_cygwin_shell': 1, 'extension': 'S', - 'inputs': ['<(RULE_INPUT_PATH)'], 'outputs': ['output4.obj'], 'arguments': ['-v'], 'action': ['python', '-c', 'import shutil; ' @@ -73,7 +69,6 @@ 'rule_name': 'build_with_batch3', 'msvs_cygwin_shell': 1, 'extension': 'S', - 'inputs': ['<(RULE_INPUT_PATH)'], 'outputs': ['output5.obj'], 'action': ['python', '-c', "import shutil; " "shutil.copy('<(RULE_INPUT_PATH)', 'output5.obj')"], diff -Nru gyp-0.1~svn1729/test/win/command-quote/subdir/and/another/in-subdir.gyp gyp-0.1+20150913git1f374df9/test/win/command-quote/subdir/and/another/in-subdir.gyp --- gyp-0.1~svn1729/test/win/command-quote/subdir/and/another/in-subdir.gyp 2012-05-03 22:44:10.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/command-quote/subdir/and/another/in-subdir.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -18,7 +18,6 @@ 'rule_name': 'build_with_batch4', 'msvs_cygwin_shell': 0, 'extension': 'S', - 'inputs': ['<(RULE_INPUT_PATH)'], 'outputs': ['output4.obj'], 'action': ['<@(filepath)', '<(RULE_INPUT_PATH)', 'output4.obj'], },], diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/calling-convention.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention.cc --- gyp-0.1~svn1729/test/win/compiler-flags/calling-convention.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern "C" void foo() { +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-cdecl.def gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-cdecl.def --- gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-cdecl.def 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-cdecl.def 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +; Copyright (c) 2014 Google Inc. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. + +EXPORTS + foo diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-fastcall.def gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-fastcall.def --- gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-fastcall.def 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-fastcall.def 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +; Copyright (c) 2014 Google Inc. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. + +EXPORTS + @foo@0 diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/calling-convention.gyp gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention.gyp --- gyp-0.1~svn1729/test/win/compiler-flags/calling-convention.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,66 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_cdecl', + 'type': 'loadable_module', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'CallingConvention': 0, + }, + }, + 'sources': [ + 'calling-convention.cc', + 'calling-convention-cdecl.def', + ], + }, + { + 'target_name': 'test_fastcall', + 'type': 'loadable_module', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'CallingConvention': 1, + }, + }, + 'sources': [ + 'calling-convention.cc', + 'calling-convention-fastcall.def', + ], + }, + { + 'target_name': 'test_stdcall', + 'type': 'loadable_module', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'CallingConvention': 2, + }, + }, + 'sources': [ + 'calling-convention.cc', + 'calling-convention-stdcall.def', + ], + }, + ], + 'conditions': [ + ['MSVS_VERSION[0:4]>="2013"', { + 'targets': [ + { + 'target_name': 'test_vectorcall', + 'type': 'loadable_module', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'CallingConvention': 3, + }, + }, + 'sources': [ + 'calling-convention.cc', + 'calling-convention-vectorcall.def', + ], + }, + ], + }], + ], +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-stdcall.def gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-stdcall.def --- gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-stdcall.def 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-stdcall.def 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +; Copyright (c) 2014 Google Inc. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. + +EXPORTS + _foo@0 diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-vectorcall.def gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-vectorcall.def --- gyp-0.1~svn1729/test/win/compiler-flags/calling-convention-vectorcall.def 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/calling-convention-vectorcall.def 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +; Copyright (c) 2014 Google Inc. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. + +EXPORTS + foo@@0 diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/compile-as-managed.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/compile-as-managed.cc --- gyp-0.1~svn1729/test/win/compiler-flags/compile-as-managed.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/compile-as-managed.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +// Copyright (c) 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/compile-as-managed.gyp gyp-0.1+20150913git1f374df9/test/win/compiler-flags/compile-as-managed.gyp --- gyp-0.1~svn1729/test/win/compiler-flags/compile-as-managed.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/compile-as-managed.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test-compile-as-managed', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'CompileAsManaged': 'true', + 'ExceptionHandling': '0' # /clr is incompatible with /EHs + } + }, + 'sources': ['compile-as-managed.cc'], + }, + { + 'target_name': 'test-compile-as-unmanaged', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'CompileAsManaged': 'false', + } + }, + 'sources': ['compile-as-managed.cc'], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/disable-specific-warnings.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/disable-specific-warnings.cc --- gyp-0.1~svn1729/test/win/compiler-flags/disable-specific-warnings.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/disable-specific-warnings.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + // Causes level 1 warning (C4700) + int i; + return i; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/disable-specific-warnings.gyp gyp-0.1+20150913git1f374df9/test/win/compiler-flags/disable-specific-warnings.gyp --- gyp-0.1~svn1729/test/win/compiler-flags/disable-specific-warnings.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/disable-specific-warnings.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_disable_specific_warnings_set', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'true', + 'DisableSpecificWarnings': ['4700'] + } + }, + 'sources': ['disable-specific-warnings.cc'] + }, + { + 'target_name': 'test_disable_specific_warnings_unset', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'true' + } + }, + 'sources': ['disable-specific-warnings.cc'] + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/enable-enhanced-instruction-set.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/enable-enhanced-instruction-set.cc --- gyp-0.1~svn1729/test/win/compiler-flags/enable-enhanced-instruction-set.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/enable-enhanced-instruction-set.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,28 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +static const char* GetArchOption() { +#if _M_IX86_FP == 0 + return "IA32"; +#elif _M_IX86_FP == 1 + return "SSE"; +#elif _M_IX86_FP == 2 +# if defined(__AVX2__) + return "AVX2"; +# elif defined(__AVX__) + return "AVX"; +# else + return "SSE2"; +# endif +#else + return "UNSUPPORTED OPTION"; +#endif +} + +int main() { + printf("/arch:%s\n", GetArchOption()); + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/enable-enhanced-instruction-set.gyp gyp-0.1+20150913git1f374df9/test/win/compiler-flags/enable-enhanced-instruction-set.gyp --- gyp-0.1~svn1729/test/win/compiler-flags/enable-enhanced-instruction-set.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/enable-enhanced-instruction-set.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,68 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'sse_extensions', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableEnhancedInstructionSet': '1', # StreamingSIMDExtensions + } + }, + 'sources': ['enable-enhanced-instruction-set.cc'], + }, + { + 'target_name': 'sse2_extensions', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableEnhancedInstructionSet': '2', # StreamingSIMDExtensions2 + } + }, + 'sources': ['enable-enhanced-instruction-set.cc'], + }, + ], + 'conditions': [ + ['MSVS_VERSION[0:4]>"2010"', { + 'targets': [ + { + 'target_name': 'avx_extensions', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableEnhancedInstructionSet': '3', # AdvancedVectorExtensions + } + }, + 'sources': ['enable-enhanced-instruction-set.cc'], + }, + { + 'target_name': 'no_extensions', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableEnhancedInstructionSet': '4', # NoExtensions + } + }, + 'sources': ['enable-enhanced-instruction-set.cc'], + }, + ], + }], + ['MSVS_VERSION[0:4]>="2013"', { + 'targets': [ + { + 'target_name': 'avx2_extensions', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'EnableEnhancedInstructionSet': '5', # AdvancedVectorExtensions2 + } + }, + 'sources': ['enable-enhanced-instruction-set.cc'], + }, + ], + }], + ], +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model-fast.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model-fast.cc --- gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model-fast.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model-fast.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifdef _M_FP_PRECISE +#error +#endif + +#ifdef _M_FP_STRICT +#error +#endif + +#ifndef _M_FP_FAST +#error +#endif + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model.gyp gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model.gyp --- gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,43 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test-floating-point-model-default', + 'type': 'executable', + 'sources': ['floating-point-model-precise.cc'], + }, + { + 'target_name': 'test-floating-point-model-precise', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'FloatingPointModel': '0' + } + }, + 'sources': ['floating-point-model-precise.cc'], + }, + { + 'target_name': 'test-floating-point-model-strict', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'FloatingPointModel': '1' + } + }, + 'sources': ['floating-point-model-strict.cc'], + }, + { + 'target_name': 'test-floating-point-model-fast', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'FloatingPointModel': '2' + } + }, + 'sources': ['floating-point-model-fast.cc'], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model-precise.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model-precise.cc --- gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model-precise.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model-precise.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef _M_FP_PRECISE +#error +#endif + +#ifdef _M_FP_STRICT +#error +#endif + +#ifdef _M_FP_FAST +#error +#endif + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model-strict.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model-strict.cc --- gyp-0.1~svn1729/test/win/compiler-flags/floating-point-model-strict.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/floating-point-model-strict.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,19 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifdef _M_FP_PRECISE +#error +#endif + +#ifndef _M_FP_STRICT +#error +#endif + +#ifdef _M_FP_FAST +#error +#endif + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/force-include-files.gyp gyp-0.1+20150913git1f374df9/test/win/compiler-flags/force-include-files.gyp --- gyp-0.1~svn1729/test/win/compiler-flags/force-include-files.gyp 2012-11-30 23:48:46.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/force-include-files.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -16,5 +16,21 @@ 'force-include-files.cc', ], }, + { + 'target_name': 'test_force_include_with_precompiled', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ForcedIncludeFiles': ['string'], + }, + }, + 'msvs_precompiled_header': 'stdio.h', + 'msvs_precompiled_source': 'precomp.cc', + 'msvs_disabled_warnings': [ 4530, ], + 'sources': [ + 'force-include-files-with-precompiled.cc', + 'precomp.cc', + ], + }, ], } diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/force-include-files-with-precompiled.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/force-include-files-with-precompiled.cc --- gyp-0.1~svn1729/test/win/compiler-flags/force-include-files-with-precompiled.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/force-include-files-with-precompiled.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2012 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +int main() { + std::string s; + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/compiler-flags/precomp.cc gyp-0.1+20150913git1f374df9/test/win/compiler-flags/precomp.cc --- gyp-0.1~svn1729/test/win/compiler-flags/precomp.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/compiler-flags/precomp.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include diff -Nru gyp-0.1~svn1729/test/win/enable-winrt/dllmain.cc gyp-0.1+20150913git1f374df9/test/win/enable-winrt/dllmain.cc --- gyp-0.1~svn1729/test/win/enable-winrt/dllmain.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/enable-winrt/dllmain.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,30 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Graphics::Display; + +bool TryToUseSomeWinRT() { + ComPtr dp; + HStringReference s(RuntimeClass_Windows_Graphics_Display_DisplayProperties); + HRESULT hr = GetActivationFactory(s.Get(), dp.GetAddressOf()); + if (SUCCEEDED(hr)) { + float dpi = 96.0f; + if (SUCCEEDED(dp->get_LogicalDpi(&dpi))) { + return true; + } + } + return false; +} + +BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved) { + return TRUE; +} diff -Nru gyp-0.1~svn1729/test/win/enable-winrt/enable-winrt.gyp gyp-0.1+20150913git1f374df9/test/win/enable-winrt/enable-winrt.gyp --- gyp-0.1~svn1729/test/win/enable-winrt/enable-winrt.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/enable-winrt/enable-winrt.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,39 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'enable_winrt_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_missing_dll', + 'type': 'shared_library', + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_winphone_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_enable_winphone': 1, + 'sources': [ + 'dllmain.cc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + '%(AdditionalDependencies)', + ], + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/generator-output-different-drive/prog.c gyp-0.1+20150913git1f374df9/test/win/generator-output-different-drive/prog.c --- gyp-0.1~svn1729/test/win/generator-output-different-drive/prog.c 2013-07-22 20:30:27.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/generator-output-different-drive/prog.c 2015-09-13 13:41:20.000000000 +0000 @@ -4,7 +4,7 @@ #include -int main(int argc, char *argv[]) { +int main(void) { printf("Hello from prog.c\n"); return 0; } diff -Nru gyp-0.1~svn1729/test/win/gyptest-cl-calling-convention.py gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-calling-convention.py --- gyp-0.1~svn1729/test/win/gyptest-cl-calling-convention.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-calling-convention.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure calling convention setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('calling-convention.gyp', chdir=CHDIR) + test.build('calling-convention.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-cl-compile-as-managed.py gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-compile-as-managed.py --- gyp-0.1~svn1729/test/win/gyptest-cl-compile-as-managed.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-compile-as-managed.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure compile as managed (clr) settings are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp() + + CHDIR = 'compiler-flags' + test.run_gyp('compile-as-managed.gyp', chdir=CHDIR) + test.build('compile-as-managed.gyp', "test-compile-as-managed", chdir=CHDIR) + # Must fail. + test.build('compile-as-managed.gyp', "test-compile-as-unmanaged", + chdir=CHDIR, status=1) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-cl-disable-specific-warnings.py gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-disable-specific-warnings.py --- gyp-0.1~svn1729/test/win/gyptest-cl-disable-specific-warnings.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-disable-specific-warnings.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure disable specific warnings is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'compiler-flags' + test.run_gyp('disable-specific-warnings.gyp', chdir=CHDIR) + + # The source file contains a warning, so if WarnAsError is true and + # DisableSpecificWarnings for the warning in question is set, then the build + # should succeed, otherwise it must fail. + + test.build('disable-specific-warnings.gyp', + 'test_disable_specific_warnings_set', + chdir=CHDIR) + test.build('disable-specific-warnings.gyp', + 'test_disable_specific_warnings_unset', + chdir=CHDIR, status=1) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-cl-enable-enhanced-instruction-set.py gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-enable-enhanced-instruction-set.py --- gyp-0.1~svn1729/test/win/gyptest-cl-enable-enhanced-instruction-set.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-enable-enhanced-instruction-set.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Test VCCLCompilerTool EnableEnhancedInstructionSet setting. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + test = TestGyp.TestGyp() + + CHDIR = 'compiler-flags' + test.run_gyp('enable-enhanced-instruction-set.gyp', chdir=CHDIR) + + test.build('enable-enhanced-instruction-set.gyp', test.ALL, chdir=CHDIR) + + test.run_built_executable('sse_extensions', chdir=CHDIR, + stdout='/arch:SSE\n') + test.run_built_executable('sse2_extensions', chdir=CHDIR, + stdout='/arch:SSE2\n') + + # /arch:AVX introduced in VS2010, but MSBuild support lagged until 2012. + if os.path.exists(test.built_file_path('avx_extensions')): + test.run_built_executable('avx_extensions', chdir=CHDIR, + stdout='/arch:AVX\n') + + # /arch:IA32 introduced in VS2012. + if os.path.exists(test.built_file_path('no_extensions')): + test.run_built_executable('no_extensions', chdir=CHDIR, + stdout='/arch:IA32\n') + + # /arch:AVX2 introduced in VS2013r2. + if os.path.exists(test.built_file_path('avx2_extensions')): + test.run_built_executable('avx2_extensions', chdir=CHDIR, + stdout='/arch:AVX2\n') + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-cl-floating-point-model.py gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-floating-point-model.py --- gyp-0.1~svn1729/test/win/gyptest-cl-floating-point-model.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-floating-point-model.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure floating point model settings are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp() + + CHDIR = 'compiler-flags' + test.run_gyp('floating-point-model.gyp', chdir=CHDIR) + test.build('floating-point-model.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-cl-pdbname.py gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-pdbname.py --- gyp-0.1~svn1729/test/win/gyptest-cl-pdbname.py 2013-01-09 05:07:55.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-cl-pdbname.py 2015-09-13 13:41:20.000000000 +0000 @@ -21,7 +21,7 @@ # Confirm that the default behaviour is to name the .pdb per-target (rather # than per .cc file). - test.built_file_must_exist('obj/test_pdbname.pdb', chdir=CHDIR) + test.built_file_must_exist('obj/test_pdbname.cc.pdb', chdir=CHDIR) # Confirm that there should be a .pdb alongside the executable. test.built_file_must_exist('test_pdbname.exe', chdir=CHDIR) diff -Nru gyp-0.1~svn1729/test/win/gyptest-command-quote.py gyp-0.1+20150913git1f374df9/test/win/gyptest-command-quote.py --- gyp-0.1~svn1729/test/win/gyptest-command-quote.py 2012-07-18 23:57:01.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-command-quote.py 2015-09-13 13:41:20.000000000 +0000 @@ -17,6 +17,9 @@ import sys if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) CHDIR = 'command-quote' test.run_gyp('command-quote.gyp', chdir=CHDIR) diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-base-address.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-base-address.py --- gyp-0.1~svn1729/test/win/gyptest-link-base-address.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-base-address.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +# Copyright 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure the base address setting is extracted properly. +""" + +import TestGyp + +import re +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('base-address.gyp', chdir=CHDIR) + test.build('base-address.gyp', test.ALL, chdir=CHDIR) + + def GetHeaders(exe): + full_path = test.built_file_path(exe, chdir=CHDIR) + return test.run_dumpbin('/headers', full_path) + + # Extract the image base address from the headers output. + image_base_reg_ex = re.compile(r'.*\s+([0-9]+) image base.*', re.DOTALL) + + exe_headers = GetHeaders('test_base_specified_exe.exe') + exe_match = image_base_reg_ex.match(exe_headers) + + if not exe_match or not exe_match.group(1): + test.fail_test() + if exe_match.group(1) != '420000': + test.fail_test() + + dll_headers = GetHeaders('test_base_specified_dll.dll') + dll_match = image_base_reg_ex.match(dll_headers) + + if not dll_match or not dll_match.group(1): + test.fail_test() + if dll_match.group(1) != '10420000': + test.fail_test() + + default_exe_headers = GetHeaders('test_base_default_exe.exe') + default_exe_match = image_base_reg_ex.match(default_exe_headers) + + if not default_exe_match or not default_exe_match.group(1): + test.fail_test() + if default_exe_match.group(1) != '400000': + test.fail_test() + + default_dll_headers = GetHeaders('test_base_default_dll.dll') + default_dll_match = image_base_reg_ex.match(default_dll_headers) + + if not default_dll_match or not default_dll_match.group(1): + test.fail_test() + if default_dll_match.group(1) != '10000000': + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-defrelink.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-defrelink.py --- gyp-0.1~svn1729/test/win/gyptest-link-defrelink.py 2013-07-06 00:26:12.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-defrelink.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) CHDIR = 'linker-flags' diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-enable-winrt-app-revision.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-enable-winrt-app-revision.py --- gyp-0.1~svn1729/test/win/gyptest-link-enable-winrt-app-revision.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-enable-winrt-app-revision.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure msvs_application_type_revision works correctly. +""" + +import TestGyp + +import os +import sys +import struct + +CHDIR = 'winrt-app-type-revision' + +print 'This test is not currently working on the bots: https://code.google.com/p/gyp/issues/detail?id=466' +sys.exit(0) + +if (sys.platform == 'win32' and + int(os.environ.get('GYP_MSVS_VERSION', 0)) == 2013): + test = TestGyp.TestGyp(formats=['msvs']) + + test.run_gyp('winrt-app-type-revision.gyp', chdir=CHDIR) + + test.build('winrt-app-type-revision.gyp', 'enable_winrt_81_revision_dll', + chdir=CHDIR) + + # Revision is set to 8.2 which is invalid for 2013 projects so compilation + # must fail. + test.build('winrt-app-type-revision.gyp', 'enable_winrt_82_revision_dll', + chdir=CHDIR, status=1) + + # Revision is set to an invalid value for 2013 projects so compilation + # must fail. + test.build('winrt-app-type-revision.gyp', 'enable_winrt_invalid_revision_dll', + chdir=CHDIR, status=1) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-enable-winrt.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-enable-winrt.py --- gyp-0.1~svn1729/test/win/gyptest-link-enable-winrt.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-enable-winrt.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure msvs_enable_winrt works correctly. +""" + +import TestGyp + +import os +import sys +import struct + +CHDIR = 'enable-winrt' + +print 'This test is not currently working on the bots: https://code.google.com/p/gyp/issues/detail?id=466' +sys.exit(0) + +if (sys.platform == 'win32' and + int(os.environ.get('GYP_MSVS_VERSION', 0)) >= 2013): + test = TestGyp.TestGyp(formats=['msvs']) + + test.run_gyp('enable-winrt.gyp', chdir=CHDIR) + + test.build('enable-winrt.gyp', 'enable_winrt_dll', chdir=CHDIR) + + test.build('enable-winrt.gyp', 'enable_winrt_missing_dll', chdir=CHDIR, + status=1) + + test.build('enable-winrt.gyp', 'enable_winrt_winphone_dll', chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-enable-winrt-target-platform-version.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-enable-winrt-target-platform-version.py --- gyp-0.1~svn1729/test/win/gyptest-link-enable-winrt-target-platform-version.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-enable-winrt-target-platform-version.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure msvs_target_platform_version works correctly. +""" + +import TestGyp + +import os +import sys +import struct + +CHDIR = 'winrt-target-platform-version' + +print 'This test is not currently working on the bots: https://code.google.com/p/gyp/issues/detail?id=466' +sys.exit(0) + +if (sys.platform == 'win32' and + int(os.environ.get('GYP_MSVS_VERSION', 0)) == 2015): + test = TestGyp.TestGyp(formats=['msvs']) + + test.run_gyp('winrt-target-platform-version.gyp', chdir=CHDIR) + + test.build('winrt-target-platform-version.gyp', + 'enable_winrt_10_platversion_dll', chdir=CHDIR) + + # Target Platform without Minimum Target Platform version defaults to a valid + # Target Platform and compiles. + test.build('winrt-target-platform-version.gyp', + 'enable_winrt_10_platversion_nominver_dll', chdir=CHDIR) + + # Target Platform is set to 9.0 which is invalid for 2015 projects so + # compilation must fail. + test.build('winrt-target-platform-version.gyp', + 'enable_winrt_9_platversion_dll', chdir=CHDIR, status=1) + + # Missing Target Platform for 2015 projects must fail. + test.build('winrt-target-platform-version.gyp', + 'enable_winrt_missing_platversion_dll', chdir=CHDIR, status=1) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-force-symbol-reference.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-force-symbol-reference.py --- gyp-0.1~svn1729/test/win/gyptest-link-force-symbol-reference.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-force-symbol-reference.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure ForceSymbolReference is translated properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('force-symbol-reference.gyp', chdir=CHDIR) + test.build('force-symbol-reference.gyp', test.ALL, chdir=CHDIR) + + output = test.run_dumpbin( + '/disasm', test.built_file_path('test_force_reference.exe', chdir=CHDIR)) + if '?x@@YAHXZ:' not in output or '?y@@YAHXZ:' not in output: + test.fail_test() + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-generate-manifest.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-generate-manifest.py --- gyp-0.1~svn1729/test/win/gyptest-link-generate-manifest.py 2012-07-25 21:04:23.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-generate-manifest.py 2015-09-13 13:41:20.000000000 +0000 @@ -14,31 +14,114 @@ import sys if sys.platform == 'win32': + import pywintypes + import win32api + import winerror + + RT_MANIFEST = 24 + + class LoadLibrary(object): + """Context manager for loading and releasing binaries in Windows. + Yields the handle of the binary loaded.""" + def __init__(self, path): + self._path = path + self._handle = None + + def __enter__(self): + self._handle = win32api.LoadLibrary(self._path) + return self._handle + + def __exit__(self, type, value, traceback): + win32api.FreeLibrary(self._handle) + + def extract_manifest(path, resource_name): + """Reads manifest from |path| and returns it as a string. + Returns None is there is no such manifest.""" + with LoadLibrary(path) as handle: + try: + return win32api.LoadResource(handle, RT_MANIFEST, resource_name) + except pywintypes.error as error: + if error.args[0] == winerror.ERROR_RESOURCE_DATA_NOT_FOUND: + return None + else: + raise + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) CHDIR = 'linker-flags' test.run_gyp('generate-manifest.gyp', chdir=CHDIR) test.build('generate-manifest.gyp', test.ALL, chdir=CHDIR) - test.built_file_must_exist('test_manifest_exe.exe.manifest', chdir=CHDIR) - test.built_file_must_exist('test_manifest_dll.dll.manifest', chdir=CHDIR) - # Must contain the Win7 support GUID, but not the Vista one (from - # extra2.manifest). - extra1_manifest = test.built_file_path( - 'test_manifest_extra1.exe.manifest', chdir=CHDIR) - test.must_contain(extra1_manifest, '35138b9a-5d96-4fbd-8e2d-a2440225f93a') - test.must_not_contain(extra1_manifest, 'e2011457-1546-43c5-a5fe-008deee3d3f0') - - # Must contain both. - extra2_manifest = test.built_file_path( - 'test_manifest_extra2.exe.manifest', chdir=CHDIR) - test.must_contain(extra2_manifest, '35138b9a-5d96-4fbd-8e2d-a2440225f93a') - test.must_contain(extra2_manifest, 'e2011457-1546-43c5-a5fe-008deee3d3f0') - - # Same as extra2, but using list syntax instead. - extra_list_manifest = test.built_file_path( - 'test_manifest_extra_list.exe.manifest', chdir=CHDIR) - test.must_contain(extra_list_manifest, '35138b9a-5d96-4fbd-8e2d-a2440225f93a') - test.must_contain(extra_list_manifest, 'e2011457-1546-43c5-a5fe-008deee3d3f0') + # Make sure that generation of .generated.manifest does not cause a relink. + test.run_gyp('generate-manifest.gyp', chdir=CHDIR) + test.up_to_date('generate-manifest.gyp', test.ALL, chdir=CHDIR) + def test_manifest(filename, generate_manifest, embedded_manifest, + extra_manifest): + exe_file = test.built_file_path(filename, chdir=CHDIR) + if not generate_manifest: + test.must_not_exist(exe_file + '.manifest') + manifest = extract_manifest(exe_file, 1) + test.fail_test(manifest) + return + if embedded_manifest: + manifest = extract_manifest(exe_file, 1) + test.fail_test(not manifest) + else: + test.must_exist(exe_file + '.manifest') + manifest = test.read(exe_file + '.manifest') + test.fail_test(not manifest) + test.fail_test(extract_manifest(exe_file, 1)) + if generate_manifest: + test.must_contain_any_line(manifest, 'requestedExecutionLevel') + if extra_manifest: + test.must_contain_any_line(manifest, + '35138b9a-5d96-4fbd-8e2d-a2440225f93a') + test.must_contain_any_line(manifest, + 'e2011457-1546-43c5-a5fe-008deee3d3f0') + + test_manifest('test_generate_manifest_true.exe', + generate_manifest=True, + embedded_manifest=False, + extra_manifest=False) + test_manifest('test_generate_manifest_false.exe', + generate_manifest=False, + embedded_manifest=False, + extra_manifest=False) + test_manifest('test_generate_manifest_default.exe', + generate_manifest=True, + embedded_manifest=False, + extra_manifest=False) + test_manifest('test_generate_manifest_true_as_embedded.exe', + generate_manifest=True, + embedded_manifest=True, + extra_manifest=False) + test_manifest('test_generate_manifest_false_as_embedded.exe', + generate_manifest=False, + embedded_manifest=True, + extra_manifest=False) + test_manifest('test_generate_manifest_default_as_embedded.exe', + generate_manifest=True, + embedded_manifest=True, + extra_manifest=False) + test_manifest('test_generate_manifest_true_with_extra_manifest.exe', + generate_manifest=True, + embedded_manifest=False, + extra_manifest=True) + test_manifest('test_generate_manifest_false_with_extra_manifest.exe', + generate_manifest=False, + embedded_manifest=False, + extra_manifest=True) + test_manifest('test_generate_manifest_true_with_extra_manifest_list.exe', + generate_manifest=True, + embedded_manifest=False, + extra_manifest=True) + test_manifest('test_generate_manifest_false_with_extra_manifest_list.exe', + generate_manifest=False, + embedded_manifest=False, + extra_manifest=True) + test_manifest('test_generate_manifest_default_embed_default.exe', + generate_manifest=True, + embedded_manifest=True, + extra_manifest=False) test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-large-pdb.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-large-pdb.py --- gyp-0.1~svn1729/test/win/gyptest-link-large-pdb.py 2013-03-27 14:49:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-large-pdb.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,10 @@ import struct import sys +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + CHDIR = 'large-pdb' diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-ltcg.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-ltcg.py --- gyp-0.1~svn1729/test/win/gyptest-link-ltcg.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-ltcg.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure LTCG is working properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('ltcg.gyp', chdir=CHDIR) + + # Here we expect LTCG is able to inline functions beyond compile unit. + # Note: This marker is embedded in 'inline_test_main.cc' + INLINE_MARKER = '==== inlined ====' + + # test 'LinkTimeCodeGenerationOptionDefault' + test.build('ltcg.gyp', 'test_ltcg_off', chdir=CHDIR) + test.run_built_executable('test_ltcg_off', chdir=CHDIR) + test.must_not_contain_any_line(test.stdout(), [INLINE_MARKER]) + + # test 'LinkTimeCodeGenerationOptionUse' + test.build('ltcg.gyp', 'test_ltcg_on', chdir=CHDIR) + test.must_contain_any_line(test.stdout(), ['Generating code']) + test.run_built_executable('test_ltcg_on', chdir=CHDIR) + test.must_contain_any_line(test.stdout(), [INLINE_MARKER]) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-noimportlib.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-noimportlib.py --- gyp-0.1~svn1729/test/win/gyptest-link-noimportlib.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-noimportlib.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure that the (custom) NoImportLibrary flag is handled correctly. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'importlib' + test.run_gyp('noimplib.gyp', chdir=CHDIR) + test.build('noimplib.gyp', test.ALL, chdir=CHDIR) + + # The target has an entry point, but no exports. Ordinarily, ninja expects + # all DLLs to export some symbols (with the exception of /NOENTRY resource- + # only DLLs). When the NoImportLibrary flag is set, this is suppressed. If + # this is not working correctly, the expected .lib will never be generated + # but will be expected, so the build will not be up to date. + test.up_to_date('noimplib.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-ordering.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-ordering.py --- gyp-0.1~svn1729/test/win/gyptest-link-ordering.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-ordering.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure the link order of object files is the same between msvs and ninja. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('link-ordering.gyp', chdir=CHDIR) + test.build('link-ordering.gyp', test.ALL, chdir=CHDIR) + + def GetDisasm(exe): + full_path = test.built_file_path(exe, chdir=CHDIR) + # Get disassembly and drop int3 padding between functions. + return '\n'.join( + x for x in test.run_dumpbin('/disasm', full_path).splitlines() + if 'CC' not in x) + + # This is the full dump that we expect. The source files in the .gyp match + # this order which is what determines the ordering in the binary. + + expected_disasm_basic = ''' +_mainCRTStartup: + 00401000: B8 05 00 00 00 mov eax,5 + 00401005: C3 ret +?z@@YAHXZ: + 00401010: B8 03 00 00 00 mov eax,3 + 00401015: C3 ret +?x@@YAHXZ: + 00401020: B8 01 00 00 00 mov eax,1 + 00401025: C3 ret +?y@@YAHXZ: + 00401030: B8 02 00 00 00 mov eax,2 + 00401035: C3 ret +_main: + 00401040: 33 C0 xor eax,eax + 00401042: C3 ret +''' + + if expected_disasm_basic not in GetDisasm('test_ordering_exe.exe'): + print GetDisasm('test_ordering_exe.exe') + test.fail_test() + + # Similar to above. The VS generator handles subdirectories differently. + + expected_disasm_subdirs = ''' +_mainCRTStartup: + 00401000: B8 05 00 00 00 mov eax,5 + 00401005: C3 ret +_main: + 00401010: 33 C0 xor eax,eax + 00401012: C3 ret +?y@@YAHXZ: + 00401020: B8 02 00 00 00 mov eax,2 + 00401025: C3 ret +?z@@YAHXZ: + 00401030: B8 03 00 00 00 mov eax,3 + 00401035: C3 ret +''' + + if expected_disasm_subdirs not in GetDisasm('test_ordering_subdirs.exe'): + print GetDisasm('test_ordering_subdirs.exe') + test.fail_test() + + # Similar, but with directories mixed into folders (crt and main at the same + # level, but with a subdir in the middle). + + expected_disasm_subdirs_mixed = ''' +_mainCRTStartup: + 00401000: B8 05 00 00 00 mov eax,5 + 00401005: C3 ret +?x@@YAHXZ: + 00401010: B8 01 00 00 00 mov eax,1 + 00401015: C3 ret +_main: + 00401020: 33 C0 xor eax,eax + 00401022: C3 ret +?z@@YAHXZ: + 00401030: B8 03 00 00 00 mov eax,3 + 00401035: C3 ret +?y@@YAHXZ: + 00401040: B8 02 00 00 00 mov eax,2 + 00401045: C3 ret +''' + + if (expected_disasm_subdirs_mixed not in + GetDisasm('test_ordering_subdirs_mixed.exe')): + print GetDisasm('test_ordering_subdirs_mixed.exe') + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-pdb-no-output.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pdb-no-output.py --- gyp-0.1~svn1729/test/win/gyptest-link-pdb-no-output.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pdb-no-output.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Ensure that when debug information is not output, a pdb is not expected. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp() + CHDIR = 'linker-flags' + test.run_gyp('pdb-output.gyp', chdir=CHDIR) + test.build('pdb-output.gyp', 'test_pdb_output_disabled', chdir=CHDIR) + # Make sure that the build doesn't expect a PDB to be generated when there + # will be none. + test.up_to_date('pdb-output.gyp', 'test_pdb_output_disabled', chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-pdb-output.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pdb-output.py --- gyp-0.1~svn1729/test/win/gyptest-link-pdb-output.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pdb-output.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Ensure that ninja includes the .pdb as an output file from linking. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + CHDIR = 'linker-flags' + test.run_gyp('pdb-output.gyp', chdir=CHDIR) + # Note, building the pdbs rather than ALL or gyp target. + test.build('pdb-output.gyp', 'output_exe.pdb', chdir=CHDIR) + test.build('pdb-output.gyp', 'output_dll.pdb', chdir=CHDIR) + + def FindFile(pdb): + full_path = test.built_file_path(pdb, chdir=CHDIR) + return os.path.isfile(full_path) + + if not FindFile('output_exe.pdb'): + test.fail_test() + if not FindFile('output_dll.pdb'): + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-pdb.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pdb.py --- gyp-0.1~svn1729/test/win/gyptest-link-pdb.py 2012-11-03 00:08:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pdb.py 2015-09-13 13:41:20.000000000 +0000 @@ -5,7 +5,8 @@ # found in the LICENSE file. """ -Verifies that the 'Profile' attribute in VCLinker is extracted properly. +Verifies that the 'ProgramDatabaseFile' attribute in VCLinker is extracted +properly. """ import TestGyp diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-pgo.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pgo.py --- gyp-0.1~svn1729/test/win/gyptest-link-pgo.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-pgo.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure PGO is working properly. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('pgo.gyp', chdir=CHDIR) + + def IsPGOAvailable(): + """Returns true if the Visual Studio available here supports PGO.""" + test.build('pgo.gyp', 'gen_linker_option', chdir=CHDIR) + tmpfile = test.read(test.built_file_path('linker_options.txt', chdir=CHDIR)) + return any(line.find('PGOPTIMIZE') for line in tmpfile) + + # Test generated build files look fine. + if test.format == 'ninja': + ninja = test.built_file_path('obj/test_pgo_instrument.ninja', chdir=CHDIR) + test.must_contain(ninja, '/LTCG:PGINSTRUMENT') + test.must_contain(ninja, 'test_pgo.pgd') + ninja = test.built_file_path('obj/test_pgo_optimize.ninja', chdir=CHDIR) + test.must_contain(ninja, '/LTCG:PGOPTIMIZE') + test.must_contain(ninja, 'test_pgo.pgd') + ninja = test.built_file_path('obj/test_pgo_update.ninja', chdir=CHDIR) + test.must_contain(ninja, '/LTCG:PGUPDATE') + test.must_contain(ninja, 'test_pgo.pgd') + elif test.format == 'msvs': + LTCG_FORMAT = '%s' + vcproj = test.workpath('linker-flags/test_pgo_instrument.vcxproj') + test.must_contain(vcproj, LTCG_FORMAT % 'PGInstrument') + test.must_contain(vcproj, 'test_pgo.pgd') + vcproj = test.workpath('linker-flags/test_pgo_optimize.vcxproj') + test.must_contain(vcproj, LTCG_FORMAT % 'PGOptimization') + test.must_contain(vcproj, 'test_pgo.pgd') + vcproj = test.workpath('linker-flags/test_pgo_update.vcxproj') + test.must_contain(vcproj, LTCG_FORMAT % 'PGUpdate') + test.must_contain(vcproj, 'test_pgo.pgd') + + # When PGO is available, try building binaries with PGO. + if IsPGOAvailable(): + pgd_path = test.built_file_path('test_pgo.pgd', chdir=CHDIR) + + # Test if 'PGInstrument' generates PGD (Profile-Guided Database) file. + if os.path.exists(pgd_path): + test.unlink(pgd_path) + test.must_not_exist(pgd_path) + test.build('pgo.gyp', 'test_pgo_instrument', chdir=CHDIR) + test.must_exist(pgd_path) + + # Test if 'PGOptimize' works well + test.build('pgo.gyp', 'test_pgo_optimize', chdir=CHDIR) + test.must_contain_any_line(test.stdout(), ['profiled functions']) + + # Test if 'PGUpdate' works well + test.build('pgo.gyp', 'test_pgo_update', chdir=CHDIR) + # With 'PGUpdate', linker should not complain that sources are changed after + # the previous training run. + test.touch(test.workpath('linker-flags/inline_test_main.cc')) + test.unlink(test.built_file_path('test_pgo_update.exe', chdir=CHDIR)) + test.build('pgo.gyp', 'test_pgo_update', chdir=CHDIR) + test.must_contain_any_line(test.stdout(), ['profiled functions']) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-profile.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-profile.py --- gyp-0.1~svn1729/test/win/gyptest-link-profile.py 2012-10-29 22:03:42.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-profile.py 2015-09-13 13:41:20.000000000 +0000 @@ -34,4 +34,4 @@ if not '.idata' in GetSummary('test_profile_default.exe'): test.fail_test() - test.pass_test() \ No newline at end of file + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-restat-importlib.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-restat-importlib.py --- gyp-0.1~svn1729/test/win/gyptest-link-restat-importlib.py 2012-04-25 19:42:37.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-restat-importlib.py 2015-09-13 13:41:20.000000000 +0000 @@ -11,12 +11,18 @@ import TestGyp +import os import sys import time if sys.platform == 'win32': test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + if not os.environ.get('ProgramFiles(x86)'): + # TODO(scottmg) + print 'Skipping test on x86, http://crbug.com/365833' + test.pass_test() + CHDIR = 'importlib' test.run_gyp('importlib.gyp', chdir=CHDIR) test.build('importlib.gyp', test.ALL, chdir=CHDIR) diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-safeseh.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-safeseh.py --- gyp-0.1~svn1729/test/win/gyptest-link-safeseh.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-safeseh.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure safeseh setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp() + + CHDIR = 'linker-flags' + test.run_gyp('safeseh.gyp', chdir=CHDIR) + test.build('safeseh.gyp', test.ALL, chdir=CHDIR) + + def HasSafeExceptionHandlers(exe): + full_path = test.built_file_path(exe, chdir=CHDIR) + output = test.run_dumpbin('/LOADCONFIG', full_path) + return ' Safe Exception Handler Table' in output + + # From MSDN: http://msdn.microsoft.com/en-us/library/9a89h429.aspx + # If /SAFESEH is not specified, the linker will produce an image with a + # table of safe exceptions handlers if all modules are compatible with + # the safe exception handling feature. If any modules were not + # compatible with safe exception handling feature, the resulting image + # will not contain a table of safe exception handlers. + # However, the msvs IDE passes /SAFESEH to the linker by default, if + # ImageHasSafeExceptionHandlers is not set to false in the vcxproj file. + # We emulate this behavior in msvs_emulation.py, so 'test_safeseh_default' + # and 'test_safeseh_yes' are built identically. + if not HasSafeExceptionHandlers('test_safeseh_default.exe'): + test.fail_test() + if HasSafeExceptionHandlers('test_safeseh_no.exe'): + test.fail_test() + if not HasSafeExceptionHandlers('test_safeseh_yes.exe'): + test.fail_test() + if HasSafeExceptionHandlers('test_safeseh_x64.exe'): + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-shard.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-shard.py --- gyp-0.1~svn1729/test/win/gyptest-link-shard.py 2013-02-06 01:01:32.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-shard.py 2015-09-13 13:41:20.000000000 +0000 @@ -24,4 +24,7 @@ test.built_file_must_exist('shard_2.lib', chdir=CHDIR) test.built_file_must_exist('shard_3.lib', chdir=CHDIR) + test.run_gyp('shard_ref.gyp', chdir=CHDIR) + test.build('shard_ref.gyp', test.ALL, chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-stacksize.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-stacksize.py --- gyp-0.1~svn1729/test/win/gyptest-link-stacksize.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-stacksize.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure StackReserveSize and StackCommitSize settings are extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('stacksize.gyp', chdir=CHDIR) + test.build('stacksize.gyp', test.ALL, chdir=CHDIR) + + def GetHeaders(exe): + return test.run_dumpbin('/headers', test.built_file_path(exe, chdir=CHDIR)) + + # Verify default sizes as reported by dumpbin: + # 100000h = 1MB + # 1000h = 4KB + default_headers = GetHeaders('test_default.exe') + if '100000 size of stack reserve' not in default_headers: + test.fail_test() + if '1000 size of stack commit' not in default_headers: + test.fail_test() + + # Verify that reserved size is changed, but commit size is unchanged: + # 200000h = 2MB + # 1000h = 4KB + set_reserved_size_headers = GetHeaders('test_set_reserved_size.exe') + if '200000 size of stack reserve' not in set_reserved_size_headers: + test.fail_test() + if '1000 size of stack commit' not in set_reserved_size_headers: + test.fail_test() + + # Verify that setting the commit size, without the reserve size, has no + # effect: + # 100000h = 1MB + # 1000h = 4KB + set_commit_size_headers = GetHeaders('test_set_commit_size.exe') + if '100000 size of stack reserve' not in set_commit_size_headers: + test.fail_test() + if '1000 size of stack commit' not in set_commit_size_headers: + test.fail_test() + + # Verify that setting both works: + # 200000h = 2MB + # 2000h = 8KB + set_both_headers = GetHeaders('test_set_both.exe') + if '200000 size of stack reserve' not in set_both_headers: + test.fail_test() + if '2000 size of stack commit' not in set_both_headers: + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-subsystem.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-subsystem.py --- gyp-0.1~svn1729/test/win/gyptest-link-subsystem.py 2012-03-26 23:58:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-subsystem.py 2015-09-13 13:41:20.000000000 +0000 @@ -23,6 +23,16 @@ test.build('subsystem.gyp', 'test_windows_ok', chdir=CHDIR) test.build('subsystem.gyp', 'test_windows_fail', chdir=CHDIR, status=1) + test.build('subsystem.gyp', 'test_console_xp', chdir=CHDIR) + test.build('subsystem.gyp', 'test_windows_xp', chdir=CHDIR) + # Make sure we are targeting XP. + def GetHeaders(exe): + return test.run_dumpbin('/headers', test.built_file_path(exe, chdir=CHDIR)) + if '5.01 subsystem version' not in GetHeaders('test_console_xp.exe'): + test.fail_test() + if '5.01 subsystem version' not in GetHeaders('test_windows_xp.exe'): + test.fail_test() + # TODO(scottmg): There are other subsystems (WinCE, etc.) that we don't use. test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-target-machine.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-target-machine.py --- gyp-0.1~svn1729/test/win/gyptest-link-target-machine.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-target-machine.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure TargetMachine setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('target-machine.gyp', chdir=CHDIR) + # The .cc file is compiled as x86 (the default), so the link/libs that are + # x64 need to fail. + test.build('target-machine.gyp', 'test_target_link_x86', chdir=CHDIR) + test.build( + 'target-machine.gyp', 'test_target_link_x64', chdir=CHDIR, status=1) + test.build('target-machine.gyp', 'test_target_lib_x86', chdir=CHDIR) + test.build('target-machine.gyp', 'test_target_lib_x64', chdir=CHDIR, status=1) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-unsupported-manifest.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-unsupported-manifest.py --- gyp-0.1~svn1729/test/win/gyptest-link-unsupported-manifest.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-unsupported-manifest.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure we error out if #pragma comments are used to modify manifests. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + # This assertion only applies to the ninja build. + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('unsupported-manifest.gyp', chdir=CHDIR) + + # Just needs to fail to build. + test.build('unsupported-manifest.gyp', + 'test_unsupported', chdir=CHDIR, status=1) + test.must_not_exist(test.built_file_path('test_unsupported.exe', chdir=CHDIR)) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-update-manifest.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-update-manifest.py --- gyp-0.1~svn1729/test/win/gyptest-link-update-manifest.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-update-manifest.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure binary is relinked when manifest settings are changed. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + import pywintypes + import win32api + import winerror + + RT_MANIFEST = 24 + + class LoadLibrary(object): + """Context manager for loading and releasing binaries in Windows. + Yields the handle of the binary loaded.""" + def __init__(self, path): + self._path = path + self._handle = None + + def __enter__(self): + self._handle = win32api.LoadLibrary(self._path) + return self._handle + + def __exit__(self, type, value, traceback): + win32api.FreeLibrary(self._handle) + + def extract_manifest(path, resource_name): + """Reads manifest from |path| and returns it as a string. + Returns None is there is no such manifest.""" + with LoadLibrary(path) as handle: + try: + return win32api.LoadResource(handle, RT_MANIFEST, resource_name) + except pywintypes.error as error: + if error.args[0] == winerror.ERROR_RESOURCE_DATA_NOT_FOUND: + return None + else: + raise + + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + + gyp_template = ''' +{ + 'targets': [ + { + 'target_name': 'test_update_manifest', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'UACExecutionLevel': '%(uac_execution_level)d', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + 'AdditionalManifestFiles': '%(additional_manifest_files)s', + }, + }, + }, + ], +} +''' + + gypfile = 'update-manifest.gyp' + + def WriteAndUpdate(uac_execution_level, additional_manifest_files, do_build): + with open(os.path.join(CHDIR, gypfile), 'wb') as f: + f.write(gyp_template % { + 'uac_execution_level': uac_execution_level, + 'additional_manifest_files': additional_manifest_files, + }) + test.run_gyp(gypfile, chdir=CHDIR) + if do_build: + test.build(gypfile, chdir=CHDIR) + exe_file = test.built_file_path('test_update_manifest.exe', chdir=CHDIR) + return extract_manifest(exe_file, 1) + + manifest = WriteAndUpdate(0, '', True) + test.fail_test('asInvoker' not in manifest) + test.fail_test('35138b9a-5d96-4fbd-8e2d-a2440225f93a' in manifest) + + # Make sure that updating .gyp and regenerating doesn't cause a rebuild. + WriteAndUpdate(0, '', False) + test.up_to_date(gypfile, test.ALL, chdir=CHDIR) + + # But make sure that changing a manifest property does cause a relink. + manifest = WriteAndUpdate(2, '', True) + test.fail_test('requireAdministrator' not in manifest) + + # Adding a manifest causes a rebuild. + manifest = WriteAndUpdate(2, 'extra.manifest', True) + test.fail_test('35138b9a-5d96-4fbd-8e2d-a2440225f93a' not in manifest) diff -Nru gyp-0.1~svn1729/test/win/gyptest-link-warnings-as-errors.py gyp-0.1+20150913git1f374df9/test/win/gyptest-link-warnings-as-errors.py --- gyp-0.1~svn1729/test/win/gyptest-link-warnings-as-errors.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-link-warnings-as-errors.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure linker warnings-as-errors setting is extracted properly. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'linker-flags' + test.run_gyp('warn-as-error.gyp', chdir=CHDIR) + + test.build('warn-as-error.gyp', 'test_on', chdir=CHDIR, status=1) + test.build('warn-as-error.gyp', 'test_off', chdir=CHDIR) + test.build('warn-as-error.gyp', 'test_default', chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-macro-targetext.py gyp-0.1+20150913git1f374df9/test/win/gyptest-macro-targetext.py --- gyp-0.1~svn1729/test/win/gyptest-macro-targetext.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-macro-targetext.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure macro expansion of $(TargetExt) is handled. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'vs-macros' + test.run_gyp('targetext.gyp', chdir=CHDIR) + test.build('targetext.gyp', test.ALL, chdir=CHDIR) + test.built_file_must_exist('executable.exe', chdir=CHDIR) + test.built_file_must_exist('loadable_module.dll', chdir=CHDIR) + test.built_file_must_exist('shared_library.dll', chdir=CHDIR) + test.built_file_must_exist('static_library.lib', chdir=CHDIR) + test.built_file_must_exist('product_extension.library', chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-macro-targetfilename.py gyp-0.1+20150913git1f374df9/test/win/gyptest-macro-targetfilename.py --- gyp-0.1~svn1729/test/win/gyptest-macro-targetfilename.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-macro-targetfilename.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure macro expansion of $(TargetFileName) is handled. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + if not (test.format == 'msvs' and + int(os.environ.get('GYP_MSVS_VERSION', 0)) == 2013): + CHDIR = 'vs-macros' + test.run_gyp('targetfilename.gyp', chdir=CHDIR) + test.build('targetfilename.gyp', test.ALL, chdir=CHDIR) + test.built_file_must_exist('test_targetfilename_executable.exe', chdir=CHDIR) + test.built_file_must_exist('test_targetfilename_loadable_module.dll', + chdir=CHDIR) + test.built_file_must_exist('test_targetfilename_shared_library.dll', + chdir=CHDIR) + test.built_file_must_exist('test_targetfilename_static_library.lib', + chdir=CHDIR) + test.built_file_must_exist('test_targetfilename_product_extension.foo', + chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-macro-targetpath.py gyp-0.1+20150913git1f374df9/test/win/gyptest-macro-targetpath.py --- gyp-0.1~svn1729/test/win/gyptest-macro-targetpath.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-macro-targetpath.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure macro expansion of $(TargetPath) is handled. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'vs-macros' + test.run_gyp('targetpath.gyp', chdir=CHDIR) + test.build('targetpath.gyp', test.ALL, chdir=CHDIR) + test.built_file_must_exist('test_targetpath_executable.exe', chdir=CHDIR) + test.built_file_must_exist('test_targetpath_loadable_module.dll', + chdir=CHDIR) + test.built_file_must_exist('test_targetpath_shared_library.dll', + chdir=CHDIR) + test.built_file_must_exist('test_targetpath_static_library.lib', + chdir=CHDIR) + test.built_file_must_exist('test_targetpath_product_extension.foo', + chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-midl-excluded.py gyp-0.1+20150913git1f374df9/test/win/gyptest-midl-excluded.py --- gyp-0.1~svn1729/test/win/gyptest-midl-excluded.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-midl-excluded.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Test that .idl files in actions and non-native rules are excluded. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'idl-excluded' + test.run_gyp('idl-excluded.gyp', chdir=CHDIR) + test.build('idl-excluded.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-midl-includedirs.py gyp-0.1+20150913git1f374df9/test/win/gyptest-midl-includedirs.py --- gyp-0.1~svn1729/test/win/gyptest-midl-includedirs.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-midl-includedirs.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Verify that 'midl_include_dirs' is handled. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'idl-includedirs' + test.run_gyp('idl-includedirs.gyp', chdir=CHDIR) + test.build('idl-includedirs.gyp', test.ALL, chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-midl-rules.py gyp-0.1+20150913git1f374df9/test/win/gyptest-midl-rules.py --- gyp-0.1~svn1729/test/win/gyptest-midl-rules.py 2013-02-21 20:09:46.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-midl-rules.py 2015-09-13 13:41:20.000000000 +0000 @@ -21,4 +21,8 @@ test.set_configuration('Debug|%s' % platform) test.build('basic-idl.gyp', test.ALL, chdir=CHDIR) + # Make sure ninja win_tool.py filters out noisy lines. + if test.format == 'ninja' and 'Processing' in test.stdout(): + test.fail_test() + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-ml-safeseh.py gyp-0.1+20150913git1f374df9/test/win/gyptest-ml-safeseh.py --- gyp-0.1~svn1729/test/win/gyptest-ml-safeseh.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-ml-safeseh.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure the /safeseh option can be passed to ml. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + CHDIR = 'ml-safeseh' + test.run_gyp('ml-safeseh.gyp', chdir=CHDIR) + test.build('ml-safeseh.gyp', test.ALL, chdir=CHDIR) + + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/gyptest-rc-build.py gyp-0.1+20150913git1f374df9/test/win/gyptest-rc-build.py --- gyp-0.1~svn1729/test/win/gyptest-rc-build.py 2012-09-01 00:24:44.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-rc-build.py 2015-09-13 13:41:20.000000000 +0000 @@ -13,6 +13,9 @@ import sys if sys.platform == 'win32': + print "This test is currently disabled: https://crbug.com/483696." + sys.exit(0) + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) CHDIR = 'rc-build' diff -Nru gyp-0.1~svn1729/test/win/gyptest-system-include.py gyp-0.1+20150913git1f374df9/test/win/gyptest-system-include.py --- gyp-0.1~svn1729/test/win/gyptest-system-include.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/gyptest-system-include.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Checks that msvs_system_include_dirs works. +""" + +import TestGyp + +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['msvs', 'ninja']) + + CHDIR = 'system-include' + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) + test.pass_test() diff -Nru gyp-0.1~svn1729/test/win/idl-excluded/bad.idl gyp-0.1+20150913git1f374df9/test/win/idl-excluded/bad.idl --- gyp-0.1~svn1729/test/win/idl-excluded/bad.idl 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-excluded/bad.idl 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,6 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +This is a dummy .idl file that will trigger an error if it is not excluded from +the build. diff -Nru gyp-0.1~svn1729/test/win/idl-excluded/copy-file.py gyp-0.1+20150913git1f374df9/test/win/idl-excluded/copy-file.py --- gyp-0.1~svn1729/test/win/idl-excluded/copy-file.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-excluded/copy-file.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +# Copyright (c) 2009 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import sys + +contents = open(sys.argv[1], 'r').read() +open(sys.argv[2], 'wb').write(contents) + +sys.exit(0) diff -Nru gyp-0.1~svn1729/test/win/idl-excluded/idl-excluded.gyp gyp-0.1+20150913git1f374df9/test/win/idl-excluded/idl-excluded.gyp --- gyp-0.1~svn1729/test/win/idl-excluded/idl-excluded.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-excluded/idl-excluded.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,58 @@ +# Copyright (c) 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'exclude_with_action', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [{ + 'action_name': 'copy_action', + 'inputs': [ + 'copy-file.py', + 'bad.idl', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/bad.idl', + ], + 'action': [ + 'python', '<@(_inputs)', '<@(_outputs)', + ], + }], + }, + { + 'target_name': 'exclude_with_rule', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'bad.idl', + ], + 'rules': [{ + 'rule_name': 'copy_rule', + 'extension': 'idl', + 'inputs': [ + 'copy-file.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).idl', + ], + 'action': [ + 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + }], + }, + { + 'target_name': 'program', + 'type': 'executable', + 'sources': [ + 'program.cc', + ], + 'dependencies': [ + 'exclude_with_action', + 'exclude_with_rule', + ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/win/idl-excluded/program.cc gyp-0.1+20150913git1f374df9/test/win/idl-excluded/program.cc --- gyp-0.1~svn1729/test/win/idl-excluded/program.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-excluded/program.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/idl-includedirs/hello.cc gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/hello.cc --- gyp-0.1~svn1729/test/win/idl-includedirs/hello.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/hello.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/idl-includedirs/idl-includedirs.gyp gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/idl-includedirs.gyp --- gyp-0.1~svn1729/test/win/idl-includedirs/idl-includedirs.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/idl-includedirs.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +# Copyright (c) 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_midl_include_dirs', + 'type': 'executable', + 'sources': [ + 'hello.cc', + 'subdir/foo.idl', + 'subdir/bar.idl', + ], + 'midl_include_dirs': [ + 'subdir', + ], + 'msvs_settings': { + 'VCMIDLTool': { + 'OutputDirectory': '<(INTERMEDIATE_DIR)', + 'DLLDataFileName': '$(InputName)_dlldata.h', + }, + }, + }, + ], +} diff -Nru gyp-0.1~svn1729/test/win/idl-includedirs/subdir/bar.idl gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/subdir/bar.idl --- gyp-0.1~svn1729/test/win/idl-includedirs/subdir/bar.idl 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/subdir/bar.idl 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import "oaidl.idl"; + +[ + object, + uuid(A03D1421-B1EC-11D0-8C3A-00C04FC31D3F), +] +interface Bar : IUnknown { + HRESULT BarFunction(); +}; diff -Nru gyp-0.1~svn1729/test/win/idl-includedirs/subdir/foo.idl gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/subdir/foo.idl --- gyp-0.1~svn1729/test/win/idl-includedirs/subdir/foo.idl 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-includedirs/subdir/foo.idl 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,14 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import "oaidl.idl"; +import "bar.idl"; + +[ + object, + uuid(9C1100DD-51D4-4827-AE9F-3B8FAC4AED72), +] +interface Foo : IUnknown { + HRESULT FooFunction(Bar* bar); +}; diff -Nru gyp-0.1~svn1729/test/win/idl-rules/basic-idl.gyp gyp-0.1+20150913git1f374df9/test/win/idl-rules/basic-idl.gyp --- gyp-0.1~svn1729/test/win/idl-rules/basic-idl.gyp 2013-02-25 22:29:21.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-rules/basic-idl.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -1,42 +1,67 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'variables': { - 'midl_out_dir': '<(SHARED_INTERMEDIATE_DIR)', - }, - 'target_defaults': { - 'configurations': { - 'Debug': { - 'msvs_configuration_platform': 'Win32', - }, - 'Debug_x64': { - 'inherit_from': ['Debug'], - 'msvs_configuration_platform': 'x64', - }, - }, - }, - 'targets': [ - { - 'target_name': 'idl_test', - 'type': 'executable', - 'sources': [ - 'history_indexer.idl', - '<(midl_out_dir)/history_indexer.h', - '<(midl_out_dir)/history_indexer_i.c', - 'history_indexer_user.cc', - ], - 'libraries': ['ole32.lib'], - 'include_dirs': [ - '<(midl_out_dir)', - ], - 'msvs_settings': { - 'VCMIDLTool': { - 'OutputDirectory': '<(midl_out_dir)', - 'HeaderFileName': '<(RULE_INPUT_ROOT).h', - }, - }, - }, - ], -} +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'midl_out_dir': '<(SHARED_INTERMEDIATE_DIR)', + }, + 'target_defaults': { + 'configurations': { + 'Debug': { + 'msvs_configuration_platform': 'Win32', + }, + 'Debug_x64': { + 'inherit_from': ['Debug'], + 'msvs_configuration_platform': 'x64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'idl_test', + 'type': 'executable', + 'sources': [ + 'history_indexer.idl', + '<(midl_out_dir)/history_indexer.h', + '<(midl_out_dir)/history_indexer_i.c', + 'history_indexer_user.cc', + ], + 'libraries': ['ole32.lib'], + 'include_dirs': [ + '<(midl_out_dir)', + ], + 'msvs_settings': { + 'VCMIDLTool': { + 'OutputDirectory': '<(midl_out_dir)', + 'HeaderFileName': '<(RULE_INPUT_ROOT).h', + }, + }, + }, + { + 'target_name': 'idl_explicit_action', + 'type': 'none', + 'sources': [ + 'Window.idl', + ], + 'actions': [{ + 'action_name': 'blink_idl', + 'explicit_idl_action': 1, + 'msvs_cygwin_shell': 0, + 'inputs': [ + 'Window.idl', + 'idl_compiler.py', + ], + 'outputs': [ + 'Window.cpp', + 'Window.h', + ], + 'action': [ + 'python', + 'idl_compiler.py', + 'Window.idl', + ], + }], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/win/idl-rules/idl_compiler.py gyp-0.1+20150913git1f374df9/test/win/idl-rules/idl_compiler.py --- gyp-0.1~svn1729/test/win/idl-rules/idl_compiler.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-rules/idl_compiler.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# mock, just outputs empty .h/.cpp files + +import os +import sys + +if len(sys.argv) == 2: + basename, ext = os.path.splitext(sys.argv[1]) + with open('%s.h' % basename, 'w') as f: + f.write('// %s.h\n' % basename) + with open('%s.cpp' % basename, 'w') as f: + f.write('// %s.cpp\n' % basename) diff -Nru gyp-0.1~svn1729/test/win/idl-rules/Window.idl gyp-0.1+20150913git1f374df9/test/win/idl-rules/Window.idl --- gyp-0.1~svn1729/test/win/idl-rules/Window.idl 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/idl-rules/Window.idl 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + WillBeGarbageCollected, +] interface Window { + void alert(); +}; diff -Nru gyp-0.1~svn1729/test/win/importlib/dll_no_exports.cc gyp-0.1+20150913git1f374df9/test/win/importlib/dll_no_exports.cc --- gyp-0.1~svn1729/test/win/importlib/dll_no_exports.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/importlib/dll_no_exports.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +// Copyright (c) 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { + return TRUE; +} diff -Nru gyp-0.1~svn1729/test/win/importlib/noimplib.gyp gyp-0.1+20150913git1f374df9/test/win/importlib/noimplib.gyp --- gyp-0.1~svn1729/test/win/importlib/noimplib.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/importlib/noimplib.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,16 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'no_import_library', + 'type': 'loadable_module', + 'msvs_settings': { + 'NoImportLibrary': 'true', + }, + 'sources': ['dll_no_exports.cc'], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/large-pdb/main.cc gyp-0.1+20150913git1f374df9/test/win/large-pdb/main.cc --- gyp-0.1~svn1729/test/win/large-pdb/main.cc 2013-03-18 19:32:05.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/large-pdb/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -int main(int argc, const char** argv) { +int main(void) { return 0; } diff -Nru gyp-0.1~svn1729/test/win/linker-flags/a/x.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/a/x.cc --- gyp-0.1~svn1729/test/win/linker-flags/a/x.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/a/x.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int x() { + return 1; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/a/z.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/a/z.cc --- gyp-0.1~svn1729/test/win/linker-flags/a/z.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/a/z.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int z() { + return 3; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/b/y.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/b/y.cc --- gyp-0.1~svn1729/test/win/linker-flags/b/y.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/b/y.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int y() { + return 2; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/base-address.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/base-address.gyp --- gyp-0.1~svn1729/test/win/linker-flags/base-address.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/base-address.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,38 @@ +# Copyright 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_base_specified_exe', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'BaseAddress': '0x00420000', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_base_specified_dll', + 'type': 'shared_library', + 'msvs_settings': { + 'VCLinkerTool': { + 'BaseAddress': '0x10420000', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_base_default_exe', + 'type': 'executable', + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_base_default_dll', + 'type': 'shared_library', + 'sources': ['hello.cc'], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/force-symbol-reference.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/force-symbol-reference.gyp --- gyp-0.1~svn1729/test/win/linker-flags/force-symbol-reference.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/force-symbol-reference.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,39 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_force_reference_lib', + 'type': 'static_library', + 'sources': ['x.cc', 'y.cc'], + }, + { + 'target_name': 'test_force_reference', + 'type': 'executable', + # Turn on debug info to get symbols in disasm for the test code, and + # turn on opt:ref to drop unused symbols to make sure we wouldn't + # otherwise have the symbols. + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'AdditionalOptions': [ + '/OPT:REF', + ], + 'ForceSymbolReferences': [ + '?x@@YAHXZ', + '?y@@YAHXZ', + ], + }, + }, + 'sources': ['hello.cc'], + 'dependencies': [ + 'test_force_reference_lib', + ], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/generate-manifest.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/generate-manifest.gyp --- gyp-0.1~svn1729/test/win/linker-flags/generate-manifest.gyp 2012-07-25 21:04:23.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/generate-manifest.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -1,64 +1,166 @@ -# Copyright (c) 2012 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -{ - 'targets': [ - { - 'target_name': 'test_manifest_exe', - 'type': 'executable', - 'sources': ['hello.cc'], - 'msvs_settings': { - 'VCManifestTool': { - 'EmbedManifest': 'false', - } - }, - }, - { - 'target_name': 'test_manifest_dll', - 'type': 'shared_library', - 'sources': ['hello.cc'], - 'msvs_settings': { - 'VCManifestTool': { - 'EmbedManifest': 'false', - } - }, - }, - { - 'target_name': 'test_manifest_extra1', - 'type': 'executable', - 'sources': ['hello.cc'], - 'msvs_settings': { - 'VCManifestTool': { - 'EmbedManifest': 'false', - 'AdditionalManifestFiles': 'extra.manifest', - } - }, - }, - { - 'target_name': 'test_manifest_extra2', - 'type': 'executable', - 'sources': ['hello.cc'], - 'msvs_settings': { - 'VCManifestTool': { - 'EmbedManifest': 'false', - 'AdditionalManifestFiles': 'extra.manifest;extra2.manifest', - } - }, - }, - { - 'target_name': 'test_manifest_extra_list', - 'type': 'executable', - 'sources': ['hello.cc'], - 'msvs_settings': { - 'VCManifestTool': { - 'EmbedManifest': 'false', - 'AdditionalManifestFiles': [ - 'extra.manifest', - 'extra2.manifest' - ], - } - }, - }, - ] -} +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_generate_manifest_true', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_false', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'false', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_default', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_true_as_embedded', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_false_as_embedded', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'false', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_default_as_embedded', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'true', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_true_with_extra_manifest', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + 'AdditionalManifestFiles': 'extra.manifest;extra2.manifest', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_false_with_extra_manifest', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'false', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + 'AdditionalManifestFiles': 'extra.manifest;extra2.manifest', + }, + }, + }, + { + 'target_name': 'test_generate_manifest_true_with_extra_manifest_list', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'true', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + 'AdditionalManifestFiles': [ + 'extra.manifest', + 'extra2.manifest', + ], + }, + }, + }, + { + 'target_name': 'test_generate_manifest_false_with_extra_manifest_list', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + 'GenerateManifest': 'false', + }, + 'VCManifestTool': { + 'EmbedManifest': 'false', + 'AdditionalManifestFiles': [ + 'extra.manifest', + 'extra2.manifest', + ], + }, + }, + }, + { + 'target_name': 'test_generate_manifest_default_embed_default', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'EnableUAC': 'true', + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/inline_test.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/inline_test.cc --- gyp-0.1~svn1729/test/win/linker-flags/inline_test.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/inline_test.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,12 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "inline_test.h" + +#include +#pragma intrinsic(_ReturnAddress) + +bool IsFunctionInlined(void* caller_return_address) { + return _ReturnAddress() == caller_return_address; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/inline_test.h gyp-0.1+20150913git1f374df9/test/win/linker-flags/inline_test.h --- gyp-0.1~svn1729/test/win/linker-flags/inline_test.h 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/inline_test.h 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,5 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +bool IsFunctionInlined(void* current_return_address); diff -Nru gyp-0.1~svn1729/test/win/linker-flags/inline_test_main.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/inline_test_main.cc --- gyp-0.1~svn1729/test/win/linker-flags/inline_test_main.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/inline_test_main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "inline_test.h" + +#include +#include + +#pragma intrinsic(_ReturnAddress) + +int main() { + if (IsFunctionInlined(_ReturnAddress())) + puts("==== inlined ====\n"); +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/link-ordering.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/link-ordering.gyp --- gyp-0.1~svn1729/test/win/linker-flags/link-ordering.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/link-ordering.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,95 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_ordering_exe', + 'type': 'executable', + # These are so the names of the functions appear in the disassembly. + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + 'Optimization': '2', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '1', + 'GenerateManifest': 'false', + # Minimize the disassembly to just our code. + 'AdditionalOptions': [ + '/NODEFAULTLIB', + ], + }, + }, + 'sources': [ + # Explicitly sorted the same way as the disassembly in the test .py. + 'main-crt.c', + 'z.cc', + 'x.cc', + 'y.cc', + 'hello.cc', + ], + }, + + { + 'target_name': 'test_ordering_subdirs', + 'type': 'executable', + # These are so the names of the functions appear in the disassembly. + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + 'Optimization': '2', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '1', + 'GenerateManifest': 'false', + # Minimize the disassembly to just our code. + 'AdditionalOptions': [ + '/NODEFAULTLIB', + ], + }, + }, + 'sources': [ + # Explicitly sorted the same way as the disassembly in the test .py. + 'main-crt.c', + 'hello.cc', + 'b/y.cc', + 'a/z.cc', + ], + }, + + + { + 'target_name': 'test_ordering_subdirs_mixed', + 'type': 'executable', + # These are so the names of the functions appear in the disassembly. + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + 'Optimization': '2', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'LinkIncremental': '1', + 'GenerateManifest': 'false', + # Minimize the disassembly to just our code. + 'AdditionalOptions': [ + '/NODEFAULTLIB', + ], + }, + }, + 'sources': [ + # Explicitly sorted the same way as the disassembly in the test .py. + 'main-crt.c', + 'a/x.cc', + 'hello.cc', + 'a/z.cc', + 'y.cc', + ], + }, + + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/link-warning.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/link-warning.cc --- gyp-0.1~svn1729/test/win/linker-flags/link-warning.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/link-warning.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This will cause LNK4254. +#pragma comment(linker, "/merge:.data=.text") + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/ltcg.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/ltcg.gyp --- gyp-0.1~svn1729/test/win/linker-flags/ltcg.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/ltcg.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,42 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_ltcg_off', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WholeProgramOptimization': 'false', + }, + 'VCLinkerTool': { + 'LinkTimeCodeGeneration': '0', + }, + }, + 'sources': [ + 'inline_test.h', + 'inline_test.cc', + 'inline_test_main.cc', + ], + }, + { + 'target_name': 'test_ltcg_on', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WholeProgramOptimization': 'true', # /GL + }, + 'VCLinkerTool': { + 'LinkTimeCodeGeneration': '1', # /LTCG + }, + }, + 'sources': [ + 'inline_test.h', + 'inline_test.cc', + 'inline_test_main.cc', + ], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/main-crt.c gyp-0.1+20150913git1f374df9/test/win/linker-flags/main-crt.c --- gyp-0.1~svn1729/test/win/linker-flags/main-crt.c 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/main-crt.c 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,8 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Stub so we can link with /NODEFAULTLIB when checking disasm. +int mainCRTStartup() { + return 5; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/manifest-in-comment.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/manifest-in-comment.cc --- gyp-0.1~svn1729/test/win/linker-flags/manifest-in-comment.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/manifest-in-comment.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +// Copyright 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' " \ + "name='Test.Research.SampleAssembly' version='6.0.0.0' " \ + "processorArchitecture='X86' " \ + "publicKeyToken='0000000000000000' language='*'\"") + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/pdb-output.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/pdb-output.gyp --- gyp-0.1~svn1729/test/win/linker-flags/pdb-output.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/pdb-output.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,49 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_pdb_output_exe', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': 'output_exe.pdb', + }, + }, + }, + { + 'target_name': 'test_pdb_output_dll', + 'type': 'shared_library', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3' + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + 'ProgramDatabaseFile': 'output_dll.pdb', + }, + }, + }, + { + 'target_name': 'test_pdb_output_disabled', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '0' + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'false', + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/pgo.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/pgo.gyp --- gyp-0.1~svn1729/test/win/linker-flags/pgo.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/pgo.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,143 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'pgd_basename': 'test_pgo', + }, + 'targets': [ + # In the PGO (Profile-Guided Optimization) build flow, we need to build the + # target binary multiple times. To implement this flow with gyp, here we + # define multiple 'executable' targets, each of which represents one build + # particular build/profile stage. On tricky part to do this is that these + # 'executable' targets should share the code itself so that profile data + # can be reused among these 'executable' files. In other words, the only + # differences among below 'executable' targets are: + # 1) PGO (Profile-Guided Optimization) database, and + # 2) linker options. + # The following static library contains all the logic including entry point. + # Basically we don't need to rebuild this target once we enter profiling + # phase of PGO. + { + 'target_name': 'test_pgo_main', + 'type': 'static_library', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WholeProgramOptimization': 'true', # /GL + }, + 'VCLibrarianTool': { + 'LinkTimeCodeGeneration': 'true', + }, + }, + 'link_settings': { + 'msvs_settings': { + 'VCLinkerTool': { + 'ProfileGuidedDatabase': '$(OutDir)\\<(pgd_basename).pgd', + 'TargetMachine': '1', # x86 - 32 + 'SubSystem': '1', # /SUBSYSTEM:CONSOLE + # Tell ninja generator not to pass /ManifestFile: option + # to the linker, because it causes LNK1268 error in PGO biuld. + 'GenerateManifest': 'false', + # We need to specify 'libcmt.lib' here so that the linker can pick + # up a valid entry point. + 'AdditionalDependencies': [ + 'libcmt.lib', + ], + }, + }, + }, + 'sources': [ + 'inline_test.h', + 'inline_test.cc', + 'inline_test_main.cc', + ], + }, + { + 'target_name': 'test_pgo_instrument', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkTimeCodeGeneration': '2', + }, + }, + 'dependencies': [ + 'test_pgo_main', + ], + }, + { + 'target_name': 'gen_profile_guided_database', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'action_main', + 'inputs': [], + 'outputs': [ + '$(OutDir)\\<(pgd_basename).pgd', + ], + 'action': [ + 'python', 'update_pgd.py', + '--vcbindir', '$(VCInstallDir)bin', + '--exe', '$(OutDir)\\test_pgo_instrument.exe', + '--pgd', '$(OutDir)\\<(pgd_basename).pgd', + ], + }, + ], + 'dependencies': [ + 'test_pgo_instrument', + ], + }, + { + 'target_name': 'test_pgo_optimize', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkTimeCodeGeneration': '3', + }, + }, + 'sources': [ + '$(OutDir)\\<(pgd_basename).pgd', + ], + 'dependencies': [ + 'test_pgo_main', + 'gen_profile_guided_database', + ], + }, + { + 'target_name': 'test_pgo_update', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkTimeCodeGeneration': '4', + }, + }, + 'sources': [ + '$(OutDir)\\<(pgd_basename).pgd', + ], + 'dependencies': [ + 'test_pgo_main', + ], + }, + # A helper target to dump link.exe's command line options. We can use the + # output to determine if PGO (Profile-Guided Optimization) is available on + # the test environment. + { + 'target_name': 'gen_linker_option', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'actions': [ + { + 'action_name': 'action_main', + 'inputs': [], + 'outputs': [ + '$(OutDir)\\linker_options.txt', + ], + 'action': [ + 'cmd.exe', '/c link.exe > $(OutDir)\\linker_options.txt & exit 0', + ], + }, + ], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/program-database.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/program-database.gyp --- gyp-0.1~svn1729/test/win/linker-flags/program-database.gyp 2012-11-03 00:08:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/program-database.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -4,9 +4,10 @@ { 'targets': [ - # Verify that 'ProgramDataBase' option correctly makes it to LINK step in Ninja + # Verify that 'ProgramDatabaseFile' option correctly makes it to LINK + # step in Ninja. { - # Verify that VC macros and windows paths work correctly + # Verify that VC macros and windows paths work correctly. 'target_name': 'test_pdb_outdir', 'type': 'executable', 'sources': ['hello.cc'], @@ -21,7 +22,7 @@ }, }, { - # Verify that GYP macros and POSIX paths work correctly + # Verify that GYP macros and POSIX paths work correctly. 'target_name': 'test_pdb_proddir', 'type': 'executable', 'sources': ['hello.cc'], diff -Nru gyp-0.1~svn1729/test/win/linker-flags/safeseh.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh.gyp --- gyp-0.1~svn1729/test/win/linker-flags/safeseh.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,79 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'target_defaults': { + 'configurations': { + 'Default': { + 'msvs_configuration_platform': 'Win32', + }, + 'Default_x64': { + 'inherit_from': ['Default'], + 'msvs_configuration_platform': 'x64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'test_safeseh_default', + 'type': 'executable', + 'msvs_settings': { + # By default, msvs passes /SAFESEH for Link, but not for MASM. In + # order for test_safeseh_default to link successfully, we need to + # explicitly specify /SAFESEH for MASM. + 'MASM': { + 'UseSafeExceptionHandlers': 'true', + }, + }, + 'sources': [ + 'safeseh_hello.cc', + 'safeseh_zero.asm', + ], + }, + { + 'target_name': 'test_safeseh_no', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'ImageHasSafeExceptionHandlers': 'false', + }, + }, + 'sources': [ + 'safeseh_hello.cc', + 'safeseh_zero.asm', + ], + }, + { + 'target_name': 'test_safeseh_yes', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'ImageHasSafeExceptionHandlers': 'true', + }, + 'MASM': { + 'UseSafeExceptionHandlers': 'true', + }, + }, + 'sources': [ + 'safeseh_hello.cc', + 'safeseh_zero.asm', + ], + }, + { + # x64 targets cannot have ImageHasSafeExceptionHandlers or + # UseSafeExceptionHandlers set. + 'target_name': 'test_safeseh_x64', + 'type': 'executable', + 'configurations': { + 'Default': { + 'msvs_target_platform': 'x64', + }, + }, + 'sources': [ + 'safeseh_hello.cc', + 'safeseh_zero64.asm', + ], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/safeseh_hello.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh_hello.cc --- gyp-0.1~svn1729/test/win/linker-flags/safeseh_hello.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh_hello.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern "C" { +int zero(void); +} + +int main() { + return zero(); +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/safeseh_zero64.asm gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh_zero64.asm --- gyp-0.1~svn1729/test/win/linker-flags/safeseh_zero64.asm 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh_zero64.asm 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,9 @@ +.CODE + +PUBLIC zero +zero PROC + xor eax, eax + ret 0 +zero ENDP + +END diff -Nru gyp-0.1~svn1729/test/win/linker-flags/safeseh_zero.asm gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh_zero.asm --- gyp-0.1~svn1729/test/win/linker-flags/safeseh_zero.asm 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/safeseh_zero.asm 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +.MODEL FLAT, C +.CODE + +PUBLIC zero +zero PROC + xor eax, eax + ret 0 +zero ENDP + +END diff -Nru gyp-0.1~svn1729/test/win/linker-flags/stacksize.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/stacksize.gyp --- gyp-0.1~svn1729/test/win/linker-flags/stacksize.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/stacksize.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,44 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_default', + 'type': 'executable', + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_set_reserved_size', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'StackReserveSize': 2097152, # 2MB + } + }, + }, + { + 'target_name': 'test_set_commit_size', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'StackCommitSize': 8192, # 8KB + } + }, + }, + { + 'target_name': 'test_set_both', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'StackReserveSize': 2097152, # 2MB + 'StackCommitSize': 8192, # 8KB + } + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/subsystem.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/subsystem.gyp --- gyp-0.1~svn1729/test/win/linker-flags/subsystem.gyp 2012-03-26 23:58:02.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/subsystem.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -44,5 +44,27 @@ }, 'sources': ['hello.cc'], }, + { + 'target_name': 'test_console_xp', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '1', + 'MinimumRequiredVersion': '5.01', # XP. + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_windows_xp', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2', + 'MinimumRequiredVersion': '5.01', # XP. + } + }, + 'sources': ['subsystem-windows.cc'], + }, ] } diff -Nru gyp-0.1~svn1729/test/win/linker-flags/target-machine.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/target-machine.gyp --- gyp-0.1~svn1729/test/win/linker-flags/target-machine.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/target-machine.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,48 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_target_link_x86', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'TargetMachine': '1', + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_target_link_x64', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'TargetMachine': '17', + }, + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_target_lib_x86', + 'type': 'static_library', + 'msvs_settings': { + 'VCLibrarianTool': { + 'TargetMachine': '1', + } + }, + 'sources': ['hello.cc'], + }, + { + 'target_name': 'test_target_lib_x64', + 'type': 'static_library', + 'msvs_settings': { + 'VCLibrarianTool': { + 'TargetMachine': '17', + }, + }, + 'sources': ['hello.cc'], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/unsupported-manifest.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/unsupported-manifest.gyp --- gyp-0.1~svn1729/test/win/linker-flags/unsupported-manifest.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/unsupported-manifest.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,13 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_unsupported', + 'type': 'executable', + 'sources': ['manifest-in-comment.cc'], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/update_pgd.py gyp-0.1+20150913git1f374df9/test/win/linker-flags/update_pgd.py --- gyp-0.1~svn1729/test/win/linker-flags/update_pgd.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/update_pgd.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from optparse import OptionParser +import glob +import os +import subprocess + +parser = OptionParser() +parser.add_option('--exe', dest='exe') +parser.add_option('--vcbindir', dest='vcbindir') +parser.add_option('--pgd', dest='pgd') +(options, args) = parser.parse_args() + +# Instrumented binaries fail to run unless the Visual C++'s bin dir is included +# in the PATH environment variable. +os.environ['PATH'] = os.environ['PATH'] + os.pathsep + options.vcbindir + +# Run Instrumented binary. The profile will be recorded into *.pgc file. +subprocess.call([options.exe]) + +# Merge *.pgc files into a *.pgd (Profile-Guided Database) file. +subprocess.call(['pgomgr', '/merge', options.pgd]) + +# *.pgc files are no longer necessary. Clear all of them. +pgd_file = os.path.abspath(options.pgd) +pgd_dir = os.path.dirname(pgd_file) +(pgd_basename, _) = os.path.splitext(os.path.basename(pgd_file)) +pgc_filepattern = os.path.join(pgd_dir, '%s!*.pgc' % pgd_basename) +pgc_files= glob.glob(pgc_filepattern) +for pgc_file in pgc_files: + os.unlink(pgc_file) diff -Nru gyp-0.1~svn1729/test/win/linker-flags/warn-as-error.gyp gyp-0.1+20150913git1f374df9/test/win/linker-flags/warn-as-error.gyp --- gyp-0.1~svn1729/test/win/linker-flags/warn-as-error.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/warn-as-error.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,33 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_on', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'TreatLinkerWarningAsErrors': 'true', + } + }, + 'sources': ['link-warning.cc'], + }, + { + 'target_name': 'test_off', + 'type': 'executable', + 'msvs_settings': { + 'VCLinkerTool': { + 'TreatLinkerWarningAsErrors': 'false', + } + }, + 'sources': ['link-warning.cc'], + }, + { + 'target_name': 'test_default', + 'type': 'executable', + 'sources': ['link-warning.cc'], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/x.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/x.cc --- gyp-0.1~svn1729/test/win/linker-flags/x.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/x.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int x() { + return 1; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/y.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/y.cc --- gyp-0.1~svn1729/test/win/linker-flags/y.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/y.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int y() { + return 2; +} diff -Nru gyp-0.1~svn1729/test/win/linker-flags/z.cc gyp-0.1+20150913git1f374df9/test/win/linker-flags/z.cc --- gyp-0.1~svn1729/test/win/linker-flags/z.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/linker-flags/z.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int z() { + return 3; +} diff -Nru gyp-0.1~svn1729/test/win/ml-safeseh/a.asm gyp-0.1+20150913git1f374df9/test/win/ml-safeseh/a.asm --- gyp-0.1~svn1729/test/win/ml-safeseh/a.asm 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/ml-safeseh/a.asm 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,10 @@ +.MODEL FLAT, C +.CODE + +PUBLIC zero +zero PROC + xor eax, eax + ret 0 +zero ENDP + +END diff -Nru gyp-0.1~svn1729/test/win/ml-safeseh/hello.cc gyp-0.1+20150913git1f374df9/test/win/ml-safeseh/hello.cc --- gyp-0.1~svn1729/test/win/ml-safeseh/hello.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/ml-safeseh/hello.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern "C" { +int zero(void); +} + +int main() { + return zero(); +} diff -Nru gyp-0.1~svn1729/test/win/ml-safeseh/ml-safeseh.gyp gyp-0.1+20150913git1f374df9/test/win/ml-safeseh/ml-safeseh.gyp --- gyp-0.1~svn1729/test/win/ml-safeseh/ml-safeseh.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/ml-safeseh/ml-safeseh.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,24 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'ml_safeseh', + 'type': 'executable', + 'sources': [ + 'hello.cc', + 'a.asm', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'ImageHasSafeExceptionHandlers': 'true', + }, + 'MASM': { + 'UseSafeExceptionHandlers': 'true', + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/precompiled/hello.c gyp-0.1+20150913git1f374df9/test/win/precompiled/hello.c --- gyp-0.1~svn1729/test/win/precompiled/hello.c 2012-05-28 18:27:42.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/precompiled/hello.c 2015-09-13 13:41:20.000000000 +0000 @@ -7,7 +7,7 @@ extern int hello2(); -int main(int argc, char *argv[]) { +int main(void) { printf("Hello, world!\n"); hello2(); return 0; diff -Nru gyp-0.1~svn1729/test/win/rc-build/hello3.rc gyp-0.1+20150913git1f374df9/test/win/rc-build/hello3.rc --- gyp-0.1~svn1729/test/win/rc-build/hello3.rc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/rc-build/hello3.rc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,87 @@ +//Microsoft Visual C++ generated resource script. +// +#include "include.h" +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifndef APSTUDIO_INVOKED +#include "targetver.h" +#endif +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(932) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +IDI_HELLO ICON "hello.ico" +IDI_SMALL ICON "small.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDC_HELLO "HELLO" + IDS_APP_TITLE "hello" +END + +#endif +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff -Nru gyp-0.1~svn1729/test/win/rc-build/hello.gyp gyp-0.1+20150913git1f374df9/test/win/rc-build/hello.gyp --- gyp-0.1~svn1729/test/win/rc-build/hello.gyp 2013-02-25 22:29:21.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/rc-build/hello.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -51,6 +51,32 @@ ], }, { + 'target_name': 'with_include_subdir', + 'type': 'executable', + 'msvs_settings': { + 'VCCLCompilerTool': { + 'DebugInformationFormat': '3', + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + 'VCResourceCompilerTool': { + 'Culture' : '1033', + }, + }, + 'resource_include_dirs': [ + '$(ProjectDir)\\subdir', + ], + 'sources': [ + 'hello.cpp', + 'hello3.rc', + ], + 'libraries': [ + 'kernel32.lib', + 'user32.lib', + ], + }, + { 'target_name': 'resource_only_dll', 'type': 'shared_library', 'msvs_settings': { diff -Nru gyp-0.1~svn1729/test/win/shard/hello.cc gyp-0.1+20150913git1f374df9/test/win/shard/hello.cc --- gyp-0.1~svn1729/test/win/shard/hello.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/shard/hello.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,7 @@ +// Copyright 2014 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +int main() { + return 0; +} diff -Nru gyp-0.1~svn1729/test/win/shard/shard.gyp gyp-0.1+20150913git1f374df9/test/win/shard/shard.gyp --- gyp-0.1~svn1729/test/win/shard/shard.gyp 2013-02-06 01:01:32.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/shard/shard.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -16,5 +16,16 @@ ], 'product_dir': '<(PRODUCT_DIR)', }, + { + 'target_name': 'refs_to_shard', + 'type': 'executable', + 'dependencies': [ + # Make sure references are correctly updated. + 'shard', + ], + 'sources': [ + 'hello.cc', + ], + }, ] } diff -Nru gyp-0.1~svn1729/test/win/shard/shard_ref.gyp gyp-0.1+20150913git1f374df9/test/win/shard/shard_ref.gyp --- gyp-0.1~svn1729/test/win/shard/shard_ref.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/shard/shard_ref.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,41 @@ +# Copyright 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'refs_to_shard_external_lib', + 'type': 'static_library', + 'dependencies': [ + # Make sure references in other files are updated correctly. + 'shard.gyp:shard', + ], + 'sources': [ + 'hello.cc', + ], + }, + { + 'target_name': 'refs_to_shard_external_exe', + 'type': 'executable', + 'dependencies': [ + # Make sure references in other files are updated correctly. + 'shard.gyp:shard', + ], + 'sources': [ + 'hello.cc', + ], + }, + { + 'target_name': 'refs_to_shard_external_dll', + 'type': 'shared_library', + 'dependencies': [ + # Make sure references in other files are updated correctly. + 'shard.gyp:shard', + ], + 'sources': [ + 'hello.cc', + ], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/system-include/main.cc gyp-0.1+20150913git1f374df9/test/win/system-include/main.cc --- gyp-0.1~svn1729/test/win/system-include/main.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/system-include/main.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,4 @@ +#include +#include + +int main() {} diff -Nru gyp-0.1~svn1729/test/win/system-include/test.gyp gyp-0.1+20150913git1f374df9/test/win/system-include/test.gyp --- gyp-0.1~svn1729/test/win/system-include/test.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/system-include/test.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,26 @@ +{ + 'target_defaults': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '4', + 'WarnAsError': 'true', + }, + }, + 'msvs_system_include_dirs': [ + '$(ProjectName)', # Different for each target + 'common', # Same for all targets + ], + }, + 'targets': [ + { + 'target_name': 'foo', + 'type': 'executable', + 'sources': [ 'main.cc', ], + }, + { + 'target_name': 'bar', + 'type': 'executable', + 'sources': [ 'main.cc', ], + }, + ], +} diff -Nru gyp-0.1~svn1729/test/win/vs-macros/containing-gyp.gyp gyp-0.1+20150913git1f374df9/test/win/vs-macros/containing-gyp.gyp --- gyp-0.1~svn1729/test/win/vs-macros/containing-gyp.gyp 2012-05-01 00:14:53.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/vs-macros/containing-gyp.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -16,7 +16,6 @@ 'extension': 'S', 'inputs': [ 'as.py', - '$(InputPath)' ], 'outputs': [ '$(IntDir)/$(InputName).obj', diff -Nru gyp-0.1~svn1729/test/win/vs-macros/input-output-macros.gyp gyp-0.1+20150913git1f374df9/test/win/vs-macros/input-output-macros.gyp --- gyp-0.1~svn1729/test/win/vs-macros/input-output-macros.gyp 2012-04-05 21:58:36.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/vs-macros/input-output-macros.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -13,7 +13,6 @@ 'rule_name': 'generate_file', 'extension': 'blah', 'inputs': [ - '<(RULE_INPUT_PATH)', 'do_stuff.py', ], 'outputs': [ diff -Nru gyp-0.1~svn1729/test/win/vs-macros/targetext.gyp gyp-0.1+20150913git1f374df9/test/win/vs-macros/targetext.gyp --- gyp-0.1~svn1729/test/win/vs-macros/targetext.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/vs-macros/targetext.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,59 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_targetext_executable', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\executable$(TargetExt)', + }, + }, + }, + { + 'target_name': 'test_targetext_loadable_module', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\loadable_module$(TargetExt)', + }, + }, + }, + { + 'target_name': 'test_targetext_shared_library', + 'type': 'shared_library', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\shared_library$(TargetExt)', + }, + }, + }, + { + 'target_name': 'test_targetext_static_library', + 'type': 'static_library', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLibrarianTool': { + 'OutputFile': '$(TargetDir)\\static_library$(TargetExt)', + }, + }, + }, + { + 'target_name': 'test_targetext_product_extension', + 'type': 'executable', + 'sources': ['hello.cc'], + 'product_extension': 'library', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\product_extension$(TargetExt)', + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/vs-macros/targetfilename.gyp gyp-0.1+20150913git1f374df9/test/win/vs-macros/targetfilename.gyp --- gyp-0.1~svn1729/test/win/vs-macros/targetfilename.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/vs-macros/targetfilename.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,59 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_targetfilename_executable', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetFileName)', + }, + }, + }, + { + 'target_name': 'test_targetfilename_loadable_module', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetFileName)', + }, + }, + }, + { + 'target_name': 'test_targetfilename_shared_library', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetFileName)', + }, + }, + }, + { + 'target_name': 'test_targetfilename_static_library', + 'type': 'static_library', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLibrarianTool': { + 'OutputFile': '$(TargetDir)\\$(TargetFileName)', + }, + }, + }, + { + 'target_name': 'test_targetfilename_product_extension', + 'type': 'executable', + 'sources': ['hello.cc'], + 'product_extension': 'foo', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetDir)\\$(TargetFileName)', + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/vs-macros/targetpath.gyp gyp-0.1+20150913git1f374df9/test/win/vs-macros/targetpath.gyp --- gyp-0.1~svn1729/test/win/vs-macros/targetpath.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/vs-macros/targetpath.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,59 @@ +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_targetpath_executable', + 'type': 'executable', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetPath)', + }, + }, + }, + { + 'target_name': 'test_targetpath_loadable_module', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetPath)', + }, + }, + }, + { + 'target_name': 'test_targetpath_shared_library', + 'type': 'loadable_module', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetPath)', + }, + }, + }, + { + 'target_name': 'test_targetpath_static_library', + 'type': 'static_library', + 'sources': ['hello.cc'], + 'msvs_settings': { + 'VCLibrarianTool': { + 'OutputFile': '$(TargetPath)', + }, + }, + }, + { + 'target_name': 'test_targetpath_product_extension', + 'type': 'executable', + 'sources': ['hello.cc'], + 'product_extension': 'foo', + 'msvs_settings': { + 'VCLinkerTool': { + 'OutputFile': '$(TargetPath)', + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/winrt-app-type-revision/dllmain.cc gyp-0.1+20150913git1f374df9/test/win/winrt-app-type-revision/dllmain.cc --- gyp-0.1~svn1729/test/win/winrt-app-type-revision/dllmain.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/winrt-app-type-revision/dllmain.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,30 @@ +// Copyright (c) 2013 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Graphics::Display; + +bool TryToUseSomeWinRT() { + ComPtr dp; + HStringReference s(RuntimeClass_Windows_Graphics_Display_DisplayProperties); + HRESULT hr = GetActivationFactory(s.Get(), dp.GetAddressOf()); + if (SUCCEEDED(hr)) { + float dpi = 96.0f; + if (SUCCEEDED(dp->get_LogicalDpi(&dpi))) { + return true; + } + } + return false; +} + +BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved) { + return TRUE; +} diff -Nru gyp-0.1~svn1729/test/win/winrt-app-type-revision/winrt-app-type-revison.gyp gyp-0.1+20150913git1f374df9/test/win/winrt-app-type-revision/winrt-app-type-revison.gyp --- gyp-0.1~svn1729/test/win/winrt-app-type-revision/winrt-app-type-revison.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/winrt-app-type-revision/winrt-app-type-revison.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,43 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'enable_winrt_81_revision_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '8.1' + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_82_revision_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '8.2' + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_invalid_revision_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '999' + 'sources': [ + 'dllmain.cc', + ], + }, + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + '%(AdditionalDependencies)', + ], + }, + }, + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/winrt-target-platform-version/dllmain.cc gyp-0.1+20150913git1f374df9/test/win/winrt-target-platform-version/dllmain.cc --- gyp-0.1~svn1729/test/win/winrt-target-platform-version/dllmain.cc 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/winrt-target-platform-version/dllmain.cc 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,30 @@ +// Copyright (c) 2015 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Graphics::Display; + +bool TryToUseSomeWinRT() { + ComPtr dp; + HStringReference s(RuntimeClass_Windows_Graphics_Display_DisplayProperties); + HRESULT hr = GetActivationFactory(s.Get(), dp.GetAddressOf()); + if (SUCCEEDED(hr)) { + float dpi = 96.0f; + if (SUCCEEDED(dp->get_LogicalDpi(&dpi))) { + return true; + } + } + return false; +} + +BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved) { + return TRUE; +} diff -Nru gyp-0.1~svn1729/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp gyp-0.1+20150913git1f374df9/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp --- gyp-0.1~svn1729/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/winrt-target-platform-version/winrt-target-platform-version.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,49 @@ +# Copyright (c) 2015 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'enable_winrt_10_platversion_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '10.0', + 'msvs_target_platform_version':'10.0.10240.0', + 'msvs_target_platform_minversion':'10.0.10240.0' + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_10_platversion_nominver_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '10.0', + 'msvs_target_platform_version':'10.0.10240.0', + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_9_platversion_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '10.0', + 'msvs_target_platform_version':'9.0.0.0', + 'msvs_target_platform_minversion':'9.0.0.0' + 'sources': [ + 'dllmain.cc', + ], + }, + { + 'target_name': 'enable_winrt_missing_platversion_dll', + 'type': 'shared_library', + 'msvs_enable_winrt': 1, + 'msvs_application_type_revision': '10.0', + 'sources': [ + 'dllmain.cc', + ], + }, + ] +} diff -Nru gyp-0.1~svn1729/test/win/win-tool/copies_readonly_files.gyp gyp-0.1+20150913git1f374df9/test/win/win-tool/copies_readonly_files.gyp --- gyp-0.1~svn1729/test/win/win-tool/copies_readonly_files.gyp 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/win-tool/copies_readonly_files.gyp 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,29 @@ +{ + 'targets': [ + { + 'target_name': 'foo', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/dest', + 'files': [ + 'read-only-file', + ], + }, + ], + }, # target: foo + + { + 'target_name': 'bar', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/dest', + 'files': [ + 'subdir/', + ], + }, + ], + }, # target: bar + ], +} diff -Nru gyp-0.1~svn1729/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py gyp-0.1+20150913git1f374df9/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py --- gyp-0.1~svn1729/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py 1970-01-01 00:00:00.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/test/win/win-tool/gyptest-win-tool-handles-readonly-files.py 2015-09-13 13:41:20.000000000 +0000 @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +# Copyright (c) 2014 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Make sure overwriting read-only files works as expected (via win-tool). +""" + +import TestGyp + +import filecmp +import os +import stat +import sys + +if sys.platform == 'win32': + test = TestGyp.TestGyp(formats=['ninja']) + + # First, create the source files. + os.makedirs('subdir') + read_only_files = ['read-only-file', 'subdir/A', 'subdir/B', 'subdir/C'] + for f in read_only_files: + test.write(f, 'source_contents') + test.chmod(f, stat.S_IREAD) + if os.access(f, os.W_OK): + test.fail_test() + + # Second, create the read-only destination files. Note that we are creating + # them where the ninja and win-tool will try to copy them to, in order to test + # that copies overwrite the files. + os.makedirs(test.built_file_path('dest/subdir')) + for f in read_only_files: + f = os.path.join('dest', f) + test.write(test.built_file_path(f), 'SHOULD BE OVERWRITTEN') + test.chmod(test.built_file_path(f), stat.S_IREAD) + # Ensure not writable. + if os.access(test.built_file_path(f), os.W_OK): + test.fail_test() + + test.run_gyp('copies_readonly_files.gyp') + test.build('copies_readonly_files.gyp') + + # Check the destination files were overwritten by ninja. + for f in read_only_files: + f = os.path.join('dest', f) + test.must_contain(test.built_file_path(f), 'source_contents') + + # This will fail if the files are not the same mode or contents. + for f in read_only_files: + if not filecmp.cmp(f, test.built_file_path(os.path.join('dest', f))): + test.fail_test() + + test.pass_test() diff -Nru gyp-0.1~svn1729/tools/emacs/gyp.el gyp-0.1+20150913git1f374df9/tools/emacs/gyp.el --- gyp-0.1~svn1729/tools/emacs/gyp.el 2013-08-22 16:50:21.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/tools/emacs/gyp.el 2015-09-13 13:41:20.000000000 +0000 @@ -15,14 +15,36 @@ "recent emacsen), not from the older and less maintained " "python-mode.el"))) -(defadvice python-calculate-indentation (after ami-outdent-closing-parens - activate) +(defadvice python-indent-calculate-levels (after gyp-outdent-closing-parens + activate) "De-indent closing parens, braces, and brackets in gyp-mode." - (if (and (eq major-mode 'gyp-mode) - (string-match "^ *[])}][],)}]* *$" - (buffer-substring-no-properties - (line-beginning-position) (line-end-position)))) - (setq ad-return-value (- ad-return-value 2)))) + (when (and (eq major-mode 'gyp-mode) + (string-match "^ *[])}][],)}]* *$" + (buffer-substring-no-properties + (line-beginning-position) (line-end-position)))) + (setf (first python-indent-levels) + (- (first python-indent-levels) python-continuation-offset)))) + +(defadvice python-indent-guess-indent-offset (around + gyp-indent-guess-indent-offset + activate) + "Guess correct indent offset in gyp-mode." + (or (and (not (eq major-mode 'gyp-mode)) + ad-do-it) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + ;; Find first line ending with an opening brace that is not a comment. + (or (and (re-search-forward "\\(^[[{]$\\|^.*[^#].*[[{]$\\)") + (forward-line) + (/= (current-indentation) 0) + (set (make-local-variable 'python-indent-offset) + (current-indentation)) + (set (make-local-variable 'python-continuation-offset) + (current-indentation))) + (message "Can't guess gyp indent offset, using default: %s" + python-continuation-offset)))))) (define-derived-mode gyp-mode python-mode "Gyp" "Major mode for editing .gyp files. See http://code.google.com/p/gyp/" @@ -35,9 +57,10 @@ (defun gyp-set-indentation () "Hook function to configure python indentation to suit gyp mode." - (setq python-continuation-offset 2 - python-indent 2 - python-guess-indent nil)) + (set (make-local-variable 'python-indent-offset) 2) + (set (make-local-variable 'python-continuation-offset) 2) + (set (make-local-variable 'python-indent-guess-indent-offset) t) + (python-indent-guess-indent-offset)) (add-hook 'gyp-mode-hook 'gyp-set-indentation) @@ -218,11 +241,11 @@ ;; Top-level keywords (list (concat "['\"]\\(" (regexp-opt (list "action" "action_name" "actions" "cflags" - "conditions" "configurations" "copies" "defines" - "dependencies" "destination" + "cflags_cc" "conditions" "configurations" + "copies" "defines" "dependencies" "destination" "direct_dependent_settings" "export_dependent_settings" "extension" "files" - "include_dirs" "includes" "inputs" "libraries" + "include_dirs" "includes" "inputs" "ldflags" "libraries" "link_settings" "mac_bundle" "message" "msvs_external_rule" "outputs" "product_name" "process_outputs_as_sources" "rules" "rule_name" diff -Nru gyp-0.1~svn1729/tools/pretty_sln.py gyp-0.1+20150913git1f374df9/tools/pretty_sln.py --- gyp-0.1~svn1729/tools/pretty_sln.py 2012-05-22 21:06:31.000000000 +0000 +++ gyp-0.1+20150913git1f374df9/tools/pretty_sln.py 2015-09-13 13:41:20.000000000 +0000 @@ -38,12 +38,13 @@ # Regular expressions that matches the SLN format. # The first line of a project definition. - begin_project = re.compile(('^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942' - '}"\) = "(.*)", "(.*)", "(.*)"$')) + begin_project = re.compile(r'^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942' + r'}"\) = "(.*)", "(.*)", "(.*)"$') # The last line of a project definition. end_project = re.compile('^EndProject$') # The first line of a dependency list. - begin_dep = re.compile('ProjectSection\(ProjectDependencies\) = postProject$') + begin_dep = re.compile( + r'ProjectSection\(ProjectDependencies\) = postProject$') # The last line of a dependency list. end_dep = re.compile('EndProjectSection$') # A line describing a dependency.